-
Notifications
You must be signed in to change notification settings - Fork 366
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
Use a single peer state map for all channel phases in peer state #2495
Use a single peer state map for all channel phases in peer state #2495
Conversation
Codecov ReportPatch coverage:
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## main #2495 +/- ##
==========================================
- Coverage 90.63% 90.48% -0.15%
==========================================
Files 110 112 +2
Lines 58199 58429 +230
Branches 58199 58429 +230
==========================================
+ Hits 52747 52870 +123
- Misses 5452 5559 +107
☔ View full report in Codecov by Sentry. |
9bd6169
to
d0d158a
Compare
Was nice while it lasted, but, yea, I think this makes sense 😢 |
Yeah, there were some benefits to the multi-map approach, but I believe there's just too many negatives and harder to consolidate. The one con to single map is that there is added verbosity in places but I think we can |
d0d158a
to
eba38d8
Compare
#2428 landed 🎉 |
eba38d8
to
963540f
Compare
963540f
to
63d294a
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.
Just a few questions
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.
Got maybe ~half way through
63d294a
to
1802e22
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.
Mainly was trying to look at where we match every variant vs. _
(or do an if let
) since one of the nice things with this PR is to have the compiler notify us of important places when adding new ChannelPhase
s, and these places seem to be good (or at least lean towards being stricter) AFAICT, might have to think on these more though. Otherwise, mainly just some smaller style comments and whatnot
hash_map::Entry::Occupied(mut chan_phase_entry) => { | ||
if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() { | ||
let (closing_signed, tx) = try_chan_phase_entry!(self, chan.closing_signed(&self.fee_estimator, &msg), chan_phase_entry); |
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.
but I think we can impl helper methods on a newtype for the map to make things more readable and dedup stuff.
One thing I noticed while reviewing is there are a good amount of places where we want to use the chan_phase_entry
and the chan
, and only match on one variant, and otherwise if it's vacant in the hashmap or a different variant, we return roughly the same error. This might be a pattern where a helper/macro could simplify some things, not sure if it's best fit for this PR or a followup but just an idea :)
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.
Keeping this for a followup for now, but might tack it on in this PR still.
45cfaf1
to
7ca24f6
Compare
} | ||
for channel in peer_state.channel_by_id.iter().filter_map( | ||
|(_, phase)| if let ChannelPhase::Funded(channel) = phase { | ||
if channel.context.is_funding_initiated() { Some(channel) } else { 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.
Checking is_funding_initiated
seems redundant?
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.
There's a case where we're the channel opener and the unfunded channel becomes a funded Channel
when we generate the funding transaction and before we receive funding_signed
. Then is_funding_initiated()
would return false.
I think you had suggested we only promote a channel to funded when we receive funding_signed and create a monitor for it, but the consensus was that we do it when we generate the txid-based channel ID so we don't mix them in the maps (and some other stuff). But now we're back to having one map so they would be mixed anyway. So maybe we go back to that and then can get rid of is_funding_initiated()
?
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 I think we should.
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.
Irrespective of if we change when a channel becomes funded (which we can change, I think, sgtm), we'll still have this issue here with dual-funded channels where one channel has completed its monitor update and another has not. See discussion at #2486, but lets at least leave this LoC. If we want to move the post for when a channel becomes funded, should we do that in a separate PR?
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 I wasn't thinking of changing it here. If we do end up shifting it then it'll be a separate PR after dual funding is considered. Focus is to get this PR through and get that V2 establishment PR ready for review and make progress there.
Thanks for the review. Addressing. |
c67d033
to
ad7b75e
Compare
b559f33
to
592db11
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, just a few minor comments
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 aside from @wpaulino's comments and two nits below. Feel free to squash as you go I think, would like to land this tomorrow.
592db11
to
775eef4
Compare
We introduce the `ChannelPhase` enum which will contain the different channel structs wrapped by each of its variants so that we can place these within a single `channel_by_id` map in `peer_state` in the following commits. This will reduce the number of map lookup operations we need to do in `ChannelManager`'s various methods. It will also make certain channel counting logic easier to reason about with less risk of forgetting to modify logic when new channels structs are introduced for V2 channel establishment.
775eef4
to
9a1692e
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, just a couple more nits
lightning/src/ln/channelmanager.rs
Outdated
@@ -2057,7 +2113,21 @@ macro_rules! handle_new_monitor_update { | |||
}) | |||
} }; | |||
($self: ident, $funding_txo: expr, $update: expr, $peer_state_lock: expr, $peer_state: expr, $per_peer_state_lock: expr, $chan_entry: expr) => { | |||
handle_new_monitor_update!($self, $funding_txo, $update, $peer_state_lock, $peer_state, $per_peer_state_lock, $chan_entry.get_mut(), MANUALLY_REMOVING, $chan_entry.remove_entry()) | |||
if let ChannelPhase::Funded(chan) = $chan_entry.get_mut() { | |||
handle_new_monitor_update!($self, $funding_txo, $update, $peer_state_lock, $peer_state, $per_peer_state_lock, chan, MANUALLY_REMOVING, { |
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.
Nit: extra blank space at end of line
lightning/src/ln/channelmanager.rs
Outdated
handle_new_monitor_update!($self, $funding_txo, $update, $peer_state_lock, $peer_state, $per_peer_state_lock, $chan_entry.get_mut(), MANUALLY_REMOVING, $chan_entry.remove_entry()) | ||
if let ChannelPhase::Funded(chan) = $chan_entry.get_mut() { | ||
handle_new_monitor_update!($self, $funding_txo, $update, $peer_state_lock, $peer_state, $per_peer_state_lock, chan, MANUALLY_REMOVING, { | ||
if let ChannelPhase::Funded(chan) = $chan_entry.remove() { chan } else { unreachable!() } |
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.
Remove without variant check
let (_, err) = convert_chan_phase_err!($self, ChannelError::Close( | ||
"Cannot update monitor for unfunded channels as they don't have monitors yet".into()), | ||
$chan_entry.get_mut(), &channel_id); | ||
$chan_entry.remove(); | ||
Err(err) |
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 think we can just use try_chan_phase_entry
?
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 think it leads to an early return and messes things up here.
Whenever possible, if not using fixups, please keep rebases as their own push when also addressing feedback so that it's easier to tell what changed. |
Sorry about that. |
9a1692e
to
88db0b8
Compare
Fixes #2422
Will unblock progress on #2302.