-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add NodeAnnouncment Cache to the Gossiper #10248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add NodeAnnouncment Cache to the Gossiper #10248
Conversation
942019a
to
8237e54
Compare
8237e54
to
ef97de6
Compare
20e1b0c
to
632f18d
Compare
This makes sure also our source node is part of the cache. Currently there is use of the source node but also adding it to the cache seems the right way here.
86f2e8e
to
b5c963d
Compare
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request primarily enforces that all hops in a route must support TLV-encoded onion payloads, which improves routing reliability by failing early for incompatible paths. The core logic is implemented in routing/pathfind.go
. Additionally, there are significant improvements to the gossip handling mechanism in discovery/gossiper.go
, which now caches and replays premature node announcements, enhancing graph sync robustness. The test suite has been updated accordingly to reflect these changes. My review includes a suggestion to fix a potential logic issue in blinded path feature handling and a minor style improvement.
features := lnwire.EmptyFeatureVector() | ||
features.Set(lnwire.TLVOnionPayloadOptional) | ||
if b.Features != nil { | ||
features = b.Features.Clone() | ||
|
||
// In case the feature set is empty, we set the TLV onion | ||
// payload optional feature. | ||
if features.IsEmpty() { | ||
features.Set(lnwire.TLVOnionPayloadOptional) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for ensuring the TLVOnionPayloadOptional
feature is set for blinded paths is flawed. If b.Features
is non-nil and non-empty but lacks the TLVOnionPayloadOptional
feature, this required bit won't be added. This can lead to creating invalid blinded routes.
The logic can be simplified to ensure the feature is always set:
features := lnwire.EmptyFeatureVector()
if b.Features != nil {
features = b.Features.Clone()
}
features.Set(lnwire.TLVOnionPayloadOptional)
graph.ErrIgnored, | ||
) { | ||
switch { | ||
case graph.IsError(err, graph.ErrIgnored): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the style guide, each case
in a switch
statement should be preceded by a brief comment explaining the condition. This case
is missing that comment.1
// If the node is ignored because we don't have any of its
// channels, we'll cache it for later processing.
case graph.IsError(err, graph.ErrIgnored):
Style Guide References
Footnotes
b5c963d
to
1a99c62
Compare
Short summary:
Overall I tend to merge this PR because it favours more strict pathfinding and also graph consistency and moreover fix some flakes as well we saw previously not having the node_annoucment. However I just want to point out that this PR is not strictly needed for the payment series so happy to hear the thoughts of the reviews. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im not sure this is the correct direction for deprecating a legacy feature bit. THe spec labels this bit as "Assumed" in bolt 9. So I think instead we can just stop checking for the bit completely and just assume that all nodes on any route support the new format?
Rather than now going and adding the bit everywhere where an empty feature vector would have sufficed (as this also makes testing trickier)
// currently don't use the feature set of the blinded path currently so | ||
// we always set it to allow the path finder to succeed because LND | ||
// only creates paths with tlv payload encoding.. | ||
features := lnwire.EmptyFeatureVector() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might make sense to have an lnwire.AssumedFeatures()
which would include all the feature bits that the spec has marked as assumed? non-blocking
// updates that we'll hold onto. | ||
maxPrematureUpdates = 100 | ||
|
||
// maxPrematureNodeAnnouncements tracks the max amount of premature node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feels like this should be in its own PR? or at least have a commit message body? doesnt seem related to the TLV enforcement
req := &routerrpc.SendPaymentRequest{ | ||
Dest: carol.PubKey[:], | ||
Amt: int64(payAmt), | ||
PaymentHash: ht.Random32Bytes(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we need the node announcment to create a route because
we always verify if the node supports tlv payloads
i dont know if we should do this... i feel like we should lean more towards just assuming that all nodes support this format? Ie, i think when we deprecate a legacy encoding via a feature bit, we should in general be removing code & not adding extra checks etc?
I think for route hints, we should just assume that all nodes on that route support the TLV format
agree, it adds too much complexity without much benefit, I think we can still use the prematureNodeAnnouncment cache from this PR tho, which reveiled some flakes where we would not have a proper node_announcment set. So will drop all the commits except the one which introduced the cache. |
badc471
to
3f6730f
Compare
During some tests it was reveiled that there might be a race condition where we would receive a node annoucment without having received the Channel Announcment especially for private channels this might be the case because sending the channel announcment and sending the node annoucnment happens by default at the same time (3 blocks by default). Now we cache node annoucments when received and no channel has been found yet and later replay them as soon as a new channel announcment for this channel is received.
3f6730f
to
58e6b6b
Compare
While this PR started to enforce the tlv onion, we decided against the enforcement of assumed feature bits. During the implementation however I encountered some flaky tests where we would not add the node currently in our graph because we would receive the node announcement before the channel announcement which would lead us to drop the node announcement message. Now we precache them similar to channel update messages and replay them as soon as a new channel announcement is received. The cache is a LRU storage which makes sure we limit its capacity to prevent OOM attacks.