Skip to content

Commit 83f3245

Browse files
committed
f - Check KeysInterface::get_shutdown_scriptpubkey
Check that the user-provided shutdown_scriptpubkey is compatible with the counterparty's features (option_shutdown_anysegwit). TODO: Implement for ChannelManager::close_channel TODO: Add unit tests
1 parent 541193e commit 83f3245

File tree

3 files changed

+52
-27
lines changed

3 files changed

+52
-27
lines changed

lightning/src/ln/channel.rs

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ impl<Signer: Sign> Channel<Signer> {
567567
}
568568

569569
// Constructors:
570-
pub fn new_outbound<K: Deref, F: Deref>(fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig) -> Result<Channel<Signer>, APIError>
570+
pub fn new_outbound<K: Deref, F: Deref>(fee_estimator: &F, keys_provider: &K, counterparty_node_id: PublicKey, their_features: InitFeatures, channel_value_satoshis: u64, push_msat: u64, user_id: u64, config: &UserConfig) -> Result<Channel<Signer>, APIError>
571571
where K::Target: KeysInterface<Signer = Signer>,
572572
F::Target: FeeEstimator,
573573
{
@@ -597,9 +597,13 @@ impl<Signer: Sign> Channel<Signer> {
597597

598598
let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
599599
Some(keys_provider.get_shutdown_scriptpubkey())
600-
} else {
601-
None
602-
};
600+
} else { None };
601+
602+
if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey {
603+
if !shutdown_scriptpubkey.is_compatible(&their_features) {
604+
return Err(APIError::APIMisuseError { err: format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex()) });
605+
}
606+
}
603607

604608
Ok(Channel {
605609
user_id,
@@ -843,14 +847,18 @@ impl<Signer: Sign> Channel<Signer> {
843847
}
844848
} else { None };
845849

846-
let mut secp_ctx = Secp256k1::new();
847-
secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
848-
849850
let shutdown_scriptpubkey = if config.channel_options.commit_upfront_shutdown_pubkey {
850851
Some(keys_provider.get_shutdown_scriptpubkey())
851-
} else {
852-
None
853-
};
852+
} else { None };
853+
854+
if let Some(shutdown_scriptpubkey) = &shutdown_scriptpubkey {
855+
if !shutdown_scriptpubkey.is_compatible(&their_features) {
856+
return Err(ChannelError::Close(format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex())));
857+
}
858+
}
859+
860+
let mut secp_ctx = Secp256k1::new();
861+
secp_ctx.seeded_randomize(&keys_provider.get_secure_random_bytes());
854862

855863
let chan = Channel {
856864
user_id,
@@ -3262,6 +3270,23 @@ impl<Signer: Sign> Channel<Signer> {
32623270
self.counterparty_shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
32633271
}
32643272

3273+
// If we have any LocalAnnounced updates we'll probably just get back a update_fail_htlc
3274+
// immediately after the commitment dance, but we can send a Shutdown cause we won't send
3275+
// any further commitment updates after we set LocalShutdownSent.
3276+
let send_shutdown = (self.channel_state & ChannelState::LocalShutdownSent as u32) != ChannelState::LocalShutdownSent as u32;
3277+
3278+
let shutdown_scriptpubkey = match self.shutdown_scriptpubkey {
3279+
Some(_) => None,
3280+
None => {
3281+
assert!(send_shutdown);
3282+
let shutdown_scriptpubkey = keys_provider.get_shutdown_scriptpubkey();
3283+
if !shutdown_scriptpubkey.is_compatible(their_features) {
3284+
return Err(ChannelError::Close(format!("Provided a scriptpubkey format not accepted by peer. script: ({})", shutdown_scriptpubkey.clone().into_inner().to_bytes().to_hex())));
3285+
}
3286+
Some(shutdown_scriptpubkey)
3287+
},
3288+
};
3289+
32653290
// From here on out, we may not fail!
32663291

32673292
self.channel_state |= ChannelState::RemoteShutdownSent as u32;
@@ -3282,15 +3307,9 @@ impl<Signer: Sign> Channel<Signer> {
32823307
}
32833308
});
32843309

