Ensure a 1:1 mapping of value sendable to send success in fuzzing
[rust-lightning] / lightning / src / ln / functional_tests.rs
index 81c42861a8d8df22b1881b81552f92d0e43a2591..3985ac03bbd1ce391067264d914d951439f0fc05 100644 (file)
@@ -1102,6 +1102,9 @@ fn holding_cell_htlc_counting() {
        create_announced_chan_between_nodes(&nodes, 0, 1);
        let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
 
+       // Fetch a route in advance as we will be unable to once we're unable to send.
+       let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
+
        let mut payments = Vec::new();
        for _ in 0..50 {
                let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
@@ -1119,7 +1122,6 @@ fn holding_cell_htlc_counting() {
        // There is now one HTLC in an outbound commitment transaction and (OUR_MAX_HTLCS - 1) HTLCs in
        // the holding cell waiting on B's RAA to send. At this point we should not be able to add
        // another HTLC.
-       let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
        {
                unwrap_send_err!(nodes[1].node.send_payment_with_route(&route, payment_hash_1,
                                RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)
@@ -1525,13 +1527,14 @@ fn test_chan_reserve_violation_outbound_htlc_inbound_chan() {
 
        let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, push_amt);
 
+       // Fetch a route in advance as we will be unable to once we're unable to send.
+       let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 1_000_000);
        // Sending exactly enough to hit the reserve amount should be accepted
        for _ in 0..MIN_AFFORDABLE_HTLC_COUNT {
                let (_, _, _) = route_payment(&nodes[1], &[&nodes[0]], 1_000_000);
        }
 
        // However one more HTLC should be significantly over the reserve amount and fail.
-       let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 1_000_000);
        unwrap_send_err!(nodes[1].node.send_payment_with_route(&route, our_payment_hash,
                        RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)
                ), true, APIError::ChannelUnavailable { ref err },
@@ -1563,7 +1566,9 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() {
                let (_, _, _) = route_payment(&nodes[1], &[&nodes[0]], 1_000_000);
        }
 
-       let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 700_000);
+       let (mut route, payment_hash, _, payment_secret) =
+               get_route_and_payment_hash!(nodes[1], nodes[0], 1000);
+       route.paths[0].hops[0].fee_msat = 700_000;
        // Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc()
        let secp_ctx = Secp256k1::new();
        let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
@@ -1625,7 +1630,9 @@ fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() {
        }
 
        // One more than the dust amt should fail, however.
-       let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], dust_amt + 1);
+       let (mut route, our_payment_hash, _, our_payment_secret) =
+               get_route_and_payment_hash!(nodes[1], nodes[0], dust_amt);
+       route.paths[0].hops[0].fee_msat += 1;
        unwrap_send_err!(nodes[1].node.send_payment_with_route(&route, our_payment_hash,
                        RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)
                ), true, APIError::ChannelUnavailable { ref err },
@@ -6112,6 +6119,8 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment()
        let max_accepted_htlcs = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id())
                .unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().counterparty_max_accepted_htlcs as u64;
 
