bob_config.peer_channel_config_limits.force_announced_channel_preference = false;
bob_config.own_channel_config.our_to_self_delay = 6 * 24 * 3;
let user_cfgs = [Some(alice_config), Some(bob_config)];
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
+ chanmon_cfgs[1].keys_manager.disable_revocation_policy_check = true;
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &user_cfgs);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
#[test]
fn claim_htlc_outputs_shared_tx() {
// Node revoked old state, htlcs haven't time out yet, claim them in shared justice tx
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
#[test]
fn claim_htlc_outputs_single_tx() {
// Node revoked old state, htlcs have timed out, claim each of them in separated justice tx
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
route_payment(&nodes[0], &[&nodes[1]], 10000000);
- nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id);
+ nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id).unwrap();
check_closed_broadcast!(nodes[0], false);
check_added_monitors!(nodes[0], 1);
// state or updated nodes[1]' state. Now force-close and broadcast that commitment/HTLC
// transaction and ensure nodes[1] doesn't fail-backwards (this was originally a bug!).
- nodes[2].node.force_close_channel(&payment_event.commitment_msg.channel_id);
+ nodes[2].node.force_close_channel(&payment_event.commitment_msg.channel_id).unwrap();
check_closed_broadcast!(nodes[2], false);
check_added_monitors!(nodes[2], 1);
let tx = {
Event::SpendableOutputs { ref outputs } => {
for outp in outputs {
match *outp {
- SpendableOutputDescriptor::StaticOutputCounterpartyPayment { ref outpoint, ref output, ref key_derivation_params } => {
+ SpendableOutputDescriptor::StaticOutputCounterpartyPayment { ref outpoint, ref output, ref channel_keys_id } => {
let input = TxIn {
previous_output: outpoint.into_bitcoin_outpoint(),
script_sig: Script::new(),
};
spend_tx.output[0].value -= (spend_tx.get_weight() + 2 + 1 + 73 + 35 + 3) as u64 / 4; // (Max weight + 3 (to round up)) / 4
let secp_ctx = Secp256k1::new();
- let keys = $keysinterface.derive_channel_keys($chan_value, key_derivation_params.0, key_derivation_params.1);
+ let keys = $keysinterface.derive_channel_keys($chan_value, channel_keys_id);
let remotepubkey = keys.pubkeys().payment_point;
let witness_script = Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: remotepubkey}, Network::Testnet).script_pubkey();
let sighash = Message::from_slice(&bip143::SigHashCache::new(&spend_tx).signature_hash(0, &witness_script, output.value, SigHashType::All)[..]).unwrap();
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec());
txn.push(spend_tx);
},
- SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref per_commitment_point, ref to_self_delay, ref output, ref key_derivation_params, ref revocation_pubkey } => {
+ SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref per_commitment_point, ref to_self_delay, ref output, ref channel_keys_id, ref revocation_pubkey } => {
let input = TxIn {
previous_output: outpoint.into_bitcoin_outpoint(),
script_sig: Script::new(),
output: vec![outp],
};
let secp_ctx = Secp256k1::new();
- let keys = $keysinterface.derive_channel_keys($chan_value, key_derivation_params.0, key_derivation_params.1);
+ let keys = $keysinterface.derive_channel_keys($chan_value, channel_keys_id);
if let Ok(delayed_payment_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &keys.inner.delayed_payment_base_key) {
let delayed_payment_pubkey = PublicKey::from_secret_key(&secp_ctx, &delayed_payment_key);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000, InitFeatures::known(), InitFeatures::known());
- nodes[1].node.force_close_channel(&chan.2);
+ nodes[1].node.force_close_channel(&chan.2).unwrap();
check_closed_broadcast!(nodes[1], false);
check_added_monitors!(nodes[1], 1);
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 99000000, InitFeatures::known(), InitFeatures::known());
- nodes[0].node.force_close_channel(&chan.2);
+ nodes[0].node.force_close_channel(&chan.2).unwrap();
check_closed_broadcast!(nodes[0], false);
check_added_monitors!(nodes[0], 1);
#[test]
fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
#[test]
fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ chanmon_cfgs[1].keys_manager.disable_revocation_policy_check = true;
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// We can have at most two valid local commitment tx, so both cases must be covered, and both txs must be checked to get them all as
// HTLC could have been removed from lastest local commitment tx but still valid until we get remote RAA
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let fee_estimator;
let tx_broadcaster;
let chain_source;
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ // We broadcast during Drop because chanmon is out of sync with chanmgr, which would cause a panic
+ // during signing due to revoked tx
+ chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
let keys_manager = &chanmon_cfgs[0].keys_manager;
let monitor;
let node_state_0;
// In case of penalty txn with too low feerates for getting into mempools, RBF-bump them to sure
// we're able to claim outputs on revoked HTLC transactions before timelocks expiration
- let chanmon_cfgs = create_chanmon_cfgs(2);
+ let mut chanmon_cfgs = create_chanmon_cfgs(2);
+ chanmon_cfgs[1].keys_manager.disable_revocation_policy_check = true;
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
// responds by (1) broadcasting a channel update and (2) adding a new ChannelMonitor.
let mut force_closing_node = 0; // Alice force-closes
if !broadcast_alice { force_closing_node = 1; } // Bob force-closes
- nodes[force_closing_node].node.force_close_channel(&chan_ab.2);
+ nodes[force_closing_node].node.force_close_channel(&chan_ab.2).unwrap();
check_closed_broadcast!(nodes[force_closing_node], false);
check_added_monitors!(nodes[force_closing_node], 1);
if go_onchain_before_fulfill {
update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update);
send_payment(&nodes[0], &[&nodes[1]], 8000000, 8_000_000);
}
+
+#[test]
+fn test_error_chans_closed() {
+ // Test that we properly handle error messages, closing appropriate channels.
+ //
+ // Prior to #787 we'd allow a peer to make us force-close a channel we had with a different
+ // peer. The "real" fix for that is to index channels with peers_ids, however in the mean time
+ // we can test various edge cases around it to ensure we don't regress.
+ let chanmon_cfgs = create_chanmon_cfgs(3);
+ let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+ let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+ // Create some initial channels
+ let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ let chan_3 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+
+ assert_eq!(nodes[0].node.list_usable_channels().len(), 3);
+ assert_eq!(nodes[1].node.list_usable_channels().len(), 2);
+ assert_eq!(nodes[2].node.list_usable_channels().len(), 1);
+
+ // Closing a channel from a different peer has no effect
+ nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id: chan_3.2, data: "ERR".to_owned() });
+ assert_eq!(nodes[0].node.list_usable_channels().len(), 3);
+
+ // Closing one channel doesn't impact others
+ nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id: chan_2.2, data: "ERR".to_owned() });
+ check_added_monitors!(nodes[0], 1);
+ check_closed_broadcast!(nodes[0], false);
+ assert_eq!(nodes[0].node.list_usable_channels().len(), 2);
+ assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_1.2 || nodes[0].node.list_usable_channels()[1].channel_id == chan_1.2);
+ assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2 || nodes[0].node.list_usable_channels()[1].channel_id == chan_3.2);
+
+ // A null channel ID should close all channels
+ let _chan_4 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+ nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &msgs::ErrorMessage { channel_id: [0; 32], data: "ERR".to_owned() });
+ check_added_monitors!(nodes[0], 2);
+ let events = nodes[0].node.get_and_clear_pending_msg_events();
+ assert_eq!(events.len(), 2);
+ match events[0] {
+ MessageSendEvent::BroadcastChannelUpdate { ref msg } => {
+ assert_eq!(msg.contents.flags & 2, 2);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ match events[1] {
+ MessageSendEvent::BroadcastChannelUpdate { ref msg } => {
+ assert_eq!(msg.contents.flags & 2, 2);
+ },
+ _ => panic!("Unexpected event"),
+ }
+ // Note that at this point users of a standard PeerHandler will end up calling
+ // peer_disconnected with no_connection_possible set to false, duplicating the
+ // close-all-channels logic. That's OK, we don't want to end up not force-closing channels for
+ // users with their own peer handling logic. We duplicate the call here, however.
+ assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
+ assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2);
+
+ nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), true);
+ assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
+ assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2);
+}