Merge pull request #1159 from wpaulino/onion-service-support
multi: add onion services support
This commit is contained in:
22 files changed
+1694
-623
No files matched your search
+92
-22
@@ -11,6 +11,7 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/tor"
|
||||
"github.com/roasbeef/btcd/btcec"
|
||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
@@ -43,8 +44,7 @@ const (
|
||||
// v2OnionAddr denotes a version 2 Tor onion service address.
|
||||
v2OnionAddr addressType = 3
|
||||
|
||||
// v3OnionAddr denotes a version 3 Tor (prop224) onion service
|
||||
// addresses
|
||||
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
|
||||
v3OnionAddr addressType = 4
|
||||
)
|
||||
|
||||
@@ -56,16 +56,12 @@ func (a addressType) AddrLen() uint16 {
|
||||
return 0
|
||||
case tcp4Addr:
|
||||
return 6
|
||||
|
||||
case tcp6Addr:
|
||||
return 18
|
||||
|
||||
case v2OnionAddr:
|
||||
return 12
|
||||
|
||||
case v3OnionAddr:
|
||||
return 37
|
||||
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
@@ -300,7 +296,6 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return fmt.Errorf("cannot write nil TCPAddr")
|
||||
}
|
||||
|
||||
// TODO(roasbeef): account for onion types too
|
||||
if e.IP.To4() != nil {
|
||||
var descriptor [1]byte
|
||||
descriptor[0] = uint8(tcp4Addr)
|
||||
@@ -331,6 +326,45 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
case *tor.OnionAddr:
|
||||
if e == nil {
|
||||
return errors.New("cannot write nil onion address")
|
||||
}
|
||||
|
||||
var suffixIndex int
|
||||
switch len(e.OnionService) {
|
||||
case tor.V2Len:
|
||||
descriptor := []byte{byte(v2OnionAddr)}
|
||||
if _, err := w.Write(descriptor); err != nil {
|
||||
return err
|
||||
}
|
||||
suffixIndex = tor.V2Len - tor.OnionSuffixLen
|
||||
case tor.V3Len:
|
||||
descriptor := []byte{byte(v3OnionAddr)}
|
||||
if _, err := w.Write(descriptor); err != nil {
|
||||
return err
|
||||
}
|
||||
suffixIndex = tor.V3Len - tor.OnionSuffixLen
|
||||
default:
|
||||
return errors.New("unknown onion service length")
|
||||
}
|
||||
|
||||
host, err := tor.Base32Encoding.DecodeString(
|
||||
e.OnionService[:suffixIndex],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(host); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
binary.BigEndian.PutUint16(port[:], uint16(e.Port))
|
||||
if _, err := w.Write(port[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case []net.Addr:
|
||||
// First, we'll encode all the addresses into an intermediate
|
||||
// buffer. We need to do this in order to compute the total
|
||||
@@ -632,6 +666,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
addresses []net.Addr
|
||||
addrBytesRead uint16
|
||||
)
|
||||
|
||||
for addrBytesRead < addrsLen {
|
||||
var descriptor [1]byte
|
||||
if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
|
||||
@@ -640,52 +675,87 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
|
||||
addrBytesRead++
|
||||
|
||||
address := &net.TCPAddr{}
|
||||
aType := addressType(descriptor[0])
|
||||
switch aType {
|
||||
|
||||
var address net.Addr
|
||||
switch aType := addressType(descriptor[0]); aType {
|
||||
case noAddr:
|
||||
addrBytesRead += aType.AddrLen()
|
||||
continue
|
||||
|
||||
case tcp4Addr:
|
||||
var ip [4]byte
|
||||
if _, err = io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
address.IP = (net.IP)(ip[:])
|
||||
|
||||
var port [2]byte
|
||||
if _, err = io.ReadFull(addrBuf, port[:]); err != nil {
|
||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
address.Port = int(binary.BigEndian.Uint16(port[:]))
|
||||
|
||||
address = &net.TCPAddr{
|
||||
IP: net.IP(ip[:]),
|
||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
|
||||
case tcp6Addr:
|
||||
var ip [16]byte
|
||||
if _, err = io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
address.IP = (net.IP)(ip[:])
|
||||
|
||||
var port [2]byte
|
||||
if _, err = io.ReadFull(addrBuf, port[:]); err != nil {
|
||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
address.Port = int(binary.BigEndian.Uint16(port[:]))
|
||||
|
||||
address = &net.TCPAddr{
|
||||
IP: net.IP(ip[:]),
|
||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
|
||||
case v2OnionAddr:
|
||||
var h [tor.V2DecodedLen]byte
|
||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var p [2]byte
|
||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||
onionService += tor.OnionSuffix
|
||||
port := int(binary.BigEndian.Uint16(p[:]))
|
||||
|
||||
address = &tor.OnionAddr{
|
||||
OnionService: onionService,
|
||||
Port: port,
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
continue
|
||||
|
||||
case v3OnionAddr:
|
||||
var h [tor.V3DecodedLen]byte
|
||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var p [2]byte
|
||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||
onionService += tor.OnionSuffix
|
||||
port := int(binary.BigEndian.Uint16(p[:]))
|
||||
|
||||
address = &tor.OnionAddr{
|
||||
OnionService: onionService,
|
||||
Port: port,
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
continue
|
||||
|
||||
default:
|
||||
return &ErrUnknownAddrType{aType}
|
||||
|
||||
+101
-7
@@ -2,6 +2,7 @@ package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"image/color"
|
||||
"math"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/tor"
|
||||
"github.com/roasbeef/btcd/btcec"
|
||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
@@ -37,11 +39,6 @@ var (
|
||||
}
|
||||
_, _ = testSig.R.SetString("63724406601629180062774974542967536251589935445068131219452686511677818569431", 10)
|
||||
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
|
||||
|
||||
// TODO(roasbeef): randomly generate from three types of addrs
|
||||
a1 = &net.TCPAddr{IP: (net.IP)([]byte{0x7f, 0x0, 0x0, 0x1}), Port: 8333}
|
||||
a2, _ = net.ResolveTCPAddr("tcp", "[2001:db8:85a3:0:0:8a2e:370:7334]:80")
|
||||
testAddrs = []net.Addr{a1, a2}
|
||||
)
|
||||
|
||||
func randPubKey() (*btcec.PublicKey, error) {
|
||||
@@ -76,6 +73,100 @@ func randRawFeatureVector(r *rand.Rand) *RawFeatureVector {
|
||||
return featureVec
|
||||
}
|
||||
|
||||
func randTCP4Addr(r *rand.Rand) (*net.TCPAddr, error) {
|
||||
var ip [4]byte
|
||||
if _, err := r.Read(ip[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
if _, err := r.Read(port[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addrIP := net.IP(ip[:])
|
||||
addrPort := int(binary.BigEndian.Uint16(port[:]))
|
||||
|
||||
return &net.TCPAddr{IP: addrIP, Port: addrPort}, nil
|
||||
}
|
||||
|
||||
func randTCP6Addr(r *rand.Rand) (*net.TCPAddr, error) {
|
||||
var ip [16]byte
|
||||
if _, err := r.Read(ip[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
if _, err := r.Read(port[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addrIP := net.IP(ip[:])
|
||||
addrPort := int(binary.BigEndian.Uint16(port[:]))
|
||||
|
||||
return &net.TCPAddr{IP: addrIP, Port: addrPort}, nil
|
||||
}
|
||||
|
||||
func randV2OnionAddr(r *rand.Rand) (*tor.OnionAddr, error) {
|
||||
var serviceID [tor.V2DecodedLen]byte
|
||||
if _, err := r.Read(serviceID[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
if _, err := r.Read(port[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
onionService := tor.Base32Encoding.EncodeToString(serviceID[:])
|
||||
onionService += tor.OnionSuffix
|
||||
addrPort := int(binary.BigEndian.Uint16(port[:]))
|
||||
|
||||
return &tor.OnionAddr{OnionService: onionService, Port: addrPort}, nil
|
||||
}
|
||||
|
||||
func randV3OnionAddr(r *rand.Rand) (*tor.OnionAddr, error) {
|
||||
var serviceID [tor.V3DecodedLen]byte
|
||||
if _, err := r.Read(serviceID[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
if _, err := r.Read(port[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
onionService := tor.Base32Encoding.EncodeToString(serviceID[:])
|
||||
onionService += tor.OnionSuffix
|
||||
addrPort := int(binary.BigEndian.Uint16(port[:]))
|
||||
|
||||
return &tor.OnionAddr{OnionService: onionService, Port: addrPort}, nil
|
||||
}
|
||||
|
||||
func randAddrs(r *rand.Rand) ([]net.Addr, error) {
|
||||
tcp4Addr, err := randTCP4Addr(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tcp6Addr, err := randTCP6Addr(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v2OnionAddr, err := randV2OnionAddr(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v3OnionAddr, err := randV3OnionAddr(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []net.Addr{tcp4Addr, tcp6Addr, v2OnionAddr, v3OnionAddr}, nil
|
||||
}
|
||||
|
||||
func TestMaxOutPointIndex(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -465,8 +556,6 @@ func TestLightningWireProtocol(t *testing.T) {
|
||||
G: uint8(r.Int31()),
|
||||
B: uint8(r.Int31()),
|
||||
},
|
||||
// TODO(roasbeef): proper gen rand addrs
|
||||
Addresses: testAddrs,
|
||||
}
|
||||
req.Signature, err = NewSigFromSignature(testSig)
|
||||
if err != nil {
|
||||
@@ -480,6 +569,11 @@ func TestLightningWireProtocol(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
req.Addresses, err = randAddrs(r)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate addresses: %v", err)
|
||||
}
|
||||
|
||||
v[0] = reflect.ValueOf(req)
|
||||
},
|
||||
MsgChannelUpdate: func(v []reflect.Value, r *rand.Rand) {
|
||||
|
||||
Reference in new issue
Block a user