-
Notifications
You must be signed in to change notification settings - Fork 415
Make channel_type required #3896
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3838,18 +3838,10 @@ where | |
return Err(ChannelError::close("Got an accept_channel message at a strange time".to_owned())); | ||
} | ||
|
||
if let Some(ty) = &common_fields.channel_type { | ||
if ty != funding.get_channel_type() { | ||
return Err(ChannelError::close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned())); | ||
} | ||
} else if their_features.supports_channel_type() { | ||
// Assume they've accepted the channel type as they said they understand it. | ||
} else { | ||
let channel_type = ChannelTypeFeatures::from_init(&their_features); | ||
if channel_type != ChannelTypeFeatures::only_static_remote_key() { | ||
return Err(ChannelError::close("Only static_remote_key is supported for non-negotiated channel types".to_owned())); | ||
} | ||
funding.channel_transaction_parameters.channel_type_features = channel_type; | ||
let channel_type = common_fields.channel_type.as_ref() | ||
.ok_or_else(|| ChannelError::close("option_channel_type assumed to be supported".to_owned()))?; | ||
if channel_type != funding.get_channel_type() { | ||
return Err(ChannelError::close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned())); | ||
} | ||
|
||
if common_fields.dust_limit_satoshis > 21000000 * 100000000 { | ||
|
@@ -11542,37 +11534,31 @@ where | |
/// [`msgs::CommonOpenChannelFields`]. | ||
#[rustfmt::skip] | ||
pub(super) fn channel_type_from_open_channel( | ||
common_fields: &msgs::CommonOpenChannelFields, their_features: &InitFeatures, | ||
our_supported_features: &ChannelTypeFeatures | ||
common_fields: &msgs::CommonOpenChannelFields, our_supported_features: &ChannelTypeFeatures | ||
) -> Result<ChannelTypeFeatures, ChannelError> { | ||
if let Some(channel_type) = &common_fields.channel_type { | ||
if channel_type.supports_any_optional_bits() { | ||
return Err(ChannelError::close("Channel Type field contained optional bits - this is not allowed".to_owned())); | ||
} | ||
let channel_type = common_fields.channel_type.as_ref() | ||
.ok_or_else(|| ChannelError::close("option_channel_type assumed to be supported".to_owned()))?; | ||
|
||
// We only support the channel types defined by the `ChannelManager` in | ||
// `provided_channel_type_features`. The channel type must always support | ||
// `static_remote_key`, either implicitly with `option_zero_fee_commitments` | ||
// or explicitly. | ||
if !channel_type.requires_static_remote_key() && !channel_type.requires_anchor_zero_fee_commitments() { | ||
return Err(ChannelError::close("Channel Type was not understood - we require static remote key".to_owned())); | ||
} | ||
// Make sure we support all of the features behind the channel type. | ||
if channel_type.requires_unknown_bits_from(&our_supported_features) { | ||
return Err(ChannelError::close("Channel Type contains unsupported features".to_owned())); | ||
} | ||
let announce_for_forwarding = if (common_fields.channel_flags & 1) == 1 { true } else { false }; | ||
if channel_type.requires_scid_privacy() && announce_for_forwarding { | ||
return Err(ChannelError::close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned())); | ||
} | ||
Ok(channel_type.clone()) | ||
} else { | ||
let channel_type = ChannelTypeFeatures::from_init(&their_features); | ||
if channel_type != ChannelTypeFeatures::only_static_remote_key() { | ||
return Err(ChannelError::close("Only static_remote_key is supported for non-negotiated channel types".to_owned())); | ||
} | ||
Ok(channel_type) | ||
if channel_type.supports_any_optional_bits() { | ||
return Err(ChannelError::close("Channel Type field contained optional bits - this is not allowed".to_owned())); | ||
} | ||
|
||
// We only support the channel types defined by the `ChannelManager` in | ||
// `provided_channel_type_features`. The channel type must always support | ||
// `static_remote_key`, either implicitly with `option_zero_fee_commitments` | ||
// or explicitly. | ||
if !channel_type.requires_static_remote_key() && !channel_type.requires_anchor_zero_fee_commitments() { | ||
return Err(ChannelError::close("Channel Type was not understood - we require static remote key".to_owned())); | ||
} | ||
// Make sure we support all of the features behind the channel type. | ||
if channel_type.requires_unknown_bits_from(&our_supported_features) { | ||
return Err(ChannelError::close("Channel Type contains unsupported features".to_owned())); | ||
} | ||
let announce_for_forwarding = if (common_fields.channel_flags & 1) == 1 { true } else { false }; | ||
if channel_type.requires_scid_privacy() && announce_for_forwarding { | ||
return Err(ChannelError::close("SCID Alias/Privacy Channel Type cannot be set on a public channel".to_owned())); | ||
} | ||
Ok(channel_type.clone()) | ||
} | ||
|
||
impl<SP: Deref> InboundV1Channel<SP> | ||
|
@@ -11596,7 +11582,7 @@ where | |
|
||
// First check the channel type is known, failing before we do anything else if we don't | ||
// support this channel type. | ||
let channel_type = channel_type_from_open_channel(&msg.common_fields, their_features, our_supported_features)?; | ||
let channel_type = channel_type_from_open_channel(&msg.common_fields, our_supported_features)?; | ||
|
||
let holder_selected_channel_reserve_satoshis = get_holder_selected_channel_reserve_satoshis(msg.common_fields.funding_satoshis, config); | ||
let counterparty_pubkeys = ChannelPublicKeys { | ||
|
@@ -11993,13 +11979,7 @@ where | |
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis( | ||
channel_value_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS); | ||
|
||
// First check the channel type is known, failing before we do anything else if we don't | ||
// support this channel type. | ||
if msg.common_fields.channel_type.is_none() { | ||
return Err(ChannelError::close(format!("Rejecting V2 channel {} missing channel_type", | ||
msg.common_fields.temporary_channel_id))) | ||
} | ||
let channel_type = channel_type_from_open_channel(&msg.common_fields, their_features, our_supported_features)?; | ||
let channel_type = channel_type_from_open_channel(&msg.common_fields, our_supported_features)?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Directly above there is already a check for non channel type. Is that redundant now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, yeah seems that can be removed, thanks |
||
|
||
let counterparty_pubkeys = ChannelPublicKeys { | ||
funding_pubkey: msg.common_fields.funding_pubkey, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -295,9 +295,9 @@ fn do_test_supports_channel_type(config: UserConfig, expected_channel_type: Chan | |
} | ||
|
||
#[test] | ||
fn test_rejects_implicit_simple_anchors() { | ||
// Tests that if `option_anchors` is being negotiated implicitly through the intersection of | ||
// each side's `InitFeatures`, it is rejected. | ||
fn test_rejects_if_channel_type_not_set() { | ||
// Tests that if `channel_type` is not set in `open_channel` and `accept_channel`, it is | ||
// rejected. | ||
let secp_ctx = Secp256k1::new(); | ||
let test_est = TestFeeEstimator::new(15000); | ||
let fee_estimator = LowerBoundedFeeEstimator::new(&test_est); | ||
|
@@ -312,13 +312,6 @@ fn test_rejects_implicit_simple_anchors() { | |
|
||
let config = UserConfig::default(); | ||
|
||
// See feature bit assignments: https://github.com/lightning/bolts/blob/master/09-features.md | ||
let static_remote_key_required: u64 = 1 << 12; | ||
let simple_anchors_required: u64 = 1 << 20; | ||
let raw_init_features = static_remote_key_required | simple_anchors_required; | ||
let init_features_with_simple_anchors = | ||
InitFeatures::from_le_bytes(raw_init_features.to_le_bytes().to_vec()); | ||
|
||
let mut channel_a = OutboundV1Channel::<&TestKeysInterface>::new( | ||
&fee_estimator, | ||
&&keys_provider, | ||
|
@@ -336,20 +329,18 @@ fn test_rejects_implicit_simple_anchors() { | |
) | ||
.unwrap(); | ||
|
||
// Set `channel_type` to `None` to force the implicit feature negotiation. | ||
// Set `channel_type` to `None` to cause failure. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this coverage be kept? // Since A supports both `static_remote_key` and `option_anchors`, but B only accepts
// `static_remote_key`, it will fail the channel. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought no since the code doing that implicit negotiation will be removed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree this can be removed - we have |
||
let mut open_channel_msg = | ||
channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); | ||
open_channel_msg.common_fields.channel_type = None; | ||
|
||
// Since A supports both `static_remote_key` and `option_anchors`, but B only accepts | ||
// `static_remote_key`, it will fail the channel. | ||
let channel_b = InboundV1Channel::<&TestKeysInterface>::new( | ||
&fee_estimator, | ||
&&keys_provider, | ||
&&keys_provider, | ||
node_id_a, | ||
&channelmanager::provided_channel_type_features(&config), | ||
&init_features_with_simple_anchors, | ||
&channelmanager::provided_init_features(&config), | ||
&open_channel_msg, | ||
7, | ||
&config, | ||
|
@@ -358,6 +349,104 @@ fn test_rejects_implicit_simple_anchors() { | |
/*is_0conf=*/ false, | ||
); | ||
assert!(channel_b.is_err()); | ||
|
||
open_channel_msg.common_fields.channel_type = | ||
Some(channel_a.funding.get_channel_type().clone()); | ||
let mut channel_b = InboundV1Channel::<&TestKeysInterface>::new( | ||
&fee_estimator, | ||
&&keys_provider, | ||
&&keys_provider, | ||
node_id_a, | ||
&channelmanager::provided_channel_type_features(&config), | ||
&channelmanager::provided_init_features(&config), | ||
&open_channel_msg, | ||
7, | ||
&config, | ||
0, | ||
&&logger, | ||
/*is_0conf=*/ false, | ||
) | ||
.unwrap(); | ||
|
||
// Set `channel_type` to `None` in `accept_channel` to cause failure. | ||
let mut accept_channel_msg = channel_b.get_accept_channel_message(&&logger).unwrap(); | ||
accept_channel_msg.common_fields.channel_type = None; | ||
|
||
let res = channel_a.accept_channel( | ||
&accept_channel_msg, | ||
&config.channel_handshake_limits, | ||
&channelmanager::provided_init_features(&config), | ||
); | ||
assert!(res.is_err()); | ||
} | ||
|
||
#[test] | ||
fn test_rejects_if_channel_type_differ() { | ||
// Tests that if the `channel_type` in `accept_channel` does not match the one set in | ||
// `open_channel` it rejects the channel. | ||
let secp_ctx = Secp256k1::new(); | ||
let test_est = TestFeeEstimator::new(15000); | ||
let fee_estimator = LowerBoundedFeeEstimator::new(&test_est); | ||
let network = Network::Testnet; | ||
let keys_provider = TestKeysInterface::new(&[42; 32], network); | ||
let logger = TestLogger::new(); | ||
|
||
let node_id_a = | ||
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap()); | ||
let node_id_b = | ||
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap()); | ||
|
||
let config = UserConfig::default(); | ||
|
||
let mut channel_a = OutboundV1Channel::<&TestKeysInterface>::new( | ||
&fee_estimator, | ||
&&keys_provider, | ||
&&keys_provider, | ||
node_id_b, | ||
&channelmanager::provided_init_features(&config), | ||
10000000, | ||
100000, | ||
42, | ||
&config, | ||
0, | ||
42, | ||
None, | ||
&logger, | ||
) | ||
.unwrap(); | ||
|
||
let open_channel_msg = | ||
channel_a.get_open_channel(ChainHash::using_genesis_block(network), &&logger).unwrap(); | ||
|
||
let mut channel_b = InboundV1Channel::<&TestKeysInterface>::new( | ||
&fee_estimator, | ||
&&keys_provider, | ||
&&keys_provider, | ||
node_id_a, | ||
&channelmanager::provided_channel_type_features(&config), | ||
&channelmanager::provided_init_features(&config), | ||
&open_channel_msg, | ||
7, | ||
&config, | ||
0, | ||
&&logger, | ||
/*is_0conf=*/ false, | ||
) | ||
.unwrap(); | ||
|
||
// Change the `channel_type` in `accept_channel` msg to make it different from the one set in | ||
// `open_channel` to cause failure. | ||
let mut accept_channel_msg = channel_b.get_accept_channel_message(&&logger).unwrap(); | ||
let mut channel_type = channelmanager::provided_channel_type_features(&config); | ||
channel_type.set_zero_conf_required(); | ||
accept_channel_msg.common_fields.channel_type = Some(channel_type.clone()); | ||
|
||
let res = channel_a.accept_channel( | ||
&accept_channel_msg, | ||
&config.channel_handshake_limits, | ||
&channelmanager::provided_init_features(&config), | ||
); | ||
assert!(res.is_err()); | ||
} | ||
|
||
#[test] | ||
|
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 of these comments need an update?