diff --git a/channeldb/addr.go b/channeldb/addr.go index daa61a8b..f97e8a5b 100644 --- a/channeldb/addr.go +++ b/channeldb/addr.go @@ -3,6 +3,8 @@ package channeldb import ( "io" "net" + + "github.com/btcsuite/go-socks/socks" ) // addressType specifies the network protocol and version that should be used @@ -23,6 +25,40 @@ const ( v3OnionAddr addressType = 3 ) +func encodeTCPAddr(w io.Writer, addr *net.TCPAddr) error { + var scratch [16]byte + + if addr.IP.To4() != nil { + scratch[0] = uint8(tcp4Addr) + if _, err := w.Write(scratch[:1]); err != nil { + return err + } + + copy(scratch[:4], addr.IP.To4()) + if _, err := w.Write(scratch[:4]); err != nil { + return err + } + + } else { + scratch[0] = uint8(tcp6Addr) + if _, err := w.Write(scratch[:1]); err != nil { + return err + } + + copy(scratch[:], addr.IP.To16()) + if _, err := w.Write(scratch[:]); err != nil { + return err + } + } + + byteOrder.PutUint16(scratch[:2], uint16(addr.Port)) + if _, err := w.Write(scratch[:2]); err != nil { + return err + } + + return nil +} + // deserializeAddr reads the serialized raw representation of an address and // deserializes it into the actual address, to avoid performing address // resolution in the database module @@ -70,33 +106,31 @@ func deserializeAddr(r io.Reader) (net.Addr, error) { // serializeAddr serializes an address into a raw byte representation so it // can be deserialized without requiring address resolution func serializeAddr(w io.Writer, address net.Addr) error { - var scratch [16]byte - if address.Network() == "tcp" { - if address.(*net.TCPAddr).IP.To4() != nil { - scratch[0] = uint8(tcp4Addr) - if _, err := w.Write(scratch[:1]); err != nil { - return err - } - copy(scratch[:4], address.(*net.TCPAddr).IP.To4()) - if _, err := w.Write(scratch[:4]); err != nil { - return err - } - } else { - scratch[0] = uint8(tcp6Addr) - if _, err := w.Write(scratch[:1]); err != nil { - return err - } - copy(scratch[:], address.(*net.TCPAddr).IP.To16()) - if _, err := w.Write(scratch[:]); err != nil { - return err - } + switch addr := address.(type) { + case *net.TCPAddr: + return encodeTCPAddr(w, addr) + + // If this is a proxied address (due to the connection being + // established over a SOCKs proxy, then we'll convert it into its + // corresponding TCP address. + case *socks.ProxiedAddr: + // If we can't parse the host as an IP (though we should be + // able to at this point), then we'll skip this address all + // together. + // + // TODO(roasbeef): would be nice to be able to store hosts + // though... + ip := net.ParseIP(addr.Host) + if ip == nil { + return nil } - byteOrder.PutUint16(scratch[:2], - uint16(address.(*net.TCPAddr).Port)) - if _, err := w.Write(scratch[:2]); err != nil { - return err + + tcpAddr := &net.TCPAddr{ + IP: ip, + Port: addr.Port, } + return encodeTCPAddr(w, tcpAddr) } return nil diff --git a/channeldb/channel.go b/channeldb/channel.go index 8e246e3e..d9d56c96 100644 --- a/channeldb/channel.go +++ b/channeldb/channel.go @@ -623,7 +623,7 @@ func fetchOpenChannel(chanBucket *bolt.Bucket, // // TODO(roasbeef): addr param should eventually be a lnwire.NetAddress type // that includes service bits. -func (c *OpenChannel) SyncPending(addr *net.TCPAddr, pendingHeight uint32) error { +func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error { c.Lock() defer c.Unlock() diff --git a/channeldb/nodes.go b/channeldb/nodes.go index 9274bc08..57626e76 100644 --- a/channeldb/nodes.go +++ b/channeldb/nodes.go @@ -56,7 +56,7 @@ type LinkNode struct { // authenticated connection for the stored identity public key. // // TODO(roasbeef): also need to support hidden service addrs - Addresses []*net.TCPAddr + Addresses []net.Addr db *DB } @@ -64,13 +64,13 @@ type LinkNode struct { // NewLinkNode creates a new LinkNode from the provided parameters, which is // backed by an instance of channeldb. func (db *DB) NewLinkNode(bitNet wire.BitcoinNet, pub *btcec.PublicKey, - addr *net.TCPAddr) *LinkNode { + addr net.Addr) *LinkNode { return &LinkNode{ Network: bitNet, IdentityPub: pub, LastSeen: time.Now(), - Addresses: []*net.TCPAddr{addr}, + Addresses: []net.Addr{addr}, db: db, } } @@ -267,13 +267,13 @@ func deserializeLinkNode(r io.Reader) (*LinkNode, error) { } numAddrs := byteOrder.Uint32(buf[:4]) - node.Addresses = make([]*net.TCPAddr, numAddrs) + node.Addresses = make([]net.Addr, numAddrs) for i := uint32(0); i < numAddrs; i++ { addr, err := deserializeAddr(r) if err != nil { return nil, err } - node.Addresses[i] = addr.(*net.TCPAddr) + node.Addresses[i] = addr } return node, nil diff --git a/fundingmanager.go b/fundingmanager.go index a07c1cff..8039d9fd 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "fmt" + "net" "sync" "sync/atomic" "time" @@ -26,7 +27,6 @@ import ( "github.com/roasbeef/btcd/chaincfg/chainhash" "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" - "net" ) const ( @@ -847,7 +847,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { chainHash := chainhash.Hash(msg.ChainHash) reservation, err := f.cfg.Wallet.InitChannelReservation(amt, 0, msg.PushAmount, btcutil.Amount(msg.FeePerKiloWeight), 0, - fmsg.peerAddress.IdentityKey, fmsg.peerAddress.Address.(*net.TCPAddr), + fmsg.peerAddress.IdentityKey, fmsg.peerAddress.Address, &chainHash, msg.ChannelFlags) if err != nil { fndgLog.Errorf("Unable to initialize reservation: %v", err) diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index 84f59182..d856dfd1 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -110,7 +110,7 @@ type ChannelReservation struct { theirContribution *ChannelContribution partialState *channeldb.OpenChannel - nodeAddr *net.TCPAddr + nodeAddr net.Addr // The ID of this reservation, used to uniquely track the reservation // throughout its lifetime. diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index c80af1ef..275674e1 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -82,10 +82,10 @@ type initFundingReserveMsg struct { // with. nodeID *btcec.PublicKey - // nodeAddr is the IP address plus port that we used to either - // establish or accept the connection which led to the negotiation of - // this funding workflow. - nodeAddr *net.TCPAddr + // nodeAddr is the address port that we used to either establish or + // accept the connection which led to the negotiation of this funding + // workflow. + nodeAddr net.Addr // fundingAmount is the amount of funds requested for this channel. fundingAmount btcutil.Amount @@ -452,7 +452,7 @@ out: func (l *LightningWallet) InitChannelReservation( capacity, ourFundAmt btcutil.Amount, pushMSat lnwire.MilliSatoshi, commitFeePerKw, fundingFeePerWeight btcutil.Amount, - theirID *btcec.PublicKey, theirAddr *net.TCPAddr, + theirID *btcec.PublicKey, theirAddr net.Addr, chainHash *chainhash.Hash, flags lnwire.FundingFlag) (*ChannelReservation, error) { errChan := make(chan error, 1) diff --git a/server.go b/server.go index 60b513e5..b52be48c 100644 --- a/server.go +++ b/server.go @@ -815,7 +815,7 @@ func (s *server) genNodeAnnouncement( type nodeAddresses struct { pubKey *btcec.PublicKey - addresses []*net.TCPAddr + addresses []net.Addr } // establishPersistentConnections attempts to establish persistent connections @@ -838,9 +838,13 @@ func (s *server) establishPersistentConnections() error { } for _, node := range linkNodes { for _, address := range node.Addresses { - if address.Port == 0 { - address.Port = defaultPeerPort + switch addr := address.(type) { + case *net.TCPAddr: + if addr.Port == 0 { + addr.Port = defaultPeerPort + } } + } pubStr := string(node.IdentityPub.SerializeCompressed()) @@ -872,14 +876,19 @@ func (s *server) establishPersistentConnections() error { // list of addresses we'll connect to. If there are duplicates // that have different ports specified, the port from the // channel graph should supersede the port from the link node. - var addrs []*net.TCPAddr + var addrs []net.Addr linkNodeAddrs, ok := nodeAddrsMap[pubStr] if ok { for _, lnAddress := range linkNodeAddrs.addresses { + lnAddrTCP, ok := lnAddress.(*net.TCPAddr) + if !ok { + continue + } + var addrMatched bool for _, polAddress := range policy.Node.Addresses { polTCPAddr, ok := polAddress.(*net.TCPAddr) - if ok && polTCPAddr.IP.Equal(lnAddress.IP) { + if ok && polTCPAddr.IP.Equal(lnAddrTCP.IP) { addrMatched = true addrs = append(addrs, polTCPAddr) }