- fn fail_payment(origin_node: &Node, expected_route: &[&Node], our_payment_hash: [u8; 32]) {
- fail_payment_along_route(origin_node, expected_route, false, our_payment_hash);
- }
-
- fn create_network(node_count: usize) -> Vec<Node> {
- let mut nodes = Vec::new();
- let mut rng = thread_rng();
- let secp_ctx = Secp256k1::new();
- let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
-
- let chan_count = Rc::new(RefCell::new(0));
- let payment_count = Rc::new(RefCell::new(0));
-
- for _ in 0..node_count {
- let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 });
- let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
- let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())});
- let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone()));
- let node_id = {
- let mut key_slice = [0; 32];
- rng.fill_bytes(&mut key_slice);
- SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
- };
- let node = ChannelManager::new(node_id.clone(), 0, true, Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger)).unwrap();
- let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), chain_monitor.clone(), Arc::clone(&logger));
- nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router,
- network_payment_count: payment_count.clone(),
- network_chan_count: chan_count.clone(),
- });
- }
-
- nodes
- }
-
- #[test]
- fn fake_network_test() {
- // Simple test which builds a network of ChannelManagers, connects them to each other, and
- // tests that payments get routed and transactions broadcast in semi-reasonable ways.
- let nodes = create_network(4);
-
- // Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
- let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3);
-
- // Rebalance the network a bit by relaying one payment through all the channels...
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 8000000);
-
- // Send some more payments
- send_payment(&nodes[1], &vec!(&nodes[2], &nodes[3])[..], 1000000);
- send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1], &nodes[0])[..], 1000000);
- send_payment(&nodes[3], &vec!(&nodes[2], &nodes[1])[..], 1000000);
-
- // Test failure packets
- let payment_hash_1 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], 1000000).1;
- fail_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3])[..], payment_hash_1);
-
- // Add a new channel that skips 3
- let chan_4 = create_announced_chan_between_nodes(&nodes, 1, 3);
-
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 1000000);
- send_payment(&nodes[2], &vec!(&nodes[3])[..], 1000000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
- send_payment(&nodes[1], &vec!(&nodes[3])[..], 8000000);
-
- // Do some rebalance loop payments, simultaneously
- let mut hops = Vec::with_capacity(3);
- hops.push(RouteHop {
- pubkey: nodes[2].node.get_our_node_id(),
- short_channel_id: chan_2.0.contents.short_channel_id,
- fee_msat: 0,
- cltv_expiry_delta: chan_3.0.contents.cltv_expiry_delta as u32
- });
- hops.push(RouteHop {
- pubkey: nodes[3].node.get_our_node_id(),
- short_channel_id: chan_3.0.contents.short_channel_id,
- fee_msat: 0,
- cltv_expiry_delta: chan_4.1.contents.cltv_expiry_delta as u32
- });
- hops.push(RouteHop {
- pubkey: nodes[1].node.get_our_node_id(),
- short_channel_id: chan_4.0.contents.short_channel_id,
- fee_msat: 1000000,
- cltv_expiry_delta: TEST_FINAL_CLTV,
- });
- hops[1].fee_msat = chan_4.1.contents.fee_base_msat as u64 + chan_4.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
- hops[0].fee_msat = chan_3.0.contents.fee_base_msat as u64 + chan_3.0.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
- let payment_preimage_1 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[2], &nodes[3], &nodes[1])[..], 1000000).0;
-
- let mut hops = Vec::with_capacity(3);
- hops.push(RouteHop {
- pubkey: nodes[3].node.get_our_node_id(),
- short_channel_id: chan_4.0.contents.short_channel_id,
- fee_msat: 0,
- cltv_expiry_delta: chan_3.1.contents.cltv_expiry_delta as u32
- });
- hops.push(RouteHop {
- pubkey: nodes[2].node.get_our_node_id(),
- short_channel_id: chan_3.0.contents.short_channel_id,
- fee_msat: 0,
- cltv_expiry_delta: chan_2.1.contents.cltv_expiry_delta as u32
- });
- hops.push(RouteHop {
- pubkey: nodes[1].node.get_our_node_id(),
- short_channel_id: chan_2.0.contents.short_channel_id,
- fee_msat: 1000000,
- cltv_expiry_delta: TEST_FINAL_CLTV,
- });
- hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
- hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
- let payment_hash_2 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).1;
-
- // Claim the rebalances...
- fail_payment(&nodes[1], &vec!(&nodes[3], &nodes[2], &nodes[1])[..], payment_hash_2);
- claim_payment(&nodes[1], &vec!(&nodes[2], &nodes[3], &nodes[1])[..], payment_preimage_1);
-
- // Add a duplicate new channel from 2 to 4
- let chan_5 = create_announced_chan_between_nodes(&nodes, 1, 3);
-
- // Send some payments across both channels
- let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 3000000).0;
- let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 3000000).0;
- let payment_preimage_5 = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 3000000).0;
-
- route_over_limit(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], 3000000);
-
- //TODO: Test that routes work again here as we've been notified that the channel is full
-
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_3);
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_4);
- claim_payment(&nodes[0], &vec!(&nodes[1], &nodes[3])[..], payment_preimage_5);
-
- // Close down the channels...
- close_channel(&nodes[0], &nodes[1], &chan_1.2, chan_1.3, true);
- close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, false);
- close_channel(&nodes[2], &nodes[3], &chan_3.2, chan_3.3, true);
- close_channel(&nodes[1], &nodes[3], &chan_4.2, chan_4.3, false);
- close_channel(&nodes[1], &nodes[3], &chan_5.2, chan_5.3, false);
- }
-
- #[test]
- fn duplicate_htlc_test() {
- // Test that we accept duplicate payment_hash HTLCs across the network and that
- // claiming/failing them are all separate and don't effect each other
- let mut nodes = create_network(6);
-
- // Create some initial channels to route via 3 to 4/5 from 0/1/2
- create_announced_chan_between_nodes(&nodes, 0, 3);
- create_announced_chan_between_nodes(&nodes, 1, 3);
- create_announced_chan_between_nodes(&nodes, 2, 3);
- create_announced_chan_between_nodes(&nodes, 3, 4);
- create_announced_chan_between_nodes(&nodes, 3, 5);
-
- let (payment_preimage, payment_hash) = route_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], 1000000);
-
- *nodes[0].network_payment_count.borrow_mut() -= 1;
- assert_eq!(route_payment(&nodes[1], &vec!(&nodes[3])[..], 1000000).0, payment_preimage);
-
- *nodes[0].network_payment_count.borrow_mut() -= 1;
- assert_eq!(route_payment(&nodes[2], &vec!(&nodes[3], &nodes[5])[..], 1000000).0, payment_preimage);
-
- claim_payment(&nodes[0], &vec!(&nodes[3], &nodes[4])[..], payment_preimage);
- fail_payment(&nodes[2], &vec!(&nodes[3], &nodes[5])[..], payment_hash);
- claim_payment(&nodes[1], &vec!(&nodes[3])[..], payment_preimage);
- }
-
- #[derive(PartialEq)]
- 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
- /// commitment_tx is provided, which may be used to test that a remote commitment tx was
- /// broadcast and the revoked outputs were claimed.
- ///
- /// Next tests that there is (or is not) a transaction that spends the commitment transaction
- /// that appears to be the type of HTLC transaction specified in has_htlc_tx.
- ///
- /// All broadcast transactions must be accounted for in one of the above three types of we'll
- /// also fail.
- fn test_txn_broadcast(node: &Node, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction), commitment_tx: Option<Transaction>, has_htlc_tx: HTLCType) -> Vec<Transaction> {
- let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert!(node_txn.len() >= if commitment_tx.is_some() { 0 } else { 1 } + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 });
-
- let mut res = Vec::with_capacity(2);
- node_txn.retain(|tx| {
- if tx.input.len() == 1 && tx.input[0].previous_output.txid == chan.3.txid() {
- let mut funding_tx_map = HashMap::new();
- funding_tx_map.insert(chan.3.txid(), chan.3.clone());
- tx.verify(&funding_tx_map).unwrap();
- if commitment_tx.is_none() {
- res.push(tx.clone());
- }
- false
- } else { true }
- });
- if let Some(explicit_tx) = commitment_tx {
- res.push(explicit_tx.clone());
- }
-
- assert_eq!(res.len(), 1);
-
- if has_htlc_tx != HTLCType::NONE {
- node_txn.retain(|tx| {
- if tx.input.len() == 1 && tx.input[0].previous_output.txid == res[0].txid() {
- let mut funding_tx_map = HashMap::new();
- funding_tx_map.insert(res[0].txid(), res[0].clone());
- tx.verify(&funding_tx_map).unwrap();
- if has_htlc_tx == HTLCType::TIMEOUT {
- assert!(tx.lock_time != 0);
- } else {
- assert!(tx.lock_time == 0);
- }
- res.push(tx.clone());
- false
- } else { true }
- });
- assert_eq!(res.len(), 2);
- }
-
- assert!(node_txn.is_empty());
- res
- }
-
- /// Tests that the given node has broadcast a claim transaction against the provided revoked
- /// HTLC transaction.
- fn test_revoked_htlc_claim_txn_broadcast(node: &Node, revoked_tx: Transaction) {
- let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(node_txn.len(), 1);
- node_txn.retain(|tx| {
- if tx.input.len() == 1 && tx.input[0].previous_output.txid == revoked_tx.txid() {
- let mut funding_tx_map = HashMap::new();
- funding_tx_map.insert(revoked_tx.txid(), revoked_tx.clone());
- tx.verify(&funding_tx_map).unwrap();
- false
- } else { true }
- });
- assert!(node_txn.is_empty());
- }
-
- fn check_preimage_claim(node: &Node, prev_txn: &Vec<Transaction>) -> Vec<Transaction> {
- let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
-
- assert!(node_txn.len() >= 1);
- assert_eq!(node_txn[0].input.len(), 1);
- let mut found_prev = false;
-
- for tx in prev_txn {
- if node_txn[0].input[0].previous_output.txid == tx.txid() {
- let mut funding_tx_map = HashMap::new();
- funding_tx_map.insert(tx.txid(), tx.clone());
- node_txn[0].verify(&funding_tx_map).unwrap();
-
- assert!(node_txn[0].input[0].witness[2].len() > 106); // must spend an htlc output
- assert_eq!(tx.input.len(), 1); // must spend a commitment tx
-
- found_prev = true;
- break;
- }