Sadly the connected-in-order tests have to be skipped in our normal
test suite as many tests violate it. Luckily we can still enforce
it in the tests which run in other crates.
Co-authored-by: Matt Corallo <git@bluematt.me>
Co-authored-by: Jeffrey Czyz <jkczyz@gmail.com>
macro_rules! confirm_txn {
($node: expr) => { {
macro_rules! confirm_txn {
($node: expr) => { {
- let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ let chain_hash = genesis_block(Network::Bitcoin).block_hash();
+ let mut header = BlockHeader { version: 0x20000000, prev_blockhash: chain_hash, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
let txdata: Vec<_> = channel_txn.iter().enumerate().map(|(i, tx)| (i + 1, tx)).collect();
$node.block_connected(&header, &txdata, 1);
for i in 2..100 {
let txdata: Vec<_> = channel_txn.iter().enumerate().map(|(i, tx)| (i + 1, tx)).collect();
$node.block_connected(&header, &txdata, 1);
for i in 2..100 {
peers: &'a RefCell<[bool; 256]>,
funding_txn: Vec<Transaction>,
txids_confirmed: HashMap<Txid, usize>,
peers: &'a RefCell<[bool; 256]>,
funding_txn: Vec<Transaction>,
txids_confirmed: HashMap<Txid, usize>,
- header_hashes: Vec<BlockHash>,
+ header_hashes: Vec<(BlockHash, u32)>,
height: usize,
max_height: usize,
blocks_connected: u32,
height: usize,
max_height: usize,
blocks_connected: u32,
peers,
funding_txn: Vec::new(),
txids_confirmed: HashMap::new(),
peers,
funding_txn: Vec::new(),
txids_confirmed: HashMap::new(),
- header_hashes: vec![Default::default()],
+ header_hashes: vec![(genesis_block(Network::Bitcoin).block_hash(), 0)],
height: 0,
max_height: 0,
blocks_connected: 0,
height: 0,
max_height: 0,
blocks_connected: 0,
- let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: self.blocks_connected, bits: 42, nonce: 42 };
- self.height += 1;
self.blocks_connected += 1;
self.blocks_connected += 1;
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height].0, merkle_root: Default::default(), time: self.blocks_connected, bits: 42, nonce: 42 };
+ self.height += 1;
self.manager.block_connected(&header, &txdata, self.height as u32);
(*self.monitor).block_connected(&header, &txdata, self.height as u32);
if self.header_hashes.len() > self.height {
self.manager.block_connected(&header, &txdata, self.height as u32);
(*self.monitor).block_connected(&header, &txdata, self.height as u32);
if self.header_hashes.len() > self.height {
- self.header_hashes[self.height] = header.block_hash();
+ self.header_hashes[self.height] = (header.block_hash(), self.blocks_connected);
} else {
assert_eq!(self.header_hashes.len(), self.height);
} else {
assert_eq!(self.header_hashes.len(), self.height);
- self.header_hashes.push(header.block_hash());
+ self.header_hashes.push((header.block_hash(), self.blocks_connected));
}
self.max_height = cmp::max(self.height, self.max_height);
}
fn disconnect_block(&mut self) {
if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) {
}
self.max_height = cmp::max(self.height, self.max_height);
}
fn disconnect_block(&mut self) {
if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) {
- let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height - 1].0, merkle_root: Default::default(), time: self.header_hashes[self.height].1, bits: 42, nonce: 42 };
self.manager.block_disconnected(&header);
self.monitor.block_disconnected(&header, self.height as u32);
self.height -= 1;
self.manager.block_disconnected(&header);
self.monitor.block_disconnected(&header, self.height as u32);
self.height -= 1;
let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- connect_block(&nodes[1], &Block { header, txdata: vec![node_txn[0].clone(), node_txn[0].clone()]}, 1);
+ let header = BlockHeader { version: 0x20000000, prev_blockhash: nodes[0].best_block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ connect_block(&nodes[1], &Block { header, txdata: vec![node_txn[0].clone(), node_txn[0].clone()]}, CHAN_CONFIRM_DEPTH);
check_closed_broadcast!(nodes[1], false);
check_added_monitors!(nodes[1], 1);
check_closed_broadcast!(nodes[1], false);
check_added_monitors!(nodes[1], 1);
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
+
+ // This assertion should be enforced in tests, however we have a number of tests that
+ // were written before this requirement and do not meet it.
+ #[cfg(not(test))]
+ {
+ assert_eq!(*self.last_block_hash.read().unwrap(), header.prev_blockhash,
+ "Blocks must be connected in chain-order - the connected header must build on the last connected header");
+ assert_eq!(self.latest_block_height.load(Ordering::Acquire) as u64, height as u64 - 1,
+ "Blocks must be connected in chain-order - the connected header must build on the last connected header");
+ }
self.latest_block_height.store(height as usize, Ordering::Release);
*self.last_block_hash.write().unwrap() = block_hash;
self.latest_block_height.store(height as usize, Ordering::Release);
*self.last_block_hash.write().unwrap() = block_hash;
// See the docs for `ChannelManagerReadArgs` for more.
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
// See the docs for `ChannelManagerReadArgs` for more.
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
+ assert_eq!(*self.last_block_hash.read().unwrap(), header.block_hash(),
+ "Blocks must be disconnected in chain-order - the disconnected header must be the last connected header");
self.latest_block_height.fetch_sub(1, Ordering::AcqRel);
*self.last_block_hash.write().unwrap() = header.prev_blockhash;
self.latest_block_height.fetch_sub(1, Ordering::AcqRel);
*self.last_block_hash.write().unwrap() = header.prev_blockhash;
let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
let dummy_tx_count = tx.version as usize;
let mut block = Block {
let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
let dummy_tx_count = tx.version as usize;
let mut block = Block {
- header: BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ 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],
};
block.txdata.push(tx.clone());
txdata: vec![dummy_tx; dummy_tx_count],
};
block.txdata.push(tx.clone());
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.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_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 struct TestChanMonCfg {
}
pub struct TestChanMonCfg {
pub network_payment_count: Rc<RefCell<u8>>,
pub network_chan_count: Rc<RefCell<u32>>,
pub logger: &'c test_utils::TestLogger,
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> {
}
impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> {
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,
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)])
use util::ser::{ReadableArgs, Writeable};
use bitcoin::blockdata::block::{Block, BlockHeader};
use util::ser::{ReadableArgs, Writeable};
use bitcoin::blockdata::block::{Block, BlockHeader};
+use bitcoin::blockdata::constants::genesis_block;
use bitcoin::hash_types::BlockHash;
use bitcoin::hash_types::BlockHash;
+use bitcoin::network::constants::Network;
use std::collections::HashMap;
use std::mem;
use std::collections::HashMap;
use std::mem;
mem::drop(channel_state);
let mut headers = Vec::new();
mem::drop(channel_state);
let mut headers = Vec::new();
- let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ let mut header = BlockHeader { version: 0x20000000, prev_blockhash: genesis_block(Network::Testnet).header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
headers.push(header.clone());
for _i in 2..100 {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
headers.push(header.clone());
for _i in 2..100 {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
check_spends!(remote_txn[2], remote_txn[0]);
// Connect blocks on node A to advance height towards TEST_FINAL_CLTV
check_spends!(remote_txn[2], remote_txn[0]);
// Connect blocks on node A to advance height towards TEST_FINAL_CLTV
- let prev_header_100 = connect_blocks(&nodes[1], 100, 0, false, Default::default());
+ let block_hash_100 = connect_blocks(&nodes[1], 100, 0, false, genesis_block(Network::Testnet).header.block_hash());
// Provide node A with both preimage
nodes[0].node.claim_funds(payment_preimage_1, &None, 3_000_000);
nodes[0].node.claim_funds(payment_preimage_2, &None, 3_000_000);
// Provide node A with both preimage
nodes[0].node.claim_funds(payment_preimage_1, &None, 3_000_000);
nodes[0].node.claim_funds(payment_preimage_2, &None, 3_000_000);
nodes[0].node.get_and_clear_pending_msg_events();
// Connect blocks on node A commitment transaction
nodes[0].node.get_and_clear_pending_msg_events();
// Connect blocks on node A commitment transaction
- let header = BlockHeader { version: 0x20000000, prev_blockhash: prev_header_100, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- connect_block(&nodes[0], &Block { header, txdata: vec![remote_txn[0].clone()] }, 101);
+ let header_101 = BlockHeader { version: 0x20000000, prev_blockhash: block_hash_100, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ connect_block(&nodes[0], &Block { header: header_101, txdata: vec![remote_txn[0].clone()] }, 101);
check_closed_broadcast!(nodes[0], false);
check_added_monitors!(nodes[0], 1);
// Verify node A broadcast tx claiming both HTLCs
check_closed_broadcast!(nodes[0], false);
check_added_monitors!(nodes[0], 1);
// Verify node A broadcast tx claiming both HTLCs
};
// Broadcast partial claim on node A, should regenerate a claiming tx with HTLC dropped
};
// Broadcast partial claim on node A, should regenerate a claiming tx with HTLC dropped
- let header = BlockHeader { version: 0x20000000, prev_blockhash: header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- connect_block(&nodes[0], &Block { header, txdata: vec![partial_claim_tx.clone()] }, 102);
+ let header_102 = BlockHeader { version: 0x20000000, prev_blockhash: header_101.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+ connect_block(&nodes[0], &Block { header: header_102, txdata: vec![partial_claim_tx.clone()] }, 102);
{
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
{
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
nodes[0].node.get_and_clear_pending_msg_events();
// Disconnect last block on node A, should regenerate a claiming tx with HTLC dropped
nodes[0].node.get_and_clear_pending_msg_events();
// Disconnect last block on node A, should regenerate a claiming tx with HTLC dropped
- disconnect_block(&nodes[0], &header, 102);
+ disconnect_block(&nodes[0], &header_102, 102);
{
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
{
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
}
//// Disconnect one more block and then reconnect multiple no transaction should be generated
}
//// Disconnect one more block and then reconnect multiple no transaction should be generated
- disconnect_block(&nodes[0], &header, 101);
- connect_blocks(&nodes[1], 15, 101, false, prev_header_100);
+ disconnect_block(&nodes[0], &header_101, 101);
+ connect_blocks(&nodes[1], 15, 101, false, block_hash_100);
{
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 0);
{
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 0);