-
Notifications
You must be signed in to change notification settings - Fork 404
Refactor ChannelState to decouple state flags from states #2691
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 ChannelState to decouple state flags from states #2691
Conversation
Codecov ReportAttention:
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## main #2691 +/- ##
==========================================
- Coverage 88.64% 88.49% -0.15%
==========================================
Files 115 115
Lines 90446 90786 +340
Branches 90446 90786 +340
==========================================
+ Hits 80173 80345 +172
- Misses 7874 8022 +148
- Partials 2399 2419 +20 ☔ View full report in Codecov by Sentry. |
aefe8cf
to
df1dd80
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.
Concept ACK this implementation.
We're going to be touch a lot more of the state in splicing so it makes sense to have the extra type safety.
lightning/src/ln/channel.rs
Outdated
FundingCreated, | ||
/// We've received/sent `funding_created` and `funding_signed` and are thus now waiting on the | ||
/// funding transaction to confirm. | ||
FundingSent(FundingSentFlags), |
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.
Can we now rename this to something more general like AwaitingConfirmation
so that it can also apply to V2 channel establishment?
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 probably something like AwaitingChannelReady
/FundingSigned
since it also applies to zero conf.
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 that's better :)
lightning/src/ln/channel.rs
Outdated
/// We have sent `funding_created` and are awaiting a `funding_signed` to advance to | ||
/// `FundingSent`. Note that this is nonsense for an inbound channel as we immediately generate | ||
/// `funding_signed` upon receipt of `funding_created`, so simply skip this state. | ||
FundingCreated, |
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 guess this could be used for both inbound and outbound channels in V2 establishment when the one party has sent the initial commitment_signed
and not received the counterparty`s yet. I don't know what a good general name for that would be but happy to just use this state.
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.
FundingNegotiated
?
lightning/src/ln/channel.rs
Outdated
|
||
define_state_flags!( | ||
"Flags that only apply to [`ChannelState::FundingSent`].", | ||
FUNDED_STATE, FundingSentFlags, [ |
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 confused here, we can be PEER_DISCONNECTED and even MONITOR_UPDATE_IN_PROGRESS in FundingSent
.
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.
It's a bit subtle, but using the FUNDED_STATE
arm of the macro includes all FundedStateFlags
(PeerDisconnected
, MonitorUpdateInProgress
, LocalShutdownSent
, RemoteShutdownSent
) as well.
df1dd80
to
312965b
Compare
Needs rebase. |
Previously, our `ChannelState` contained bits for both states and flags. To make matters worse, some of the flags could apply to multiple states. This led to its API being very cumbersome, having to apply masks in most scenarios to check for certain states. As LDK grows and more features are added requiring more states/flags, the need for a simpler API arises. This refactor aims to improve this by decoupling the state flags from the `ChannelState` enum. Each state that requires flags will now have its own flags type, to ensure flags can only be applied to their intended state. All of this is done while maintaining backwards and forwards compatibility.
312965b
to
158c14c
Compare
Rebased and also added a fixup for the flag renames @dunxen pointed out. |
IMO the second commit shouldn't be a fixup, renaming the flags should be a separate commit. |
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. I don't believe there are any other additions required by V2 establishment, but after rebase I'll know for sure. Would belong in another PR anyway.
`FundingCreated` and `FundingSent` were mostly named after the respective `funding_created` and `funding_sent` wire messages. They include the signature for the initial commitment transaction when opening a channel. With dual funding, these messages are no longer used, and instead we rely on the existing `commitment_signed` to exchange those signatures.
158c14c
to
6492cc9
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. With the new design I think we can/should push for more compile-time checking as well as more assertions of valid state, but it doesn't have to happen here.
|
||
impl core::ops::Not for $flag_type { | ||
type Output = Self; | ||
fn not(self) -> Self::Output { Self(!self.0) } |
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 want an invariant that only valid flags are set?
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.
You can only set valid flags already 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.
This method returns a flags object with a pile of invalid flags set.
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 don't think this is safe because sometimes we use Not
to obtain a mask, and we wouldn't want to clear out the other bits of the thing we're masking.
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 mean maybe we should update the callsites to not depend on disallowed bits being set?
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 what I did in #2780.
Previously, our
ChannelState
contained bits for both states and flags. To make matters worse, some of the flags could apply to multiple states. This led to its API being very cumbersome, having to apply masks in most scenarios to check for certain states. As LDK grows and more features are added requiring more states/flags, the need for a simpler API arises.This refactor aims to improve this by decoupling the state flags from the
ChannelState
enum. Each state that requires flags will now have its own flags type, to ensure flags can only be applied to their intended state. All of this is done while maintaining backwards and forwards compatibility.While conceptualizing this design, I also explored two other options: