+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
//! A bunch of useful utilities for building networks of nodes and exchanging messages between
//! nodes for functional tests.
use util::config::UserConfig;
use util::ser::{ReadableArgs, Writeable, Readable};
-use bitcoin::util::hash::BitcoinHash;
-use bitcoin::blockdata::block::BlockHeader;
+use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::network::constants::Network;
use bitcoin::secp256k1::key::PublicKey;
-use rand::{thread_rng,Rng};
-
use std::cell::RefCell;
use std::rc::Rc;
-use std::sync::{Mutex, RwLock};
+use std::sync::Mutex;
use std::mem;
use std::collections::HashMap;
pub const CHAN_CONFIRM_DEPTH: u32 = 100;
-pub fn confirm_transaction<'a, 'b: 'a>(notifier: &'a chaininterface::BlockNotifierRef<'b, &chaininterface::ChainWatchInterfaceUtil>, chain: &chaininterface::ChainWatchInterfaceUtil, tx: &Transaction, chan_id: u32) {
- assert!(chain.does_match_tx(tx));
- let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- notifier.block_connected_checked(&header, 1, &[tx; 1], &[chan_id; 1]);
+
+pub fn confirm_transaction<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &Transaction) {
+ let notifier = &node.block_notifier;
+ 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 },
+ txdata: vec![dummy_tx; dummy_tx_count],
+ };
+ block.txdata.push(tx.clone());
+ notifier.block_connected(&block, 1);
for i in 2..CHAN_CONFIRM_DEPTH {
- header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- notifier.block_connected_checked(&header, i, &vec![], &[0; 0]);
+ block = Block {
+ header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ txdata: vec![],
+ };
+ notifier.block_connected(&block, i);
}
}
-pub fn connect_blocks<'a, 'b>(notifier: &'a chaininterface::BlockNotifierRef<'b, &chaininterface::ChainWatchInterfaceUtil>, depth: u32, height: u32, parent: bool, prev_blockhash: BlockHash) -> BlockHash {
- let mut header = BlockHeader { version: 0x2000000, prev_blockhash: if parent { prev_blockhash } else { Default::default() }, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- notifier.block_connected_checked(&header, height + 1, &Vec::new(), &Vec::new());
+pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32, height: u32, parent: bool, prev_blockhash: BlockHash) -> BlockHash {
+ let notifier = &node.block_notifier;
+ 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 },
+ txdata: vec![],
+ };
+ notifier.block_connected(&block, height + 1);
for i in 2..depth + 1 {
- header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- notifier.block_connected_checked(&header, height + i, &Vec::new(), &Vec::new());
+ block = Block {
+ header: BlockHeader { version: 0x20000000, prev_blockhash: block.header.block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
+ txdata: vec![],
+ };
+ notifier.block_connected(&block, height + i);
}
- header.bitcoin_hash()
+ block.header.block_hash()
}
pub struct TestChanMonCfg {
}
pub struct Node<'a, 'b: 'a, 'c: 'b> {
- pub block_notifier: chaininterface::BlockNotifierRef<'a, &'c chaininterface::ChainWatchInterfaceUtil>,
+ pub block_notifier: chaininterface::BlockNotifierRef<'a>,
pub chain_monitor: &'c chaininterface::ChainWatchInterfaceUtil,
pub tx_broadcaster: &'c test_utils::TestBroadcaster,
pub chan_monitor: &'b test_utils::TestChannelMonitor<'c>,
let network_graph_deser = <NetworkGraph>::read(&mut ::std::io::Cursor::new(&w.0)).unwrap();
assert!(network_graph_deser == *self.net_graph_msg_handler.network_graph.read().unwrap());
let net_graph_msg_handler = NetGraphMsgHandler::from_net_graph(
- self.chain_monitor, self.logger, RwLock::new(network_graph_deser)
+ self.chain_monitor, self.logger, network_graph_deser
);
let mut chan_progress = 0;
loop {
{
let mut channel_monitors = HashMap::new();
for monitor in deserialized_monitors.iter_mut() {
- channel_monitors.insert(monitor.get_funding_txo(), monitor);
+ channel_monitors.insert(monitor.get_funding_txo().0, monitor);
}
let mut w = test_utils::TestVecWriter(Vec::new());
monitor: self.chan_monitor,
tx_broadcaster: self.tx_broadcaster.clone(),
logger: &test_utils::TestLogger::new(),
- channel_monitors: &mut channel_monitors,
+ channel_monitors,
}).unwrap();
}
let chain_watch = chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet);
let channel_monitor = test_utils::TestChannelMonitor::new(&chain_watch, self.tx_broadcaster.clone(), &self.logger, &feeest);
for deserialized_monitor in deserialized_monitors.drain(..) {
- if let Err(_) = channel_monitor.add_monitor(deserialized_monitor.get_funding_txo(), deserialized_monitor) {
+ if let Err(_) = channel_monitor.add_monitor(deserialized_monitor.get_funding_txo().0, deserialized_monitor) {
panic!();
}
}
let mut commitment_txn = None;
for (funding_txo, monitor) in monitors.iter_mut() {
if funding_txo.to_channel_id() == $channel_id {
- commitment_txn = Some(monitor.unsafe_get_latest_local_commitment_txn(&$node.logger));
+ commitment_txn = Some(monitor.unsafe_get_latest_holder_commitment_txn(&$node.logger));
break;
}
}
assert_eq!(*channel_value_satoshis, expected_chan_value);
assert_eq!(user_channel_id, expected_user_chan_id);
- let tx = Transaction { version: chan_id as u32, lock_time: 0, input: Vec::new(), output: vec![TxOut {
+ let tx = Transaction { version: chan_id as i32, lock_time: 0, input: Vec::new(), output: vec![TxOut {
value: *channel_value_satoshis, script_pubkey: output_script.clone(),
}]};
let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 };
}
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.block_notifier, &node_conf.chain_monitor, &tx, tx.version);
+ confirm_transaction(node_conf, tx);
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.block_notifier, &node_a.chain_monitor, &tx, tx.version);
+ confirm_transaction(node_a, tx);
create_chan_between_nodes_with_value_confirm_second(node_b, node_a)
}
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 logger = test_utils::TestLogger::new();
- let route = get_route(&origin_node.node.get_our_node_id(), net_graph_msg_handler, &expected_route.last().unwrap().node.get_our_node_id(), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) {
let logger = test_utils::TestLogger::new();
let net_graph_msg_handler = &origin_node.net_graph_msg_handler;
- let route = get_route(&origin_node.node.get_our_node_id(), net_graph_msg_handler, &expected_route.last().unwrap().node.get_our_node_id(), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
+ let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap();
assert_eq!(route.paths.len(), 1);
assert_eq!(route.paths[0].len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
}
let (_, our_payment_hash) = get_payment_preimage_hash!(origin_node);
- unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
- assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
+ unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err },
+ assert!(err.contains("Cannot send value that would put us over the max HTLC value in flight our peer will accept")));
}
pub fn send_payment<'a, 'b, 'c>(origin: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64, expected_value: u64) {
pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec<TestChanMonCfg>) -> Vec<NodeCfg<'a>> {
let mut nodes = Vec::new();
- let mut rng = thread_rng();
for i in 0..node_count {
- let mut seed = [0; 32];
- rng.fill_bytes(&mut seed);
+ let seed = [i as u8; 32];
let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
let chan_monitor = test_utils::TestChannelMonitor::new(&chanmon_cfgs[i].chain_monitor, &chanmon_cfgs[i].tx_broadcaster, &chanmon_cfgs[i].logger, &chanmon_cfgs[i].fee_estimator);
nodes.push(NodeCfg { chain_monitor: &chanmon_cfgs[i].chain_monitor, logger: &chanmon_cfgs[i].logger, tx_broadcaster: &chanmon_cfgs[i].tx_broadcaster, fee_estimator: &chanmon_cfgs[i].fee_estimator, chan_monitor, keys_manager, node_seed: seed });
let payment_count = Rc::new(RefCell::new(0));
for i in 0..node_count {
- let block_notifier = chaininterface::BlockNotifier::new(cfgs[i].chain_monitor);
+ let block_notifier = chaininterface::BlockNotifier::new();
block_notifier.register_listener(&cfgs[i].chan_monitor.simple_monitor as &chaininterface::ChainListener);
block_notifier.register_listener(&chan_mgrs[i] as &chaininterface::ChainListener);
let net_graph_msg_handler = NetGraphMsgHandler::new(cfgs[i].chain_monitor, cfgs[i].logger);
pub enum HTLCType { NONE, TIMEOUT, SUCCESS }
/// Tests that the given node has broadcast transactions for the given Channel
///
-/// First checks that the latest local commitment tx has been broadcast, unless an explicit
+/// First checks that the latest holder commitment tx has been broadcast, unless an explicit
/// commitment_tx is provided, which may be used to test that a remote commitment tx was
/// broadcast and the revoked outputs were claimed.
///
}
if send_funding_locked.0 || send_funding_locked.1 {
// If we expect any funding_locked's, both sides better have set
- // next_local_commitment_number to 1
+ // next_holder_commitment_number to 1
for reestablish in reestablish_1.iter() {
assert_eq!(reestablish.next_local_commitment_number, 1);
}