-
Notifications
You must be signed in to change notification settings - Fork 421
Implement option_upfront_shutdown_script on both sides #348
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
Implement option_upfront_shutdown_script on both sides #348
Conversation
This could probably use some tests, no? |
Technically, I think you can drop the entire "Provide peer local_features to handle_open_channel/accept_channel" commit - the way I read the spec, if the peer sends an upfront_shutdown_script but didn't bother signaling for it, we should still honor and enforce it. Further, we should be allowed to send our own upfront_shutdown_script whether they signal for it or not - they should ignore any unknown parts at the end of a message. |
Yes, was waiting for your interpretation of the spec before to write tests, specially on the question of peer need to opt-in for it, the way I read the spec is the reverse "if both nodes advertised the option_upfront_shutdown_script feature" seems to mean both peers need to signal for it. |
For sending our own upfront_shutdown_script, I think I've implemented with simple opt-in of user (via config), as spec always let us "MAY include ashutdown_scriptpubkey." |
No, the section you're quoting only talks about when to include the serialized script (or a zero-length one to opt-out if we signal). This implies that we should just always signal, but send either a zero-length script or one specified by the user, but never None. The shutdown discussion talks only about whether a non-zero-length shutdown script was sent, not whether the flag was set. |
From the shutdown discussion : "if both nodes advertised the option_upfront_shutdown_script feature, and the receiving node received a non-zero-length shutdown_scriptpubkey in open_channel or accept_channel, and that shutdown_scriptpubkey is not equal to scriptpubkey:
You're right on user-side we should send zero-length script to opt-out not None if we signal. |
Ah, you're right, I missed the difference between the sending side of shutdown and the receiving side of shutdown, alright, looks good. |
Cool will join tests now we agree on interpretation :) |
Test on 8b245b2. Larger diff is about modification of test utilities to pass LocalFeatures and UserConfig, it should become more used with the bunch of 1.1 features being flag-gated. |
src/ln/channelmanager.rs
Outdated
} | ||
|
||
fn internal_open_channel(&self, their_node_id: &PublicKey, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> { | ||
fn internal_open_channel(&self, their_node_id: &PublicKey, their_local_features: &Option<LocalFeatures>, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> { |
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.
Hmm, why Optional? Protocol should enforce that its always set, no?
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.
Yes, after verification it's always set, corrected
src/ln/channel.rs
Outdated
if features.supports_upfront_shutdown_script() { | ||
match &msg.shutdown_scriptpubkey { | ||
&OptionalField::Present(ref script) => { | ||
if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wsh() || script.is_v0_p2wpkh() { |
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.
Hmm, shouldn't we reject channels with a shutdown script set to something other than these (or 0-length)?
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.
Reworked to reject channels with a shutdown script different from accepted formats if peer is signaling option. BOLT2 : "if the scriptpubkey is not in one of the above forms:
SHOULD fail the connection.
"
src/ln/peer_handler.rs
Outdated
if self.initial_syncs_sent.load(Ordering::Acquire) < INITIAL_SYNCS_TO_SEND { | ||
self.initial_syncs_sent.fetch_add(1, Ordering::AcqRel); | ||
local_features.set_initial_routing_sync(); | ||
local_features.set_upfront_shutdown_script(); |
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.
Huh? We should set this on all peers, not just the first 5.
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.
Also, technically this hunk should go in a later commit, when we set ourselves to always send (at least) a 0-length script.
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 add a test that connects a bunch of peers, too, while you're at 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.
Oh yes confused myself on this one! Move to right commit
channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint); | ||
channel_monitor.set_their_to_self_delay(msg.to_self_delay); | ||
|
||
let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() { |
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.
Shouldn't we use the shutdown_scriptpubkey if it is Present (ad not-0-length) even if they have't set their local features? We just reject the message if they did set local features (and we did too) and they didnt send a shutdown_scriptpubkey?
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.
On first point, spec said "otherwise:
MAY include ashutdown_scriptpubkey."
But that's a option offered for sending node, not a requirement for the receiving node to enforce upfront_shutdown it sending doesn't signal?
Second point, well I think 0-length is the correct opt-out mechanism, which is exactly to avoid ambiguity. IMO, a node signaling upfront_shutdown should opt-out or we may assume it's a buggy 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.
Oops, you're right, sorry, still reading the wrong side of the spec.
Peer may send us a shutdown_scriptpubkey in open_channel or accept_channel messages. Before to enforce this policy on channel closing, we want to be sure that our peer has opt-in to it. Extend LocalFeatures new method visibilty from crate to public for fuzz tests
src/ln/channel.rs
Outdated
match &msg.shutdown_scriptpubkey { | ||
&OptionalField::Present(ref script) => { | ||
// Peer is signaling upfront_shutdown and has provided a non-accepted scriptpubkey format. We enforce it while receiving shutdown msg | ||
if script.is_p2pkh() || script.is_p2sh() || script.is_v0_p2wsh() || script.is_v0_p2wpkh() || script.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.
the script.len()== 0 check at the end breaks the next if.
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.
Are you on the latest tip ? I've pushed a version with this bug but it was corrected at least on b603d94
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 its still there on the latest?
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.
Sorry, I've forgot to correct on both open_channel/accept_channel case, extend test_option_upfront_shutdown_script to cover it
} | ||
|
||
pub fn create_network(node_count: usize) -> Vec<Node> { | ||
pub fn create_network(node_count: usize, node_config: &[Option<UserConfig>]) -> Vec<Node> { |
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: If we're just gonna call UserConfig::new() here, why not just do that everywhere instead of None, None? Its not much different and keeps things obvious.
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 but if we pass a new UserConfig, then we set default flags in create_network but for some specific tests I want to deactivate them ?
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.
Ehh, I meant just drop the 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.
Wait if I pass create_network(2, UserConfig::new(), UserConfig::new()) create_network is going to set default flags, a behavior I wish to opt-out?
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 provide custom ones instead where needed?
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 can, but if create_network override them with the default ones, how I signal to do it with a per-node granularity ?
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.
Keep the array? Anyway, not worth fixing if its just this left to fix.
Track shutdown_pubkey of peer at open/accept_channel messages Fix encoding_init test
We use user config to decide to commit to closing script in open_channel/accept_channel messages. We don't check that other peer supporting the option as including script without other peer public support is borne by the protocol. If user opt-out, following protocol and due to the fact we always signal, we provide a zero-length script
We may want more granularity on the set of features activated at a given time, specially with new 1.1 spec features
We way want more granularity on the set of user opt-in features at a given time, specially with new 1.1 spec features
We take care of not enforcing the option if remote peer send us an open_channel/accept_channel messages including an shutdown_scriptpubkey but without asking for in feature flags.
On the user-side, we rely on the config to decide to commit.
Close #239