use std::mem;
use std::collections::HashMap;
-pub const CHAN_CONFIRM_DEPTH: u32 = 100;
+pub const CHAN_CONFIRM_DEPTH: u32 = 10;
+/// Mine the given transaction in the next block and then mine CHAN_CONFIRM_DEPTH - 1 blocks on
+/// top, giving the given transaction CHAN_CONFIRM_DEPTH confirmations.
pub fn confirm_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
- let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
- let dummy_tx_count = tx.version as usize;
+ confirm_transaction_at(node, tx, node.best_block_info().1 + 1);
+ connect_blocks(node, CHAN_CONFIRM_DEPTH - 1);
+}
+/// Mine a signle block containing the given transaction
+pub fn mine_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
+ let height = node.best_block_info().1 + 1;
+ confirm_transaction_at(node, tx, height);
+}
+/// Mine the given transaction at the given height, mining blocks as required to build to that
+/// height
+pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) {
+ let starting_block = node.best_block_info();
let mut block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
- txdata: vec![dummy_tx; dummy_tx_count],
+ header: BlockHeader { version: 0x20000000, prev_blockhash: starting_block.0, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ txdata: Vec::new(),
};
- block.txdata.push(tx.clone());
- connect_block(node, &block, 1);
- for i in 2..CHAN_CONFIRM_DEPTH {
+ let height = starting_block.1 + 1;
+ assert!(height <= conf_height);
+ for _ in height..conf_height {
+ connect_block(node, &block);
block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
- connect_block(node, &block, i);
}
+
+ 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: 0, input: Vec::new(), output: Vec::new() });
+ }
+ block.txdata.push(tx.clone());
+ connect_block(node, &block);
}
-pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32, height: u32, parent: bool, prev_blockhash: BlockHash) -> BlockHash {
+pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) -> BlockHash {
let mut block = Block {
- header: BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
- connect_block(node, &block, height + 1);
- for i in 2..depth + 1 {
+ connect_block(node, &block);
+ for _ in 2..depth + 1 {
block = Block {
header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
txdata: vec![],
};
- connect_block(node, &block, height + i);
+ connect_block(node, &block);
}
block.header.block_hash()
}
-pub fn connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block, height: u32) {
+pub fn connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block) {
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
+ let height = node.best_block_info().1 + 1;
node.chain_monitor.chain_monitor.block_connected(&block.header, &txdata, height);
node.node.block_connected(&block.header, &txdata, height);
node.node.test_process_background_events();
node.blocks.borrow_mut().push((block.header, height));
}
-pub fn disconnect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, header: &BlockHeader, height: u32) {
- node.chain_monitor.chain_monitor.block_disconnected(header, height);
- node.node.block_disconnected(header);
- node.node.test_process_background_events();
- node.blocks.borrow_mut().pop();
+pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) {
+ for _ in 0..count {
+ let orig_header = node.blocks.borrow_mut().pop().unwrap();
+ assert!(orig_header.1 > 0); // Cannot disconnect genesis
+ node.chain_monitor.chain_monitor.block_disconnected(&orig_header.0, orig_header.1);
+ node.node.block_disconnected(&orig_header.0);
+ }
+}
+
+pub fn disconnect_all_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) {
+ let count = node.blocks.borrow_mut().len() as u32 - 1;
+ disconnect_blocks(node, count);
}
pub struct TestChanMonCfg {
}
}
+/// Get a specific event from the pending events queue.
+#[macro_export]
+macro_rules! get_event {
+ ($node: expr, $event_type: path) => {
+ {
+ let mut events = $node.node.get_and_clear_pending_events();
+ assert_eq!(events.len(), 1);
+ let ev = events.pop().unwrap();
+ match ev {
+ $event_type { .. } => {
+ ev
+ },
+ _ => panic!("Unexpected event"),
+ }
+ }
+ }
+}
+
#[cfg(test)]
macro_rules! get_htlc_update_msgs {
($node: expr, $node_id: expr) => {
}
}
-#[cfg(test)]
+/// Returns any local commitment transactions for the channel.
+#[macro_export]
macro_rules! get_local_commitment_txn {
($node: expr, $channel_id: expr) => {
{
tx
}
-pub fn create_chan_between_nodes_with_value_confirm_first<'a, 'b, 'c, 'd>(node_recv: &'a Node<'b, 'c, 'c>, node_conf: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
- confirm_transaction(node_conf, tx);
+pub fn create_chan_between_nodes_with_value_confirm_first<'a, 'b, 'c, 'd>(node_recv: &'a Node<'b, 'c, 'c>, node_conf: &'a Node<'b, 'c, 'd>, tx: &Transaction, conf_height: u32) {
+ confirm_transaction_at(node_conf, tx, conf_height);
+ connect_blocks(node_conf, CHAN_CONFIRM_DEPTH - 1);
node_recv.node.handle_funding_locked(&node_conf.node.get_our_node_id(), &get_event_msg!(node_conf, MessageSendEvent::SendFundingLocked, node_recv.node.get_our_node_id()));
}
}
pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, tx: &Transaction) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32]) {
- create_chan_between_nodes_with_value_confirm_first(node_a, node_b, tx);
- confirm_transaction(node_a, tx);
+ let conf_height = std::cmp::max(node_a.best_block_info().1 + 1, node_b.best_block_info().1 + 1);
+ create_chan_between_nodes_with_value_confirm_first(node_a, node_b, tx, conf_height);
+ confirm_transaction_at(node_a, tx, conf_height);
+ connect_blocks(node_a, CHAN_CONFIRM_DEPTH - 1);
create_chan_between_nodes_with_value_confirm_second(node_b, node_a)
}
}}
}
-#[cfg(test)]
+#[cfg(any(test, feature = "unstable"))]
macro_rules! expect_payment_received {
($node: expr, $expected_payment_hash: expr, $expected_recv_value: expr) => {
let events = $node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
Event::PaymentFailed { ref payment_hash, rejected_by_dest, ref error_code, ref error_data } => {
- assert_eq!(*payment_hash, $expected_payment_hash);
- assert_eq!(rejected_by_dest, $rejected_by_dest);
- assert!(error_code.is_some());
- assert!(error_data.is_some());
+ assert_eq!(*payment_hash, $expected_payment_hash, "unexpected payment_hash");
+ assert_eq!(rejected_by_dest, $rejected_by_dest, "unexpected rejected_by_dest value");
+ assert!(error_code.is_some(), "expected error_code.is_some() = true");
+ assert!(error_data.is_some(), "expected error_data.is_some() = true");
$(
- assert_eq!(error_code.unwrap(), $expected_error_code);
- assert_eq!(&error_data.as_ref().unwrap()[..], $expected_error_data);
+ assert_eq!(error_code.unwrap(), $expected_error_code, "unexpected error code");
+ assert_eq!(&error_data.as_ref().unwrap()[..], $expected_error_data, "unexpected error data");
)*
},
_ => panic!("Unexpected event"),
claim_payment_along_route(origin_node, expected_route, false, our_payment_preimage, expected_amount);
}
-pub const TEST_FINAL_CLTV: u32 = 32;
+pub const TEST_FINAL_CLTV: u32 = 50;
pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash) {
let net_graph_msg_handler = &origin_node.net_graph_msg_handler;
let mut chanmgrs = Vec::new();
for i in 0..node_count {
let mut default_config = UserConfig::default();
+ // Set cltv_expiry_delta slightly lower to keep the final CLTV values inside one byte in our
+ // tests so that our script-length checks don't fail (see ACCEPTED_HTLC_SCRIPT_WEIGHT).
+ default_config.channel_options.cltv_expiry_delta = 6*6;
default_config.channel_options.announced_channel = true;
default_config.peer_channel_config_limits.force_announced_channel_preference = false;
default_config.own_channel_config.our_htlc_minimum_msat = 1000; // sanitization being done by the sender, to exerce receiver logic we need to lift of limit
nodes
}
-pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
+// Note that the following only works for CLTV values up to 128
+pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 137; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
#[derive(PartialEq)]