multi: remove HaveNodeAnnouncement field from Node
What changed, and why it matters
This commit removes a redundant flag called HaveNodeAnnouncement from LND's internal node records and replaces it with a simple rule: if a node has a stored signature, it has an announcement. It is a code-quality/refactoring change that eliminates two conflicting ways of answering the same question. There is no direct evidence in the commit that this fixes an active security vulnerability, but inconsistent state can historically lead to subtle bugs in how node information is stored, forwarded, or validated.
Treat as a defensive refactoring commit. Review the devrpc ImportGraph workaround (AuthSigBytes: []byte{0}) to ensure it does not bypass signature validation or cause invalid signed announcements to be generated/forwarded. Verify that SQL and KV migration paths correctly preserve the distinction between shell nodes and fully announced nodes, and that HaveAnnouncement() cannot be spoofed by malformed database state.
Security signals we found
Elimination of dual sources of truth for node-announcement state
New HaveAnnouncement() predicate depends solely on presence of AuthSigBytes
Workaround in devrpc ImportGraph sets a dummy one-byte signature to force persistence of node metadata
Legacy on-disk marker retained in KV store for backward compatibility
No explicit security framing or CVE reference in commit message or diff
Evidence from the diff
The patch deletes the HaveNodeAnnouncement boolean field from graph/db/models.Node and adds a method HaveAnnouncement() that returns true when len(AuthSigBytes) > 0. All call sites (KV store serialization, SQL store, SQL migration, graph builder, discovery gossip, dev RPC import, server self-node updates, and tests) are updated to use the method or simply stop setting the removed field. The KV serialization still writes/reads the legacy 0/1 marker for backward compatibility, but the in-memory representation is now derived from the presence of AuthSigBytes. A notable side effect appears in lnrpc/devrpc/dev_server.go ImportGraph, which now sets AuthSigBytes: []byte{0} as a workaround so HaveAnnouncement() returns true and other fields are persisted; the inline comment is cut off mid-sentence, suggesting the workaround may need follow-up.
Changed components
graph/db/models.Nodegraph/db/kv_store.gograph/db/sql_store.gograph/db/sql_migration.godiscovery/chan_series.golnrpc/devrpc/dev_server.goserver.gograph/builder_test.gograph/db/graph_test.gograph/db/sql_migration_test.gograph/notifications_test.gorouting/pathfind_test.gorouting/router_test.goautopilot/prefattach_test.gochanneldb/db_test.goInspect captured patch +154 / −182
diff --git a/autopilot/prefattach_test.go b/autopilot/prefattach_test.go
index d93cda2..d9ec630 100644
--- a/autopilot/prefattach_test.go
+++ b/autopilot/prefattach_test.go
@@ -418,7 +418,6 @@ func (d *testDBGraph) addRandChannel(node1, node2 *btcec.PublicKey,
fallthrough
case errors.Is(err, graphdb.ErrGraphNotFound):
graphNode := &models.Node{
- HaveNodeAnnouncement: true,
Addresses: []net.Addr{&net.TCPAddr{
IP: bytes.Repeat(
[]byte("a"), 16,
@@ -451,7 +450,6 @@ func (d *testDBGraph) addRandChannel(node1, node2 *btcec.PublicKey,
return nil, err
}
dbNode := &models.Node{
- HaveNodeAnnouncement: true,
Addresses: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
@@ -552,7 +550,6 @@ func (d *testDBGraph) addRandNode() (*btcec.PublicKey, error) {
return nil, err
}
dbNode := &models.Node{
- HaveNodeAnnouncement: true,
Addresses: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
diff --git a/channeldb/db_test.go b/channeldb/db_test.go
index ec2394a..50a9457 100644
--- a/channeldb/db_test.go
+++ b/channeldb/db_test.go
@@ -812,13 +812,12 @@ func createNode(priv *btcec.PrivateKey) *models.Node {
pub := priv.PubKey().SerializeCompressed()
n := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSig.Serialize(),
- LastUpdate: time.Unix(updateTime, 0),
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "kek" + string(pub),
- Features: testFeatures,
- Addresses: testAddrs,
+ AuthSigBytes: testSig.Serialize(),
+ LastUpdate: time.Unix(updateTime, 0),
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "kek" + string(pub),
+ Features: testFeatures,
+ Addresses: testAddrs,
}
copy(n.PubKeyBytes[:], priv.PubKey().SerializeCompressed())
diff --git a/discovery/chan_series.go b/discovery/chan_series.go
index 8ecb3a4..050b82b 100644
--- a/discovery/chan_series.go
+++ b/discovery/chan_series.go
@@ -295,7 +295,7 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash,
// If this edge has a validated node announcement, that
// we haven't yet sent, then we'll send that as well.
nodePub := channel.Node2.PubKeyBytes
- hasNodeAnn := channel.Node2.HaveNodeAnnouncement
+ hasNodeAnn := channel.Node2.HaveAnnouncement()
if _, ok := nodePubsSent[nodePub]; !ok && hasNodeAnn {
nodeAnn, err := channel.Node2.NodeAnnouncement(
true,
@@ -321,7 +321,7 @@ func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash,
// If this edge has a validated node announcement, that
// we haven't yet sent, then we'll send that as well.
nodePub := channel.Node1.PubKeyBytes
- hasNodeAnn := channel.Node1.HaveNodeAnnouncement
+ hasNodeAnn := channel.Node1.HaveAnnouncement()
if _, ok := nodePubsSent[nodePub]; !ok && hasNodeAnn {
nodeAnn, err := channel.Node1.NodeAnnouncement(
true,
diff --git a/graph/builder_test.go b/graph/builder_test.go
index 0461c4f..6e362fb 100644
--- a/graph/builder_test.go
+++ b/graph/builder_test.go
@@ -98,13 +98,12 @@ func TestIgnoreNodeAnnouncement(t *testing.T) {
pub := priv1.PubKey()
node := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: time.Unix(123, 0),
- Addresses: testAddrs,
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "node11",
- AuthSigBytes: testSig.Serialize(),
- Features: testFeatures,
+ LastUpdate: time.Unix(123, 0),
+ Addresses: testAddrs,
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "node11",
+ AuthSigBytes: testSig.Serialize(),
+ Features: testFeatures,
}
copy(node.PubKeyBytes[:], pub.SerializeCompressed())
@@ -1085,13 +1084,12 @@ func TestIsStaleNode(t *testing.T) {
// With the node stub in the database, we'll add the fully node
// announcement to the database.
n1 := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: updateTimeStamp,
- Addresses: testAddrs,
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "node11",
- AuthSigBytes: testSig.Serialize(),
- Features: testFeatures,
+ LastUpdate: updateTimeStamp,
+ Addresses: testAddrs,
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "node11",
+ AuthSigBytes: testSig.Serialize(),
+ Features: testFeatures,
}
copy(n1.PubKeyBytes[:], priv1.PubKey().SerializeCompressed())
if err := ctx.builder.AddNode(t.Context(), n1); err != nil {
@@ -1402,12 +1400,11 @@ func parseTestGraph(t *testing.T, useCache bool, path string) (
}
dbNode := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSig.Serialize(),
- LastUpdate: testTime,
- Addresses: testAddrs,
- Alias: node.Alias,
- Features: testFeatures,
+ AuthSigBytes: testSig.Serialize(),
+ LastUpdate: testTime,
+ Addresses: testAddrs,
+ Alias: node.Alias,
+ Features: testFeatures,
}
copy(dbNode.PubKeyBytes[:], pubBytes)
@@ -1788,12 +1785,11 @@ func createTestGraphFromChannels(t *testing.T, useCache bool,
}
dbNode := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSig.Serialize(),
- LastUpdate: testTime,
- Addresses: testAddrs,
- Alias: alias,
- Features: features,
+ AuthSigBytes: testSig.Serialize(),
+ LastUpdate: testTime,
+ Addresses: testAddrs,
+ Alias: alias,
+ Features: features,
}
copy(dbNode.PubKeyBytes[:], pubKey.SerializeCompressed())
diff --git a/graph/db/graph_test.go b/graph/db/graph_test.go
index ee5cf8d..2e12351 100644
--- a/graph/db/graph_test.go
+++ b/graph/db/graph_test.go
@@ -72,13 +72,12 @@ var (
func createNode(priv *btcec.PrivateKey) *models.Node {
pub := priv.PubKey().SerializeCompressed()
n := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSig.Serialize(),
- LastUpdate: nextUpdateTime(),
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "kek" + hex.EncodeToString(pub),
- Features: testFeatures,
- Addresses: testAddrs,
+ AuthSigBytes: testSig.Serialize(),
+ LastUpdate: nextUpdateTime(),
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "kek" + hex.EncodeToString(pub),
+ Features: testFeatures,
+ Addresses: testAddrs,
}
copy(n.PubKeyBytes[:], priv.PubKey().SerializeCompressed())
@@ -107,15 +106,14 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
nodeWithAddrs := func(addrs []net.Addr) *models.Node {
timeStamp++
return &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSig.Serialize(),
- LastUpdate: time.Unix(timeStamp, 0),
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "kek",
- Features: testFeatures,
- Addresses: addrs,
- ExtraOpaqueData: []byte{1, 1, 1, 2, 2, 2, 2},
- PubKeyBytes: testPub,
+ AuthSigBytes: testSig.Serialize(),
+ LastUpdate: time.Unix(timeStamp, 0),
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "kek",
+ Features: testFeatures,
+ Addresses: addrs,
+ ExtraOpaqueData: []byte{1, 1, 1, 2, 2, 2, 2},
+ PubKeyBytes: testPub,
}
}
@@ -316,10 +314,9 @@ func TestPartialNode(t *testing.T) {
// The two nodes should match exactly! (with default values for
// LastUpdate and db set to satisfy compareNodes())
expectedNode1 := &models.Node{
- HaveNodeAnnouncement: false,
- LastUpdate: time.Unix(0, 0),
- PubKeyBytes: pubKey1,
- Features: lnwire.EmptyFeatureVector(),
+ LastUpdate: time.Unix(0, 0),
+ PubKeyBytes: pubKey1,
+ Features: lnwire.EmptyFeatureVector(),
}
compareNodes(t, expectedNode1, dbNode1)
@@ -330,10 +327,9 @@ func TestPartialNode(t *testing.T) {
// The two nodes should match exactly! (with default values for
// LastUpdate and db set to satisfy compareNodes())
expectedNode2 := &models.Node{
- HaveNodeAnnouncement: false,
- LastUpdate: time.Unix(0, 0),
- PubKeyBytes: pubKey2,
- Features: lnwire.EmptyFeatureVector(),
+ LastUpdate: time.Unix(0, 0),
+ PubKeyBytes: pubKey2,
+ Features: lnwire.EmptyFeatureVector(),
}
compareNodes(t, expectedNode2, dbNode2)
@@ -3782,11 +3778,11 @@ func TestAddChannelEdgeShellNodes(t *testing.T) {
// a shell node present.
node1, err := graph.FetchNode(ctx, node1.PubKeyBytes)
require.NoError(t, err, "unable to fetch node1")
- require.True(t, node1.HaveNodeAnnouncement)
+ require.True(t, node1.HaveAnnouncement())
node2, err = graph.FetchNode(ctx, node2.PubKeyBytes)
require.NoError(t, err, "unable to fetch node2")
- require.False(t, node2.HaveNodeAnnouncement)
+ require.False(t, node2.HaveAnnouncement())
// Show that attempting to add the channel again will result in an
// error.
diff --git a/graph/db/kv_store.go b/graph/db/kv_store.go
index cc9a148..99c9584 100644
--- a/graph/db/kv_store.go
+++ b/graph/db/kv_store.go
@@ -1206,8 +1206,7 @@ func (c *KVStore) addChannelEdge(tx kvdb.RwTx,
switch {
case errors.Is(node1Err, ErrGraphNodeNotFound):
node1Shell := models.Node{
- PubKeyBytes: edge.NodeKey1Bytes,
- HaveNodeAnnouncement: false,
+ PubKeyBytes: edge.NodeKey1Bytes,
}
err := addLightningNode(tx, &node1Shell)
if err != nil {
@@ -1222,8 +1221,7 @@ func (c *KVStore) addChannelEdge(tx kvdb.RwTx,
switch {
case errors.Is(node2Err, ErrGraphNodeNotFound):
node2Shell := models.Node{
- PubKeyBytes: edge.NodeKey2Bytes,
- HaveNodeAnnouncement: false,
+ PubKeyBytes: edge.NodeKey2Bytes,
}
err := addLightningNode(tx, &node2Shell)
if err != nil {
@@ -4369,7 +4367,7 @@ func putLightningNode(nodeBucket, aliasBucket, updateIndex kvdb.RwBucket,
// If we got a node announcement for this node, we will have the rest
// of the data available. If not we don't have more data to write.
- if !node.HaveNodeAnnouncement {
+ if !node.HaveAnnouncement() {
// Write HaveNodeAnnouncement=0.
byteOrder.PutUint16(scratch[:2], 0)
if _, err := b.Write(scratch[:2]); err != nil {
@@ -4562,15 +4560,9 @@ func deserializeLightningNode(r io.Reader) (models.Node, error) {
}
hasNodeAnn := byteOrder.Uint16(scratch[:2])
- if hasNodeAnn == 1 {
- node.HaveNodeAnnouncement = true
- } else {
- node.HaveNodeAnnouncement = false
- }
-
// The rest of the data is optional, and will only be there if we got a
// node announcement for this node.
- if !node.HaveNodeAnnouncement {
+ if hasNodeAnn == 0 {
return node, nil
}
diff --git a/graph/db/models/node.go b/graph/db/models/node.go
index d67aa4b..c347db5 100644
--- a/graph/db/models/node.go
+++ b/graph/db/models/node.go
@@ -19,11 +19,6 @@ type Node struct {
PubKeyBytes [33]byte
pubKey *btcec.PublicKey
- // HaveNodeAnnouncement indicates whether we received a node
- // announcement for this particular node. If true, the remaining fields
- // will be set, if false only the PubKey is known for this node.
- HaveNodeAnnouncement bool
-
// LastUpdate is the last time the vertex information for this node has
// been updated.
LastUpdate time.Time
@@ -54,53 +49,62 @@ type Node struct {
ExtraOpaqueData []byte
}
+// HaveAnnouncement returns true if we have received a node announcement for
+// this node. We determine this by checking if we have a signature for the
+// announcement.
+func (n *Node) HaveAnnouncement() bool {
+ return len(n.AuthSigBytes) > 0
+}
+
// PubKey is the node's long-term identity public key. This key will be used to
// authenticated any advertisements/updates sent by the node.
//
// NOTE: By having this method to access an attribute, we ensure we only need
// to fully deserialize the pubkey if absolutely necessary.
-func (l *Node) PubKey() (*btcec.PublicKey, error) {
- if l.pubKey != nil {
- return l.pubKey, nil
+func (n *Node) PubKey() (*btcec.PublicKey, error) {
+ if n.pubKey != nil {
+ return n.pubKey, nil
}
- key, err := btcec.ParsePubKey(l.PubKeyBytes[:])
+ key, err := btcec.ParsePubKey(n.PubKeyBytes[:])
if err != nil {
return nil, err
}
- l.pubKey = key
+ n.pubKey = key
return key, nil
}
// NodeAnnouncement retrieves the latest node announcement of the node.
-func (l *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement1,
+func (n *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement1,
error) {
- if !l.HaveNodeAnnouncement {
+ // Error out if we request the signed announcement, but we don't have
+ // a signature for this announcement.
+ if !n.HaveAnnouncement() && signed {
return nil, fmt.Errorf("node does not have node announcement")
}
- alias, err := lnwire.NewNodeAlias(l.Alias)
+ alias, err := lnwire.NewNodeAlias(n.Alias)
if err != nil {
return nil, err
}
nodeAnn := &lnwire.NodeAnnouncement1{
- Features: l.Features.RawFeatureVector,
- NodeID: l.PubKeyBytes,
- RGBColor: l.Color,
+ Features: n.Features.RawFeatureVector,
+ NodeID: n.PubKeyBytes,
+ RGBColor: n.Color,
Alias: alias,
- Addresses: l.Addresses,
- Timestamp: uint32(l.LastUpdate.Unix()),
- ExtraOpaqueData: l.ExtraOpaqueData,
+ Addresses: n.Addresses,
+ Timestamp: uint32(n.LastUpdate.Unix()),
+ ExtraOpaqueData: n.ExtraOpaqueData,
}
if !signed {
return nodeAnn, nil
}
- sig, err := lnwire.NewSigFromECDSARawSignature(l.AuthSigBytes)
+ sig, err := lnwire.NewSigFromECDSARawSignature(n.AuthSigBytes)
if err != nil {
return nil, err
}
@@ -117,14 +121,13 @@ func NodeFromWireAnnouncement(msg *lnwire.NodeAnnouncement1) *Node {
features := lnwire.NewFeatureVector(msg.Features, lnwire.Features)
return &Node{
- HaveNodeAnnouncement: true,
- LastUpdate: timestamp,
- Addresses: msg.Addresses,
- PubKeyBytes: msg.NodeID,
- Alias: msg.Alias.String(),
- AuthSigBytes: msg.Signature.ToSignatureBytes(),
- Features: features,
- Color: msg.RGBColor,
- ExtraOpaqueData: msg.ExtraOpaqueData,
+ LastUpdate: timestamp,
+ Addresses: msg.Addresses,
+ PubKeyBytes: msg.NodeID,
+ Alias: msg.Alias.String(),
+ AuthSigBytes: msg.Signature.ToSignatureBytes(),
+ Features: features,
+ Color: msg.RGBColor,
+ ExtraOpaqueData: msg.ExtraOpaqueData,
}
}
diff --git a/graph/db/sql_migration.go b/graph/db/sql_migration.go
index e737718..71a5525 100644
--- a/graph/db/sql_migration.go
+++ b/graph/db/sql_migration.go
@@ -1449,7 +1449,7 @@ func insertNodeSQLMig(ctx context.Context, db SQLQueries,
PubKey: node.PubKeyBytes[:],
}
- if node.HaveNodeAnnouncement {
+ if node.HaveAnnouncement() {
params.LastUpdate = sqldb.SQLInt64(node.LastUpdate.Unix())
params.Color = sqldb.SQLStrValid(EncodeHexColor(node.Color))
params.Alias = sqldb.SQLStrValid(node.Alias)
@@ -1463,7 +1463,7 @@ func insertNodeSQLMig(ctx context.Context, db SQLQueries,
}
// We can exit here if we don't have the announcement yet.
- if !node.HaveNodeAnnouncement {
+ if !node.HaveAnnouncement() {
return nodeID, nil
}
diff --git a/graph/db/sql_migration_test.go b/graph/db/sql_migration_test.go
index 66a1984..fd44e0f 100644
--- a/graph/db/sql_migration_test.go
+++ b/graph/db/sql_migration_test.go
@@ -385,8 +385,7 @@ func TestMigrateGraphToSQL(t *testing.T) {
// node be set. So that is the first object
// we will write.
&models.Node{
- HaveNodeAnnouncement: false,
- PubKeyBytes: testPub,
+ PubKeyBytes: testPub,
},
// Now we add some block heights to prune
// the graph at.
@@ -748,15 +747,14 @@ type testNodeOpt func(*models.Node)
// functional options can be used to modify the node's attributes.
func makeTestNode(t *testing.T, opts ...testNodeOpt) *models.Node {
n := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSigBytes,
- LastUpdate: testTime,
- Color: testColor,
- Alias: "kek",
- Features: testFeatures,
- Addresses: testAddrs,
- ExtraOpaqueData: testExtraData,
- PubKeyBytes: genPubKey(t),
+ AuthSigBytes: testSigBytes,
+ LastUpdate: testTime,
+ Color: testColor,
+ Alias: "kek",
+ Features: testFeatures,
+ Addresses: testAddrs,
+ ExtraOpaqueData: testExtraData,
+ PubKeyBytes: genPubKey(t),
}
for _, opt := range opts {
@@ -777,10 +775,9 @@ func makeTestShellNode(t *testing.T,
opts ...testNodeOpt) *models.Node {
n := &models.Node{
- HaveNodeAnnouncement: false,
- PubKeyBytes: genPubKey(t),
- Features: testEmptyFeatures,
- LastUpdate: time.Unix(0, 0),
+ PubKeyBytes: genPubKey(t),
+ Features: testEmptyFeatures,
+ LastUpdate: time.Unix(0, 0),
}
for _, opt := range opts {
@@ -1817,11 +1814,10 @@ func genRandomNode(t *rapid.T) *models.Node {
}
node := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: sigBytes,
- LastUpdate: randTime,
- Color: randColor,
- Alias: alias.String(),
+ AuthSigBytes: sigBytes,
+ LastUpdate: randTime,
+ Color: randColor,
+ Alias: alias.String(),
Features: lnwire.NewFeatureVector(
features, lnwire.Features,
),
diff --git a/graph/db/sql_store.go b/graph/db/sql_store.go
index c9283df..d63021a 100644
--- a/graph/db/sql_store.go
+++ b/graph/db/sql_store.go
@@ -3495,7 +3495,6 @@ func buildNodeWithBatchData(dbNode sqlc.GraphNode,
return node, nil
}
- node.HaveNodeAnnouncement = true
node.AuthSigBytes = dbNode.Signature
node.Alias = dbNode.Alias.String
node.LastUpdate = time.Unix(dbNode.LastUpdate.Int64, 0)
@@ -3608,7 +3607,7 @@ func upsertNode(ctx context.Context, db SQLQueries,
PubKey: node.PubKeyBytes[:],
}
- if node.HaveNodeAnnouncement {
+ if node.HaveAnnouncement() {
params.LastUpdate = sqldb.SQLInt64(node.LastUpdate.Unix())
params.Color = sqldb.SQLStrValid(EncodeHexColor(node.Color))
params.Alias = sqldb.SQLStrValid(node.Alias)
@@ -3622,7 +3621,7 @@ func upsertNode(ctx context.Context, db SQLQueries,
}
// We can exit here if we don't have the announcement yet.
- if !node.HaveNodeAnnouncement {
+ if !node.HaveAnnouncement() {
return nodeID, nil
}
diff --git a/graph/notifications_test.go b/graph/notifications_test.go
index 3240842..c3db240 100644
--- a/graph/notifications_test.go
+++ b/graph/notifications_test.go
@@ -84,13 +84,12 @@ func createTestNode(t *testing.T) *models.Node {
pub := priv.PubKey().SerializeCompressed()
n := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: time.Unix(updateTime, 0),
- Addresses: testAddrs,
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "kek" + hex.EncodeToString(pub),
- AuthSigBytes: testSig.Serialize(),
- Features: testFeatures,
+ LastUpdate: time.Unix(updateTime, 0),
+ Addresses: testAddrs,
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "kek" + hex.EncodeToString(pub),
+ AuthSigBytes: testSig.Serialize(),
+ Features: testFeatures,
}
copy(n.PubKeyBytes[:], pub)
diff --git a/lnrpc/devrpc/dev_server.go b/lnrpc/devrpc/dev_server.go
index 6cc4347..de142b9 100644
--- a/lnrpc/devrpc/dev_server.go
+++ b/lnrpc/devrpc/dev_server.go
@@ -227,11 +227,14 @@ func (s *Server) ImportGraph(ctx context.Context,
var err error
for _, rpcNode := range graph.Nodes {
node := &models.Node{
- HaveNodeAnnouncement: true,
LastUpdate: time.Unix(
int64(rpcNode.LastUpdate), 0,
),
Alias: rpcNode.Alias,
+ // NOTE: this is a workaround to ensure that
+ // HaveAnnouncement() returns true so that the other
+ // fields are properly persisted. However,
+ AuthSigBytes: []byte{0},
}
node.PubKeyBytes, err = parsePubKey(rpcNode.PubKey)
diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go
index 4414aa1..664f5c0 100644
--- a/routing/pathfind_test.go
+++ b/routing/pathfind_test.go
@@ -229,12 +229,11 @@ func parseTestGraph(t *testing.T, useCache bool, path string) (
}
dbNode := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSig.Serialize(),
- LastUpdate: testTime,
- Addresses: testAddrs,
- Alias: node.Alias,
- Features: testFeatures,
+ AuthSigBytes: testSig.Serialize(),
+ LastUpdate: testTime,
+ Addresses: testAddrs,
+ Alias: node.Alias,
+ Features: testFeatures,
}
copy(dbNode.PubKeyBytes[:], pubBytes)
@@ -566,12 +565,11 @@ func createTestGraphFromChannels(t *testing.T, useCache bool,
}
dbNode := &models.Node{
- HaveNodeAnnouncement: true,
- AuthSigBytes: testSig.Serialize(),
- LastUpdate: testTime,
- Addresses: testAddrs,
- Alias: alias,
- Features: features,
+ AuthSigBytes: testSig.Serialize(),
+ LastUpdate: testTime,
+ Addresses: testAddrs,
+ Alias: alias,
+ Features: features,
}
copy(dbNode.PubKeyBytes[:], pubKey.SerializeCompressed())
diff --git a/routing/router_test.go b/routing/router_test.go
index b811793..e46bb1f 100644
--- a/routing/router_test.go
+++ b/routing/router_test.go
@@ -193,13 +193,12 @@ func createTestNode() (*models.Node, error) {
pub := priv.PubKey().SerializeCompressed()
n := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: time.Unix(updateTime, 0),
- Addresses: testAddrs,
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "kek" + string(pub),
- AuthSigBytes: testSig.Serialize(),
- Features: testFeatures,
+ LastUpdate: time.Unix(updateTime, 0),
+ Addresses: testAddrs,
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "kek" + string(pub),
+ AuthSigBytes: testSig.Serialize(),
+ Features: testFeatures,
}
copy(n.PubKeyBytes[:], pub)
@@ -2872,26 +2871,24 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
// Now check that we can update the node info for the partial node
// without messing up the channel graph.
n1 := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: time.Unix(123, 0),
- Addresses: testAddrs,
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "node11",
- AuthSigBytes: testSig.Serialize(),
- Features: testFeatures,
+ LastUpdate: time.Unix(123, 0),
+ Addresses: testAddrs,
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "node11",
+ AuthSigBytes: testSig.Serialize(),
+ Features: testFeatures,
}
copy(n1.PubKeyBytes[:], priv1.PubKey().SerializeCompressed())
require.NoError(t, ctx.graph.AddNode(ctxb, n1))
n2 := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: time.Unix(123, 0),
- Addresses: testAddrs,
- Color: color.RGBA{1, 2, 3, 0},
- Alias: "node22",
- AuthSigBytes: testSig.Serialize(),
- Features: testFeatures,
+ LastUpdate: time.Unix(123, 0),
+ Addresses: testAddrs,
+ Color: color.RGBA{1, 2, 3, 0},
+ Alias: "node22",
+ AuthSigBytes: testSig.Serialize(),
+ Features: testFeatures,
}
copy(n2.PubKeyBytes[:], priv2.PubKey().SerializeCompressed())
diff --git a/server.go b/server.go
index 6149db0..3594b7d 100644
--- a/server.go
+++ b/server.go
@@ -3300,10 +3300,9 @@ func (s *server) createNewHiddenService(ctx context.Context) error {
// Finally, we'll update the on-disk version of our announcement so it
// will eventually propagate to nodes in the network.
selfNode := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: time.Unix(int64(newNodeAnn.Timestamp), 0),
- Addresses: newNodeAnn.Addresses,
- Alias: newNodeAnn.Alias.String(),
+ LastUpdate: time.Unix(int64(newNodeAnn.Timestamp), 0),
+ Addresses: newNodeAnn.Addresses,
+ Alias: newNodeAnn.Alias.String(),
Features: lnwire.NewFeatureVector(
newNodeAnn.Features, lnwire.Features,
),
@@ -3424,7 +3423,6 @@ func (s *server) updateAndBroadcastSelfNode(ctx context.Context,
return fmt.Errorf("unable to get current source node: %w", err)
}
- selfNode.HaveNodeAnnouncement = true
selfNode.LastUpdate = time.Unix(int64(newNodeAnn.Timestamp), 0)
selfNode.Addresses = newNodeAnn.Addresses
selfNode.Alias = newNodeAnn.Alias.String()
@@ -5646,12 +5644,11 @@ func (s *server) setSelfNode(ctx context.Context, nodePub route.Vertex,
// TODO(abdulkbk): potentially find a way to use the source node's
// features in the self node.
selfNode := &models.Node{
- HaveNodeAnnouncement: true,
- LastUpdate: nodeLastUpdate,
- Addresses: addrs,
- Alias: nodeAlias.String(),
- Color: color,
- Features: s.featureMgr.Get(feature.SetNodeAnn),
+ LastUpdate: nodeLastUpdate,
+ Addresses: addrs,
+ Alias: nodeAlias.String(),
+ Color: color,
+ Features: s.featureMgr.Get(feature.SetNodeAnn),
}
copy(selfNode.PubKeyBytes[:], nodePub[:])
Why this scored 28/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.