+       // Fetch a route in advance as we will be unable to once we're unable to send.
+       let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
        for i in 0..max_accepted_htlcs {
                let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
                let payment_event = {
@@ -6135,7 +6144,6 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment()
                expect_pending_htlcs_forwardable!(nodes[1]);
                expect_payment_claimable!(nodes[1], our_payment_hash, our_payment_secret, 100000);
        }
-       let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
        unwrap_send_err!(nodes[0].node.send_payment_with_route(&route, our_payment_hash,
                        RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)
                ), true, APIError::ChannelUnavailable { ref err },
@@ -9627,6 +9635,10 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
        let (announcement, as_update, bs_update) = create_chan_between_nodes_with_value_b(&nodes[0], &nodes[1], &channel_ready);
        update_nodes_with_chan_announce(&nodes, 0, 1, &announcement, &as_update, &bs_update);
 
+       // Fetch a route in advance as we will be unable to once we're unable to send.
+       let (mut route, payment_hash, _, payment_secret) =
+               get_route_and_payment_hash!(nodes[0], nodes[1], 1000);
+
        let dust_buffer_feerate = {
                let per_peer_state = nodes[0].node.per_peer_state.read().unwrap();
                let chan_lock = per_peer_state.get(&nodes[1].node.get_our_node_id()).unwrap().lock().unwrap();
@@ -9639,7 +9651,7 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
        let dust_inbound_htlc_on_holder_tx_msat: u64 = (dust_buffer_feerate * htlc_success_tx_weight(opt_anchors) / 1000 + open_channel.dust_limit_satoshis - 1) * 1000;
        let dust_inbound_htlc_on_holder_tx: u64 = config.channel_config.max_dust_htlc_exposure_msat / dust_inbound_htlc_on_holder_tx_msat;
 
-       let dust_htlc_on_counterparty_tx: u64 = 25;
+       let dust_htlc_on_counterparty_tx: u64 = 4;
        let dust_htlc_on_counterparty_tx_msat: u64 = config.channel_config.max_dust_htlc_exposure_msat / dust_htlc_on_counterparty_tx;
 
        if on_holder_tx {
@@ -9664,7 +9676,7 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
                if dust_outbound_balance {
                        // Outbound dust threshold: 2132 sats (`dust_buffer_feerate` * HTLC_TIMEOUT_TX_WEIGHT / 1000 + counteparty's `dust_limit_satoshis`)
                        // Outbound dust balance: 5000 sats
-                       for _ in 0..dust_htlc_on_counterparty_tx {
+                       for _ in 0..dust_htlc_on_counterparty_tx - 1 {
                                let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], dust_htlc_on_counterparty_tx_msat);
                                nodes[0].node.send_payment_with_route(&route, payment_hash,
                                        RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
@@ -9672,15 +9684,15 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
                } else {
                        // Inbound dust threshold: 2031 sats (`dust_buffer_feerate` * HTLC_TIMEOUT_TX_WEIGHT / 1000 + counteparty's `dust_limit_satoshis`)
                        // Inbound dust balance: 5000 sats
-                       for _ in 0..dust_htlc_on_counterparty_tx {
+                       for _ in 0..dust_htlc_on_counterparty_tx - 1 {
                                route_payment(&nodes[1], &[&nodes[0]], dust_htlc_on_counterparty_tx_msat);
                        }
                }
        }
 
-       let dust_overflow = dust_htlc_on_counterparty_tx_msat * (dust_htlc_on_counterparty_tx + 1);
        if exposure_breach_event == ExposureEvent::AtHTLCForward {
-               let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], if on_holder_tx { dust_outbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat });
+               route.paths[0].hops.last_mut().unwrap().fee_msat =
+                       if on_holder_tx { dust_outbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 1 };
                let mut config = UserConfig::default();
                // With default dust exposure: 5000 sats
                if on_holder_tx {
@@ -9694,10 +9706,13 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
                        unwrap_send_err!(nodes[0].node.send_payment_with_route(&route, payment_hash,
                                        RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)
                                ), true, APIError::ChannelUnavailable { ref err },
-                               assert_eq!(err, &format!("Cannot send value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx", dust_overflow, config.channel_config.max_dust_htlc_exposure_msat)));
+                               assert_eq!(err,
+                                       &format!("Cannot send value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
+                                               dust_htlc_on_counterparty_tx_msat * (dust_htlc_on_counterparty_tx - 1) + dust_htlc_on_counterparty_tx_msat + 1,
+                                               config.channel_config.max_dust_htlc_exposure_msat)));
                }
        } else if exposure_breach_event == ExposureEvent::AtHTLCReception {
-               let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], if on_holder_tx { dust_inbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat });
+               let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], if on_holder_tx { dust_inbound_htlc_on_holder_tx_msat } else { dust_htlc_on_counterparty_tx_msat + 1 });
                nodes[1].node.send_payment_with_route(&route, payment_hash,
                        RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
                check_added_monitors!(nodes[1], 1);
@@ -9713,10 +9728,13 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
                        nodes[0].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", if dust_outbound_balance { dust_outbound_overflow } else { dust_inbound_overflow }, config.channel_config.max_dust_htlc_exposure_msat), 1);
                } else {
                        // Outbound dust balance: 5200 sats
-                       nodes[0].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx", dust_overflow, config.channel_config.max_dust_htlc_exposure_msat), 1);
+                       nodes[0].logger.assert_log("lightning::ln::channel".to_string(),
+                               format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
+                                       dust_htlc_on_counterparty_tx_msat * (dust_htlc_on_counterparty_tx - 1) + dust_htlc_on_counterparty_tx_msat + 1,
+                                       config.channel_config.max_dust_htlc_exposure_msat), 1);
                }
        } else if exposure_breach_event == ExposureEvent::AtUpdateFeeOutbound {
-               let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 2_500_000);
+               route.paths[0].hops.last_mut().unwrap().fee_msat = 2_500_000;
                nodes[0].node.send_payment_with_route(&route, payment_hash,
                        RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
                {