-
Notifications
You must be signed in to change notification settings - Fork 376
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
Preparations for storing channels per peer #1542
Preparations for storing channels per peer #1542
Conversation
@@ -7579,6 +7619,121 @@ mod tests { | |||
// Check that using the original payment hash succeeds. | |||
assert!(inbound_payment::verify(payment_hash, &payment_data, nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, &nodes[0].node.inbound_payment_key, &nodes[0].logger).is_ok()); | |||
} | |||
|
|||
#[test] | |||
fn test_id_to_peer_coverage() { |
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.
Let me know if you'd like me to add the by_id
map (channel_by_id
in #1507) and the short_to_chan_info
map to this test. Also let me know if you'd like me to update the test with force closing the channel etc. :)
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 not too picky here, given the code is in the same place as other similar changes I'm not too worried about it.
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 you want to improve test coverage, I'd instead recommend debug_assert!()
s during channelmanager operation, eg in the removal macro, etc.
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! I'll look into that.
/// We should add `counterparty_node_id`s to `MonitorEvent`s, and eventually rely on it in the | ||
/// future. That would make this map redundant, as only the `ChannelManager::per_peer_state` is | ||
/// required to access the channel with the `counterparty_node_id`. | ||
id_to_peer: Mutex<HashMap<[u8; 32], PublicKey>>, |
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.
What consistency do we expect between id_to_peer
and ChannelHolder::by_id
, like anything in the later should be in the former ? If yes, I think there are few call sites where we retain()
, e.g in timer_tick_occurred
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 all cases where false
is returned to retain
for a channel and we have received an OpenChannel
or AcceptChannel
msg for the channel, update_maps_on_chan_removal!
is triggered, which removes the channel entry from the id_to_peer
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.
Okay, I went to verify the retain
callsites and I think this statement is correct. Even if id_to_peer
might not be long-lived on the great scheme of things, it would be nice to document the consistency requirements among the two maps. Like say by_id
removal should always be follow-up by a call to update_maps_on_chan_removal!
.
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! Oh yeah, that's a great idea! I'll update the docs with that in #1507 :)
Codecov Report
@@ Coverage Diff @@
## main #1542 +/- ##
==========================================
- Coverage 91.04% 90.81% -0.23%
==========================================
Files 80 80
Lines 44194 44526 +332
Branches 44194 44526 +332
==========================================
+ Hits 40235 40437 +202
- Misses 3959 4089 +130
Continue to review full report at Codecov.
|
Thanks for the reviews @TheBlueMatt & @ariard! Addressed the nits in the new fixup commits :) |
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.
ab43fcd
to
0644621
Compare
0644621
to
8a8a4de
Compare
Thanks for the review @wpaulino :)! Adressed the feedback and squashed the changes in the last 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.
Code Review ACK 8a8a4de
Oops sorry, this needs a rebase now :(. Should be good to go once that happens, though! |
As the map values are no longer only `channel_id`s, but also a `counterparty_node_id`s, the map is renamed to better correspond to whats actually stored in the map.
8a8a4de
to
549c42f
Compare
Rebased on upstream! Apologies for the delay. |
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.
Oops, sorry, one issue.
lightning/src/ln/channelmanager.rs
Outdated
@@ -4511,12 +4538,16 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana | |||
return Err(MsgHandleErrInternal::send_err_msg_no_close("Already had channel with the new channel_id".to_owned(), funding_msg.channel_id)) | |||
}, | |||
hash_map::Entry::Vacant(e) => { | |||
let mut id_to_peer = self.id_to_peer.lock().unwrap(); | |||
if id_to_peer.insert(funding_msg.channel_id, *counterparty_node_id).is_some() { | |||
panic!("id_to_peer map already contained funding txid, which shouldn't be possible"); |
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 is definitely reachable - a counterparty could send us a channel with a conflicting txid. Sure, it wont have the output script pubkey that we agreed upon with the counterparty (which used unique keys), but we dont know that until we see the txid on-chain. Instead, this should be handled as a channel-closure error.
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.
Well, okay, its obviously not reachable today as of this PR, but post-per-peer-channels it will be, so we should handle it here, no? If you want to handle it in the per-peer-storage PR that's okay too.
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.
IIUC your concern, you think about a counterparty collisioning the id_to_peer
map by announcing Channel 2 with temporary_id=XYZ
from announced-by-us Channel 1 temporary_id
? Even if our temporary ids are generated by get_secure_random_bytes()
.
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.
No, this is post-temporary ids, this is generated from the funding txid - the issue is a peer can open two channels and give us the same txid to us on both channels (using different peer ids/node private keys).
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.
Oh yeah, good catch! I'll update this PR to fix it.
@ariard, no at this stage the temporary_channel_id
is unrelated to the problem that @TheBlueMatt is raising, as this is when we are inserting the actual channel_id
. As of today with this PR, the panic isn't reachable as the channel_state.by_id
entry check right above will catch the scenario Matt raised as the channel_state.by_id
isn't peer specific. But once per-peer-storage PR is merged, that check will be peer specific while the id_to_peer
insert remains peer unspecific, and therefore 2 different peers could send us the same txid
and not be catched by the first entry check above, hence triggering the panic.
Edit: Ah Matt got to it first :)
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.
Hmmm @TheBlueMatt, won't the scenario you are describing already be caught by:
rust-lightning/lightning/src/ln/channelmanager.rs
Line 2900 in 4e5f74a
return Err(APIError::APIMisuseError { |
That doesn't apply for funding_transaction_generated_unchecked
of course, but that's for testing only.
We can of course add an extra guard for it in funding_transaction_generated_intern
if you think that it's suitable 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.
For outbound channels, yes, for inbound channels we don't see the funding transaction until it hits the chain.
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.
Oh I'm stupid...!
Fixed in c09903b.
lightning/src/ln/channelmanager.rs
Outdated
/// TODO: | ||
/// The `counterparty_node_id` isn't passed with `MonitorEvent`s currently. To pass it, we need | ||
/// to add the `counterparty_node_id` to `ChannelMonitor`s. However, adding it as a required | ||
/// field in `ChannelMonitor`s would break backwards compatability. |
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: THis is a bit confusing - its not adding the field that breaks backwards compat (in fact we're gonna do it in #1596), its requiring it.
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.
lightning/src/ln/channelmanager.rs
Outdated
{ | ||
// Assert that the channel is removed from both parties `id_to_peer` map once they both | ||
// have everything required to fully close the channel. | ||
assert_eq!(nodes[0].node.id_to_peer.lock().unwrap().len(), 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.
I think this check is redundant with the one above. Though can be kept if you wanna assert node[0]'s id_to_peer has not been modified.
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.
lightning/src/ln/channelmanager.rs
Outdated
|
||
// Clear the `ChannelClosed` event for the nodes. | ||
nodes[0].node.get_and_clear_pending_events(); | ||
nodes[1].node.get_and_clear_pending_events(); |
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 you could use the macro get_event()
to test the expected ChannelClosed
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.
Thanks!
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.
lightning/src/ln/channelmanager.rs
Outdated
@@ -4511,12 +4538,16 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana | |||
return Err(MsgHandleErrInternal::send_err_msg_no_close("Already had channel with the new channel_id".to_owned(), funding_msg.channel_id)) | |||
}, | |||
hash_map::Entry::Vacant(e) => { | |||
let mut id_to_peer = self.id_to_peer.lock().unwrap(); | |||
if id_to_peer.insert(funding_msg.channel_id, *counterparty_node_id).is_some() { | |||
panic!("id_to_peer map already contained funding txid, which shouldn't be possible"); |
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.
IIUC your concern, you think about a counterparty collisioning the id_to_peer
map by announcing Channel 2 with temporary_id=XYZ
from announced-by-us Channel 1 temporary_id
? Even if our temporary ids are generated by get_secure_random_bytes()
.
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.
SGTM
77b7477
to
c09903b
Compare
lightning/src/ln/channelmanager.rs
Outdated
match id_to_peer.entry(chan.channel_id()) { | ||
hash_map::Entry::Occupied(_) => { | ||
return Err(MsgHandleErrInternal::send_err_msg_no_close( | ||
"Funding txid already exists with for another peer (or likely the |
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 make the error here a bit more compact? Note that we send our peer the error and log it, so it should generally be readable for both. Maybe "funding_created message had the same funding txid as an existing channel - funding is not possible" or something simple like that?
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.
Oh thanks, that makes sense:
81fc01f
lightning/src/ln/channelmanager.rs
Outdated
|
||
// Clear the `ChannelClosed` event for the nodes. | ||
get_event!(&nodes[0], Event::ChannelClosed); | ||
get_event!(&nodes[1], Event::ChannelClosed); |
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: check_closed_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.
LGTM. Needs squash, but will let other reviewers comment on that. |
Can you squash the fixup commits down to clean up the history and I think we can basically land this. |
93497bf
to
fa7f170
Compare
Squashed without changes |
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.
Code Review ACK fa7f170
Changes since last review :
- update the sentence about breaking backwards compatibility
- makes the collusion-triggerable-by-counterparty panic actually an error
- fix few comments in test
With #1507, we will store channels per peer in the
per_peer_state
map, instead of thechannel_state
. This PR splits up some of the functionality of #1507. To enable the transition to storing channels per peer, we need to update theshort_to_id
map to also include thecounterparty_node_id
.The
counterparty_node_id
isn't passed withMonitorEvent
s currently, we also need to add an additional mapid_to_peer
, which gives us thecounterparty_node_id
when we only have access to thechannel_id
. However, we would preferably like to avoid the need for this map, so it is only used forMonitorEvent
handling, so that it can be removed once we have thecounterparty_node_id
as an required field inChannelMonitor
s.