X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_tests.rs;h=4006c87a684a62d5d1a82a6e202a5a900bdd2f86;hb=1443509d77a1ee0edc16dbf1ff962861a1a5e1de;hp=06621986495c14fed048c0d983972d7b7292f5a3;hpb=4833d1acf9fd7755db5aaaaa50f3e54e8446d6b3;p=rust-lightning diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 066219864..4006c87a6 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -3,13 +3,13 @@ //! claim outputs on-chain. use chain::transaction::OutPoint; -use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor}; +use chain::keysinterface::{ChannelKeys, KeysInterface, SpendableOutputDescriptor}; use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil, BlockNotifier}; use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC}; use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT}; use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY}; use ln::channel::{Channel, ChannelError}; -use ln::onion_utils; +use ln::{chan_utils, onion_utils}; use ln::router::{Route, RouteHop}; use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use ln::msgs; @@ -3432,8 +3432,8 @@ fn test_invalid_channel_announcement() { nodes[0].router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id : as_chan.get_short_channel_id().unwrap(), is_permanent: false } ); - let as_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &as_chan.get_local_keys().inner.funding_key); - let bs_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &bs_chan.get_local_keys().inner.funding_key); + let as_bitcoin_key = as_chan.get_local_keys().inner.local_channel_pubkeys.funding_pubkey; + let bs_bitcoin_key = bs_chan.get_local_keys().inner.local_channel_pubkeys.funding_pubkey; let as_network_key = nodes[0].node.get_our_node_id(); let bs_network_key = nodes[1].node.get_our_node_id(); @@ -3460,8 +3460,8 @@ fn test_invalid_channel_announcement() { macro_rules! sign_msg { ($unsigned_msg: expr) => { let msghash = Message::from_slice(&Sha256dHash::hash(&$unsigned_msg.encode()[..])[..]).unwrap(); - let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().inner.funding_key); - let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().inner.funding_key); + let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().inner.funding_key()); + let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().inner.funding_key()); let as_node_sig = secp_ctx.sign(&msghash, &nodes[0].keys_manager.get_node_secret()); let bs_node_sig = secp_ctx.sign(&msghash, &nodes[1].keys_manager.get_node_secret()); chan_announcement = msgs::ChannelAnnouncement { @@ -3510,7 +3510,7 @@ fn test_no_txn_manager_serialize_deserialize() { new_chan_monitor = test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone(), Arc::new(test_utils::TestLogger::new()), Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 })); nodes[0].chan_monitor = &new_chan_monitor; let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; - let (_, mut chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap(); + let (_, mut chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap(); assert!(chan_0_monitor_read.is_empty()); let mut nodes_0_read = &nodes_0_serialized[..]; @@ -3580,7 +3580,7 @@ fn test_simple_manager_serialize_deserialize() { new_chan_monitor = test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone(), Arc::new(test_utils::TestLogger::new()), Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 })); nodes[0].chan_monitor = &new_chan_monitor; let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; - let (_, mut chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap(); + let (_, mut chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap(); assert!(chan_0_monitor_read.is_empty()); let mut nodes_0_read = &nodes_0_serialized[..]; @@ -3647,7 +3647,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let mut node_0_monitors = Vec::new(); for serialized in node_0_monitors_serialized.iter() { let mut read = &serialized[..]; - let (_, monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut read, Arc::new(test_utils::TestLogger::new())).unwrap(); + let (_, monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut read, Arc::new(test_utils::TestLogger::new())).unwrap(); assert!(read.is_empty()); node_0_monitors.push(monitor); } @@ -6310,7 +6310,7 @@ fn test_data_loss_protect() { // Restore node A from previous state let logger: Arc = Arc::new(test_utils::TestLogger::with_id(format!("node {}", 0))); - let mut chan_monitor = <(Sha256dHash, ChannelMonitor)>::read(&mut ::std::io::Cursor::new(previous_chan_monitor_state.0), Arc::clone(&logger)).unwrap().1; + let mut chan_monitor = <(Sha256dHash, ChannelMonitor)>::read(&mut ::std::io::Cursor::new(previous_chan_monitor_state.0), Arc::clone(&logger)).unwrap().1; let chain_monitor = Arc::new(ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger))); let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}); let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }); @@ -6692,30 +6692,46 @@ fn test_bump_penalty_txn_on_revoked_htlcs() { // Connect three more block to see if bumped penalty are issued for HTLC txn let header_132 = connect_blocks(&nodes[0].block_notifier, 3, 129, true, header_129.bitcoin_hash()); - let node_txn = { + let penalty_local_tx; + { let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); - assert_eq!(node_txn.len(), 5); // 2 bumped penalty txn on offered/received HTLC outputs of revoked commitment tx + 1 penalty tx on to_local of revoked commitment tx + 2 bumped penalty tx on revoked HTLC txn + assert_eq!(node_txn.len(), 3); // 2 bumped penalty txn on offered/received HTLC outputs of revoked commitment tx + 1 penalty tx on to_local of revoked commitment tx + 2 bumped penalty tx on revoked HTLC txn check_spends!(node_txn[0], revoked_local_txn[0].clone()); check_spends!(node_txn[1], revoked_local_txn[0].clone()); - let mut penalty_local = ::std::usize::MAX; + check_spends!(node_txn[2], revoked_local_txn[0].clone()); + + penalty_local_tx = node_txn[2].clone(); + node_txn.clear(); + }; + // Few more blocks to broadcast and confirm penalty_local_tx + let header_133 = BlockHeader { version: 0x20000000, prev_blockhash: header_132, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[0].block_notifier.block_connected(&Block { header: header_133, txdata: vec![penalty_local_tx] }, 133); + let header_135 = connect_blocks(&nodes[0].block_notifier, 2, 133, true, header_133.bitcoin_hash()); + { + let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 1); + check_spends!(node_txn[0], revoked_local_txn[0].clone()); + node_txn.clear(); + } + let header_144 = connect_blocks(&nodes[0].block_notifier, 9, 135, true, header_135); + let node_txn = { + let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 2); + let mut penalty_offered = ::std::usize::MAX; let mut penalty_received = ::std::usize::MAX; { - let iter_txn = node_txn[2..].iter(); - for (i, tx) in iter_txn.enumerate() { - if tx.input[0].previous_output.txid == revoked_local_txn[0].txid() { - penalty_local = 2 + i; - } else if tx.input[0].previous_output.txid == revoked_htlc_txn[offered].txid() { - penalty_offered = 2+ i; + for (i, tx) in node_txn.iter().enumerate() { + if tx.input[0].previous_output.txid == revoked_htlc_txn[offered].txid() { + penalty_offered = i; } else if tx.input[0].previous_output.txid == revoked_htlc_txn[received].txid() { - penalty_received = 2 + i; + penalty_received = i; } } } - check_spends!(node_txn[penalty_local], revoked_local_txn[0].clone()); assert_eq!(node_txn[penalty_received].input.len(), 1); assert_eq!(node_txn[penalty_received].output.len(), 1); @@ -6733,24 +6749,17 @@ fn test_bump_penalty_txn_on_revoked_htlcs() { let fee = revoked_htlc_txn[received].output[0].value - node_txn[penalty_received].output[0].value; let new_feerate = fee * 1000 / node_txn[penalty_received].get_weight() as u64; assert!(new_feerate * 100 > feerate_2 * 125); - let txn = vec![node_txn[2].clone(), node_txn[3].clone(), node_txn[4].clone()]; + let txn = vec![node_txn[0].clone(), node_txn[1].clone()]; node_txn.clear(); txn }; // Broadcast claim txn and confirm blocks to avoid further bumps on this outputs - let header_133 = BlockHeader { version: 0x20000000, prev_blockhash: header_132, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - nodes[0].block_notifier.block_connected(&Block { header: header_133, txdata: node_txn }, 133); - let header_140 = connect_blocks(&nodes[0].block_notifier, 6, 134, true, header_133.bitcoin_hash()); - { - let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); - node_txn.clear(); - } - - // Connect few more blocks and check only penalty transaction for to_local output have been issued - connect_blocks(&nodes[0].block_notifier, 7, 140, true, header_140); + let header_145 = BlockHeader { version: 0x20000000, prev_blockhash: header_144, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[0].block_notifier.block_connected(&Block { header: header_145, txdata: node_txn }, 145); + connect_blocks(&nodes[0].block_notifier, 20, 145, true, header_145.bitcoin_hash()); { let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); - assert_eq!(node_txn.len(), 2); //TODO: should be zero when we fix check_spend_remote_htlc + assert_eq!(node_txn.len(), 2); //TODO: fix check_spend_remote_htlc lack of watch output node_txn.clear(); } check_closed_broadcast!(nodes[0], false); @@ -6963,6 +6972,32 @@ fn test_set_outpoints_partial_claiming() { } } +#[test] +fn test_counterparty_raa_skip_no_crash() { + // Previously, if our counterparty sent two RAAs in a row without us having provided a + // commitment transaction, we would have happily carried on and provided them the next + // commitment transaction based on one RAA forward. This would probably eventually have led to + // channel closure, but it would not have resulted in funds loss. Still, our + // EnforcingChannelKeys would have paniced as it doesn't like jumps into the future. Here, we + // check simply that the channel is closed in response to such an RAA, but don't check whether + // we decide to punish our counterparty for revoking their funds (as we don't currently + // implement that). + let node_cfgs = create_node_cfgs(2); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; + + let commitment_seed = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&channel_id).unwrap().local_keys.commitment_seed().clone(); + const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; + let next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(), + &SecretKey::from_slice(&chan_utils::build_commitment_secret(&commitment_seed, INITIAL_COMMITMENT_NUMBER - 2)).unwrap()); + let per_commitment_secret = chan_utils::build_commitment_secret(&commitment_seed, INITIAL_COMMITMENT_NUMBER); + + nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), + &msgs::RevokeAndACK { channel_id, per_commitment_secret, next_per_commitment_point }); + assert_eq!(check_closed_broadcast!(nodes[1], true).unwrap().data, "Received an unexpected revoke_and_ack"); +} + #[test] fn test_bump_txn_sanitize_tracking_maps() { // Sanitizing pendning_claim_request and claimable_outpoints used to be buggy,