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:
Elle Mouton
2025-02-05 08:29:25 +02:00
parent d68d24d97e
commit 71b2338d53
2 changed files with 69 additions and 9 deletions

View File

@@ -7,6 +7,7 @@ import (
"io"
"net"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/tor"
)
@@ -26,6 +27,10 @@ const (
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
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
@@ -121,6 +126,27 @@ func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
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
// deserializes it into the actual address. This allows us to avoid address
// resolution within the channeldb package.
@@ -147,6 +173,7 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
IP: net.IP(ip[:]),
Port: int(binary.BigEndian.Uint16(port[:])),
}
case tcp6Addr:
var ip [16]byte
if _, err := r.Read(ip[:]); err != nil {
@@ -162,6 +189,7 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
IP: net.IP(ip[:]),
Port: int(binary.BigEndian.Uint16(port[:])),
}
case v2OnionAddr:
var h [tor.V2DecodedLen]byte
if _, err := r.Read(h[:]); err != nil {
@@ -181,6 +209,7 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
OnionService: onionService,
Port: port,
}
case v3OnionAddr:
var h [tor.V3DecodedLen]byte
if _, err := r.Read(h[:]); err != nil {
@@ -200,6 +229,24 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
OnionService: onionService,
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:
return nil, ErrUnknownAddressType
}
@@ -215,6 +262,8 @@ func SerializeAddr(w io.Writer, address net.Addr) error {
return encodeTCPAddr(w, addr)
case *tor.OnionAddr:
return encodeOnionAddr(w, addr)
case *lnwire.OpaqueAddrs:
return encodeOpaqueAddrs(w, addr)
default:
return ErrUnknownAddressType
}

View File

@@ -4074,12 +4074,9 @@ var testNodeAnn = "01012674c2e7ef68c73a086b7de2603f4ef1567358df84bb4edaa06c" +
"80000000d0000000005cd2a001260706204c"
// TestLightningNodePersistence takes a raw serialized node announcement
// message, converts it to our internal models.LightningNode type and attempts
// to persist this to disk.
//
// 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.
// message, converts it to our internal models.LightningNode type, persists it
// to disk, reads it again and converts it back to a wire message and asserts
// that the two messages are equal.
func TestLightningNodePersistence(t *testing.T) {
t.Parallel()
@@ -4100,8 +4097,22 @@ func TestLightningNodePersistence(t *testing.T) {
// Convert the wire message to our internal node representation.
node := models.NodeFromWireAnnouncement(na)
// Attempt to persist the node to disk. This currently fails due to the
// unknown address type.
// Persist the node to disk.
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())
}