X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=50aed2c5b4355283f77695708235c25f5d36d761;hb=ec3aa494953c7d720370119f673e8e6b3a2155d5;hp=e818bd95502ba9f9869c44e7e479204a23c2a918;hpb=6e7000c5e7d246585d876e65a1aa8106fa948f7a;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index e818bd95..50aed2c5 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -30,7 +30,6 @@ use crate::util::config::UserConfig; use crate::util::ser::{ReadableArgs, Writeable}; use bitcoin::blockdata::block::{Block, BlockHeader}; -use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::transaction::{Transaction, TxOut}; use bitcoin::network::constants::Network; @@ -137,6 +136,34 @@ pub enum ConnectStyle { } impl ConnectStyle { + pub fn skips_blocks(&self) -> bool { + match self { + ConnectStyle::BestBlockFirst => false, + ConnectStyle::BestBlockFirstSkippingBlocks => true, + ConnectStyle::BestBlockFirstReorgsOnlyTip => true, + ConnectStyle::TransactionsFirst => false, + ConnectStyle::TransactionsFirstSkippingBlocks => true, + ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks => true, + ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks => true, + ConnectStyle::TransactionsFirstReorgsOnlyTip => true, + ConnectStyle::FullBlockViaListen => false, + } + } + + pub fn updates_best_block_first(&self) -> bool { + match self { + ConnectStyle::BestBlockFirst => true, + ConnectStyle::BestBlockFirstSkippingBlocks => true, + ConnectStyle::BestBlockFirstReorgsOnlyTip => true, + ConnectStyle::TransactionsFirst => false, + ConnectStyle::TransactionsFirstSkippingBlocks => false, + ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks => false, + ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks => false, + ConnectStyle::TransactionsFirstReorgsOnlyTip => false, + ConnectStyle::FullBlockViaListen => false, + } + } + fn random_style() -> ConnectStyle { #[cfg(feature = "std")] { use core::hash::{BuildHasher, Hasher}; @@ -164,12 +191,7 @@ impl ConnectStyle { } pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) -> BlockHash { - let skip_intermediaries = match *node.connect_style.borrow() { - ConnectStyle::BestBlockFirstSkippingBlocks|ConnectStyle::TransactionsFirstSkippingBlocks| - ConnectStyle::TransactionsDuplicativelyFirstSkippingBlocks|ConnectStyle::HighlyRedundantTransactionsFirstSkippingBlocks| - ConnectStyle::BestBlockFirstReorgsOnlyTip|ConnectStyle::TransactionsFirstReorgsOnlyTip => true, - _ => false, - }; + let skip_intermediaries = node.connect_style.borrow().skips_blocks(); let height = node.best_block_info().1 + 1; let mut block = Block { @@ -207,6 +229,9 @@ fn do_connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: Block, sk #[cfg(feature = "std")] { eprintln!("Connecting block using Block Connection Style: {:?}", *node.connect_style.borrow()); } + // Update the block internally before handing it over to LDK, to ensure our assertions regarding + // transaction broadcast are correct. + node.blocks.lock().unwrap().push((block.clone(), height)); if !skip_intermediaries { let txdata: Vec<_> = block.txdata.iter().enumerate().collect(); match *node.connect_style.borrow() { @@ -256,7 +281,6 @@ fn do_connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: Block, sk } call_claimable_balances(node); node.node.test_process_background_events(); - node.blocks.lock().unwrap().push((block, height)); } pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) { @@ -2034,21 +2058,26 @@ pub fn do_pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_p let events_2 = node.node.get_and_clear_pending_events(); if payment_claimable_expected { assert_eq!(events_2.len(), 1); - match events_2[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, ref via_channel_id, ref via_user_channel_id, claim_deadline } => { + match &events_2[0] { + Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, + receiver_node_id, ref via_channel_id, ref via_user_channel_id, + claim_deadline, onion_fields, + } => { assert_eq!(our_payment_hash, *payment_hash); assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap()); + assert!(onion_fields.is_some()); match &purpose { PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => { assert_eq!(expected_preimage, *payment_preimage); assert_eq!(our_payment_secret.unwrap(), *payment_secret); + assert_eq!(Some(*payment_secret), onion_fields.as_ref().unwrap().payment_secret); }, PaymentPurpose::SpontaneousPayment(payment_preimage) => { assert_eq!(expected_preimage.unwrap(), *payment_preimage); assert!(our_payment_secret.is_none()); }, } - assert_eq!(amount_msat, recv_value); + assert_eq!(*amount_msat, recv_value); assert!(node.node.list_channels().iter().any(|details| details.channel_id == via_channel_id.unwrap())); assert!(node.node.list_channels().iter().any(|details| details.user_channel_id == via_user_channel_id.unwrap())); assert!(claim_deadline.unwrap() > node.best_block_info().1); @@ -2246,8 +2275,8 @@ pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: .with_features(expected_route.last().unwrap().node.invoice_features()); let route = get_route(origin_node, &payment_params, recv_value, TEST_FINAL_CLTV).unwrap(); assert_eq!(route.paths.len(), 1); - assert_eq!(route.paths[0].len(), expected_route.len()); - for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) { + assert_eq!(route.paths[0].hops.len(), expected_route.len()); + for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) { assert_eq!(hop.pubkey, node.node.get_our_node_id()); } @@ -2267,8 +2296,8 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou &origin_node.node.get_our_node_id(), &payment_params, &network_graph, None, recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap(); assert_eq!(route.paths.len(), 1); - assert_eq!(route.paths[0].len(), expected_route.len()); - for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) { + assert_eq!(route.paths[0].hops.len(), expected_route.len()); + for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) { assert_eq!(hop.pubkey, node.node.get_our_node_id()); } @@ -2374,7 +2403,7 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe assert_eq!(payment_hash, our_payment_hash); assert!(payment_failed_permanently); for (idx, hop) in expected_route.iter().enumerate() { - assert_eq!(hop.node.get_our_node_id(), path[idx].pubkey); + assert_eq!(hop.node.get_our_node_id(), path.hops[idx].pubkey); } payment_id.unwrap() }, @@ -2407,10 +2436,7 @@ pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: & pub fn create_chanmon_cfgs(node_count: usize) -> Vec { let mut chan_mon_cfgs = Vec::new(); for i in 0..node_count { - let tx_broadcaster = test_utils::TestBroadcaster { - txn_broadcasted: Mutex::new(Vec::new()), - blocks: Arc::new(Mutex::new(vec![(genesis_block(Network::Testnet), 0)])), - }; + let tx_broadcaster = test_utils::TestBroadcaster::new(Network::Testnet); let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", i)); @@ -2530,6 +2556,8 @@ pub enum HTLCType { NONE, TIMEOUT, SUCCESS } /// also fail. pub fn test_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction), commitment_tx: Option, has_htlc_tx: HTLCType) -> Vec { let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap(); + let mut txn_seen = HashSet::new(); + node_txn.retain(|tx| txn_seen.insert(tx.txid())); assert!(node_txn.len() >= if commitment_tx.is_some() { 0 } else { 1 } + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 }); let mut res = Vec::with_capacity(2); @@ -2593,22 +2621,23 @@ pub fn test_revoked_htlc_claim_txn_broadcast<'a, 'b, 'c>(node: &Node<'a, 'b, 'c> pub fn check_preimage_claim<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, prev_txn: &Vec) -> Vec { let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap(); + let mut txn_seen = HashSet::new(); + node_txn.retain(|tx| txn_seen.insert(tx.txid())); - assert!(node_txn.len() >= 1); - assert_eq!(node_txn[0].input.len(), 1); let mut found_prev = false; - - for tx in prev_txn { - if node_txn[0].input[0].previous_output.txid == tx.txid() { - check_spends!(node_txn[0], tx); - let mut iter = node_txn[0].input[0].witness.iter(); - iter.next().expect("expected 3 witness items"); - iter.next().expect("expected 3 witness items"); - assert!(iter.next().expect("expected 3 witness items").len() > 106); // must spend an htlc output - assert_eq!(tx.input.len(), 1); // must spend a commitment tx - - found_prev = true; - break; + for prev_tx in prev_txn { + for tx in &*node_txn { + if tx.input[0].previous_output.txid == prev_tx.txid() { + check_spends!(tx, prev_tx); + let mut iter = tx.input[0].witness.iter(); + iter.next().expect("expected 3 witness items"); + iter.next().expect("expected 3 witness items"); + assert!(iter.next().expect("expected 3 witness items").len() > 106); // must spend an htlc output + assert_eq!(tx.input.len(), 1); // must spend a commitment tx + + found_prev = true; + break; + } } } assert!(found_prev);