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;
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
///
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>) {
}
}
-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());
}
}
}
- call_claimable_balances(node);
- node.node.test_process_background_events();
for tx in &block.txdata {
for input in &tx.input {
router::get_route(
&send_node.node.get_our_node_id(), route_params, &send_node.network_graph.read_only(),
Some(&send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
- send_node.logger, &scorer, &(), &random_seed_bytes
+ send_node.logger, &scorer, &Default::default(), &random_seed_bytes
)
}
}
}
+pub fn expect_payment_forwarded<CM: AChannelManager, H: NodeHolder<CM=CM>>(
+ event: Event, node: &H, prev_node: &H, next_node: &H, expected_fee: Option<u64>,
+ 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);
}
}
}
};
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 {
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
let route = router::get_route(&origin_node.node.get_our_node_id(), &route_params, &network_graph,
- None, origin_node.logger, &scorer, &(), &random_seed_bytes).unwrap();
+ None, origin_node.logger, &scorer, &Default::default(), &random_seed_bytes).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].hops.len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) {