-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
discovery+graph: move funding tx validation to the gossiper #9478
Conversation
Important Review skippedAuto reviews are limited to specific labels. 🏷️ Labels to auto review (1)
Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
68967bd
to
eec439a
Compare
7c10f43
to
c3c9eb3
Compare
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.
🌮
graph/interfaces.go
Outdated
@@ -88,6 +88,9 @@ type ChannelGraphSource interface { | |||
|
|||
// ForEachNode is used to iterate over every node in the known graph. | |||
ForEachNode(func(node *models.LightningNode) error) error | |||
|
|||
// AddZombieEdge marks the channel with the given ID as a zombie edge. | |||
AddZombieEdge(chanID uint64) error |
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.
nit: might as well be renamed to SetEdgeZombie
or MarkEdgeZombie
. wdyt?
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.
yeah MarkEdgeZombie
does feel more accurate
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.
cool - will do 👍
discovery/gossiper_test.go
Outdated
@@ -107,6 +107,12 @@ func (r *mockGraphSource) AddNode(node *models.LightningNode, | |||
return nil | |||
} | |||
|
|||
func (r *mockGraphSource) AddZombieEdge(scid uint64) error { |
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.
nit: typo in the commit message (transction) 🤓
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.
Thanks a lot for the PR! Been wanting to fix this for a while now, really happy to see this happening❤️ A few questions otherwise good to go!
graph/interfaces.go
Outdated
@@ -88,6 +88,9 @@ type ChannelGraphSource interface { | |||
|
|||
// ForEachNode is used to iterate over every node in the known graph. | |||
ForEachNode(func(node *models.LightningNode) error) error | |||
|
|||
// AddZombieEdge marks the channel with the given ID as a zombie edge. | |||
AddZombieEdge(chanID uint64) error |
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.
yeah MarkEdgeZombie
does feel more accurate
discovery/gossiper.go
Outdated
@@ -2724,7 +2704,7 @@ func (d *AuthenticatedGossiper) handleChanAnnouncement(nMsg *networkMsg, | |||
d.banman.incrementBanScore(nMsg.peer.PubKey()) | |||
} | |||
|
|||
default: | |||
case err != nil: |
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.
think we can just keep the old default
since the error must be non-nil here.
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.
indeed!
graph/builder.go
Outdated
return fmt.Errorf("unable to add edge: %w", err) | ||
} | ||
if err := b.cfg.Graph.AddChannelEdge(edge, op...); err != nil { | ||
return errors.Errorf("unable to add edge: %v", err) |
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.
return errors.Errorf("unable to add edge: %v", err) | |
return errors.Errorf("unable to add edge: %w", err) |
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.
good catch, thanks 🙏
discovery/gossiper.go
Outdated
func (d *AuthenticatedGossiper) validateFundingTransaction( | ||
ann *lnwire.ChannelAnnouncement1, | ||
tapscriptRoot fn.Option[chainhash.Hash]) (fn.Option[wire.OutPoint], | ||
fn.Option[btcutil.Amount], error) { |
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.
don't think they need to be options?
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.
yeah good point - i think in the PoC i have they made more sense as options but think that is for later functionality - so defs agree that for this PR they are not needed - will revert 👍
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.
i think the og reason was case I had the if AssumeValid { return nil, nil }
in here meaning we'd have a nil error but also nil return values. But in the latest iteration ive moved that check outside of the validate method (ie, now we only call validate
if !AssumeValid.
discovery/gossiper.go
Outdated
// we'll mark the edge itself as a zombie so we don't | ||
// continue to request it. We use the "zero key" for | ||
// both node pubkeys so this edge can't be resurrected. | ||
zErr := d.cfg.Graph.AddZombieEdge(scid.ToUint64()) |
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.
Think it'd be nice to move this outside of the method to keep the method's responsibility to be purely validation, plus we are catching these errors outside the validation anyway - but also non-blocking as this can be done in a future PR.
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.
totally agree - but yeah let's do in follow up as this would be more than a code move then.
} | ||
|
||
// Otherwise, this is just a regular rejected edge. | ||
key := newRejectCacheKey( |
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.
looks like these lines are repetitive - another day another PR🤓
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.
cool yeah - can do clean-up a follow up just to keep this commit a code-move 🫡
// As a new edge has been added to the channel graph, we'll update the | ||
// current UTXO filter within our active FilteredChainView so we are | ||
// notified if/when this channel is closed. | ||
filterUpdate := []graphdb.EdgePoint{ | ||
{ | ||
FundingPkScript: fundingPkScript, | ||
OutPoint: *fundingPoint, | ||
OutPoint: edge.ChannelPoint, |
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.
If we move b.cfg.ChainView.UpdateFilter
to the gossiper we can save us from doing the relatively expensive makeFundingScript
again here.
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.
with the latest update, we no longer re-calculate it and instead pass it through from the gossiper.
I think it is better to let the builder manage the ChainView anyways 👍
The `graph.Builder`'s `addZombieEdge` method is currently called during funding transaction validation for the case where the funding tx is not found. In preparation for moving this code to the gossiper, we export the method and add it to the ChannelGraphSource interface so that the gossiper will be able to call it later on.
This is in preparation for the commit where we move across all the funding tx validation so that we can test that we are correctly updating the zombie index.
in preparation for later on when we need to know when to skip funding transaction validation.
Here, we add a new fundingTxOption modifier which will configure how we set-up expected calls to the mock Chain once we have moved funding tx logic to the gossiper. Note that in this commit, these modifiers don't yet do anything.
In preparation for an upcoming commit which will move all channel funding tx validation to the gossiper, we first move the helper method which helps build the expected funding transaction script based on the fields in the channel announcement. We will still want this script later on in the builder for updating the ChainView though, and so we pass this field along with the ChannelEdgeInfo. With this change, we can remove the TapscriptRoot field from the ChannelEdgeInfo since the only reason it was there was so that the builder could reconstruct the full funding script.
As we move the funding transaction validation logic out of the builder and into the gossiper, we want to ensure that the behaviour stays consistent with what we have today. So we should aquire this lock before performing any expensive checks such as building the funding tx or valdating it.
This commit is a pure refactor. We move the transaction validation (existence, spentness, correctness) from the `graph.Builder` to the gossiper since this is where all protocol level checks should happen. All tests involved are also updated/moved.
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.
LGTM, very nice refactor! ✨
return wire.OutPoint{}, 0, nil, zErr | ||
} | ||
|
||
return wire.OutPoint{}, 0, nil, fmt.Errorf("%w: %w", |
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.
nit: previously we had some more context for this error: "output failed validation"
. afaict it's ok to remove but just flagging in case it wasn't intentional. Same in line 3737.
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.
🚢
TapscriptRoot fn.Option[chainhash.Hash] | ||
// FundingScript holds the script of the channel's funding transaction. | ||
// | ||
// NOTE: this is not currently persisted and so will not be present if |
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.
👍
Depends on:
graph.Builder
update handling #9476Fixes #9475
part of #9494