-
Notifications
You must be signed in to change notification settings - Fork 371
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
Channel phase refactor, wrap channel phase, store wrapped phase in map #3418
base: main
Are you sure you want to change the base?
Conversation
Preferably we should get this in before further substantial dual funding or splicing changes |
Thanks! Discussed this @jkczyz in some calls, makes sense and agree with moving the enum inward effectively. Happy to prioritise this as it will reduce |
Please note that this is not complete, but only the basic change to the map, further steps are possible (as noted in description). Various handling logic in |
Sounds good! :) I wasn't too worried about the extra wrapper, just wanted to get the bigger picture of its specific use. |
ed42039
to
a8f83dc
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3418 +/- ##
==========================================
- Coverage 89.22% 89.21% -0.01%
==========================================
Files 130 130
Lines 106965 107038 +73
Branches 106965 107038 +73
==========================================
+ Hits 95438 95496 +58
- Misses 8734 8748 +14
- Partials 2793 2794 +1 ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
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.
Next steps:
- Rename
Channel
->FundedChannel
andChannelWrapper
->Channel
- Create more handling method on
Channel
(channel wrapper), that dispatch into different phases.
We may as well do this now. At very least the rename.
return close_chan!(chan_err, api_err, chan); | ||
}, | ||
} | ||
Some(channel) => { |
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.
Could you pattern match on the struct to reduce the diff size here and elsewhere?
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 change here comes from the fact that the Option and the Enum are now in different level, hence it's not possible to match them in one.
For the second match with one positive and one error arm I think the if let() construct is more readable. If I change to match, the diff is still there, the unchanged inner part is only indented.
lightning/src/ln/channel.rs
Outdated
pub fn phase_take(self) -> ChannelPhase<SP> { | ||
self.phase | ||
} |
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.
Seems like we could move context
to ChannelWrapper
to avoid needing to deconstruct it. Otherwise, we still need to re-insert into the map. So, IIUC, this change doesn't really help us any.
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 should discuss this offline, I don't fully get it.
When a pending channel becomes funded, we need to remove&insert because the channel ID changed.
But when only the phase changes, there is no longer need for removal, see move_v2_to_funded
.
The method to change the phase internally is a bit tricky, as the context owned by the old phase needs to be moved to the new phase.
Moving the context to ChannelWrapper would not solve the cases when there are (will be) more than one channel contexts.
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 should discuss this offline, I don't fully get it. When a pending channel becomes funded, we need to remove&insert because the channel ID changed. But when only the phase changes, there is no longer need for removal, see
move_v2_to_funded
.
Right, for outbound channels the id will change. I had splicing on my mind where we shouldn't change once already funded, IIRC.
The method to change the phase internally is a bit tricky, as the context owned by the old phase needs to be moved to the new phase. Moving the context to ChannelWrapper would not solve the cases when there are (will be) more than one channel contexts.
That's why I was saying to move context
into ChannelWrapper
. Then you can simply override phase
with a new variant. Could you remind me when we'll have more than one channel context and how they'll be stored? Is that for splicing? Will that involve a phase transition? They could possibly be swap
ed if contained within a Vec
, for instance, or take
n from an internal Option
if not required.
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.
Could you remind me when we'll have more than one channel context and how they'll be stored?
enum ChannelPhase {
...
Funded(FundedChannel<SP>),
RefundingV2((FundedChannel<SP>, ChannelVariants<SP>)),
First is the pre-splice channel, with its context. Second has the negotiating splice channel, and possible 0 or more negotiated unconfirmed splice variants.
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 the phase transition then Funded
-> RefundingV2
-> Funded
?
I'm looking at your draft prototype. Is this up-to-date with your current plan? If so, could you explain funded_channels
and unfunded_channel
in ChannelVariants
? Just trying to wrap my head around the organization.
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.
Funded
-> RefundingV2
-> Funded
In RefundingV2
there is the original (pre-splice) context, and a pending one (inbound or outbound, V2 negotiating). When that's negotiating, it becomes (Funded)Channel, but still within RefundingV2
phase. When it is confirmed, the splice is completed, and becomes Funded
.
With splice RBF variants there can be another pending, and several funding variants.
So in RefundingV2
there is at least two contexts: pre-splice and post-splice, or even more with RBF.
In places where the Funded
channel is taken, for RefundingV2
we sometimes have to take the pre-splice channel (e.g. when listing funded channels, or forwarding a payment), sometimes the post-splice (e.g. when tx negotiation msgs are handled), and sometimes both -- e.g. in commitment update.
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.
Moving the context to ChannelWrapper
: I don't see how this could work. What would be left in the ChannelPhases then?
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.
Moving the context to
ChannelWrapper
: I don't see how this could work. What would be left in the ChannelPhases then?
Not much else for FundedChannel
, which would mean RefundingV2
would only need to hold ChannelVariants
since the ChannelWrapper
would contain the "current" ChannelContext
, leaving any other "pending" ChannelContext
s within the corresponding phase. Then, for splicing, the pending ChannelContext
can be moved / swapped to ChannelWrapper
when transitioning to Funded
. At least that's what I was thinking at a high-level to avoid the Option
.
/// The inner channel phase | ||
/// Option is used to facilitate in-place replacement (see e.g. move_v2_to_funded), | ||
/// but it is never None, ensured in new() and set_phase() | ||
phase: Option<ChannelPhase<SP>>, |
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.
See other comment about moving ChannelContext
here. Seems we shouldn't need to use an Option
.
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 agree that logically it should not be Option, but I found no other way to transport the context from one phase to another. This may be Rust technicality. Option can be taken out and left empty, which is needed as I was not able to make the transfer in one atomic operation. Maybe another solution would be if ChannelContext had a default()
.
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 swap
work?
The rename of |
92f8bc3
to
4d886fe
Compare
I don't think |
4d886fe
to
dd19f65
Compare
I've continued with this on another branch
@jkczyz , should I include these in this PR or keep separate? |
At very least we should do the rename in this PR. We can remove |
Note: splice PR #3444 contains a new phase, shows more concretely some goals for this change |
Rename added |
Rationale:
Changes in this PR:
ChannelWrapper
struct to wrap aChannelPhase
ChannelManager.channel_by_id
map holdsChannelWrapper
structs, as opposed toChannelPhase
enumsNext steps:
Channel
->FundedChannel
andChannelWrapper
->Channel
Channel
(channel wrapper), that dispatch into different phases.