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.
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].last_blockhash.lock().unwrap(), 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);
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
});
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
});
+ // 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.lock().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.last_block_hash.lock().unwrap() = block_hash;
self.latest_block_height.store(height as usize, Ordering::Release);
}
*self.last_block_hash.lock().unwrap() = block_hash;
self.latest_block_height.store(height as usize, Ordering::Release);
}
+ assert_eq!(*self.last_block_hash.lock().unwrap(), header.block_hash(),
+ "Blocks must be disconnected in chain-order - the disconnected header must be the last connected header");
*self.last_block_hash.lock().unwrap() = header.prev_blockhash;
self.latest_block_height.fetch_sub(1, Ordering::AcqRel);
}
*self.last_block_hash.lock().unwrap() = header.prev_blockhash;
self.latest_block_height.fetch_sub(1, Ordering::AcqRel);
}
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: genesis_block(Network::Testnet).header.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());
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
node.chain_monitor.chain_monitor.block_connected(&block.header, &txdata, height);
node.node.block_connected(&block.header, &txdata, height);
let txdata: Vec<_> = block.txdata.iter().enumerate().collect();
node.chain_monitor.chain_monitor.block_connected(&block.header, &txdata, height);
node.node.block_connected(&block.header, &txdata, height);
+ *node.last_blockhash.lock().unwrap() = block.header.block_hash();
}
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);
}
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.last_blockhash.lock().unwrap() = header.prev_blockhash;
}
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 last_blockhash: Mutex<BlockHash>,
}
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,
+ last_blockhash: Mutex::new(genesis_block(Network::Testnet).header.block_hash()),
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 };
};
// 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 new_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: new_header, 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], &new_header, 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);