X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_tests.rs;h=9c0a4b4b066ac1e50c5cacabf836979cd9dec792;hb=refs%2Fheads%2F2023-04-claim-from-closed;hp=38a78ab65636ed861f1d3b5707304917f5df6b48;hpb=68122bd09de5feca5538247f2533ec3b89ccf242;p=rust-lightning diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 38a78ab6..9c0a4b4b 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -541,6 +541,8 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) { assert_eq!(added_monitors[0].0, funding_output); added_monitors.clear(); } + expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); + let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); if steps & 0x0f == 5 { return; } @@ -552,6 +554,7 @@ fn do_test_sanity_on_in_flight_opens(steps: u8) { added_monitors.clear(); } + expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); let events_4 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_4.len(), 0); @@ -1963,7 +1966,7 @@ fn test_channel_reserve_holding_cell_htlcs() { let events = nodes[2].node.get_and_clear_pending_events(); assert_eq!(events.len(), 2); match events[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_id: _ } => { + Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { assert_eq!(our_payment_hash_21, *payment_hash); assert_eq!(recv_value_21, amount_msat); assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap()); @@ -1979,7 +1982,7 @@ fn test_channel_reserve_holding_cell_htlcs() { _ => panic!("Unexpected event"), } match events[1] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_id: _ } => { + Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { assert_eq!(our_payment_hash_22, *payment_hash); assert_eq!(recv_value_22, amount_msat); assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap()); @@ -2731,20 +2734,22 @@ fn test_htlc_on_chain_success() { } let chan_id = Some(chan_1.2); match forwarded_events[1] { - Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id } => { + Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, outbound_amount_forwarded_msat } => { assert_eq!(fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, chan_id); assert_eq!(claim_from_onchain_tx, true); assert_eq!(next_channel_id, Some(chan_2.2)); + assert_eq!(outbound_amount_forwarded_msat, Some(3000000)); }, _ => panic!() } match forwarded_events[2] { - Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id } => { + Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, outbound_amount_forwarded_msat } => { assert_eq!(fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, chan_id); assert_eq!(claim_from_onchain_tx, true); assert_eq!(next_channel_id, Some(chan_2.2)); + assert_eq!(outbound_amount_forwarded_msat, Some(3000000)); }, _ => panic!() } @@ -3759,7 +3764,7 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken let events_2 = nodes[1].node.get_and_clear_pending_events(); assert_eq!(events_2.len(), 1); match events_2[0] { - Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, via_user_channel_id: _ } => { + Event::PaymentClaimable { ref payment_hash, ref purpose, amount_msat, receiver_node_id, via_channel_id, .. } => { assert_eq!(payment_hash_1, *payment_hash); assert_eq!(amount_msat, 1_000_000); assert_eq!(receiver_node_id.unwrap(), nodes[1].node.get_our_node_id()); @@ -4653,11 +4658,12 @@ fn test_onchain_to_onchain_claim() { _ => panic!("Unexpected event"), } match events[1] { - Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id } => { + Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id, outbound_amount_forwarded_msat } => { assert_eq!(fee_earned_msat, Some(1000)); assert_eq!(prev_channel_id, Some(chan_1.2)); assert_eq!(claim_from_onchain_tx, true); assert_eq!(next_channel_id, Some(chan_2.2)); + assert_eq!(outbound_amount_forwarded_msat, Some(3000000)); }, _ => panic!("Unexpected event"), } @@ -7926,6 +7932,171 @@ fn test_can_not_accept_unknown_inbound_channel() { } } +#[test] +fn test_onion_value_mpp_set_calculation() { + // Test that we use the onion value `amt_to_forward` when + // calculating whether we've reached the `total_msat` of an MPP + // by having a routing node forward more than `amt_to_forward` + // and checking that the receiving node doesn't generate + // a PaymentClaimable event too early + let node_count = 4; + let chanmon_cfgs = create_chanmon_cfgs(node_count); + let node_cfgs = create_node_cfgs(node_count, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(node_count, &node_cfgs, &vec![None; node_count]); + let mut nodes = create_network(node_count, &node_cfgs, &node_chanmgrs); + + let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1).0.contents.short_channel_id; + let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2).0.contents.short_channel_id; + let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3).0.contents.short_channel_id; + let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3).0.contents.short_channel_id; + + let total_msat = 100_000; + let expected_paths: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]]; + let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(&nodes[0], nodes[3], total_msat); + let sample_path = route.paths.pop().unwrap(); + + let mut path_1 = sample_path.clone(); + path_1[0].pubkey = nodes[1].node.get_our_node_id(); + path_1[0].short_channel_id = chan_1_id; + path_1[1].pubkey = nodes[3].node.get_our_node_id(); + path_1[1].short_channel_id = chan_3_id; + path_1[1].fee_msat = 100_000; + route.paths.push(path_1); + + let mut path_2 = sample_path.clone(); + path_2[0].pubkey = nodes[2].node.get_our_node_id(); + path_2[0].short_channel_id = chan_2_id; + path_2[1].pubkey = nodes[3].node.get_our_node_id(); + path_2[1].short_channel_id = chan_4_id; + path_2[1].fee_msat = 1_000; + route.paths.push(path_2); + + // Send payment + let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes()); + let onion_session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash, Some(our_payment_secret), payment_id, &route).unwrap(); + nodes[0].node.test_send_payment_internal(&route, our_payment_hash, &Some(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); + check_added_monitors!(nodes[0], expected_paths.len()); + + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), expected_paths.len()); + + // First path + let ev = remove_first_msg_event_to_node(&expected_paths[0][0].node.get_our_node_id(), &mut events); + let mut payment_event = SendEvent::from_event(ev); + let mut prev_node = &nodes[0]; + + for (idx, &node) in expected_paths[0].iter().enumerate() { + assert_eq!(node.node.get_our_node_id(), payment_event.node_id); + + if idx == 0 { // routing node + let session_priv = [3; 32]; + let height = nodes[0].best_block_info().1; + let session_priv = SecretKey::from_slice(&session_priv).unwrap(); + let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap(); + let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], 100_000, &Some(our_payment_secret), height + 1, &None).unwrap(); + // Edit amt_to_forward to simulate the sender having set + // the final amount and the routing node taking less fee + onion_payloads[1].amt_to_forward = 99_000; + let new_onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash); + payment_event.msgs[0].onion_routing_packet = new_onion_packet; + } + + node.node.handle_update_add_htlc(&prev_node.node.get_our_node_id(), &payment_event.msgs[0]); + check_added_monitors!(node, 0); + commitment_signed_dance!(node, prev_node, payment_event.commitment_msg, false); + expect_pending_htlcs_forwardable!(node); + + if idx == 0 { + let mut events_2 = node.node.get_and_clear_pending_msg_events(); + assert_eq!(events_2.len(), 1); + check_added_monitors!(node, 1); + payment_event = SendEvent::from_event(events_2.remove(0)); + assert_eq!(payment_event.msgs.len(), 1); + } else { + let events_2 = node.node.get_and_clear_pending_events(); + assert!(events_2.is_empty()); + } + + prev_node = node; + } + + // Second path + let ev = remove_first_msg_event_to_node(&expected_paths[1][0].node.get_our_node_id(), &mut events); + pass_along_path(&nodes[0], expected_paths[1], 101_000, our_payment_hash.clone(), Some(our_payment_secret), ev, true, None); + + claim_payment_along_route(&nodes[0], expected_paths, false, our_payment_preimage); +} + +fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) { + + let routing_node_count = msat_amounts.len(); + let node_count = routing_node_count + 2; + + let chanmon_cfgs = create_chanmon_cfgs(node_count); + let node_cfgs = create_node_cfgs(node_count, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(node_count, &node_cfgs, &vec![None; node_count]); + let nodes = create_network(node_count, &node_cfgs, &node_chanmgrs); + + let src_idx = 0; + let dst_idx = 1; + + // Create channels for each amount + let mut expected_paths = Vec::with_capacity(routing_node_count); + let mut src_chan_ids = Vec::with_capacity(routing_node_count); + let mut dst_chan_ids = Vec::with_capacity(routing_node_count); + for i in 0..routing_node_count { + let routing_node = 2 + i; + let src_chan_id = create_announced_chan_between_nodes(&nodes, src_idx, routing_node).0.contents.short_channel_id; + src_chan_ids.push(src_chan_id); + let dst_chan_id = create_announced_chan_between_nodes(&nodes, routing_node, dst_idx).0.contents.short_channel_id; + dst_chan_ids.push(dst_chan_id); + let path = vec![&nodes[routing_node], &nodes[dst_idx]]; + expected_paths.push(path); + } + let expected_paths: Vec<&[&Node]> = expected_paths.iter().map(|route| route.as_slice()).collect(); + + // Create a route for each amount + let example_amount = 100000; + let (mut route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(&nodes[src_idx], nodes[dst_idx], example_amount); + let sample_path = route.paths.pop().unwrap(); + for i in 0..routing_node_count { + let routing_node = 2 + i; + let mut path = sample_path.clone(); + path[0].pubkey = nodes[routing_node].node.get_our_node_id(); + path[0].short_channel_id = src_chan_ids[i]; + path[1].pubkey = nodes[dst_idx].node.get_our_node_id(); + path[1].short_channel_id = dst_chan_ids[i]; + path[1].fee_msat = msat_amounts[i]; + route.paths.push(path); + } + + // Send payment with manually set total_msat + let payment_id = PaymentId(nodes[src_idx].keys_manager.backing.get_secure_random_bytes()); + let onion_session_privs = nodes[src_idx].node.test_add_new_pending_payment(our_payment_hash, Some(our_payment_secret), payment_id, &route).unwrap(); + nodes[src_idx].node.test_send_payment_internal(&route, our_payment_hash, &Some(our_payment_secret), None, payment_id, Some(total_msat), onion_session_privs).unwrap(); + check_added_monitors!(nodes[src_idx], expected_paths.len()); + + let mut events = nodes[src_idx].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), expected_paths.len()); + let mut amount_received = 0; + for (path_idx, expected_path) in expected_paths.iter().enumerate() { + let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events); + + let current_path_amount = msat_amounts[path_idx]; + amount_received += current_path_amount; + let became_claimable_now = amount_received >= total_msat && amount_received - current_path_amount < total_msat; + pass_along_path(&nodes[src_idx], expected_path, amount_received, our_payment_hash.clone(), Some(our_payment_secret), ev, became_claimable_now, None); + } + + claim_payment_along_route(&nodes[src_idx], &expected_paths, false, our_payment_preimage); +} + +#[test] +fn test_overshoot_mpp() { + do_test_overshoot_mpp(&[100_000, 101_000], 200_000); + do_test_overshoot_mpp(&[100_000, 10_000, 100_000], 200_000); +} + #[test] fn test_simple_mpp() { // Simple test of sending a multi-path payment. @@ -8686,6 +8857,8 @@ fn test_duplicate_chan_id() { assert_eq!(added_monitors[0].0, funding_output); added_monitors.clear(); } + expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); + let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()); let funding_outpoint = crate::chain::transaction::OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }; @@ -8761,6 +8934,7 @@ fn test_duplicate_chan_id() { assert_eq!(added_monitors[0].0, funding_output); added_monitors.clear(); } + expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); let events_4 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_4.len(), 0); @@ -8875,9 +9049,11 @@ fn test_invalid_funding_tx() { nodes[0].node.funding_transaction_generated_unchecked(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone(), 0).unwrap(); nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id())); check_added_monitors!(nodes[1], 1); + expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id())); check_added_monitors!(nodes[0], 1); + expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); let events_1 = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events_1.len(), 0); @@ -9407,9 +9583,11 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap(); nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id())); check_added_monitors!(nodes[1], 1); + expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id()); nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id())); check_added_monitors!(nodes[0], 1); + expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); let (channel_ready, channel_id) = create_chan_between_nodes_with_value_confirm(&nodes[0], &nodes[1], &tx); let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready);