-
Notifications
You must be signed in to change notification settings - Fork 436
Rework ChannelManager::funding_transaction_signed #4336
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
Rework ChannelManager::funding_transaction_signed #4336
Conversation
|
👋 Thanks for assigning @jkczyz as a reviewer! |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4336 +/- ##
==========================================
- Coverage 86.53% 86.07% -0.47%
==========================================
Files 158 156 -2
Lines 103190 102804 -386
Branches 103190 102804 -386
==========================================
- Hits 89300 88490 -810
- Misses 11469 11803 +334
- Partials 2421 2511 +90
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
c0193fe to
0fc923c
Compare
| // We should never be sending a `commitment_signed` in response to their | ||
| // `tx_signatures`. | ||
| debug_assert!(commitment_signed.is_none()); | ||
|
|
||
| if let Some(tx_signatures) = tx_signatures { | ||
| peer_state.pending_msg_events.push(MessageSendEvent::SendTxSignatures { | ||
| node_id: *counterparty_node_id, | ||
| msg: tx_signatures, | ||
| }); | ||
| } |
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'm a little confused by this. Why would we send our tx_signatures if we aren't sending our commitment_signed? Didn't we want to send both at once?
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.
We've already sent it by this point, we're sending our tx_signatures here in response to theirs
| // We may need to regenerate [`Event::FundingTransactionReadyForSigning`] for channels that | ||
| // still need their holder `tx_signatures`. |
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.
Does it make sense to start persisting this?
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.
Matt pointed out we shouldn't #4257 (comment)
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.
@TheBlueMatt Is the goal eventually to not write events that (a) can be re-constructed from ChannelMonitor / FundedChannel state or (b) aren't applicable across a restart? Presumable this falls into that category.
Seems there will at least be some events that aren't tied to a particular channel, so we may still need to persist some events?
|
🔔 1st Reminder Hey @TheBlueMatt! This PR has been waiting for your review. |
TheBlueMatt
left a comment
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.
Hmm, seems like the last commit should really get have test coverage? I guess just our dual-funding coverage isn't that great?
Also, presumably this needs documentation for how to cancel a splice instead of signing and a test that does so?
Yeah things aren't really hooked up yet to do proper testing.
Planned for a separate PR, no need for it to happen here. |
734ad69 to
04a7560
Compare
TheBlueMatt
left a comment
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.
Question somewhat orthogonal to this PR - do we need a monitor update before sending our tx-sigs? Once we send it, its possible for our counterparty to respond with a commitment sigs and then we can't cancel. If we restart without chanman persistence and the user tries to cancel at that point we'll end up getting force-closed on.
I continue to be somewhat annoyed at how many expects there are in the splicing logic, and would feel a lot better if we had a full_stack_target seed that spliced so that at least the fuzzer could explore it a tiny bit (though of course a larger refactor to reduce them would be nice too).
04a7560 to
f2dd6f2
Compare
|
🔔 1st Reminder Hey @jkczyz! This PR has been waiting for your review. |
| // We may need to regenerate [`Event::FundingTransactionReadyForSigning`] for channels that | ||
| // still need their holder `tx_signatures`. |
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.
@TheBlueMatt Is the goal eventually to not write events that (a) can be re-constructed from ChannelMonitor / FundedChannel state or (b) aren't applicable across a restart? Presumable this falls into that category.
Seems there will at least be some events that aren't tied to a particular channel, so we may still need to persist some events?
lightning/src/ln/channelmanager.rs
Outdated
| ); | ||
| } | ||
| } | ||
| return NotifyOption::DoPersist; |
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.
Is this independent of any events being generated? (i.e., some stated in the channel was made, but is_connected was false?
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.
We still want to persist the funding signatures regardless of channel connectivity
|
|
||
| // We should never be sending a `commitment_signed` in response to their | ||
| // `tx_signatures`. | ||
| debug_assert!(commitment_signed.is_none()); | ||
|
|
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.
Would it make sense to return an error 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.
If we actually do, they'll force close on us, so we get the same result.
| let funding_tx_opt = self.maybe_finalize_funding_tx(); | ||
| let holder_tx_signatures = (self.holder_sends_tx_signatures_first | ||
| || self.has_received_tx_signatures()) | ||
| let holder_tx_signatures = (self.has_received_commitment_signed |
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.
Is has_received_commitment_signed implied from has_received_tx_signatures?
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.
Yes, we force close when receiving tx_signatures without the commitment_signed first. I'd prefer keeping the code as is for clarity though.
Previously, we'd emit a FundingTransactionReadyForSigning event once the initial commitment_signed is exchanged for a splicing/dual-funding attempt and require users to call back with their signed inputs using ChannelManager::funding_transaction_signed. While this approach worked in practice, it prevents us from abandoning a splice if we cannot or no longer wish to sign as the splice has already been committed to by this point. This commit reworks the API such that this is now possible. After exchanging tx_complete, we will no longer immediately send our initial commitment_signed. We will now emit the FundingTransactionReadyForSigning event and wait for the user to call back before releasing both our initial commitment_signed and our tx_signatures. As a result, the event is now persisted, as there is only one possible path in which it is generated. Note that we continue to only emit the event if a local contribution to negotiated transaction was made. Future work will expose a cancellation API such that we can abandon splice attempts safely (we can just force close the channel with dual-funding).
This is crucial to enable the splice cancellation use case. When we process the initial commitment signed from our counterparty, we queue a monitor update that cannot be undone. To give the user a chance to abort the splice negotiation before it's committed to, we buffer the message until a successful call to `Channel::funding_transaction_signed` and process it then. Note that this is currently only done for splice and RBF attempts, as if we want to abort a dual funding negotiation, we can just force close the channel as it hasn't been funded yet.
Now that we require users to first call `ChannelManager::funding_transaction_signed` before releasing any signatures, it's possible that it is called before we receive the initial commitment signed from our counterparty, which would transition the channel to funded. Because of this, we need to support the API call while the channel is still in the unfunded phase. Note that this commit is mostly a code move of `FundedChannel::funding_transaction_signed` to `Channel::funding_transaction_signed` that doesn't alter the signing logic.
f2dd6f2 to
be67c67
Compare
Alternative version to #4257