3285-
// If we have any LocalAnnounced updates we'll probably just get back a update_fail_htlc
3286-
// immediately after the commitment dance, but we can send a Shutdown cause we won't send
3287-
// any further commitment updates after we set LocalShutdownSent.
3288-
let send_shutdown = (self.channel_state & ChannelState::LocalShutdownSent as u32) != ChannelState::LocalShutdownSent as u32;
3289-
let monitor_update = match self.shutdown_scriptpubkey {
3290-
Some(_) => None,
3291-
None => {
3292-
assert!(send_shutdown);
3293-
self.shutdown_scriptpubkey = Some(keys_provider.get_shutdown_scriptpubkey());
3310+
let monitor_update = match shutdown_scriptpubkey {
3311+
Some(shutdown_scriptpubkey) => {
3312+
self.shutdown_scriptpubkey = Some(shutdown_scriptpubkey);
32943313
self.latest_monitor_update_id += 1;
32953314
Some(ChannelMonitorUpdate {
32963315
update_id: self.latest_monitor_update_id,
@@ -3299,6 +3318,7 @@ impl<Signer: Sign> Channel<Signer> {
32993318
}],
33003319
})
33013320
},
3321+
None => None,
33023322
};
33033323
let shutdown = if send_shutdown {
33043324
Some(msgs::Shutdown {
@@ -5212,7 +5232,7 @@ mod tests {
52125232

52135233
let node_a_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
52145234
let config = UserConfig::default();
5215-
let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, 10000000, 100000, 42, &config).unwrap();
5235+
let node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_a_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
52165236

52175237
// Now change the fee so we can check that the fee in the open_channel message is the
52185238
// same as the old fee.
@@ -5237,7 +5257,7 @@ mod tests {
52375257
// Create Node A's channel pointing to Node B's pubkey
52385258
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
52395259
let config = UserConfig::default();
5240-
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, 10000000, 100000, 42, &config).unwrap();
5260+
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
52415261

52425262
// Create Node B's channel by receiving Node A's open_channel message
52435263
// Make sure A's dust limit is as we expect.
@@ -5304,7 +5324,7 @@ mod tests {
53045324

53055325
let node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
53065326
let config = UserConfig::default();
5307-
let mut chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_id, 10000000, 100000, 42, &config).unwrap();
5327+
let mut chan = Channel::<EnforcingSigner>::new_outbound(&&fee_est, &&keys_provider, node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
53085328

53095329
let commitment_tx_fee_0_htlcs = chan.commit_tx_fee_msat(0);
53105330
let commitment_tx_fee_1_htlc = chan.commit_tx_fee_msat(1);
@@ -5353,7 +5373,7 @@ mod tests {
53535373
// Create Node A's channel pointing to Node B's pubkey
53545374
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
53555375
let config = UserConfig::default();
5356-
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, 10000000, 100000, 42, &config).unwrap();
5376+
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
53575377

53585378
// Create Node B's channel by receiving Node A's open_channel message
53595379
let open_channel_msg = node_a_chan.get_open_channel(chain_hash);
@@ -5415,7 +5435,7 @@ mod tests {
54155435
// Create a channel.
54165436
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
54175437
let config = UserConfig::default();
5418-
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, 10000000, 100000, 42, &config).unwrap();
5438+
let mut node_a_chan = Channel::<EnforcingSigner>::new_outbound(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), 10000000, 100000, 42, &config).unwrap();
54195439
assert!(node_a_chan.counterparty_forwarding_info.is_none());
54205440
assert_eq!(node_a_chan.holder_htlc_minimum_msat, 1); // the default
54215441
assert!(node_a_chan.counterparty_forwarding_info().is_none());
@@ -5479,7 +5499,7 @@ mod tests {
54795499
let counterparty_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
54805500
let mut config = UserConfig::default();
54815501
config.channel_options.announced_channel = false;
5482-
let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, 10_000_000, 100000, 42, &config).unwrap(); // Nothing uses their network key in this test
5502+
let mut chan = Channel::<InMemorySigner>::new_outbound(&&feeest, &&keys_provider, counterparty_node_id, InitFeatures::known(), 10_000_000, 100000, 42, &config).unwrap(); // Nothing uses their network key in this test
54835503
chan.holder_dust_limit_satoshis = 546;
54845504
chan.counterparty_selected_channel_reserve_satoshis = Some(0); // Filled in in accept_channel
54855505

lightning/src/ln/channelmanager.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1156,8 +1156,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
11561156
return Err(APIError::APIMisuseError { err: format!("Channel value must be at least 1000 satoshis. It was {}", channel_value_satoshis) });
11571157
}
11581158

1159+
let their_features = {
1160+
let per_peer_state = self.per_peer_state.read().unwrap();
1161+
let peer_state = per_peer_state.get(&their_network_key).unwrap().lock().unwrap();
1162+
peer_state.latest_features.clone()
1163+
};
11591164
let config = if override_config.is_some() { override_config.as_ref().unwrap() } else { &self.default_configuration };
1160-
let channel = Channel::new_outbound(&self.fee_estimator, &self.keys_manager, their_network_key, channel_value_satoshis, push_msat, user_id, config)?;
1165+
let channel = Channel::new_outbound(&self.fee_estimator, &self.keys_manager, their_network_key, their_features, channel_value_satoshis, push_msat, user_id, config)?;
11611166
let res = channel.get_open_channel(self.genesis_hash.clone());
11621167

11631168
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7748,7 +7748,7 @@ fn test_user_configurable_csv_delay() {
77487748
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
77497749

77507750
// We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound()
7751-
if let Err(error) = Channel::new_outbound(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), 1000000, 1000000, 0, &low_our_to_self_config) {
7751+
if let Err(error) = Channel::new_outbound(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), InitFeatures::known(), 1000000, 1000000, 0, &low_our_to_self_config) {
77527752
match error {
77537753
APIError::APIMisuseError { err } => { assert!(regex::Regex::new(r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks").unwrap().is_match(err.as_str())); },
77547754
_ => panic!("Unexpected event"),

0 commit comments

Comments
 (0)