Take the full funding transaction from the user on generation
[rust-lightning] / lightning / src / ln / functional_test_utils.rs
index 0716fef9ff80a20377c570b9859eb31aaa21a883..2ebdac5d031f4a00b0efe2df418744a3b54199b9 100644 (file)
@@ -44,53 +44,81 @@ use std::sync::Mutex;
 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: Default::default(), 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();
+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 {
@@ -123,6 +151,15 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> {
        pub network_payment_count: Rc<RefCell<u8>>,
        pub network_chan_count: Rc<RefCell<u32>>,
        pub logger: &'c test_utils::TestLogger,
+       pub blocks: RefCell<Vec<(BlockHeader, u32)>>,
+}
+impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
+       pub fn best_block_hash(&self) -> BlockHash {
+               self.blocks.borrow_mut().last().unwrap().0.block_hash()
+       }
+       pub fn best_block_info(&self) -> (BlockHash, u32) {
+               self.blocks.borrow_mut().last().map(|(a, b)| (a.block_hash(), *b)).unwrap()
+       }
 }
 
 impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
@@ -384,7 +421,7 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
 
        let (temporary_channel_id, tx, funding_output) = create_funding_transaction(node_a, channel_value, 42);
 
-       node_a.node.funding_transaction_generated(&temporary_channel_id, funding_output);
+       node_a.node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
        check_added_monitors!(node_a, 0);
 
        node_b.node.handle_funding_created(&node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id()));
@@ -404,20 +441,18 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
        }
 
        let events_4 = node_a.node.get_and_clear_pending_events();
-       assert_eq!(events_4.len(), 1);
-       match events_4[0] {
-               Event::FundingBroadcastSafe { ref funding_txo, user_channel_id } => {
-                       assert_eq!(user_channel_id, 42);
-                       assert_eq!(*funding_txo, funding_output);
-               },
-               _ => panic!("Unexpected event"),
-       };
+       assert_eq!(events_4.len(), 0);
+
+       assert_eq!(node_a.tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
+       assert_eq!(node_a.tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx);
+       node_a.tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
 
        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()));
 }
 
@@ -442,8 +477,10 @@ pub fn create_chan_between_nodes_with_value_confirm_second<'a, 'b, 'c>(node_recv
 }
 
 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)
 }
 
@@ -843,13 +880,13 @@ macro_rules! expect_payment_failed {
                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"),
@@ -1020,7 +1057,7 @@ pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route:
        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;
@@ -1161,6 +1198,9 @@ pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec<NodeCfg<'b>
        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
@@ -1189,13 +1229,15 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
                                 keys_manager: &cfgs[i].keys_manager, node: &chan_mgrs[i], net_graph_msg_handler,
                                 node_seed: cfgs[i].node_seed, network_chan_count: chan_count.clone(),
                                 network_payment_count: payment_count.clone(), logger: cfgs[i].logger,
+                                blocks: RefCell::new(vec![(genesis_block(Network::Testnet).header, 0)])
                })
        }
 
        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)]