+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) {
+ 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 first_connect_height = node.best_block_info().1 + 1;
+ assert!(first_connect_height <= conf_height);
+ if conf_height > first_connect_height {
+ connect_blocks(node, conf_height - first_connect_height);
+ }
+ let mut block = Block {
+ header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: conf_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: 0, input: Vec::new(), output: Vec::new() });
+ }
+ block.txdata.push(tx.clone());
+ connect_block(node, &block);
+}
+
+/// The possible ways we may notify a ChannelManager of a new block
+#[derive(Clone, Copy, PartialEq)]
+pub enum ConnectStyle {
+ /// Calls best_block_updated first, detecting transactions in the block only after receiving the
+ /// header and height information.
+ BestBlockFirst,
+ /// The same as BestBlockFirst, however when we have multiple blocks to connect, we only
+ /// make a single best_block_updated call.
+ BestBlockFirstSkippingBlocks,
+ /// Calls transactions_confirmed first, detecting transactions in the block before updating the
+ /// header and height information.
+ TransactionsFirst,
+ /// The same as TransactionsFirst, however when we have multiple blocks to connect, we only
+ /// make a single best_block_updated call.
+ TransactionsFirstSkippingBlocks,
+ /// Provides the full block via the chain::Listen interface. In the current code this is
+ /// equivalent to TransactionsFirst with some additional assertions.
+ FullBlockViaListen,
+}
+
+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 => true,
+ _ => false,
+ };
+
+ let height = node.best_block_info().1 + 1;
+ let mut block = Block {
+ header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: height, bits: 42, nonce: 42 },
+ txdata: vec![],
+ };
+ assert!(depth >= 1);
+ for i in 1..depth {
+ do_connect_block(node, &block, skip_intermediaries);
+ block = Block {
+ header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: height + i, bits: 42, nonce: 42 },
+ txdata: vec![],
+ };
+ }
+ connect_block(node, &block);
+ block.header.block_hash()
+}
+
+pub fn connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block) {
+ do_connect_block(node, block, false);
+}
+
+fn do_connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block, skip_intermediaries: bool) {
+ let height = node.best_block_info().1 + 1;
+ if !skip_intermediaries {
+ let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
+ match *node.connect_style.borrow() {
+ ConnectStyle::BestBlockFirst|ConnectStyle::BestBlockFirstSkippingBlocks => {
+ node.chain_monitor.chain_monitor.best_block_updated(&block.header, height);
+ node.chain_monitor.chain_monitor.transactions_confirmed(&block.header, &txdata, height);
+ node.node.best_block_updated(&block.header, height);
+ node.node.transactions_confirmed(&block.header, &txdata, height);
+ },
+ ConnectStyle::TransactionsFirst|ConnectStyle::TransactionsFirstSkippingBlocks => {
+ node.chain_monitor.chain_monitor.transactions_confirmed(&block.header, &txdata, height);
+ node.chain_monitor.chain_monitor.best_block_updated(&block.header, height);
+ node.node.transactions_confirmed(&block.header, &txdata, height);
+ node.node.best_block_updated(&block.header, height);
+ },
+ ConnectStyle::FullBlockViaListen => {
+ node.chain_monitor.chain_monitor.block_connected(&block, height);
+ node.node.block_connected(&block, height);
+ }
+ }