-
Notifications
You must be signed in to change notification settings - Fork 382
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
Refactor ChannelContext
value fields into FundingScope
#3592
Refactor ChannelContext
value fields into FundingScope
#3592
Conversation
@wpaulino Would like some early feedback on this approach of using a The last commit and its fixups moves
The commit is later reverted and Compiles with |
Chatted with @wpaulino offline about attempting to pass |
FYI, I pushed some more commits to the branch that move some more fields into |
a8e46b7
to
18b4eac
Compare
ChannelContext
fields into FundingScope
ChannelContext
value fields into FundingScope
Went ahead with this approach as discussed offline. This PR limits the the fields moved to those related to the channel's value. Other fields will be moved in follow-up PRs. |
18b4eac
to
5beaa01
Compare
Pushed a small change to cheer up CI compiling under |
Is the thinking here that basically we'd implement things on the |
Note that the updated branch drops Generally, the idea for splice/rbf would be to maintain an additional |
lightning/src/ln/channel.rs
Outdated
impl<SP: Deref> FundedChannel<SP> | ||
where | ||
SP::Target: SignerProvider, | ||
<SP::Target as SignerProvider>::EcdsaSigner: EcdsaChannelSigner, | ||
{ |
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.
Up to you, but I'd rather move the method to keep the number of impl blocks to a minimum so we don't have to keep redefining all the generics
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.
Maybe we tack on an extra commit at the end that is purely moving code to make reviewing easier?
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.
Added fixups along the way to revert to a single impl block.
@@ -4257,7 +4313,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider { | |||
unbroadcasted_batch_funding_txid, | |||
channel_id: self.channel_id, | |||
user_channel_id: self.user_id, | |||
channel_capacity_satoshis: self.channel_value_satoshis, | |||
channel_capacity_satoshis: funding.channel_value_satoshis, |
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.
Unfortunately it seems like some of these fields will not be accurate if we tried closing the channel with the currently confirmed scope, but then a pending splice ends up confirming and we have to spend from the spliced channel instead.
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.
Discussed this a bit more offline. Seems when processing ShutdownResult
in ChannelManager::finish_close_channel
, instead of generating a ChannelClosed
event there we should do so in ChannelMonitor
. This will require including the ClosureReason
in ChannelMonitorUpdateStep::ChannelForceClosed
.
@TheBlueMatt Any thoughts on this? @wpaulino Feel free to fill in any more details that I may have left out.
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.
Right, obviously the ChannelMonitor
will know how to spend any splice at any point, but I think we already have the issue that the ChannelClosed
event can be subtly off once we hit chain - its always generated immediately, the amounts in it are intended to be informative (maybe we should clarify that more in the docs?), but eg the counterparty might broadcast a state that's one old (but not revoked...or revoked) and we'll get more or less and have to claim HTLCs on chain... I don't think we want to wait until the channel is confirmed on chain before we generate the event.
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 can't/don't want to rely on the values being correct then we might as well not include them in the event?
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 definitely open to removing them, but we should keep the info around somewhere - currently Balance
s in ChannelMonitor
don't tell you how big the channel was/what your msat balance was. The original motivation for the balance field (which may be wrong) is #1898.
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.
How about adding a closed_channel_balance
API to the monitor that users can use as long as they keep it around? We'd only return Some
once the closing transaction is no longer under reorg risk and it could include channel value, local/remote balance, and pending HTLC balance.
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, yea, that would work, I guess a related question is how Balance
s are going to work with splicing anyway - I guess we'll have to have redundant Balance
s for different splice cases?
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 HTLC balances could probably stay the same? For the local balance, when there's a splice pending, maybe we use a new variant over ClaimableOnChannelClose
(e.g., MaybeClaimableOnChannelClose
?) that gives you the balance for a particular FundingScope
. Once the splice is no longer pending, we go back to ClaimableOnChannelClose
.
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 HTLC balances could probably stay the same?
Hmm, is it possible we splice and change the commitment transaction format? That would impact the balances
For the local balance, when there's a splice pending, maybe we use a new variant over ClaimableOnChannelClose (e.g., MaybeClaimableOnChannelClose?) that gives you the balance for a particular FundingScope. Once the splice is no longer pending, we go back to ClaimableOnChannelClose.
Something like that, yea, it'd be nice to expose a vec of the possible options but makes sense.
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, is it possible we splice and change the commitment transaction format? That would impact the balances
It is possible with splicing (e.g., anchors to taproot), but the spec as is today does not mention anything regarding it
Yeah we basically want to guarantee immutability whenever we have multiple |
Right, okay, yea, makes sense, just gonna be a lot of methods that we have to split into two. |
Conceptually I think that's probably the right approach, though, not sure how else we'd do it, just a pretty awkward API. |
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.
Addressed the feedback. I'm going to add another commit to move next_local_commitment_tx_fee_info_cached
and next_remote_commitment_tx_fee_info_cached
soon.
lightning/src/ln/channel.rs
Outdated
impl<SP: Deref> FundedChannel<SP> | ||
where | ||
SP::Target: SignerProvider, | ||
<SP::Target as SignerProvider>::EcdsaSigner: EcdsaChannelSigner, | ||
{ |
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.
Added fixups along the way to revert to a single impl block.
@@ -4257,7 +4313,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider { | |||
unbroadcasted_batch_funding_txid, | |||
channel_id: self.channel_id, | |||
user_channel_id: self.user_id, | |||
channel_capacity_satoshis: self.channel_value_satoshis, | |||
channel_capacity_satoshis: funding.channel_value_satoshis, |
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.
Discussed this a bit more offline. Seems when processing ShutdownResult
in ChannelManager::finish_close_channel
, instead of generating a ChannelClosed
event there we should do so in ChannelMonitor
. This will require including the ClosureReason
in ChannelMonitorUpdateStep::ChannelForceClosed
.
@TheBlueMatt Any thoughts on this? @wpaulino Feel free to fill in any more details that I may have left out.
5beaa01
to
d2a32a7
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.
LGTM so far, it's the right abstraction, in the good direction.
When establishing a channel, the funding transaction may be replaced either: - after the funding transaction has confirmed using splicing, - before the funding transaction has confirmed for v2 channel establishment using tx_init_rbf, or - before the splice's funding transaction has confirmed using tx_init_rbf. In each of these cases, fields in ChannelContext will need to be updated once the funding transaction confirms. Additionally, the same fields for a pending attempt may need to be considered instead of a previously confirmed funding. This commit introduces a FundingScope to hold the aforementioned fields. It lives next to ChannelContext and will be needed whenever these fields are accessed. The next few commits will move the relevant fields to FundingScope and provide access to them whenever needed, allowing to swap in another FundingScope when necessary.
9a11051
to
04abb58
Compare
Rebased to resolve merge conflict. |
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 after squash
lightning/src/ln/channel.rs
Outdated
#[cfg(any(test, fuzzing))] | ||
funding: &FundingScope, |
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.
This feels a bit weird, should we move these methods to be on FundedChannel
instead?
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... this is called from ChannelContext::get_available_balances
, though.
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.
That's also only called on funded channels, but always passing it in now is fine
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.
Basically LGTM. I think ideally we walk back exposing the Funding
to channelmanager.rs
at all, but assuming we can we can also do that as this develops over coming PRs.
lightning/src/ln/channel.rs
Outdated
@@ -3805,9 +3868,17 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider { | |||
} | |||
|
|||
let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered); | |||
let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(htlc_above_dust, Some(())); | |||
let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat( | |||
#[cfg(any(test, fuzzing))] |
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.
Ha, we should probably either remove the fields and associated testing or always pass the funding. I think either is probably fine.
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.
Going to always pass FundingScope
since the follow-up PR alternative branch needs it.
@@ -3075,7 +3075,7 @@ macro_rules! convert_channel_err { | |||
ChannelError::Close((msg, reason)) => { | |||
let logger = WithChannelContext::from(&$self.logger, &$context, None); | |||
log_error!(logger, "Closing channel {} due to close-required error: {}", $channel_id, msg); | |||
let mut shutdown_res = $context.force_shutdown(true, reason); | |||
let mut shutdown_res = $context.force_shutdown($funding, true, reason); |
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.
Do we have to expose the Funding
to channelmanager.rs
at all? It seems like very much a Channel
-internal thing that ideally we wouldn't have to deal with in channelmanager.rs
(we just might get a Vec
of things like channel amounts when we go to look).
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 could probably introduce a force_shutdown
method on Channel
and have it delegate to ChannelContext
using the underlying FundingScope
. Likewise, with other methods. Here, we don't have a Channel
, though. Might be a way to restructure these macros, but they are a bit of a maze, TBH.
Also, note, the use of locked_close_channel
below will need a FundingScope
in the follow-up to call get_funding_txo
. That doesn't have a Channel
, either, just a ChannelContext
.
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.
Once we finish all of the work here, there may be a nice way to clean this up.
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.
Yea, I guess looking at it we really shouldn't be exposing the ChannelContext
at all, either. After all this work is done we should really go through channel.rs
, break it up a bit (now that we have several different structs we can draw neater lines!), clean up the API to channelmanager.rs
(one struct, with channel.rs
and new friends deciding whether it makes sense in the channel's state).
Feel free to squash from my PoV. Where are you on this @wpaulino? |
15f1c21
to
79ce104
Compare
Squashed given @wpaulino seemed good with it earlier. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3592 +/- ##
==========================================
+ Coverage 88.61% 88.92% +0.30%
==========================================
Files 149 149
Lines 116877 119290 +2413
Branches 116877 119290 +2413
==========================================
+ Hits 103572 106074 +2502
+ Misses 10798 10775 -23
+ Partials 2507 2441 -66 ☔ View full report in Codecov by Sentry. |
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.
Yea, reflecting on it more I'm not very happy with the state of our channel state (pun intended)...We've ended up with a ChannelState
which describes the channel's state stored in an enum that describes the channel's state while exposing much too much to channelmanager.rs
. As we make more progress here it would be great to clean this up as much as possible and if required do a "finish cleaning up" PR at the end to unify the state tracking, split files, and ensure a simple API to channelmanager as much as possible.
When establishing a channel, the funding transaction may be replaced either:
establishment using
tx_init_rbf
, ortx_init_rbf
.In each of these cases, fields in
ChannelContext
will need to be updated once the funding transaction confirms. Additionally, the same fields for a pending attempt may need to be considered instead of a previously confirmed funding.This PR introduces a
FundingScope
to hold the aforementioned fields. It lives next toChannelContext
and will be needed whenever these fields are accessed. It limits the the fields moved to those related to the channel's value. Other fields will be moved in follow-up PRs.