X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_tests.rs;h=d243ab288ae476ff214e6ee89e2e556fa03ff0d6;hb=a3e4f9c9671003cf7041096fe775d058bdb489b0;hp=08e8187ad9fe4ebf78bcaedb75da357440f2dcbf;hpb=6662e959c8443fd74c76c2908cfb0c78ec4f906a;p=rust-lightning diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 08e8187a..d243ab28 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -12,13 +12,12 @@ //! claim outputs on-chain. use chain::Watch; +use chain::channelmonitor; +use chain::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY}; use chain::transaction::OutPoint; use chain::keysinterface::{ChannelKeys, KeysInterface, SpendableOutputDescriptor}; -use chain::chaininterface::{ChainListener, BlockNotifier}; use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC}; use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure, BREAKDOWN_TIMEOUT}; -use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY}; -use ln::channelmonitor; use ln::channel::{Channel, ChannelError}; use ln::{chan_utils, onion_utils}; use routing::router::{Route, RouteHop, get_route}; @@ -3524,7 +3523,7 @@ fn test_force_close_fail_back() { { let mut monitors = nodes[2].chain_monitor.chain_monitor.monitors.lock().unwrap(); monitors.get_mut(&OutPoint{ txid: Txid::from_slice(&payment_event.commitment_msg.channel_id[..]).unwrap(), index: 0 }).unwrap() - .provide_payment_preimage(&our_payment_hash, &our_payment_preimage); + .provide_payment_preimage(&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, &node_cfgs[2].fee_estimator, &&logger); } connect_block(&nodes[2], &block, 1); let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap(); @@ -3558,10 +3557,8 @@ fn test_unconf_chan() { header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; headers.push(header.clone()); } - let mut height = 99; while !headers.is_empty() { - nodes[0].node.block_disconnected(&headers.pop().unwrap(), height); - height -= 1; + nodes[0].node.block_disconnected(&headers.pop().unwrap()); } check_closed_broadcast!(nodes[0], false); check_added_monitors!(nodes[0], 1); @@ -4310,6 +4307,7 @@ fn test_no_txn_manager_serialize_deserialize() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let logger: test_utils::TestLogger; let fee_estimator: test_utils::TestFeeEstimator; + let persister: test_utils::TestPersister; let new_chain_monitor: test_utils::TestChainMonitor; let keys_manager: test_utils::TestKeysInterface; let nodes_0_deserialized: ChannelManager; @@ -4321,11 +4319,12 @@ fn test_no_txn_manager_serialize_deserialize() { let nodes_0_serialized = nodes[0].node.encode(); let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut chan_0_monitor_serialized).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.serialize_for_disk(&mut chan_0_monitor_serialized).unwrap(); logger = test_utils::TestLogger::new(); fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; - new_chain_monitor = test_utils::TestChainMonitor::new(nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator); + persister = test_utils::TestPersister::new(); + new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister); nodes[0].chain_monitor = &new_chain_monitor; let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor)>::read(&mut chan_0_monitor_read).unwrap(); @@ -4352,7 +4351,6 @@ fn test_no_txn_manager_serialize_deserialize() { assert!(nodes[0].chain_monitor.watch_channel(chan_0_monitor.get_funding_txo().0, chan_0_monitor).is_ok()); nodes[0].node = &nodes_0_deserialized; - nodes[0].block_notifier.register_listener(nodes[0].node); assert_eq!(nodes[0].node.list_channels().len(), 1); check_added_monitors!(nodes[0], 1); @@ -4384,6 +4382,7 @@ fn test_manager_serialize_deserialize_events() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let fee_estimator: test_utils::TestFeeEstimator; + let persister: test_utils::TestPersister; let logger: test_utils::TestLogger; let new_chain_monitor: test_utils::TestChainMonitor; let keys_manager: test_utils::TestKeysInterface; @@ -4429,11 +4428,12 @@ fn test_manager_serialize_deserialize_events() { // Start the de/seriailization process mid-channel creation to check that the channel manager will hold onto events that are serialized let nodes_0_serialized = nodes[0].node.encode(); let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut chan_0_monitor_serialized).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.serialize_for_disk(&mut chan_0_monitor_serialized).unwrap(); fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; logger = test_utils::TestLogger::new(); - new_chain_monitor = test_utils::TestChainMonitor::new(nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator); + persister = test_utils::TestPersister::new(); + new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister); nodes[0].chain_monitor = &new_chain_monitor; let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor)>::read(&mut chan_0_monitor_read).unwrap(); @@ -4475,7 +4475,6 @@ fn test_manager_serialize_deserialize_events() { }; // Make sure the channel is functioning as though the de/serialization never happened - nodes[0].block_notifier.register_listener(nodes[0].node); assert_eq!(nodes[0].node.list_channels().len(), 1); check_added_monitors!(nodes[0], 1); @@ -4507,6 +4506,7 @@ fn test_simple_manager_serialize_deserialize() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let logger: test_utils::TestLogger; let fee_estimator: test_utils::TestFeeEstimator; + let persister: test_utils::TestPersister; let new_chain_monitor: test_utils::TestChainMonitor; let keys_manager: test_utils::TestKeysInterface; let nodes_0_deserialized: ChannelManager; @@ -4520,11 +4520,12 @@ fn test_simple_manager_serialize_deserialize() { let nodes_0_serialized = nodes[0].node.encode(); let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut chan_0_monitor_serialized).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.serialize_for_disk(&mut chan_0_monitor_serialized).unwrap(); logger = test_utils::TestLogger::new(); fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; - new_chain_monitor = test_utils::TestChainMonitor::new(nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator); + persister = test_utils::TestPersister::new(); + new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister); nodes[0].chain_monitor = &new_chain_monitor; let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor)>::read(&mut chan_0_monitor_read).unwrap(); @@ -4566,6 +4567,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); let logger: test_utils::TestLogger; let fee_estimator: test_utils::TestFeeEstimator; + let persister: test_utils::TestPersister; let new_chain_monitor: test_utils::TestChainMonitor; let keys_manager: test_utils::TestKeysInterface; let nodes_0_deserialized: ChannelManager; @@ -4577,7 +4579,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let mut node_0_stale_monitors_serialized = Vec::new(); for monitor in nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter() { let mut writer = test_utils::TestVecWriter(Vec::new()); - monitor.1.write_for_disk(&mut writer).unwrap(); + monitor.1.serialize_for_disk(&mut writer).unwrap(); node_0_stale_monitors_serialized.push(writer.0); } @@ -4596,13 +4598,14 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let mut node_0_monitors_serialized = Vec::new(); for monitor in nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter() { let mut writer = test_utils::TestVecWriter(Vec::new()); - monitor.1.write_for_disk(&mut writer).unwrap(); + monitor.1.serialize_for_disk(&mut writer).unwrap(); node_0_monitors_serialized.push(writer.0); } logger = test_utils::TestLogger::new(); fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; - new_chain_monitor = test_utils::TestChainMonitor::new(nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator); + persister = test_utils::TestPersister::new(); + new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister); nodes[0].chain_monitor = &new_chain_monitor; let mut node_0_stale_monitors = Vec::new(); @@ -4713,6 +4716,7 @@ macro_rules! check_spendable_outputs { input: vec![input], output: vec![outp], }; + 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 remotepubkey = keys.pubkeys().payment_point; @@ -4747,6 +4751,7 @@ macro_rules! check_spendable_outputs { let delayed_payment_pubkey = PublicKey::from_secret_key(&secp_ctx, &delayed_payment_key); let witness_script = chan_utils::get_revokeable_redeemscript(revocation_pubkey, *to_self_delay, &delayed_payment_pubkey); + spend_tx.output[0].value -= (spend_tx.get_weight() + 2 + 1 + 73 + 1 + witness_script.len() + 1 + 3) as u64 / 4; // (Max weight + 3 (to round up)) / 4 let sighash = Message::from_slice(&bip143::SigHashCache::new(&spend_tx).signature_hash(0, &witness_script, output.value, SigHashType::All)[..]).unwrap(); let local_delayedsig = secp_ctx.sign(&sighash, &delayed_payment_key); spend_tx.input[0].witness.push(local_delayedsig.serialize_der().to_vec()); @@ -4774,6 +4779,7 @@ macro_rules! check_spendable_outputs { input: vec![input], output: vec![outp.clone()], }; + 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 secret = { match ExtendedPrivKey::new_master(Network::Testnet, &$node.node_seed) { Ok(master_key) => { @@ -4857,8 +4863,7 @@ fn test_claim_on_remote_sizeable_push_msat() { connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1, 1, true, header.block_hash()); let spend_txn = check_spendable_outputs!(nodes[1], 1, node_cfgs[1].keys_manager, 100000); - assert_eq!(spend_txn.len(), 2); - assert_eq!(spend_txn[0], spend_txn[1]); + assert_eq!(spend_txn.len(), 1); check_spends!(spend_txn[0], node_txn[0]); } @@ -4890,10 +4895,9 @@ fn test_claim_on_remote_revoked_sizeable_push_msat() { connect_blocks(&nodes[1], ANTI_REORG_DELAY - 1, 1, true, header.block_hash()); let spend_txn = check_spendable_outputs!(nodes[1], 1, node_cfgs[1].keys_manager, 100000); - assert_eq!(spend_txn.len(), 3); - assert_eq!(spend_txn[0], spend_txn[1]); // to_remote output on revoked remote commitment_tx - check_spends!(spend_txn[0], revoked_local_txn[0]); - check_spends!(spend_txn[2], node_txn[0]); + assert_eq!(spend_txn.len(), 2); + check_spends!(spend_txn[0], revoked_local_txn[0]); // to_remote output on revoked remote commitment_tx + check_spends!(spend_txn[1], node_txn[0]); } #[test] @@ -4988,8 +4992,8 @@ fn test_static_spendable_outputs_timeout_tx() { expect_payment_failed!(nodes[1], our_payment_hash, true); let spend_txn = check_spendable_outputs!(nodes[1], 1, node_cfgs[1].keys_manager, 100000); - assert_eq!(spend_txn.len(), 3); // SpendableOutput: remote_commitment_tx.to_remote (*2), timeout_tx.output (*1) - check_spends!(spend_txn[2], node_txn[0].clone()); + assert_eq!(spend_txn.len(), 2); // SpendableOutput: remote_commitment_tx.to_remote, timeout_tx.output + check_spends!(spend_txn[1], node_txn[0]); } #[test] @@ -5164,12 +5168,11 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() { // Check A's ChannelMonitor was able to generate the right spendable output descriptor let spend_txn = check_spendable_outputs!(nodes[0], 1, node_cfgs[0].keys_manager, 100000); - assert_eq!(spend_txn.len(), 3); // Duplicated SpendableOutput due to block rescan after revoked htlc output tracking - assert_eq!(spend_txn[0], spend_txn[1]); + assert_eq!(spend_txn.len(), 2); assert_eq!(spend_txn[0].input.len(), 1); check_spends!(spend_txn[0], revoked_local_txn[0]); // spending to_remote output from revoked local tx assert_ne!(spend_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output); - check_spends!(spend_txn[2], node_txn[1]); // spending justice tx output on the htlc success tx + check_spends!(spend_txn[1], node_txn[1]); // spending justice tx output on the htlc success tx } #[test] @@ -5233,7 +5236,7 @@ fn test_onchain_to_onchain_claim() { assert_eq!(b_txn[2].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); assert!(b_txn[2].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output assert_ne!(b_txn[2].lock_time, 0); // Timeout tx - check_spends!(b_txn[0], c_txn[1]); // timeout tx on C remote commitment tx, issued by ChannelMonitor, * 2 due to block rescan + check_spends!(b_txn[0], c_txn[1]); // timeout tx on C remote commitment tx, issued by ChannelMonitor assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT); assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment assert_ne!(b_txn[2].lock_time, 0); // Timeout tx @@ -5731,10 +5734,9 @@ fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() { // Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor let spend_txn = check_spendable_outputs!(nodes[0], 1, node_cfgs[0].keys_manager, 100000); - assert_eq!(spend_txn.len(), 3); - assert_eq!(spend_txn[0], spend_txn[1]); + assert_eq!(spend_txn.len(), 2); check_spends!(spend_txn[0], local_txn[0]); - check_spends!(spend_txn[2], htlc_timeout); + check_spends!(spend_txn[1], htlc_timeout); } #[test] @@ -5748,7 +5750,7 @@ fn test_key_derivation_params() { // We manually create the node configuration to backup the seed. let seed = [42; 32]; let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); - let chain_monitor = test_utils::TestChainMonitor::new(&chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator); + let chain_monitor = test_utils::TestChainMonitor::new(Some(&chanmon_cfgs[0].chain_source), &chanmon_cfgs[0].tx_broadcaster, &chanmon_cfgs[0].logger, &chanmon_cfgs[0].fee_estimator, &chanmon_cfgs[0].persister); let node = NodeCfg { chain_source: &chanmon_cfgs[0].chain_source, logger: &chanmon_cfgs[0].logger, tx_broadcaster: &chanmon_cfgs[0].tx_broadcaster, fee_estimator: &chanmon_cfgs[0].fee_estimator, chain_monitor, keys_manager, node_seed: seed }; let mut node_cfgs = create_node_cfgs(3, &chanmon_cfgs); node_cfgs.remove(0); @@ -5802,10 +5804,9 @@ fn test_key_derivation_params() { // Verify that A is able to spend its own HTLC-Timeout tx thanks to spendable output event given back by its ChannelMonitor let new_keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); let spend_txn = check_spendable_outputs!(nodes[0], 1, new_keys_manager, 100000); - assert_eq!(spend_txn.len(), 3); - assert_eq!(spend_txn[0], spend_txn[1]); + assert_eq!(spend_txn.len(), 2); check_spends!(spend_txn[0], local_txn_1[0]); - check_spends!(spend_txn[2], htlc_timeout); + check_spends!(spend_txn[1], htlc_timeout); } #[test] @@ -7164,60 +7165,6 @@ fn test_failure_delay_dust_htlc_local_commitment() { do_test_failure_delay_dust_htlc_local_commitment(false); } -#[test] -fn test_no_failure_dust_htlc_local_commitment() { - // Transaction filters for failing back dust htlc based on local commitment txn infos has been - // prone to error, we test here that a dummy transaction don't fail them. - - let chanmon_cfgs = create_chanmon_cfgs(2); - 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 chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); - - // Rebalance a bit - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000); - - let as_dust_limit = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis; - let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().holder_dust_limit_satoshis; - - // We route 2 dust-HTLCs between A and B - let (preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000); - let (preimage_2, _) = route_payment(&nodes[1], &[&nodes[0]], as_dust_limit*1000); - - // Build a dummy invalid transaction trying to spend a commitment tx - let input = TxIn { - previous_output: BitcoinOutPoint { txid: chan.3.txid(), vout: 0 }, - script_sig: Script::new(), - sequence: 0, - witness: Vec::new(), - }; - - let outp = TxOut { - script_pubkey: Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script(), - value: 10000, - }; - - let dummy_tx = Transaction { - version: 2, - lock_time: 0, - input: vec![input], - output: vec![outp] - }; - - let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - nodes[0].chain_monitor.chain_monitor.block_connected(&header, &[(0, &dummy_tx)], 1); - assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); - assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 0); - // We broadcast a few more block to check everything is all right - connect_blocks(&nodes[0], 20, 1, true, header.block_hash()); - assert_eq!(nodes[0].node.get_and_clear_pending_events().len(), 0); - assert_eq!(nodes[0].node.get_and_clear_pending_msg_events().len(), 0); - - claim_payment(&nodes[0], &vec!(&nodes[1])[..], preimage_1, bs_dust_limit*1000); - claim_payment(&nodes[1], &vec!(&nodes[0])[..], preimage_2, as_dust_limit*1000); -} - fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) { // Outbound HTLC-failure updates must be cancelled if we get a reorg before we reach ANTI_REORG_DELAY. // Broadcast of revoked remote commitment tx, trigger failure-update of dust/non-dust HTLCs @@ -7468,6 +7415,7 @@ fn test_data_loss_protect() { // * we close channel in case of detecting other being fallen behind // * we are able to claim our own outputs thanks to to_remote being static let keys_manager; + let persister; let logger; let fee_estimator; let tx_broadcaster; @@ -7484,7 +7432,7 @@ fn test_data_loss_protect() { // Cache node A state before any channel update let previous_node_state = nodes[0].node.encode(); let mut previous_chain_monitor_state = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut previous_chain_monitor_state).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.serialize_for_disk(&mut previous_chain_monitor_state).unwrap(); send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000); send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000); @@ -7499,7 +7447,8 @@ fn test_data_loss_protect() { tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}; fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; keys_manager = test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet); - monitor = test_utils::TestChainMonitor::new(&tx_broadcaster, &logger, &fee_estimator); + persister = test_utils::TestPersister::new(); + monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &tx_broadcaster, &logger, &fee_estimator, &persister); node_state_0 = { let mut channel_monitors = HashMap::new(); channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &mut chain_monitor); @@ -7518,10 +7467,6 @@ fn test_data_loss_protect() { nodes[0].chain_monitor = &monitor; nodes[0].chain_source = &chain_source; - nodes[0].block_notifier = BlockNotifier::new(); - nodes[0].block_notifier.register_listener(&nodes[0].chain_monitor.chain_monitor); - nodes[0].block_notifier.register_listener(nodes[0].node); - check_added_monitors!(nodes[0], 1); nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() }); @@ -8362,16 +8307,18 @@ fn test_update_err_monitor_lockdown() { let preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0; // Copy ChainMonitor to simulate a watchtower and update block height of node 0 until its ChannelMonitor timeout HTLC onchain + let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", 0)); + let persister = test_utils::TestPersister::new(); let watchtower = { let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); let monitor = monitors.get(&outpoint).unwrap(); let mut w = test_utils::TestVecWriter(Vec::new()); - monitor.write_for_disk(&mut w).unwrap(); + monitor.serialize_for_disk(&mut w).unwrap(); let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut ::std::io::Cursor::new(&w.0)).unwrap().1; assert!(new_monitor == *monitor); - let watchtower = test_utils::TestChainMonitor::new(&chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator); + let watchtower = test_utils::TestChainMonitor::new(Some(&chain_source), &chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister); assert!(watchtower.watch_channel(outpoint, new_monitor).is_ok()); watchtower }; @@ -8419,16 +8366,18 @@ fn test_concurrent_monitor_claim() { route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0; // Copy ChainMonitor to simulate watchtower Alice and update block height her ChannelMonitor timeout HTLC onchain + let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", "Alice")); + let persister = test_utils::TestPersister::new(); let watchtower_alice = { let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); let monitor = monitors.get(&outpoint).unwrap(); let mut w = test_utils::TestVecWriter(Vec::new()); - monitor.write_for_disk(&mut w).unwrap(); + monitor.serialize_for_disk(&mut w).unwrap(); let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut ::std::io::Cursor::new(&w.0)).unwrap().1; assert!(new_monitor == *monitor); - let watchtower = test_utils::TestChainMonitor::new(&chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator); + let watchtower = test_utils::TestChainMonitor::new(Some(&chain_source), &chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister); assert!(watchtower.watch_channel(outpoint, new_monitor).is_ok()); watchtower }; @@ -8443,16 +8392,18 @@ fn test_concurrent_monitor_claim() { } // Copy ChainMonitor to simulate watchtower Bob and make it receive a commitment update first. + let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", "Bob")); + let persister = test_utils::TestPersister::new(); let watchtower_bob = { let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); let monitor = monitors.get(&outpoint).unwrap(); let mut w = test_utils::TestVecWriter(Vec::new()); - monitor.write_for_disk(&mut w).unwrap(); + monitor.serialize_for_disk(&mut w).unwrap(); let new_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>::read( &mut ::std::io::Cursor::new(&w.0)).unwrap().1; assert!(new_monitor == *monitor); - let watchtower = test_utils::TestChainMonitor::new(&chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator); + let watchtower = test_utils::TestChainMonitor::new(Some(&chain_source), &chanmon_cfgs[0].tx_broadcaster, &logger, &chanmon_cfgs[0].fee_estimator, &persister); assert!(watchtower.watch_channel(outpoint, new_monitor).is_ok()); watchtower }; @@ -8505,3 +8456,50 @@ fn test_concurrent_monitor_claim() { check_spends!(htlc_txn[1], bob_state_y); } } + +#[test] +fn test_htlc_no_detection() { + // This test is a mutation to underscore the detection logic bug we had + // before #653. HTLC value routed is above the remaining balance, thus + // inverting HTLC and `to_remote` output. HTLC will come second and + // it wouldn't be seen by pre-#653 detection as we were enumerate()'ing + // on a watched outputs vector (Vec) thus implicitly relying on + // outputs order detection for correct spending children filtring. + + let chanmon_cfgs = create_chanmon_cfgs(2); + 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 some initial channels + let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known()); + + send_payment(&nodes[0], &vec!(&nodes[1])[..], 1_000_000, 1_000_000); + let (_, our_payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1])[..], 2_000_000); + let local_txn = get_local_commitment_txn!(nodes[0], chan_1.2); + assert_eq!(local_txn[0].input.len(), 1); + assert_eq!(local_txn[0].output.len(), 3); + check_spends!(local_txn[0], chan_1.3); + + // Timeout HTLC on A's chain and so it can generate a HTLC-Timeout tx + let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + connect_block(&nodes[0], &Block { header, txdata: vec![local_txn[0].clone()] }, 200); + // We deliberately connect the local tx twice as this should provoke a failure calling + // this test before #653 fix. + connect_block(&nodes[0], &Block { header, txdata: vec![local_txn[0].clone()] }, 200); + check_closed_broadcast!(nodes[0], false); + check_added_monitors!(nodes[0], 1); + + let htlc_timeout = { + let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn[0].input.len(), 1); + assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); + check_spends!(node_txn[0], local_txn[0]); + node_txn[0].clone() + }; + + let header_201 = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + connect_block(&nodes[0], &Block { header: header_201, txdata: vec![htlc_timeout.clone()] }, 201); + connect_blocks(&nodes[0], ANTI_REORG_DELAY - 1, 201, true, header_201.block_hash()); + expect_payment_failed!(nodes[0], our_payment_hash, true); +}