-
Notifications
You must be signed in to change notification settings - Fork 403
Encapsulate Channel
enum variants inside a struct
#3550
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
Encapsulate Channel
enum variants inside a struct
#3550
Conversation
effabbb
to
9773f1a
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.
Looks good (so far)
Ok, AFAICT, the PR as-is should have changed all the possible phase transitions where we were removing and re-inserting into a map (except when going from a temporary channel id). Reviewers, please check that this is the case by looking at the commits introducing FYI, the changes in the last commit may interfere with #3423. |
lightning/src/ln/channelmanager.rs
Outdated
self.chain_monitor | ||
.watch_channel(funded_chan.context.get_funding_txo().unwrap(), monitor) | ||
.map_err(|()| { | ||
// We weren't able to watch the channel to begin with, so no | ||
// updates should be made on it. Previously, full_stack_target | ||
// found an (unreachable) panic when the monitor update contained | ||
// within `shutdown_finish` was applied. | ||
chan.unset_funding_info(msg.channel_id); | ||
return Err(convert_channel_err!(self, peer_state, e, chan, &msg.channel_id, FUNDED_CHANNEL).1); |
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 was a little confused by this comment given the earlier version removed the entry from the map, and this new version uses try_channel_entry
to remove it on error below. i.e., Why do we need to call unset_funding_info
if the channel is no longer in the map?
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 only need to call it in cases where the new channel conflicts with an existing channel. When locked_close_channel
eventually gets called on the new channel, it needs to have its funding info removed, otherwise we'll remove the mapping in outpoint_to_peer
for the original channel, which is crucial for its handling of MonitorEvent
s. If we pursue #3554 all the way, that map can finally be removed.
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.
Some other cases where I'd imagine a phase transition happens:
- Failed splice negotiation on an already funded channel: not yet implemented, OK for now
- Transaction reorg after confirmation: turns out we just force close anyway, and we don't transition back to unfunded regardless of the changes proposed here
9773f1a
to
f3cd992
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3550 +/- ##
==========================================
+ Coverage 88.57% 89.54% +0.96%
==========================================
Files 149 149
Lines 114539 122358 +7819
Branches 114539 122358 +7819
==========================================
+ Hits 101449 109561 +8112
+ Misses 10602 10370 -232
+ Partials 2488 2427 -61 ☔ View full report in Codecov by Sentry. |
f3cd992
to
e84d9d1
Compare
e84d9d1
to
f7f5567
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 after squash
f7f5567
to
4a30d10
Compare
@optout21 Let me know if you'd like to me to squash the fixups |
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.
New to the codebase so comments are all non-blocking, nice refactor!
4a30d10
to
22436bb
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, OK to squash
22436bb
to
6639f0c
Compare
Squashed. Looks like I need to rebase. |
Now that ChannelPhase has been renamed, drop phase from related identifiers.
Now that ChannelPhase has been renamed, drop phase from related identifiers.
Now that ChannelPhase has been renamed, drop phase from related identifiers.
Now that ChannelPhase has been renamed, drop phase from related identifiers.
Now that ChannelPhase has been renamed, drop phase from related identifiers.
Now that ChannelPhase has been renamed, drop phase from related identifiers.
The old ChannelPhase variants will be used internally in Channel, so they should no longer be used elsewhere.
Now that ChannelPhase has been renamed, drop phase from related identifiers. Also, qualify uses of chan to avoid overloading the identifier.
Instead of exposing the Channel enum variants, make a Channel struct that wraps a ChannelPhase enum. This allows updating a Channel's phase without consuming it, which isn't possible when it is in a map without removing the entry first (e.g., as is done in ChannelManager).
When attempting a ChannelPhase transition, the variant-specific channel struct needs to be taken by self in order to move its ChannelContext into the struct for the new phase. Add a variant for an intermediate state, allowing such actions.
When moving ChannelPhase logic from ChannelManager into Channel, it is useful to error when a Channel is not in the expected state. Add a ChannelError::SendError variant for this purpose, which results in sending an error message without closing the channel.
Now that ChannelPhase is encapsulated in Channel, phase transitions can be moved from ChannelManager to Channel. Update the funding_signed phase transition accordingly. This allows for simpler logic in ChannelManager since the channel does not need to removed and then readded into the channel_by_id map.
Now that ChannelPhase is encapsulated in Channel, phase transitions can be moved from ChannelManager to Channel. Update the tx_complete phase transition accordingly. This allows for simpler logic in ChannelManager since the channel does not need to removed and then re-added into the channel_by_id map.
6639f0c
to
b75ca39
Compare
Rebased. |
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
/// its variants containing an appropriate channel struct. | ||
pub(super) enum Channel<SP: Deref> where SP::Target: SignerProvider { | ||
enum ChannelPhase<SP: Deref> where SP::Target: SignerProvider { | ||
Undefined, |
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.
Bleh, I almost prefer unsafe { mem::uninitialized }
, oh well.
hash_map::Entry::Occupied(mut chan_entry) => { | ||
let chan = chan_entry.get_mut(); | ||
match chan | ||
.funding_signed(&msg, best_block, &self.signer_provider, &self.logger) |
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 need to standardize whether wrapping the logger happens in channelmanager
or channel
and make sure we're consistent...at some point
// updates should be made on it. Previously, full_stack_target | ||
// found an (unreachable) panic when the monitor update contained | ||
// within `shutdown_finish` was applied. | ||
chan.unset_funding_info(); |
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 removed debug_assert!(matches!(e, ChannelError::Close(_))
which I think is actually important here since we don't re-add the 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.
This may be ChannelError::SendError
if the channel wasn't in the expected 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.
Err, right, duh, we're no longer removing-and-adding so this is fine.
Instead of exposing the
Channel
enum variants, make aChannel
struct that wraps aChannelPhase
enum. This allows updating aChannel
's phase without consuming it, which isn't possible when it is in a map without removing the entry first. Then move phase transitions can fromChannelManager
toChannel
. This allows for simpler logic inChannelManager
since the channel does not need to removed and then re-added into thechannel_by_id
map during a phase transition (or failed one).