graph/db: de(ser)ialise opaque node addrs
In this commit, we fix the bug demonstrated in the prior commit. We correctly handle the persistence of lnwire.OpaqueAddrs.
This commit is contained in:
2 files changed
+69
-9
No files matched your search
@@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/tor"
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,6 +27,10 @@ const (
|
|||||||
|
|
||||||
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
|
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
|
||||||
v3OnionAddr addressType = 3
|
v3OnionAddr addressType = 3
|
||||||
|
|
||||||
|
// opaqueAddrs denotes an address (or a set of addresses) that LND was
|
||||||
|
// not able to parse since LND is not yet aware of the address type.
|
||||||
|
opaqueAddrs addressType = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// encodeTCPAddr serializes a TCP address into its compact raw bytes
|
// encodeTCPAddr serializes a TCP address into its compact raw bytes
|
||||||
@@ -121,6 +126,27 @@ func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// encodeOpaqueAddrs serializes the lnwire.OpaqueAddrs type to a raw set of
|
||||||
|
// bytes that we will persist.
|
||||||
|
func encodeOpaqueAddrs(w io.Writer, addr *lnwire.OpaqueAddrs) error {
|
||||||
|
// Write the type byte.
|
||||||
|
if _, err := w.Write([]byte{byte(opaqueAddrs)}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the length of the payload.
|
||||||
|
var l [2]byte
|
||||||
|
binary.BigEndian.PutUint16(l[:], uint16(len(addr.Payload)))
|
||||||
|
if _, err := w.Write(l[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the payload.
|
||||||
|
_, err := w.Write(addr.Payload)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// DeserializeAddr reads the serialized raw representation of an address and
|
// DeserializeAddr reads the serialized raw representation of an address and
|
||||||
// deserializes it into the actual address. This allows us to avoid address
|
// deserializes it into the actual address. This allows us to avoid address
|
||||||
// resolution within the channeldb package.
|
// resolution within the channeldb package.
|
||||||
@@ -147,6 +173,7 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
|
|||||||
IP: net.IP(ip[:]),
|
IP: net.IP(ip[:]),
|
||||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
}
|
}
|
||||||
|
|
||||||
case tcp6Addr:
|
case tcp6Addr:
|
||||||
var ip [16]byte
|
var ip [16]byte
|
||||||
if _, err := r.Read(ip[:]); err != nil {
|
if _, err := r.Read(ip[:]); err != nil {
|
||||||
@@ -162,6 +189,7 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
|
|||||||
IP: net.IP(ip[:]),
|
IP: net.IP(ip[:]),
|
||||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
}
|
}
|
||||||
|
|
||||||
case v2OnionAddr:
|
case v2OnionAddr:
|
||||||
var h [tor.V2DecodedLen]byte
|
var h [tor.V2DecodedLen]byte
|
||||||
if _, err := r.Read(h[:]); err != nil {
|
if _, err := r.Read(h[:]); err != nil {
|
||||||
@@ -181,6 +209,7 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
|
|||||||
OnionService: onionService,
|
OnionService: onionService,
|
||||||
Port: port,
|
Port: port,
|
||||||
}
|
}
|
||||||
|
|
||||||
case v3OnionAddr:
|
case v3OnionAddr:
|
||||||
var h [tor.V3DecodedLen]byte
|
var h [tor.V3DecodedLen]byte
|
||||||
if _, err := r.Read(h[:]); err != nil {
|
if _, err := r.Read(h[:]); err != nil {
|
||||||
@@ -200,6 +229,24 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
|
|||||||
OnionService: onionService,
|
OnionService: onionService,
|
||||||
Port: port,
|
Port: port,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case opaqueAddrs:
|
||||||
|
// Read the length of the payload.
|
||||||
|
var l [2]byte
|
||||||
|
if _, err := r.Read(l[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the payload.
|
||||||
|
payload := make([]byte, binary.BigEndian.Uint16(l[:]))
|
||||||
|
if _, err := r.Read(payload); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &lnwire.OpaqueAddrs{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, ErrUnknownAddressType
|
return nil, ErrUnknownAddressType
|
||||||
}
|
}
|
||||||
@@ -215,6 +262,8 @@ func SerializeAddr(w io.Writer, address net.Addr) error {
|
|||||||
return encodeTCPAddr(w, addr)
|
return encodeTCPAddr(w, addr)
|
||||||
case *tor.OnionAddr:
|
case *tor.OnionAddr:
|
||||||
return encodeOnionAddr(w, addr)
|
return encodeOnionAddr(w, addr)
|
||||||
|
case *lnwire.OpaqueAddrs:
|
||||||
|
return encodeOpaqueAddrs(w, addr)
|
||||||
default:
|
default:
|
||||||
return ErrUnknownAddressType
|
return ErrUnknownAddressType
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-9
@@ -4074,12 +4074,9 @@ var testNodeAnn = "01012674c2e7ef68c73a086b7de2603f4ef1567358df84bb4edaa06c" +
|
|||||||
"80000000d0000000005cd2a001260706204c"
|
"80000000d0000000005cd2a001260706204c"
|
||||||
|
|
||||||
// TestLightningNodePersistence takes a raw serialized node announcement
|
// TestLightningNodePersistence takes a raw serialized node announcement
|
||||||
// message, converts it to our internal models.LightningNode type and attempts
|
// message, converts it to our internal models.LightningNode type, persists it
|
||||||
// to persist this to disk.
|
// to disk, reads it again and converts it back to a wire message and asserts
|
||||||
//
|
// that the two messages are equal.
|
||||||
// NOTE: Currently, this tests demonstrates that we are _unable_ to do this if
|
|
||||||
// the node announcement has an address type unknown to LND. This will be fixed
|
|
||||||
// in an upcoming commit.
|
|
||||||
func TestLightningNodePersistence(t *testing.T) {
|
func TestLightningNodePersistence(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -4100,8 +4097,22 @@ func TestLightningNodePersistence(t *testing.T) {
|
|||||||
// Convert the wire message to our internal node representation.
|
// Convert the wire message to our internal node representation.
|
||||||
node := models.NodeFromWireAnnouncement(na)
|
node := models.NodeFromWireAnnouncement(na)
|
||||||
|
|
||||||
// Attempt to persist the node to disk. This currently fails due to the
|
// Persist the node to disk.
|
||||||
// unknown address type.
|
|
||||||
err = graph.AddLightningNode(node)
|
err = graph.AddLightningNode(node)
|
||||||
require.ErrorContains(t, err, "address type cannot be resolved")
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Read the node from disk.
|
||||||
|
diskNode, err := graph.FetchLightningNode(node.PubKeyBytes)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Convert it back to a wire message.
|
||||||
|
wireMsg, err := diskNode.NodeAnnouncement(true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Encode it and compare against the original.
|
||||||
|
var b bytes.Buffer
|
||||||
|
_, err = lnwire.WriteMessage(&b, wireMsg, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, nodeAnnBytes, b.Bytes())
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user