-
Notifications
You must be signed in to change notification settings - Fork 403
Wait to create a channel until after accepting. #2428
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
Wait to create a channel until after accepting. #2428
Conversation
We're looking at actually reducing the maps we create and going with an enum approach and single map for channels #2422, so this might make sense as an AwaitingAccept variant. Thanks for bringing this up. We could discuss on this PR, but I think an issue would be better. |
Sounds good. I made some changes to get the tests to pass; would be interested in discussing those. Let me update the PR. |
Codecov ReportPatch coverage:
❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more. Additional details and impacted files@@ Coverage Diff @@
## main #2428 +/- ##
==========================================
- Coverage 90.35% 90.32% -0.04%
==========================================
Files 106 106
Lines 56242 56232 -10
Branches 56242 56232 -10
==========================================
- Hits 50816 50789 -27
- Misses 5426 5443 +17
☔ View full report in Codecov by Sentry. |
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 this is looking like the right direction. I need to do some more review of what’s moved around but this looks good.
Oof, indeed, nice catch. Looks like this needs a small rebase, sorry about that. |
8e79049
to
96f52f5
Compare
41eb3b2
to
ae0ce65
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 like rebase caught some extra commits :). Otherwise, LGTM besides one comment and a nit
ae0ce65
to
8411b57
Compare
Thank you for the reviews! PTAL when you get a chance! |
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.
Looking good. I'm wondering if we can now do away with ChannelContext
's inbound_awaiting_accept and InboundV1Channel::is_awaiting_accept()
Actually I think we can punt this to a follow-up, but it would be nice to remove it if this PR makes it obsolete. |
Looks good! As for this comment, we can actually get rid of the We can do this since having an EDIT: This also means we could probably get rid of the |
So... I'm a bit worried about this exploding into a mega PR that will become increasingly difficult to review. Would you be comfortable to pursuing this cleanup in a follow-on? |
Haha sure. I thought the PR blowing up might be the case 😄 |
Ok so I believe this looks good, and I think we can squash any fixups. We'll need another reviewer 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.
Feel free to squash before addressing my feedback.
0df5629
to
b90f6c1
Compare
Thank you for the review @wpaulino! PTAL when you get a chance. Also a few unresolved that might need some advice... :) |
Oh hmm. I might have missed it but we'll need to make sure these requests get purged after some time like we do with inbound channels that are taking too long to finish handshake. And probably on disconnecting too although maybe we can keep them and try when reconnected. Probably best to just drop them on disconnect for now. EDIT: I don't see anything wrong with keeping them on disconnect so long as we still expire them after some time. |
The CI failures look like we're just missing some use of the new parameter for Otherwise looks good for squash. |
36cfb03
to
da1bc11
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.
25c4aa1
to
4e4bec7
Compare
Grr, this needs a trivial rebase, sorry about that. Conceptually LGTM, tho. |
4e4bec7
to
2888f76
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.
Oops, one issue (we fail to send an error
message when failing the channel) and a few nits.
@@ -4487,6 +4523,13 @@ where | |||
peer_state.outbound_v1_channel_by_id.retain(|chan_id, chan| process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context)); | |||
peer_state.inbound_v1_channel_by_id.retain(|chan_id, chan| process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context)); | |||
|
|||
for (chan_id, req) in peer_state.inbound_channel_request_by_id.iter_mut() { | |||
if { req.ticks_remaining -= 1 ; req.ticks_remaining } <= 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.
You can do this updating in the retain
body.
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.
Ope, hmm... after addressing the issue below I think that it might make more sense to have a separate loop. In particular, the retain
lambda gets sad about the use of peer_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.
Ah, you can make it less sad by explicitly taking reference to the inner variables separately as individual variables before the retain, but its not all that critical.
74e3c4a
to
d53b2ff
Compare
Create a new table in 'peer_state' to maintain unaccepted inbound channels; i.e., a channel for which we've received an 'open_channel' message but that user code has not yet confirmed for acceptance. When user code accepts the channel (e.g. via 'accept_inbound_channel'), create the channel object and as before. Currently, the 'open_channel' message eagerly creates an InboundV1Channel object before determining if the channel should be accepted. Because this happens /before/ the channel has been assigned a user identity (which happens in the handler for OpenChannelRequest), the channel is assigned a random user identity. As part of the creation process, the channel's cryptographic material is initialized, which then uses this randomly generated value for the user's channel identity e.g. in SignerProvider::generate_channel_keys_id. By delaying the creation of the InboundV1Channel until /after/ the channel has been accepted, we ensure that we defer cryptographic initialization until we have given the user the opportunity to assign an identity to the channel.
d53b2ff
to
0184727
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.
Thanks! Small nit.
events::MessageSendEvent::HandleError { | ||
node_id: counterparty_node_id, | ||
action: msgs::ErrorAction::SendErrorMessage { | ||
msg: msgs::ErrorMessage { channel_id: chan_id.clone(), data: "Channel force-closed".to_owned() } |
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 need a clearer description in the message here. I know we might not know the real reason for not letting the request time out, but maybe we could just say:
"Channel force-closed due to acceptance timeout"
or something better. What do you think?
P.S. I've added the missing MessageSendEvent
in #2496, which we I will rebase on main
when this PR lands.
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 no conflict between the PRs, so landed that one.
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, right lol
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, thanks!
@@ -6032,7 +6017,7 @@ impl<Signer: WriteableEcdsaChannelSigner> InboundV1Channel<Signer> { | |||
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP, | |||
counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures, | |||
their_features: &InitFeatures, msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig, | |||
current_chain_height: u32, logger: &L, outbound_scid_alias: u64 | |||
current_chain_height: u32, logger: &L, outbound_scid_alias: u64, is_0conf: bool, |
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.
oubtound_scid_alias
is now unused (always zero), so we should drop the argument here.
/// the peer is the counterparty. If the channel is accepted, then the entry in this table is | ||
/// removed, and an InboundV1Channel is created and placed in the `inbound_v1_channel_by_id` table. If | ||
/// the channel is rejected, then the entry is simply removed. | ||
pub(super) inbound_channel_request_by_id: HashMap<[u8; 32], InboundChannelRequest>, |
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 we also need to wipe this on peer disconnection and when handling errors from peers, I'll do that in a quick followup.
Create a new table in 'peer_state' to maintain unaccepted inbound channels; i.e., a channel for which we've received an 'open_channel' message but that user code has not yet confirmed for acceptance. When user code accepts the channel (e.g. via 'accept_inbound_channel'), create the channel object and as before.
Currently, the 'open_channel' message eagerly creates an InboundV1Channel object before determining if the channel should be accepted. Because this happens /before/ the channel has been assigned a user identity (which happens in the handler for OpenChannelRequest), the channel is assigned a random user identity. As part of the creation process, the channel's cryptographic material is initialized, which then uses this randomly generated value for the user's channel identity e.g. in SignerProvider::generate_channel_keys_id.
By delaying the creation of the InboundV1Channel until /after/ the channel has been accepted, we ensure that we defer cryptographic initialization until we have given the user the opportunity to assign an identity to the channel.