- // So we broadcast C's commitment tx and HTLC-Success on B's chain, we should successfully be able to extract preimage and update downstream monitor
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![c_txn[1].clone(), c_txn[2].clone()]}, 1);
- {
- let mut b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(b_txn.len(), 4);
- assert_eq!(b_txn[0], b_txn[3]);
- check_spends!(b_txn[1], chan_2.3); // B local commitment tx, issued by ChannelManager
- check_spends!(b_txn[2], b_txn[1].clone()); // HTLC-Timeout on B local commitment tx, issued by ChannelManager
- assert_eq!(b_txn[2].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
- assert!(b_txn[2].output[0].script_pubkey.is_v0_p2wsh()); // revokeable output
- assert_ne!(b_txn[2].lock_time, 0); // Timeout tx
- check_spends!(b_txn[0], c_txn[1].clone()); // timeout tx on C remote commitment tx, issued by ChannelMonitor, * 2 due to block rescan
- assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
- assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
- assert_ne!(b_txn[2].lock_time, 0); // Timeout tx
- b_txn.clear();
- }
- let msg_events = nodes[1].node.get_and_clear_pending_msg_events();
- check_added_monitors!(nodes[1], 1);
- match msg_events[0] {
- MessageSendEvent::BroadcastChannelUpdate { .. } => {},
- _ => panic!("Unexpected event"),
- }
- match msg_events[1] {
- MessageSendEvent::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, .. } } => {
- assert!(update_add_htlcs.is_empty());
- assert!(update_fail_htlcs.is_empty());
- assert_eq!(update_fulfill_htlcs.len(), 1);
- assert!(update_fail_malformed_htlcs.is_empty());
- assert_eq!(nodes[0].node.get_our_node_id(), *node_id);
- },
- _ => panic!("Unexpected event"),
- };
- // Broadcast A's commitment tx on B's chain to see if we are able to claim inbound HTLC with our HTLC-Success tx
- let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
- let b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(b_txn.len(), 3);
- check_spends!(b_txn[1], chan_1.3); // Local commitment tx, issued by ChannelManager
- assert_eq!(b_txn[0], b_txn[2]); // HTLC-Success tx, issued by ChannelMonitor, * 2 due to block rescan
- check_spends!(b_txn[0], commitment_tx[0].clone());
- assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
- assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
- assert_eq!(b_txn[2].lock_time, 0); // Success tx
-
- check_closed_broadcast!(nodes[1]);
-}
-
-#[test]
-fn test_duplicate_payment_hash_one_failure_one_success() {
- // Topology : A --> B --> C
- // We route 2 payments with same hash between B and C, one will be timeout, the other successfully claim
- let mut nodes = create_network(3);
-
- create_announced_chan_between_nodes(&nodes, 0, 1);
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
-
- let (our_payment_preimage, duplicate_payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 900000);
- *nodes[0].network_payment_count.borrow_mut() -= 1;
- assert_eq!(route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 900000).1, duplicate_payment_hash);
-
- let commitment_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().last_local_commitment_txn.clone();
- assert_eq!(commitment_txn[0].input.len(), 1);
- check_spends!(commitment_txn[0], chan_2.3.clone());
-
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1);
- check_closed_broadcast!(nodes[1]);
-
- let htlc_timeout_tx;
- { // Extract one of the two HTLC-Timeout transaction
- let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(node_txn.len(), 7);
- assert_eq!(node_txn[0], node_txn[5]);
- assert_eq!(node_txn[1], node_txn[6]);
- check_spends!(node_txn[0], commitment_txn[0].clone());
- assert_eq!(node_txn[0].input.len(), 1);
- check_spends!(node_txn[1], commitment_txn[0].clone());
- assert_eq!(node_txn[1].input.len(), 1);
- assert_ne!(node_txn[0].input[0], node_txn[1].input[0]);
- check_spends!(node_txn[2], chan_2.3.clone());
- check_spends!(node_txn[3], node_txn[2].clone());
- check_spends!(node_txn[4], node_txn[2].clone());
- htlc_timeout_tx = node_txn[1].clone();
- }
-
- nodes[2].node.claim_funds(our_payment_preimage);
- nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![commitment_txn[0].clone()] }, 1);
- check_added_monitors!(nodes[2], 2);
- let events = nodes[2].node.get_and_clear_pending_msg_events();
- match events[0] {
- MessageSendEvent::UpdateHTLCs { .. } => {},
- _ => panic!("Unexpected event"),
- }
- match events[1] {
- MessageSendEvent::BroadcastChannelUpdate { .. } => {},
- _ => panic!("Unexepected event"),
- }
- let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
- assert_eq!(htlc_success_txn.len(), 5);
- check_spends!(htlc_success_txn[2], chan_2.3.clone());
- assert_eq!(htlc_success_txn[0], htlc_success_txn[3]);
- assert_eq!(htlc_success_txn[0].input.len(), 1);
- assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
- assert_eq!(htlc_success_txn[1], htlc_success_txn[4]);
- assert_eq!(htlc_success_txn[1].input.len(), 1);
- assert_eq!(htlc_success_txn[1].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
- assert_ne!(htlc_success_txn[0].input[0], htlc_success_txn[1].input[0]);
- check_spends!(htlc_success_txn[0], commitment_txn[0].clone());
- check_spends!(htlc_success_txn[1], commitment_txn[0].clone());
-
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![htlc_timeout_tx] }, 200);
- expect_pending_htlcs_forwardable!(nodes[1]);
- let htlc_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
- assert!(htlc_updates.update_add_htlcs.is_empty());
- assert_eq!(htlc_updates.update_fail_htlcs.len(), 1);
- assert_eq!(htlc_updates.update_fail_htlcs[0].htlc_id, 1);
- assert!(htlc_updates.update_fulfill_htlcs.is_empty());
- assert!(htlc_updates.update_fail_malformed_htlcs.is_empty());
- check_added_monitors!(nodes[1], 1);
-
- nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]).unwrap();
- assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
- {
- commitment_signed_dance!(nodes[0], nodes[1], &htlc_updates.commitment_signed, false, true);
- let events = nodes[0].node.get_and_clear_pending_msg_events();
- assert_eq!(events.len(), 1);
- match events[0] {
- MessageSendEvent::PaymentFailureNetworkUpdate { update: msgs::HTLCFailChannelUpdate::ChannelClosed { .. } } => {
- },
- _ => { panic!("Unexpected event"); }
- }
- }
- let events = nodes[0].node.get_and_clear_pending_events();
- match events[0] {
- Event::PaymentFailed { ref payment_hash, .. } => {
- assert_eq!(*payment_hash, duplicate_payment_hash);
- }
- _ => panic!("Unexpected event"),
- }
-
- // Solve 2nd HTLC by broadcasting on B's chain HTLC-Success Tx from C
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![htlc_success_txn[0].clone()] }, 200);
- let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
- assert!(updates.update_add_htlcs.is_empty());
- assert!(updates.update_fail_htlcs.is_empty());
- assert_eq!(updates.update_fulfill_htlcs.len(), 1);
- assert_eq!(updates.update_fulfill_htlcs[0].htlc_id, 0);
- assert!(updates.update_fail_malformed_htlcs.is_empty());
- check_added_monitors!(nodes[1], 1);
-
- nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]).unwrap();
- commitment_signed_dance!(nodes[0], nodes[1], &updates.commitment_signed, false);
-
- let events = nodes[0].node.get_and_clear_pending_events();
- match events[0] {
- Event::PaymentSent { ref payment_preimage } => {
- assert_eq!(*payment_preimage, our_payment_preimage);
- }
- _ => panic!("Unexpected event"),
- }
-}
-
-#[test]
-fn test_dynamic_spendable_outputs_local_htlc_success_tx() {
- let nodes = create_network(2);
-
- // Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
-
- let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0;
- let local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
- assert_eq!(local_txn[0].input.len(), 1);
- check_spends!(local_txn[0], chan_1.3.clone());
-
- // Give B knowledge of preimage to be able to generate a local HTLC-Success Tx
- nodes[1].node.claim_funds(payment_preimage);
- check_added_monitors!(nodes[1], 1);
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![local_txn[0].clone()] }, 1);
- let events = nodes[1].node.get_and_clear_pending_msg_events();
- match events[0] {
- MessageSendEvent::UpdateHTLCs { .. } => {},
- _ => panic!("Unexpected event"),
- }
- match events[1] {
- MessageSendEvent::BroadcastChannelUpdate { .. } => {},
- _ => panic!("Unexepected event"),
- }
- let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(node_txn[0].input.len(), 1);
- assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
- check_spends!(node_txn[0], local_txn[0].clone());
-
- // Verify that B is able to spend its own HTLC-Success tx thanks to spendable output event given back by its ChannelMonitor
- let spend_txn = check_spendable_outputs!(nodes[1], 1);
- assert_eq!(spend_txn.len(), 2);
- check_spends!(spend_txn[0], node_txn[0].clone());
- check_spends!(spend_txn[1], node_txn[2].clone());
-}
-
-fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, announce_latest: bool) {
- // Test that we fail backwards the full set of HTLCs we need to when remote broadcasts an
- // unrevoked commitment transaction.
- // This includes HTLCs which were below the dust threshold as well as HTLCs which were awaiting
- // a remote RAA before they could be failed backwards (and combinations thereof).
- // We also test duplicate-hash HTLCs by adding two nodes on each side of the target nodes which
- // use the same payment hashes.
- // Thus, we use a six-node network:
- //
- // A \ / E
- // - C - D -
- // B / \ F
- // And test where C fails back to A/B when D announces its latest commitment transaction
- let nodes = create_network(6);
-
- create_announced_chan_between_nodes(&nodes, 0, 2);
- create_announced_chan_between_nodes(&nodes, 1, 2);
- let chan = create_announced_chan_between_nodes(&nodes, 2, 3);
- create_announced_chan_between_nodes(&nodes, 3, 4);
- create_announced_chan_between_nodes(&nodes, 3, 5);
-
- // Rebalance and check output sanity...
- send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000);
- send_payment(&nodes[1], &[&nodes[2], &nodes[3], &nodes[5]], 500000);
- assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn[0].output.len(), 2);
-
- let ds_dust_limit = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis;
- // 0th HTLC:
- let (_, payment_hash_1) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
- // 1st HTLC:
- let (_, payment_hash_2) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
- let route = nodes[1].router.get_route(&nodes[5].node.get_our_node_id(), None, &Vec::new(), ds_dust_limit*1000, TEST_FINAL_CLTV).unwrap();
- // 2nd HTLC:
- send_along_route_with_hash(&nodes[1], route.clone(), &[&nodes[2], &nodes[3], &nodes[5]], ds_dust_limit*1000, payment_hash_1); // not added < dust limit + HTLC tx fee
- // 3rd HTLC:
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], ds_dust_limit*1000, payment_hash_2); // not added < dust limit + HTLC tx fee
- // 4th HTLC:
- let (_, payment_hash_3) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
- // 5th HTLC:
- let (_, payment_hash_4) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
- let route = nodes[1].router.get_route(&nodes[5].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
- // 6th HTLC:
- send_along_route_with_hash(&nodes[1], route.clone(), &[&nodes[2], &nodes[3], &nodes[5]], 1000000, payment_hash_3);
- // 7th HTLC:
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], 1000000, payment_hash_4);
-
- // 8th HTLC:
- let (_, payment_hash_5) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 1000000);
- // 9th HTLC:
- let route = nodes[1].router.get_route(&nodes[5].node.get_our_node_id(), None, &Vec::new(), ds_dust_limit*1000, TEST_FINAL_CLTV).unwrap();
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], ds_dust_limit*1000, payment_hash_5); // not added < dust limit + HTLC tx fee
-
- // 10th HTLC:
- let (_, payment_hash_6) = route_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], ds_dust_limit*1000); // not added < dust limit + HTLC tx fee
- // 11th HTLC:
- let route = nodes[1].router.get_route(&nodes[5].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
- send_along_route_with_hash(&nodes[1], route, &[&nodes[2], &nodes[3], &nodes[5]], 1000000, payment_hash_6);
-
- // Double-check that six of the new HTLC were added
- // We now have six HTLCs pending over the dust limit and six HTLCs under the dust limit (ie,
- // with to_local and to_remote outputs, 8 outputs and 6 HTLCs not included).
- assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.len(), 1);
- assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn[0].output.len(), 8);
-
- // Now fail back three of the over-dust-limit and three of the under-dust-limit payments in one go.
- // Fail 0th below-dust, 4th above-dust, 8th above-dust, 10th below-dust HTLCs
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_1, ds_dust_limit*1000));
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_3, 1000000));
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_5, 1000000));
- assert!(nodes[4].node.fail_htlc_backwards(&payment_hash_6, ds_dust_limit*1000));
- check_added_monitors!(nodes[4], 0);
- expect_pending_htlcs_forwardable!(nodes[4]);
- check_added_monitors!(nodes[4], 1);
-
- let four_removes = get_htlc_update_msgs!(nodes[4], nodes[3].node.get_our_node_id());
- nodes[3].node.handle_update_fail_htlc(&nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[0]).unwrap();
- nodes[3].node.handle_update_fail_htlc(&nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[1]).unwrap();
- nodes[3].node.handle_update_fail_htlc(&nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[2]).unwrap();
- nodes[3].node.handle_update_fail_htlc(&nodes[4].node.get_our_node_id(), &four_removes.update_fail_htlcs[3]).unwrap();
- commitment_signed_dance!(nodes[3], nodes[4], four_removes.commitment_signed, false);
-
- // Fail 3rd below-dust and 7th above-dust HTLCs
- assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_2, ds_dust_limit*1000));
- assert!(nodes[5].node.fail_htlc_backwards(&payment_hash_4, 1000000));
- check_added_monitors!(nodes[5], 0);
- expect_pending_htlcs_forwardable!(nodes[5]);
- check_added_monitors!(nodes[5], 1);
-
- let two_removes = get_htlc_update_msgs!(nodes[5], nodes[3].node.get_our_node_id());
- nodes[3].node.handle_update_fail_htlc(&nodes[5].node.get_our_node_id(), &two_removes.update_fail_htlcs[0]).unwrap();
- nodes[3].node.handle_update_fail_htlc(&nodes[5].node.get_our_node_id(), &two_removes.update_fail_htlcs[1]).unwrap();
- commitment_signed_dance!(nodes[3], nodes[5], two_removes.commitment_signed, false);
-
- let ds_prev_commitment_tx = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
-
- expect_pending_htlcs_forwardable!(nodes[3]);
- check_added_monitors!(nodes[3], 1);
- let six_removes = get_htlc_update_msgs!(nodes[3], nodes[2].node.get_our_node_id());
- nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[0]).unwrap();
- nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[1]).unwrap();
- nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[2]).unwrap();
- nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[3]).unwrap();
- nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[4]).unwrap();
- nodes[2].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &six_removes.update_fail_htlcs[5]).unwrap();
- if deliver_last_raa {
- commitment_signed_dance!(nodes[2], nodes[3], six_removes.commitment_signed, false);
- } else {
- let _cs_last_raa = commitment_signed_dance!(nodes[2], nodes[3], six_removes.commitment_signed, false, true, false, true);
- }
-
- // D's latest commitment transaction now contains 1st + 2nd + 9th HTLCs (implicitly, they're
- // below the dust limit) and the 5th + 6th + 11th HTLCs. It has failed back the 0th, 3rd, 4th,
- // 7th, 8th, and 10th, but as we haven't yet delivered the final RAA to C, the fails haven't
- // propagated back to A/B yet (and D has two unrevoked commitment transactions).
- //
- // We now broadcast the latest commitment transaction, which *should* result in failures for
- // the 0th, 1st, 2nd, 3rd, 4th, 7th, 8th, 9th, and 10th HTLCs, ie all the below-dust HTLCs and
- // the non-broadcast above-dust HTLCs.
- //
- // Alternatively, we may broadcast the previous commitment transaction, which should only
- // result in failures for the below-dust HTLCs, ie the 0th, 1st, 2nd, 3rd, 9th, and 10th HTLCs.
- let ds_last_commitment_tx = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
-
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- if announce_latest {
- nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&ds_last_commitment_tx[0]], &[1; 1]);
- } else {
- nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&ds_prev_commitment_tx[0]], &[1; 1]);
- }
- check_closed_broadcast!(nodes[2]);
- expect_pending_htlcs_forwardable!(nodes[2]);
- check_added_monitors!(nodes[2], 2);
-
- let cs_msgs = nodes[2].node.get_and_clear_pending_msg_events();
- assert_eq!(cs_msgs.len(), 2);
- let mut a_done = false;
- for msg in cs_msgs {
- match msg {
- MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => {
- // Both under-dust HTLCs and the one above-dust HTLC that we had already failed
- // should be failed-backwards here.
- let target = if *node_id == nodes[0].node.get_our_node_id() {
- // If announce_latest, expect 0th, 1st, 4th, 8th, 10th HTLCs, else only 0th, 1st, 10th below-dust HTLCs
- for htlc in &updates.update_fail_htlcs {
- assert!(htlc.htlc_id == 1 || htlc.htlc_id == 2 || htlc.htlc_id == 6 || if announce_latest { htlc.htlc_id == 3 || htlc.htlc_id == 5 } else { false });
- }
- assert_eq!(updates.update_fail_htlcs.len(), if announce_latest { 5 } else { 3 });
- assert!(!a_done);
- a_done = true;
- &nodes[0]
- } else {
- // If announce_latest, expect 2nd, 3rd, 7th, 9th HTLCs, else only 2nd, 3rd, 9th below-dust HTLCs
- for htlc in &updates.update_fail_htlcs {
- assert!(htlc.htlc_id == 1 || htlc.htlc_id == 2 || htlc.htlc_id == 5 || if announce_latest { htlc.htlc_id == 4 } else { false });
- }
- assert_eq!(*node_id, nodes[1].node.get_our_node_id());
- assert_eq!(updates.update_fail_htlcs.len(), if announce_latest { 4 } else { 3 });
- &nodes[1]
- };
- target.node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[0]).unwrap();
- target.node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[1]).unwrap();
- target.node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[2]).unwrap();
- if announce_latest {
- target.node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[3]).unwrap();
- if *node_id == nodes[0].node.get_our_node_id() {
- target.node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fail_htlcs[4]).unwrap();
- }
- }
- commitment_signed_dance!(target, nodes[2], updates.commitment_signed, false, true);
- },
- _ => panic!("Unexpected event"),
- }
- }
-
- let as_events = nodes[0].node.get_and_clear_pending_events();
- assert_eq!(as_events.len(), if announce_latest { 5 } else { 3 });
- let mut as_failds = HashSet::new();
- for event in as_events.iter() {
- if let &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, .. } = event {
- assert!(as_failds.insert(*payment_hash));
- if *payment_hash != payment_hash_2 {
- assert_eq!(*rejected_by_dest, deliver_last_raa);
- } else {
- assert!(!rejected_by_dest);
- }
- } else { panic!("Unexpected event"); }
- }
- assert!(as_failds.contains(&payment_hash_1));
- assert!(as_failds.contains(&payment_hash_2));
- if announce_latest {
- assert!(as_failds.contains(&payment_hash_3));
- assert!(as_failds.contains(&payment_hash_5));
- }
- assert!(as_failds.contains(&payment_hash_6));
-
- let bs_events = nodes[1].node.get_and_clear_pending_events();
- assert_eq!(bs_events.len(), if announce_latest { 4 } else { 3 });
- let mut bs_failds = HashSet::new();
- for event in bs_events.iter() {
- if let &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest, .. } = event {
- assert!(bs_failds.insert(*payment_hash));
- if *payment_hash != payment_hash_1 && *payment_hash != payment_hash_5 {
- assert_eq!(*rejected_by_dest, deliver_last_raa);
- } else {
- assert!(!rejected_by_dest);
- }
- } else { panic!("Unexpected event"); }
- }
- assert!(bs_failds.contains(&payment_hash_1));
- assert!(bs_failds.contains(&payment_hash_2));
- if announce_latest {
- assert!(bs_failds.contains(&payment_hash_4));
- }
- assert!(bs_failds.contains(&payment_hash_5));
-
- // For each HTLC which was not failed-back by normal process (ie deliver_last_raa), we should
- // get a PaymentFailureNetworkUpdate. A should have gotten 4 HTLCs which were failed-back due
- // to unknown-preimage-etc, B should have gotten 2. Thus, in the
- // announce_latest && deliver_last_raa case, we should have 5-4=1 and 4-2=2
- // PaymentFailureNetworkUpdates.
- let as_msg_events = nodes[0].node.get_and_clear_pending_msg_events();
- assert_eq!(as_msg_events.len(), if deliver_last_raa { 1 } else if !announce_latest { 3 } else { 5 });
- let bs_msg_events = nodes[1].node.get_and_clear_pending_msg_events();
- assert_eq!(bs_msg_events.len(), if deliver_last_raa { 2 } else if !announce_latest { 3 } else { 4 });
- for event in as_msg_events.iter().chain(bs_msg_events.iter()) {
- match event {
- &MessageSendEvent::PaymentFailureNetworkUpdate { .. } => {},
- _ => panic!("Unexpected event"),
- }
- }
-}