X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=f6684485dba0d69964686b145b9fd3b383c854cc;hb=190867c37337f0efa37c208ea1a0abc5f9f87119;hp=cd03ae0978e7a5782beb2a64164935c7d1c70f6f;hpb=5ff51b7805969bcd867572bc8102e0efb827765d;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index cd03ae09..f6684485 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -17,7 +17,7 @@ use crate::chain::transaction::OutPoint; use crate::events::{ClaimedHTLC, ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentPurpose, PaymentFailureReason}; use crate::events::bump_transaction::{BumpTransactionEventHandler, Wallet, WalletSource}; use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret}; -use crate::ln::channelmanager::{self, AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA}; +use crate::ln::channelmanager::{AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA}; use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate}; use crate::routing::router::{self, PaymentParameters, Route, RouteParameters}; use crate::ln::features::InitFeatures; @@ -73,6 +73,20 @@ pub fn mine_transactions<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, txn: &[&Tra let height = node.best_block_info().1 + 1; confirm_transactions_at(node, txn, height); } +/// Mine a single block containing the given transaction without extra consistency checks which may +/// impact ChannelManager state. +pub fn mine_transaction_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) { + let height = node.best_block_info().1 + 1; + let mut block = Block { + header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: height, bits: 42, nonce: 42 }, + txdata: Vec::new(), + }; + for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count + block.txdata.push(Transaction { version: 0, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() }); + } + block.txdata.push((*tx).clone()); + do_connect_block_without_consistency_checks(node, block, false); +} /// Mine the given transaction at the given height, mining blocks as required to build to that /// height /// @@ -211,16 +225,16 @@ pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) -> assert!(depth >= 1); for i in 1..depth { let prev_blockhash = block.header.block_hash(); - do_connect_block(node, block, skip_intermediaries); + do_connect_block_with_consistency_checks(node, block, skip_intermediaries); block = create_dummy_block(prev_blockhash, height + i, Vec::new()); } let hash = block.header.block_hash(); - do_connect_block(node, block, false); + do_connect_block_with_consistency_checks(node, block, false); hash } pub fn connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block) { - do_connect_block(node, block.clone(), false); + do_connect_block_with_consistency_checks(node, block.clone(), false); } fn call_claimable_balances<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) { @@ -230,8 +244,14 @@ fn call_claimable_balances<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) { } } -fn do_connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: Block, skip_intermediaries: bool) { +fn do_connect_block_with_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: Block, skip_intermediaries: bool) { + call_claimable_balances(node); + do_connect_block_without_consistency_checks(node, block, skip_intermediaries); call_claimable_balances(node); + node.node.test_process_background_events(); +} + +fn do_connect_block_without_consistency_checks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: Block, skip_intermediaries: bool) { let height = node.best_block_info().1 + 1; #[cfg(feature = "std")] { eprintln!("Connecting block using Block Connection Style: {:?}", *node.connect_style.borrow()); @@ -286,8 +306,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(); for tx in &block.txdata { for input in &tx.input { @@ -1987,29 +2005,38 @@ macro_rules! expect_payment_path_successful { } } +pub fn expect_payment_forwarded>( + event: Event, node: &H, prev_node: &H, next_node: &H, expected_fee: Option, + upstream_force_closed: bool, downstream_force_closed: bool +) { + match event { + Event::PaymentForwarded { + fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, + outbound_amount_forwarded_msat: _ + } => { + assert_eq!(fee_earned_msat, expected_fee); + if !upstream_force_closed { + // Is the event prev_channel_id in one of the channels between the two nodes? + assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id == prev_node.node().get_our_node_id() && x.channel_id == prev_channel_id.unwrap())); + } + // We check for force closures since a force closed channel is removed from the + // node's channel list + if !downstream_force_closed { + assert!(node.node().list_channels().iter().any(|x| x.counterparty.node_id == next_node.node().get_our_node_id() && x.channel_id == next_channel_id.unwrap())); + } + assert_eq!(claim_from_onchain_tx, downstream_force_closed); + }, + _ => panic!("Unexpected event"), + } +} + macro_rules! expect_payment_forwarded { ($node: expr, $prev_node: expr, $next_node: expr, $expected_fee: expr, $upstream_force_closed: expr, $downstream_force_closed: expr) => { - let events = $node.node.get_and_clear_pending_events(); + let mut events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); - match events[0] { - Event::PaymentForwarded { - fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, - outbound_amount_forwarded_msat: _ - } => { - assert_eq!(fee_earned_msat, $expected_fee); - if fee_earned_msat.is_some() { - // Is the event prev_channel_id in one of the channels between the two nodes? - assert!($node.node.list_channels().iter().any(|x| x.counterparty.node_id == $prev_node.node.get_our_node_id() && x.channel_id == prev_channel_id.unwrap())); - } - // We check for force closures since a force closed channel is removed from the - // node's channel list - if !$downstream_force_closed { - assert!($node.node.list_channels().iter().any(|x| x.counterparty.node_id == $next_node.node.get_our_node_id() && x.channel_id == next_channel_id.unwrap())); - } - assert_eq!(claim_from_onchain_tx, $downstream_force_closed); - }, - _ => panic!("Unexpected event"), - } + $crate::ln::functional_test_utils::expect_payment_forwarded( + events.pop().unwrap(), &$node, &$prev_node, &$next_node, $expected_fee, + $upstream_force_closed, $downstream_force_closed); } } @@ -2386,7 +2413,7 @@ pub fn pass_claimed_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, ' } }; if $idx == 1 { fee += expected_extra_fees[i]; } - expect_payment_forwarded!($node, $next_node, $prev_node, Some(fee as u64), false, false); + expect_payment_forwarded!(*$node, $next_node, $prev_node, Some(fee as u64), false, false); expected_total_fee_msat += fee as u64; check_added_monitors!($node, 1); let new_next_msgs = if $new_msgs {