Include MPP payment amount in `RecipientOnionFields`
What changed, and why it matters
This commit is a preparatory refactor in LDK's payment-sending code. It adds a new `total_mpp_amount_msat` field to `RecipientOnionFields` so that, in future commits, a payer can send an HTLC that is only one part of a larger multi-part payment. For now the new field is always required and is asserted to match the existing payment amount, so behavior is unchanged. The commit also fixes a small related bug where probe payments were not including a payment preimage as intended. There is no immediate security vulnerability here; it is a feature-building change with a minor bug fix.
No immediate action required. Treat as a normal feature refactor. Monitor the follow-up commits that will relax the equality assertion, because that is where actual MPP-split behavior and any associated security checks will be introduced.
Security signals we found
New required field added to a core payment API (`RecipientOnionFields`)
Serialization compatibility wrapper introduced for persisted `ClaimableHTLC` onion fields
Assertion added that new `total_mpp_amount_msat` must equal existing amount (currently enforced)
Probe preimage inclusion fixed
Large test-only refactor with no production logic change to payment validation
Evidence from the diff
The change introduces total_mpp_amount_msat into RecipientOnionFields, threading it through serialization (ReadableArgs), onion payload construction, and many test call sites. The field is currently populated from the existing payment amount and validated to equal it, so no functional MPP split is enabled yet. A second, smaller change fixes probe handling to actually include a payment preimage. The commit touches 29 files and is mostly mechanical API updates plus serialization compatibility code for older persisted data.
Changed components
lightning/src/ln/channelmanager.rslightning/src/ln/onion_utils.rslightning/src/ln/outbound_payment.rslightning/src/events/mod.rslightning/src/ln/onion_payment.rsFuzz and unit test suitesInspect captured patch +504 / −343
diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs
index 21623fd..ade6790 100644
--- a/fuzz/src/chanmon_consistency.rs
+++ b/fuzz/src/chanmon_consistency.rs
@@ -613,7 +613,7 @@ fn send_payment(
}],
route_params: Some(route_params.clone()),
};
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
let res = source.send_payment_with_route(route, payment_hash, onion, payment_id);
match res {
Err(err) => {
@@ -683,7 +683,7 @@ fn send_hop_payment(
}],
route_params: Some(route_params.clone()),
};
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
let res = source.send_payment_with_route(route, payment_hash, onion, payment_id);
match res {
Err(err) => {
@@ -748,7 +748,7 @@ fn send_mpp_payment(
amt,
);
let route = Route { paths, route_params: Some(route_params) };
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
let res = source.send_payment_with_route(route, payment_hash, onion, payment_id);
match res {
Err(_) => false,
@@ -844,7 +844,7 @@ fn send_mpp_hop_payment(
amt,
);
let route = Route { paths, route_params: Some(route_params) };
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
let res = source.send_payment_with_route(route, payment_hash, onion, payment_id);
match res {
Err(_) => false,
diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs
index 085165e..03d5e48 100644
--- a/fuzz/src/full_stack.rs
+++ b/fuzz/src/full_stack.rs
@@ -743,7 +743,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger + MaybeSend + MaybeSync>
payments_sent += 1;
let _ = channelmanager.send_payment(
payment_hash,
- RecipientOnionFields::spontaneous_empty(),
+ RecipientOnionFields::spontaneous_empty(final_value_msat),
PaymentId(payment_hash.0),
params,
Retry::Attempts(2),
@@ -765,7 +765,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger + MaybeSend + MaybeSync>
payments_sent += 1;
let _ = channelmanager.send_payment(
payment_hash,
- RecipientOnionFields::secret_only(payment_secret),
+ RecipientOnionFields::secret_only(payment_secret, final_value_msat),
PaymentId(payment_hash.0),
params,
Retry::Attempts(2),
diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs
index 3735146..a8d055a 100644
--- a/lightning/src/chain/channelmonitor.rs
+++ b/lightning/src/chain/channelmonitor.rs
@@ -6850,7 +6850,7 @@ mod tests {
// the update through to the ChannelMonitor which will refuse it (as the channel is closed).
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[0], 100_000);
nodes[1].node.send_payment_with_route(route, payment_hash,
- RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)
+ RecipientOnionFields::secret_only(payment_secret, 100_000), PaymentId(payment_hash.0)
).unwrap();
check_added_monitors(&nodes[1], 1);
diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs
index 3dfed10..1f030aa 100644
--- a/lightning/src/events/mod.rs
+++ b/lightning/src/events/mod.rs
@@ -41,8 +41,8 @@ use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
use crate::types::string::UntrustedString;
use crate::util::errors::APIError;
use crate::util::ser::{
- BigSize, FixedLengthReader, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired,
- WithoutLength, Writeable, Writer,
+ BigSize, FixedLengthReader, MaybeReadable, Readable, ReadableArgs, RequiredWrapper,
+ UpgradableRequired, WithoutLength, Writeable, Writer,
};
use crate::io;
@@ -2378,7 +2378,7 @@ impl MaybeReadable for Event {
(6, _user_payment_id, option),
(7, claim_deadline, option),
(8, payment_preimage, option),
- (9, onion_fields, option),
+ (9, onion_fields, (option: ReadableArgs, amount_msat)),
(10, counterparty_skimmed_fee_msat_opt, option),
(11, payment_context, option),
(13, payment_id, option),
@@ -2710,7 +2710,8 @@ impl MaybeReadable for Event {
(4, amount_msat, required),
(5, htlcs, optional_vec),
(7, sender_intended_total_msat, option),
- (9, onion_fields, option),
+ (9, onion_fields, (option: ReadableArgs,
+ sender_intended_total_msat.unwrap_or(amount_msat))),
(11, payment_id, option),
});
Ok(Some(Event::PaymentClaimed {
diff --git a/lightning/src/ln/accountable_tests.rs b/lightning/src/ln/accountable_tests.rs
index 35c936f..a2b918a 100644
--- a/lightning/src/ln/accountable_tests.rs
+++ b/lightning/src/ln/accountable_tests.rs
@@ -32,7 +32,7 @@ fn test_accountable_forwarding_with_override(
PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV),
100_000,
);
- let onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let onion_fields = RecipientOnionFields::secret_only(payment_secret, 100_000);
let payment_id = PaymentId(payment_hash.0);
nodes[0]
.node
diff --git a/lightning/src/ln/async_payments_tests.rs b/lightning/src/ln/async_payments_tests.rs
index 8a991b1..2552234 100644
--- a/lightning/src/ln/async_payments_tests.rs
+++ b/lightning/src/ln/async_payments_tests.rs
@@ -615,7 +615,7 @@ fn invalid_keysend_payment_secret() {
.node
.send_spontaneous_payment(
Some(keysend_preimage),
- RecipientOnionFields::spontaneous_empty(),
+ RecipientOnionFields::spontaneous_empty(amt_msat),
PaymentId(keysend_preimage.0),
route_params,
Retry::Attempts(0),
diff --git a/lightning/src/ln/async_signer_tests.rs b/lightning/src/ln/async_signer_tests.rs
index 537f29f..e6cd197 100644
--- a/lightning/src/ln/async_signer_tests.rs
+++ b/lightning/src/ln/async_signer_tests.rs
@@ -296,7 +296,7 @@ fn do_test_async_commitment_signature_for_commitment_signed_revoke_and_ack(
let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) =
get_route_and_payment_hash!(src, dst, 8000000);
- let recipient_fields = RecipientOnionFields::secret_only(our_payment_secret);
+ let recipient_fields = RecipientOnionFields::secret_only(our_payment_secret, 8000000);
let payment_id = PaymentId(our_payment_hash.0);
src.node
.send_payment_with_route(route, our_payment_hash, recipient_fields, payment_id)
@@ -520,7 +520,7 @@ fn do_test_async_raa_peer_disconnect(
let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) =
get_route_and_payment_hash!(src, dst, 8000000);
- let recipient_fields = RecipientOnionFields::secret_only(our_payment_secret);
+ let recipient_fields = RecipientOnionFields::secret_only(our_payment_secret, 8000000);
let payment_id = PaymentId(our_payment_hash.0);
src.node
.send_payment_with_route(route, our_payment_hash, recipient_fields, payment_id)
@@ -669,7 +669,7 @@ fn do_test_async_commitment_signature_peer_disconnect(
let (route, our_payment_hash, _our_payment_preimage, our_payment_secret) =
get_route_and_payment_hash!(src, dst, 8000000);
- let recipient_fields = RecipientOnionFields::secret_only(our_payment_secret);
+ let recipient_fields = RecipientOnionFields::secret_only(our_payment_secret, 8000000);
let payment_id = PaymentId(our_payment_hash.0);
src.node
.send_payment_with_route(route, our_payment_hash, recipient_fields, payment_id)
@@ -804,7 +804,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
// to the peer.
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let recipient_fields = RecipientOnionFields::secret_only(payment_secret_2);
+ let recipient_fields = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let payment_id = PaymentId(payment_hash_2.0);
nodes[0]
.node
@@ -1343,14 +1343,14 @@ fn test_no_disconnect_while_async_revoke_and_ack_expecting_remote_commitment_sig
// We'll send a payment from both nodes to each other.
let (route1, payment_hash1, _, payment_secret1) =
get_route_and_payment_hash!(&nodes[0], &nodes[1], payment_amount);
- let onion1 = RecipientOnionFields::secret_only(payment_secret1);
+ let onion1 = RecipientOnionFields::secret_only(payment_secret1, payment_amount);
let payment_id1 = PaymentId(payment_hash1.0);
nodes[0].node.send_payment_with_route(route1, payment_hash1, onion1, payment_id1).unwrap();
check_added_monitors(&nodes[0], 1);
let (route2, payment_hash2, _, payment_secret2) =
get_route_and_payment_hash!(&nodes[1], &nodes[0], payment_amount);
- let onion2 = RecipientOnionFields::secret_only(payment_secret2);
+ let onion2 = RecipientOnionFields::secret_only(payment_secret2, payment_amount);
let payment_id2 = PaymentId(payment_hash2.0);
nodes[1].node.send_payment_with_route(route2, payment_hash2, onion2, payment_id2).unwrap();
check_added_monitors(&nodes[1], 1);
diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs
index d9f3374..3cabdee 100644
--- a/lightning/src/ln/blinded_payment_tests.rs
+++ b/lightning/src/ln/blinded_payment_tests.rs
@@ -187,7 +187,7 @@ fn do_one_hop_blinded_path(success: bool) {
PaymentParameters::blinded(vec![blinded_path]),
amt_msat,
);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(),
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat),
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1]]], amt_msat, payment_hash, payment_secret);
@@ -243,7 +243,7 @@ fn one_hop_blinded_path_with_dummy_hops() {
.node
.send_payment(
payment_hash,
- RecipientOnionFields::spontaneous_empty(),
+ RecipientOnionFields::spontaneous_empty(amt_msat),
PaymentId(payment_hash.0),
route_params,
Retry::Attempts(0),
@@ -307,7 +307,7 @@ fn mpp_to_one_hop_blinded_path() {
PaymentParameters::blinded(vec![blinded_path]).with_bolt12_features(bolt12_features).unwrap(),
amt_msat,
);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 2);
let expected_route: &[&[&Node]] = &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]];
@@ -399,7 +399,7 @@ fn mpp_to_three_hop_blinded_paths() {
RouteParameters::from_payment_params_and_value(pay_params, amt_msat)
};
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(),
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat),
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 2);
@@ -464,7 +464,7 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
let route = get_route(&nodes[0], &route_params).unwrap();
node_cfgs[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
macro_rules! cause_error {
@@ -474,7 +474,7 @@ fn do_forward_checks_failure(check: ForwardCheckFail, intro_fails: bool) {
$update_add.cltv_expiry = 10; // causes outbound CLTV expiry to underflow
},
ForwardCheckFail::ForwardPayloadEncodedAsReceive => {
- let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(amt_msat);
let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
let mut onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv);
let cur_height = nodes[0].best_block_info().1;
@@ -594,7 +594,7 @@ fn failed_backwards_to_intro_node() {
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2],
&chanmon_cfgs[2].keys_manager);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -680,7 +680,7 @@ fn do_forward_fail_in_process_pending_htlc_fwds(check: ProcessPendingHTLCsCheck,
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2, &chan_upd_2_3],
&chanmon_cfgs[2].keys_manager);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -790,7 +790,7 @@ fn do_blinded_intercept_payment(intercept_node_fails: bool) {
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&intercept_chan_upd],
&chanmon_cfgs[2].keys_manager);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(),
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat),
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
let payment_event = {
@@ -865,7 +865,7 @@ fn two_hop_blinded_path_success() {
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2],
&chanmon_cfgs[2].keys_manager);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
@@ -895,7 +895,7 @@ fn three_hop_blinded_path_success() {
nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(),
&[&chan_upd_2_3, &chan_upd_3_4], &chanmon_cfgs[4].keys_manager);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]], payment_preimage);
@@ -920,7 +920,7 @@ fn three_hop_blinded_path_fail() {
nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(),
&[&chan_upd_1_2, &chan_upd_2_3], &chanmon_cfgs[3].keys_manager);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], amt_msat, payment_hash, payment_secret);
@@ -1021,7 +1021,7 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
find_route(&nodes[0], &route_params).unwrap()
};
node_cfgs[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
let mut payment_event_0_1 = {
@@ -1064,7 +1064,7 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
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);
let cur_height = nodes[0].best_block_info().1;
- let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(amt_msat);
let (mut onion_payloads, ..) = onion_utils::build_onion_payloads(
&route.paths[0], amt_msat, &recipient_onion_fields, cur_height, &None, None, None).unwrap();
@@ -1210,7 +1210,7 @@ fn blinded_path_retries() {
RouteParameters::from_payment_params_and_value(pay_params, amt_msat)
};
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(2)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(2)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]]], amt_msat, payment_hash, payment_secret);
@@ -1309,7 +1309,7 @@ fn min_htlc() {
assert_eq!(min_htlc_msat,
route_params.payment_params.payee.blinded_route_hints()[0].payinfo.htlc_minimum_msat);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(min_htlc_msat), PaymentId(payment_hash.0), route_params.clone(), Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3]]], min_htlc_msat, payment_hash, payment_secret);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3]], payment_preimage);
@@ -1322,7 +1322,7 @@ fn min_htlc() {
route_hints[0].payinfo.htlc_minimum_msat -= 1;
} else { panic!() }
route_params.final_value_msat -= 1;
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(route_params.final_value_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
let mut payment_event_0_1 = {
@@ -1387,7 +1387,7 @@ fn conditionally_round_fwd_amt() {
&chanmon_cfgs[4].keys_manager);
route_params.max_total_routing_fee_msat = None;
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret);
nodes[4].node.claim_funds(payment_preimage);
@@ -1432,7 +1432,7 @@ fn custom_tlvs_to_blinded_path() {
amt_msat,
);
- let recipient_onion_fields = RecipientOnionFields::spontaneous_empty()
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(amt_msat)
.with_custom_tlvs(RecipientCustomTlvs::new(vec![((1 << 16) + 1, vec![42, 42])]).unwrap());
nodes[0].node.send_payment(payment_hash, recipient_onion_fields.clone(),
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
@@ -1487,7 +1487,7 @@ fn fails_receive_tlvs_authentication() {
);
// Test authentication works normally.
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1]]], amt_msat, payment_hash, payment_secret);
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
@@ -1517,7 +1517,7 @@ fn fails_receive_tlvs_authentication() {
amt_msat,
);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -1574,7 +1574,7 @@ fn blinded_payment_path_padding() {
let route_params = RouteParameters::from_payment_params_and_value(PaymentParameters::blinded(vec![blinded_path]), amt_msat);
- nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]], payment_preimage);
@@ -1681,7 +1681,7 @@ fn route_blinding_spec_test_vector() {
}),
};
let cur_height = 747_000;
- let (bob_onion, _, _) = onion_utils::create_payment_onion(&secp_ctx, &path, &session_priv, amt_msat, &RecipientOnionFields::spontaneous_empty(), cur_height, &PaymentHash([0; 32]), &None, None, [0; 32]).unwrap();
+ let (bob_onion, _, _) = onion_utils::create_payment_onion(&secp_ctx, &path, &session_priv, amt_msat, &RecipientOnionFields::spontaneous_empty(amt_msat), cur_height, &PaymentHash([0; 32]), &None, None, [0; 32]).unwrap();
struct TestEcdhSigner {
node_secret: SecretKey,
@@ -1904,7 +1904,7 @@ fn test_combined_trampoline_onion_creation_vectors() {
let amt_msat = 150_000_000;
let cur_height = 800_000;
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let (bob_onion, htlc_msat, htlc_cltv) = onion_utils::create_payment_onion_internal(&secp_ctx, &path, &outer_session_key, amt_msat, &recipient_onion_fields, cur_height, &associated_data, &None, None, outer_onion_prng_seed, Some(session_priv), Some([0; 32])).unwrap();
let outer_onion_packet_hex = bob_onion.encode().to_lower_hex_string();
@@ -1995,7 +1995,7 @@ fn test_trampoline_inbound_payment_decoding() {
let amt_msat = 150_000_001;
let cur_height = 800_001;
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let (bob_onion, _, _) = onion_utils::create_payment_onion(&secp_ctx, &path, &session_priv, amt_msat, &recipient_onion_fields, cur_height, &PaymentHash([0; 32]), &None, None, [0; 32]).unwrap();
struct TestEcdhSigner {
@@ -2166,12 +2166,11 @@ fn test_trampoline_forward_payload_encoded_as_receive() {
route_params: None,
};
- nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap();
+ nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let replacement_onion = {
// create a substitute onion where the last Trampoline hop is a forward
- let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
let mut blinded_tail = route.paths[0].blinded_tail.clone().unwrap();
@@ -2181,6 +2180,7 @@ fn test_trampoline_forward_payload_encoded_as_receive() {
encrypted_payload: vec![],
});
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(amt_msat);
let (mut trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) = onion_utils::build_trampoline_onion_payloads(&blinded_tail, amt_msat, &recipient_onion_fields, 32, &None).unwrap();
// pop the last dummy hop
@@ -2195,6 +2195,7 @@ fn test_trampoline_forward_payload_encoded_as_receive() {
None,
).unwrap();
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(outer_total_msat);
let (outer_payloads, _, _) = onion_utils::build_onion_payloads(&route.paths[0], outer_total_msat, &recipient_onion_fields, outer_starting_htlc_offset, &None, None, Some(trampoline_packet)).unwrap();
let outer_onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.clone().paths[0], &outer_session_priv);
let outer_packet = onion_utils::construct_onion_packet(
@@ -2331,7 +2332,7 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
route_params: None,
};
- nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap();
+ nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret);
@@ -2477,7 +2478,7 @@ fn replacement_onion(
) -> msgs::OnionPacket {
let outer_session_priv = SecretKey::from_slice(&override_random_bytes[..]).unwrap();
let trampoline_session_priv = onion_utils::compute_trampoline_session_priv(&outer_session_priv);
- let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(original_amt_msat);
let blinded_tail = route.paths[0].blinded_tail.clone().unwrap();
@@ -2525,6 +2526,7 @@ fn replacement_onion(
// Use a different session key to construct the replacement onion packet. Note that the
// sender isn't aware of this and won't be able to decode the fulfill hold times.
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(outer_total_msat);
let (mut outer_payloads, _, _) = onion_utils::build_onion_payloads(
&route.paths[0],
outer_total_msat,
@@ -2650,7 +2652,7 @@ fn do_test_trampoline_relay(blinded: bool, test_case: TrampolineTestCase) {
.send_payment_with_route(
route.clone(),
payment_hash,
- RecipientOnionFields::spontaneous_empty(),
+ RecipientOnionFields::spontaneous_empty(original_amt_msat),
PaymentId(payment_hash.0),
)
.unwrap();
@@ -2832,7 +2834,7 @@ fn test_trampoline_forward_rejection() {
route_params: None,
};
- nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap();
+ nodes[0].node.send_payment_with_route(route.clone(), payment_hash, RecipientOnionFields::spontaneous_empty(amt_msat), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs
index b66695c..cd32d21 100644
--- a/lightning/src/ln/chanmon_update_fail_tests.rs
+++ b/lightning/src/ln/chanmon_update_fail_tests.rs
@@ -187,7 +187,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- let onion = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1, 1000000);
let id = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route, payment_hash_1, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -254,7 +254,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) {
get_route_and_payment_hash!(&nodes[0], nodes[1], 1000000);
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -330,7 +330,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -735,7 +735,7 @@ fn test_monitor_update_fail_cs() {
let (route, our_payment_hash, payment_preimage, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -843,7 +843,7 @@ fn test_monitor_update_fail_no_rebroadcast() {
let (route, our_payment_hash, payment_preimage_1, payment_secret_1) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -897,7 +897,7 @@ fn test_monitor_update_raa_while_paused() {
send_payment(&nodes[0], &[&nodes[1]], 5000000);
let (route, our_payment_hash_1, payment_preimage_1, our_payment_secret_1) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret_1, 1000000);
let id = PaymentId(our_payment_hash_1.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash_1, onion, id).unwrap();
@@ -907,7 +907,7 @@ fn test_monitor_update_raa_while_paused() {
let (route, our_payment_hash_2, payment_preimage_2, our_payment_secret_2) =
get_route_and_payment_hash!(nodes[1], nodes[0], 1000000);
- let onion_2 = RecipientOnionFields::secret_only(our_payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(our_payment_secret_2, 1000000);
let id_2 = PaymentId(our_payment_hash_2.0);
nodes[1].node.send_payment_with_route(route, our_payment_hash_2, onion_2, id_2).unwrap();
@@ -1008,7 +1008,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
// holding cell.
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[2], 1000000);
- let onion_2 = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id_2 = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion_2, id_2).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1034,7 +1034,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
// being paused waiting a monitor update.
let (route, payment_hash_3, _, payment_secret_3) =
get_route_and_payment_hash!(nodes[0], nodes[2], 1000000);
- let onion_3 = RecipientOnionFields::secret_only(payment_secret_3);
+ let onion_3 = RecipientOnionFields::secret_only(payment_secret_3, 1000000);
let id_3 = PaymentId(payment_hash_3.0);
nodes[0].node.send_payment_with_route(route, payment_hash_3, onion_3, id_3).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1055,7 +1055,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) {
// Try to route another payment backwards from 2 to make sure 1 holds off on responding
let (route, payment_hash_4, payment_preimage_4, payment_secret_4) =
get_route_and_payment_hash!(nodes[2], nodes[0], 1000000);
- let onion_4 = RecipientOnionFields::secret_only(payment_secret_4);
+ let onion_4 = RecipientOnionFields::secret_only(payment_secret_4, 1000000);
let id_4 = PaymentId(payment_hash_4.0);
nodes[2].node.send_payment_with_route(route, payment_hash_4, onion_4, id_4).unwrap();
check_added_monitors(&nodes[2], 1);
@@ -1391,11 +1391,11 @@ fn raa_no_response_awaiting_raa_state() {
// immediately after a CS. By setting failing the monitor update failure from the CS (which
// requires only an RAA response due to AwaitingRAA) we can deliver the RAA and require the CS
// generation during RAA while in monitor-update-failed state.
- let onion_1 = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion_1 = RecipientOnionFields::secret_only(payment_secret_1, 1000000);
let id_1 = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash_1, onion_1, id_1).unwrap();
check_added_monitors(&nodes[0], 1);
- let onion_2 = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id_2 = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash_2, onion_2, id_2).unwrap();
check_added_monitors(&nodes[0], 0);
@@ -1444,7 +1444,7 @@ fn raa_no_response_awaiting_raa_state() {
// We send a third payment here, which is somewhat of a redundant test, but the
// chanmon_fail_consistency test required it to actually find the bug (by seeing out-of-sync
// commitment transaction states) whereas here we can explicitly check for it.
- let onion_3 = RecipientOnionFields::secret_only(payment_secret_3);
+ let onion_3 = RecipientOnionFields::secret_only(payment_secret_3, 1000000);
let id_3 = PaymentId(payment_hash_3.0);
nodes[0].node.send_payment_with_route(route, payment_hash_3, onion_3, id_3).unwrap();
check_added_monitors(&nodes[0], 0);
@@ -1546,7 +1546,7 @@ fn claim_while_disconnected_monitor_update_fail() {
// the monitor still failed
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion_2 = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id_2 = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion_2, id_2).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1653,7 +1653,7 @@ fn monitor_failed_no_reestablish_response() {
// on receipt).
let (route, payment_hash_1, payment_preimage_1, payment_secret_1) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1, 1000000);
let id = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route, payment_hash_1, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1737,7 +1737,7 @@ fn first_message_on_recv_ordering() {
// can deliver it and fail the monitor update.
let (route, payment_hash_1, payment_preimage_1, payment_secret_1) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion_1 = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion_1 = RecipientOnionFields::secret_only(payment_secret_1, 1000000);
let id_1 = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route, payment_hash_1, onion_1, id_1).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1761,7 +1761,7 @@ fn first_message_on_recv_ordering() {
// Route the second payment, generating an update_add_htlc/commitment_signed
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion_2 = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id_2 = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion_2, id_2).unwrap();
@@ -1854,7 +1854,7 @@ fn test_monitor_update_fail_claim() {
let (route, payment_hash_2, _, payment_secret_2) =
get_route_and_payment_hash!(nodes[2], nodes[0], 1_000_000);
- let onion_2 = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(payment_secret_2, 1_000_000);
let id_2 = PaymentId(payment_hash_2.0);
nodes[2].node.send_payment_with_route(route.clone(), payment_hash_2, onion_2, id_2).unwrap();
check_added_monitors(&nodes[2], 1);
@@ -1874,7 +1874,7 @@ fn test_monitor_update_fail_claim() {
let (_, payment_hash_3, payment_secret_3) = get_payment_preimage_hash(&nodes[0], None, None);
let id_3 = PaymentId(payment_hash_3.0);
- let onion_3 = RecipientOnionFields::secret_only(payment_secret_3);
+ let onion_3 = RecipientOnionFields::secret_only(payment_secret_3, 1_000_000);
nodes[2].node.send_payment_with_route(route, payment_hash_3, onion_3, id_3).unwrap();
check_added_monitors(&nodes[2], 1);
@@ -1998,7 +1998,7 @@ fn test_monitor_update_on_pending_forwards() {
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[2], nodes[0], 1000000);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id = PaymentId(payment_hash_2.0);
nodes[2].node.send_payment_with_route(route, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[2], 1);
@@ -2069,7 +2069,7 @@ fn monitor_update_claim_fail_no_response() {
// Now start forwarding a second payment, skipping the last RAA so B is in AwaitingRAA
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -2317,7 +2317,7 @@ fn test_path_paused_mpp() {
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
// The first path should have succeeded with the second getting a MonitorUpdateInProgress err.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 200000);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 2);
@@ -2373,7 +2373,7 @@ fn test_pending_update_fee_ack_on_reconnect() {
let (route, payment_hash, payment_preimage, payment_secret) =
get_route_and_payment_hash!(&nodes[1], nodes[0], 1_000_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
let id = PaymentId(payment_hash.0);
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -2688,14 +2688,14 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) {
// (c) will not be freed from the holding cell.
let (payment_preimage_0, payment_hash_0, ..) = route_payment(&nodes[1], &[&nodes[0]], 100_000);
- let onion_1 = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion_1 = RecipientOnionFields::secret_only(payment_secret_1, 100000);
let id_1 = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash_1, onion_1, id_1).unwrap();
check_added_monitors(&nodes[0], 1);
let send = SendEvent::from_node(&nodes[0]);
assert_eq!(send.msgs.len(), 1);
- let onion_2 = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(payment_secret_2, 100000);
let id_2 = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion_2, id_2).unwrap();
check_added_monitors(&nodes[0], 0);
@@ -2872,7 +2872,7 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
// awaiting a remote revoke_and_ack from nodes[0].
let (route, second_payment_hash, _, second_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
- let onion_2 = RecipientOnionFields::secret_only(second_payment_secret);
+ let onion_2 = RecipientOnionFields::secret_only(second_payment_secret, 100_000);
let id_2 = PaymentId(second_payment_hash.0);
nodes[0].node.send_payment_with_route(route, second_payment_hash, onion_2, id_2).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -4155,7 +4155,7 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) {
// With the A<->B preimage persistence not yet complete, the B<->C channel is stuck
// waiting.
- let onion_2 = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion_2 = RecipientOnionFields::secret_only(payment_secret_2, 1_000_000);
let id_2 = PaymentId(payment_hash_2.0);
nodes[1].node.send_payment_with_route(route, payment_hash_2, onion_2, id_2).unwrap();
check_added_monitors(&nodes[1], 0);
@@ -5104,7 +5104,7 @@ fn test_mpp_claim_to_holding_cell() {
// Put the C <-> D channel into AwaitingRaa
let (preimage_2, paymnt_hash_2, payment_secret_2) =
get_payment_preimage_hash(&nodes[3], None, None);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 400_000);
let id = PaymentId([42; 32]);
let pay_params = PaymentParameters::from_node_id(node_d_id, TEST_FINAL_CLTV);
let route_params = RouteParameters::from_payment_params_and_value(pay_params, 400_000);
diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 458a1f7..18bbbbc 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -1110,7 +1110,7 @@ impl_writeable_tlv_based!(ClaimingPayment, {
(4, receiver_node_id, required),
(5, htlcs, optional_vec),
(7, sender_intended_value, option),
- (9, onion_fields, option),
+ (9, onion_fields, (option: ReadableArgs, amount_msat.0.unwrap())),
(11, payment_id, option),
});
@@ -7932,6 +7932,7 @@ impl<
payment_secret: Some(payment_data.payment_secret),
payment_metadata,
custom_tlvs,
+ total_mpp_amount_msat: payment_data.total_msat,
};
(
incoming_cltv_expiry,
@@ -7960,6 +7961,10 @@ impl<
payment_secret: payment_data
.as_ref()
.map(|data| data.payment_secret),
+ total_mpp_amount_msat: payment_data
+ .as_ref()
+ .map(|data| data.total_msat)
+ .unwrap_or(outgoing_amt_msat),
payment_metadata,
custom_tlvs,
};
@@ -17551,6 +17556,18 @@ impl Readable for VecDeque<(Event, Option<EventCompletionAction>)> {
}
}
+/// We write the [`ClaimableHTLC`]'s [`RecipientOnionFields`] separately as they were added sometime
+/// later. Because [`RecipientOnionFields`] only implements [`ReadableArgs`] we have to add a
+/// wrapper which reads them without [`RecipientOnionFields::total_mpp_amount_msat`] and then fill
+/// them in later.
+struct AmountlessClaimablePaymentHTLCOnion(RecipientOnionFields);
+
+impl Readable for AmountlessClaimablePaymentHTLCOnion {
+ fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ Ok(Self(ReadableArgs::read(reader, 0)?))
+ }
+}
+
// Raw deserialized data from a ChannelManager, before validation or reconstruction.
// This is an internal DTO used in the two-stage deserialization process.
pub(super) struct ChannelManagerData<SP: SignerProvider> {
@@ -17743,8 +17760,10 @@ impl<'a, ES: EntropySource, NS: NodeSigner, SP: SignerProvider, L: Logger>
let mut fake_scid_rand_bytes: Option<[u8; 32]> = None;
let mut probing_cookie_secret: Option<[u8; 32]> = None;
let mut claimable_htlc_purposes = None;
- let mut claimable_htlc_onion_fields = None;
- let mut pending_claiming_payments = None;
+ let mut amountless_claimable_htlc_onion_fields: Option<
+ Vec<Option<AmountlessClaimablePaymentHTLCOnion>>,
+ > = None;
+ let mut pending_claiming_payments = Some(new_hash_map());
let mut monitor_update_blocked_actions_per_peer: Option<Vec<(_, BTreeMap<_, Vec<_>>)>> =
None;
let mut events_override = None;
@@ -17771,7 +17790,7 @@ impl<'a, ES: EntropySource, NS: NodeSigner, SP: SignerProvider, L: Logger>
(9, claimable_htlc_purposes, optional_vec),
(10, legacy_in_flight_monitor_updates, option),
(11, probing_cookie_secret, option),
- (13, claimable_htlc_onion_fields, optional_vec),
+ (13, amountless_claimable_htlc_onion_fields, optional_vec),
(14, decode_update_add_htlcs_legacy, option),
(15, inbound_payment_id_secret, option),
(17, in_flight_monitor_updates, option),
@@ -17836,7 +17855,7 @@ impl<'a, ES: EntropySource, NS: NodeSigner, SP: SignerProvider, L: Logger>
if purposes.len() != claimable_htlcs_list.len() {
return Err(DecodeError::InvalidValue);
}
- if let Some(onion_fields) = claimable_htlc_onion_fields {
+ if let Some(onion_fields) = amountless_claimable_htlc_onion_fields {
if onion_fields.len() != claimable_htlcs_list.len() {
return Err(DecodeError::InvalidValue);
}
@@ -17844,7 +17863,20 @@ impl<'a, ES: EntropySource, NS: NodeSigner, SP: SignerProvider, L: Logger>
.into_iter()
.zip(onion_fields.into_iter().zip(claimable_htlcs_list.into_iter()))
{
- let claimable = ClaimablePayment { purpose, htlcs, onion_fields: onion };
+ let htlcs_total_msat =
+ htlcs.first().ok_or(DecodeError::InvalidValue)?.total_msat;
+ let onion_fields = if let Some(mut onion) = onion {
+ if onion.0.total_mpp_amount_msat != 0
+ && onion.0.total_mpp_amount_msat != htlcs_total_msat
+ {
+ return Err(DecodeError::InvalidValue);
+ }
+ onion.0.total_mpp_amount_msat = htlcs_total_msat;
+ Some(onion.0)
+ } else {
+ None
+ };
+ let claimable = ClaimablePayment { purpose, htlcs, onion_fields };
let existing_payment = claimable_payments.insert(payment_hash, claimable);
if existing_payment.is_some() {
return Err(DecodeError::InvalidValue);
@@ -20040,9 +20072,9 @@ mod tests {
// indicates there are more HTLCs coming.
let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
let session_privs = nodes[0].node.test_add_new_pending_payment(our_payment_hash,
- RecipientOnionFields::secret_only(payment_secret), payment_id, &mpp_route).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 200_000), payment_id, &mpp_route).unwrap();
nodes[0].node.test_send_payment_along_path(&mpp_route.paths[0], &our_payment_hash,
- RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[0]).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 200_000), 200_000, cur_height, payment_id, &None, session_privs[0]).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
@@ -20050,7 +20082,7 @@ mod tests {
// Next, send a keysend payment with the same payment_hash and make sure it fails.
nodes[0].node.send_spontaneous_payment(
- Some(payment_preimage), RecipientOnionFields::spontaneous_empty(),
+ Some(payment_preimage), RecipientOnionFields::spontaneous_empty(100_000),
PaymentId(payment_preimage.0), route.route_params.clone().unwrap(), Retry::Attempts(0)
).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -20078,7 +20110,7 @@ mod tests {
// Send the second half of the original MPP payment.
nodes[0].node.test_send_payment_along_path(&mpp_route.paths[1], &our_payment_hash,
- RecipientOnionFields::secret_only(payment_secret), 200_000, cur_height, payment_id, &None, session_privs[1]).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 200_000), 200_000, cur_height, payment_id, &None, session_privs[1]).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
@@ -20168,7 +20200,7 @@ mod tests {
PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(),
TEST_FINAL_CLTV, false), 100_000);
nodes[0].node.send_spontaneous_payment(
- Some(payment_preimage), RecipientOnionFields::spontaneous_empty(),
+ Some(payment_preimage), RecipientOnionFields::spontaneous_empty(100_000),
PaymentId(payment_preimage.0), route_params.clone(), Retry::Attempts(0)
).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -20206,7 +20238,7 @@ mod tests {
None, nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes
).unwrap();
let payment_hash = nodes[0].node.send_spontaneous_payment(
- Some(payment_preimage), RecipientOnionFields::spontaneous_empty(),
+ Some(payment_preimage), RecipientOnionFields::spontaneous_empty(100_000),
PaymentId(payment_preimage.0), route.route_params.clone().unwrap(), Retry::Attempts(0)
).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -20219,7 +20251,7 @@ mod tests {
// Next, attempt a regular payment and make sure it fails.
let payment_secret = PaymentSecret([43; 32]);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash,
- RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 100_000), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
@@ -20249,7 +20281,7 @@ mod tests {
// To start (3), send a keysend payment but don't claim it.
let payment_id_1 = PaymentId([44; 32]);
let payment_hash = nodes[0].node.send_spontaneous_payment(
- Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_1,
+ Some(payment_preimage), RecipientOnionFields::spontaneous_empty(100_000), payment_id_1,
route.route_params.clone().unwrap(), Retry::Attempts(0)
).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -20266,7 +20298,7 @@ mod tests {
);
let payment_id_2 = PaymentId([45; 32]);
nodes[0].node.send_spontaneous_payment(
- Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), payment_id_2, route_params,
+ Some(payment_preimage), RecipientOnionFields::spontaneous_empty(100_000), payment_id_2, route_params,
Retry::Attempts(0)
).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -20324,9 +20356,9 @@ mod tests {
let test_preimage = PaymentPreimage([42; 32]);
let mismatch_payment_hash = PaymentHash([43; 32]);
let session_privs = nodes[0].node.test_add_new_pending_payment(mismatch_payment_hash,
- RecipientOnionFields::spontaneous_empty(), PaymentId(mismatch_payment_hash.0), &route).unwrap();
+ RecipientOnionFields::spontaneous_empty(10_000), PaymentId(mismatch_payment_hash.0), &route).unwrap();
nodes[0].node.test_send_payment_internal(&route, mismatch_payment_hash,
- RecipientOnionFields::spontaneous_empty(), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap();
+ RecipientOnionFields::spontaneous_empty(10_000), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
@@ -20371,7 +20403,7 @@ mod tests {
route.route_params.as_mut().unwrap().final_value_msat *= 2;
nodes[0].node.send_payment_with_route(route, payment_hash,
- RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0)).unwrap();
+ RecipientOnionFields::spontaneous_empty(200000), PaymentId(payment_hash.0)).unwrap();
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
@@ -21209,7 +21241,7 @@ pub mod bench {
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array());
let payment_secret = $node_b.create_inbound_payment_for_hash(payment_hash, None, 7200, None).unwrap();
- $node_a.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
+ $node_a.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret, 10_000),
PaymentId(payment_hash.0),
RouteParameters::from_payment_params_and_value(payment_params, 10_000),
Retry::Attempts(0)).unwrap();
diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs
index aa7eaa5..16616e5 100644
--- a/lightning/src/ln/functional_test_utils.rs
+++ b/lightning/src/ln/functional_test_utils.rs
@@ -3446,7 +3446,7 @@ pub fn send_along_route_with_secret<'a, 'b, 'c>(
.node
.send_payment(
our_payment_hash,
- RecipientOnionFields::secret_only(our_payment_secret),
+ RecipientOnionFields::secret_only(our_payment_secret, recv_value),
payment_id,
route.route_params.unwrap(),
Retry::Attempts(0),
@@ -3585,7 +3585,7 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
if is_last_hop && is_probe {
do_commitment_signed_dance(node, prev_node, &payment_event.commitment_msg, true, true);
- node.node.process_pending_htlc_forwards();
+ expect_and_process_pending_htlcs(node, true);
check_added_monitors(node, 1);
} else {
let commitment = &payment_event.commitment_msg;
diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs
index 4a2c8e0..796c151 100644
--- a/lightning/src/ln/functional_tests.rs
+++ b/lightning/src/ln/functional_tests.rs
@@ -2026,7 +2026,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(
// on nodes[2]'s RAA.
let (route, fourth_payment_hash, _, fourth_payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[2], 1000000);
- let onion = RecipientOnionFields::secret_only(fourth_payment_secret);
+ let onion = RecipientOnionFields::secret_only(fourth_payment_secret, 1000000);
let id = PaymentId(fourth_payment_hash.0);
nodes[1].node.send_payment_with_route(route, fourth_payment_hash, onion, id).unwrap();
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@@ -2249,7 +2249,7 @@ pub fn fail_backward_pending_htlc_upon_channel_failure() {
{
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 50_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 50_000);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -2267,7 +2267,7 @@ pub fn fail_backward_pending_htlc_upon_channel_failure() {
let (route, failed_payment_hash, _, failed_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 50_000);
{
- let onion = RecipientOnionFields::secret_only(failed_payment_secret);
+ let onion = RecipientOnionFields::secret_only(failed_payment_secret, 50_000);
let id = PaymentId(failed_payment_hash.0);
nodes[0].node.send_payment_with_route(route, failed_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 0);
@@ -2283,7 +2283,7 @@ pub fn fail_backward_pending_htlc_upon_channel_failure() {
let secp_ctx = Secp256k1::new();
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let current_height = nodes[1].node.best_block.read().unwrap().height + 1;
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret, 50_000);
let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(
&route.paths[0],
50_000,
@@ -2419,7 +2419,7 @@ pub fn test_force_close_fail_back() {
get_route_and_payment_hash!(nodes[0], nodes[2], 1000000);
let mut payment_event = {
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -2705,7 +2705,7 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
get_route_and_payment_hash!(nodes[0], nodes[1], 1_000_000);
let payment_event = {
- let onion = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1, 1_000_000);
let id = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route, payment_hash_1, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -3120,7 +3120,7 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() {
// Now try to send a second payment which will fail to send
let (route, payment_hash_2, payment_preimage_2, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -3309,7 +3309,7 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) {
// indicates there are more HTLCs coming.
let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
let payment_id = PaymentId([42; 32]);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100000);
let session_privs = nodes[0]
.node
.test_add_new_pending_payment(our_payment_hash, onion, payment_id, &route)
@@ -3320,7 +3320,7 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) {
.test_send_payment_along_path(
&route.paths[0],
&our_payment_hash,
- RecipientOnionFields::secret_only(payment_secret),
+ RecipientOnionFields::secret_only(payment_secret, 200_000),
200_000,
cur_height,
payment_id,
@@ -3409,7 +3409,7 @@ fn do_test_holding_cell_htlc_add_timeouts(forwarded_htlc: bool) {
// Route a first payment to get the 1 -> 2 channel in awaiting_raa...
let (route, first_payment_hash, _, first_payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
- let onion = RecipientOnionFields::secret_only(first_payment_secret);
+ let onion = RecipientOnionFields::secret_only(first_payment_secret, 100000);
let id = PaymentId(first_payment_hash.0);
nodes[1].node.send_payment_with_route(route, first_payment_hash, onion, id).unwrap();
assert_eq!(nodes[1].node.get_and_clear_pending_msg_events().len(), 1);
@@ -3419,7 +3419,7 @@ fn do_test_holding_cell_htlc_add_timeouts(forwarded_htlc: bool) {
let sending_node = if forwarded_htlc { &nodes[0] } else { &nodes[1] };
let (route, second_payment_hash, _, second_payment_secret) =
get_route_and_payment_hash!(sending_node, nodes[2], 100000);
- let onion = RecipientOnionFields::secret_only(second_payment_secret);
+ let onion = RecipientOnionFields::secret_only(second_payment_secret, 100000);
let id = PaymentId(second_payment_hash.0);
sending_node.node.send_payment_with_route(route, second_payment_hash, onion, id).unwrap();
@@ -5065,7 +5065,8 @@ fn do_htlc_claim_current_remote_commitment_only(use_dust: bool) {
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], if use_dust { 50000 } else { 3000000 });
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion =
+ RecipientOnionFields::secret_only(payment_secret, if use_dust { 50000 } else { 3000000 });
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -5235,7 +5236,7 @@ pub fn test_fail_holding_cell_htlc_upon_free() {
get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send);
// Send a payment which passes reserve checks but gets stuck in the holding cell.
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, max_can_send);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, onion, id).unwrap();
chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2);
@@ -5341,14 +5342,14 @@ pub fn test_free_and_fail_holding_cell_htlcs() {
get_route_and_payment_hash!(nodes[0], nodes[1], amt_2);
// Send 2 payments which pass reserve checks but get stuck in the holding cell.
- let onion = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1, amt_1);
let id_1 = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route_1, payment_hash_1, onion, id_1).unwrap();
chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2);
assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1);
let id_2 = PaymentId(nodes[0].keys_manager.get_secure_random_bytes());
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, amt_2);
nodes[0].node.send_payment_with_route(route_2.clone(), payment_hash_2, onion, id_2).unwrap();
chan_stat = get_channel_value_stat!(nodes[0], nodes[1], chan.2);
assert_eq!(chan_stat.holding_cell_outbound_amount_msat, amt_1 + amt_2);
@@ -5487,7 +5488,7 @@ pub fn test_fail_holding_cell_htlc_upon_free_multihop() {
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[2], max_can_send);
let payment_event = {
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, max_can_send);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -5595,7 +5596,7 @@ pub fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_
//First hop
let mut payment_event = {
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -5708,7 +5709,7 @@ pub fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() {
// First hop
let mut payment_event = {
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100_000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -6062,7 +6063,7 @@ pub fn test_check_htlc_underpaying() {
.node
.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, None)
.unwrap();
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, route.get_total_amount());
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -7007,7 +7008,7 @@ pub fn test_onion_value_mpp_set_calculation() {
// Send payment
let id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, total_msat);
let onion_session_privs =
nodes[0].node.test_add_new_pending_payment(hash, onion.clone(), id, &route).unwrap();
let amt = Some(total_msat);
@@ -7040,7 +7041,7 @@ pub fn test_onion_value_mpp_set_calculation() {
&route.paths[0],
&session_priv,
);
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret, 100_000);
let (mut onion_payloads, _, _) = onion_utils::build_onion_payloads(
&route.paths[0],
100_000,
@@ -7145,10 +7146,10 @@ fn do_test_overshoot_mpp(msat_amounts: &[u64], total_msat: u64) {
// Send payment with manually set total_msat
let id = PaymentId(nodes[src_idx].keys_manager.backing.get_secure_random_bytes());
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, total_msat);
let onion_session_privs =
nodes[src_idx].node.test_add_new_pending_payment(hash, onion, id, &route).unwrap();
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, total_msat);
let amt = Some(total_msat);
nodes[src_idx]
.node
@@ -7236,7 +7237,7 @@ pub fn test_preimage_storage() {
let (payment_hash, payment_secret) =
nodes[1].node.create_inbound_payment(Some(100_000), 7200, None).unwrap();
let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100_000);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
@@ -7328,20 +7329,20 @@ pub fn test_bad_secret_hash() {
let expected_err_data = [0, 0, 0, 0, 0, 1, 0x86, 0xa0, 0, 0, 0, CHAN_CONFIRM_DEPTH as u8];
// Send a payment with the right payment hash but the wrong payment secret
- let onion = RecipientOnionFields::secret_only(random_secret);
+ let onion = RecipientOnionFields::secret_only(random_secret, 100_000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, onion, id).unwrap();
handle_unknown_invalid_payment_data!(our_payment_hash);
expect_payment_failed!(nodes[0], our_payment_hash, true, expected_err_code, expected_err_data);
// Send a payment with a random payment hash, but the right payment secret
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100_000);
nodes[0].node.send_payment_with_route(route.clone(), random_hash, onion, id).unwrap();
handle_unknown_invalid_payment_data!(random_hash);
expect_payment_failed!(nodes[0], random_hash, true, expected_err_code, expected_err_data);
// Send a payment with a random payment hash and random payment secret
- let onion = RecipientOnionFields::secret_only(random_secret);
+ let onion = RecipientOnionFields::secret_only(random_secret, 100_000);
nodes[0].node.send_payment_with_route(route, random_hash, onion, id).unwrap();
handle_unknown_invalid_payment_data!(random_hash);
expect_payment_failed!(nodes[0], random_hash, true, expected_err_code, expected_err_data);
@@ -7570,7 +7571,7 @@ pub fn test_concurrent_monitor_claim() {
// Route another payment to generate another update with still previous HTLC pending
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], 3000000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 3000000);
let id = PaymentId(payment_hash.0);
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -8322,7 +8323,7 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) {
get_payment_preimage_hash(&nodes[1], None, None);
{
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 10_000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -8338,7 +8339,7 @@ fn do_test_dup_htlc_second_rejected(test_for_second_fail_panic: bool) {
{
// Note that we use a different PaymentId here to allow us to duplicativly pay
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 10_000);
let id = PaymentId(our_payment_secret.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -8478,10 +8479,10 @@ pub fn test_inconsistent_mpp_params() {
// ultimately have, just not right away.
let mut dup_route = route.clone();
dup_route.paths.push(route.paths[1].clone());
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 15_000_000);
nodes[0].node.test_add_new_pending_payment(hash, onion, id, &dup_route).unwrap()
};
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 15_000_000);
let path_a = &route.paths[0];
let real_amt = 15_000_000;
let priv_a = session_privs[0];
@@ -8499,7 +8500,7 @@ pub fn test_inconsistent_mpp_params() {
assert!(nodes[3].node.get_and_clear_pending_events().is_empty());
let path_b = &route.paths[1];
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 14_000_000);
let amt_b = 14_000_000;
let priv_b = session_privs[1];
nodes[0]
@@ -8559,7 +8560,7 @@ pub fn test_inconsistent_mpp_params() {
let conditions = PaymentFailedConditions::new().mpp_parts_remain();
expect_payment_failed_conditions(&nodes[0], hash, true, conditions);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, real_amt);
let path_b = &route.paths[1];
let priv_c = session_privs[2];
nodes[0]
@@ -8627,7 +8628,7 @@ pub fn test_double_partial_claim() {
pass_failed_payment_back(&nodes[0], paths, false, hash, reason);
// nodes[1] now retries one of the two paths...
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 15_000_000);
let id = PaymentId(hash.0);
nodes[0].node.send_payment_with_route(route, hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 2);
@@ -8859,12 +8860,18 @@ fn do_test_max_dust_htlc_exposure(
};
// With default dust exposure: 5000 sats
if on_holder_tx {
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(
+ payment_secret,
+ dust_outbound_htlc_on_holder_tx_msat,
+ );
let id = PaymentId(payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
} else {
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(
+ payment_secret,
+ dust_htlc_on_counterparty_tx_msat + 1,
+ );
let id = PaymentId(payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -8878,7 +8885,7 @@ fn do_test_max_dust_htlc_exposure(
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], amount_msats);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amount_msats);
let id = PaymentId(payment_hash.0);
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -8917,7 +8924,7 @@ fn do_test_max_dust_htlc_exposure(
// to cross the threshold.
for _ in 0..AT_FEE_OUTBOUND_HTLCS {
let (_, hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(1_000), None);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, route.get_total_amount());
let id = PaymentId(hash.0);
nodes[0].node.send_payment_with_route(route.clone(), hash, onion, id).unwrap();
}
@@ -9147,7 +9154,7 @@ pub fn test_nondust_htlc_excess_fees_are_dust() {
// Send an additional non-dust htlc from 1 to 0, and check the complaint
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], dust_limit * 2);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, route.get_total_amount());
let id = PaymentId(payment_hash.0);
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -9183,7 +9190,7 @@ pub fn test_nondust_htlc_excess_fees_are_dust() {
assert_eq!(nodes[1].node.list_channels()[0].pending_outbound_htlcs.len(), 0);
// Send an additional non-dust htlc from 0 to 1 using the pre-calculated route above, and check the immediate complaint
- let onion = RecipientOnionFields::secret_only(payment_secret_0_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_0_1, route_0_1.get_total_amount());
let id = PaymentId(payment_hash_0_1.0);
let res = nodes[0].node.send_payment_with_route(route_0_1, payment_hash_0_1, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -9201,7 +9208,7 @@ pub fn test_nondust_htlc_excess_fees_are_dust() {
create_announced_chan_between_nodes(&nodes, 2, 0);
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[2], nodes[1], dust_limit * 2);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, route.get_total_amount());
nodes[2].node.send_payment_with_route(route, payment_hash, onion, PaymentId([0; 32])).unwrap();
check_added_monitors(&nodes[2], 1);
let send = SendEvent::from_node(&nodes[2]);
@@ -9322,7 +9329,7 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures)
// Send an additional non-dust htlc from 0 to 1, and check the complaint
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], NON_DUST_HTLC_MSAT);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, NON_DUST_HTLC_MSAT);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -9404,7 +9411,7 @@ fn do_test_nondust_htlc_fees_dust_exposure_delta(features: ChannelTypeFeatures)
nodes[1].node.update_partial_channel_config(&node_a_id, &[chan_id], &update).unwrap();
// Send an additional non-dust htlc from 1 to 0 using the pre-calculated route above, and check the immediate complaint
- let onion = RecipientOnionFields::secret_only(payment_secret_1_0);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1_0, NON_DUST_HTLC_MSAT);
let id = PaymentId(payment_hash_1_0.0);
let res = nodes[1].node.send_payment_with_route(route_1_0, payment_hash_1_0, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -9487,7 +9494,7 @@ fn do_payment_with_custom_min_final_cltv_expiry(valid_delta: bool, use_user_hash
(hash, nodes[1].node.get_payment_preimage(hash, payment_secret).unwrap(), payment_secret)
};
let route = get_route!(nodes[0], payment_parameters, recv_value).unwrap();
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, recv_value);
nodes[0].node.send_payment_with_route(route, hash, onion, PaymentId(hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -9961,7 +9968,7 @@ fn do_test_multi_post_event_actions(do_reload: bool) {
let (route, payment_hash_3, _, payment_secret_3) =
get_route_and_payment_hash!(nodes[1], nodes[0], 100_000);
let payment_id = PaymentId(payment_hash_3.0);
- let onion = RecipientOnionFields::secret_only(payment_secret_3);
+ let onion = RecipientOnionFields::secret_only(payment_secret_3, 100_000);
nodes[1].node.send_payment_with_route(route, payment_hash_3, onion, payment_id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -10072,7 +10079,7 @@ pub fn test_dust_exposure_holding_cell_assertion() {
// messages (leaving B waiting on C's RAA) the next HTLC will go into B's holding cell.
let (route_bc, payment_hash_bc, _payment_preimage_bc, payment_secret_bc) =
get_route_and_payment_hash!(nodes[1], nodes[2], DUST_HTLC_VALUE_MSAT);
- let onion_bc = RecipientOnionFields::secret_only(payment_secret_bc);
+ let onion_bc = RecipientOnionFields::secret_only(payment_secret_bc, DUST_HTLC_VALUE_MSAT);
let id = PaymentId(payment_hash_bc.0);
nodes[1].node.send_payment_with_route(route_bc, payment_hash_bc, onion_bc, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -10092,7 +10099,7 @@ pub fn test_dust_exposure_holding_cell_assertion() {
.unwrap();
let (route_ac, payment_hash_cell, _, payment_secret_ac) =
get_route_and_payment_hash!(nodes[0], nodes[2], payment_params_ac, DUST_HTLC_VALUE_MSAT);
- let onion_ac = RecipientOnionFields::secret_only(payment_secret_ac);
+ let onion_ac = RecipientOnionFields::secret_only(payment_secret_ac, DUST_HTLC_VALUE_MSAT);
let id = PaymentId(payment_hash_cell.0);
nodes[0].node.send_payment_with_route(route_ac, payment_hash_cell, onion_ac, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -10115,7 +10122,7 @@ pub fn test_dust_exposure_holding_cell_assertion() {
// its holding cell as it would be over-exposed to dust.
let (route_cb, payment_hash_cb, payment_preimage_cb, payment_secret_cb) =
get_route_and_payment_hash!(nodes[2], nodes[1], DUST_HTLC_VALUE_MSAT);
- let onion_cb = RecipientOnionFields::secret_only(payment_secret_cb);
+ let onion_cb = RecipientOnionFields::secret_only(payment_secret_cb, DUST_HTLC_VALUE_MSAT);
let id = PaymentId(payment_hash_cb.0);
nodes[2].node.send_payment_with_route(route_cb, payment_hash_cb, onion_cb, id).unwrap();
check_added_monitors(&nodes[2], 1);
diff --git a/lightning/src/ln/htlc_reserve_unit_tests.rs b/lightning/src/ln/htlc_reserve_unit_tests.rs
index 63faa98..1a1cfed 100644
--- a/lightning/src/ln/htlc_reserve_unit_tests.rs
+++ b/lightning/src/ln/htlc_reserve_unit_tests.rs
@@ -172,7 +172,7 @@ pub fn test_channel_reserve_holding_cell_htlcs() {
route.paths[0].hops.last_mut().unwrap().fee_msat += 1;
assert!(route.paths[0].hops.iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, route.get_total_amount());
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -248,7 +248,7 @@ pub fn test_channel_reserve_holding_cell_htlcs() {
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_1);
let payment_event_1 = {
let route = route_1.clone();
- let onion = RecipientOnionFields::secret_only(our_payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret_1, recv_value_1);
let id = PaymentId(our_payment_hash_1.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash_1, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -270,7 +270,7 @@ pub fn test_channel_reserve_holding_cell_htlcs() {
route.paths[0].hops.last_mut().unwrap().fee_msat = recv_value_2 + 1;
let (_, our_payment_hash, our_payment_secret) =
get_payment_preimage_hash(&nodes[2], None, None);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, route.get_total_amount());
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -298,7 +298,7 @@ pub fn test_channel_reserve_holding_cell_htlcs() {
let (route_21, our_payment_hash_21, our_payment_preimage_21, our_payment_secret_21) =
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_21);
// but this will stuck in the holding cell
- let onion = RecipientOnionFields::secret_only(our_payment_secret_21);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret_21, recv_value_21);
let id = PaymentId(our_payment_hash_21.0);
nodes[0].node.send_payment_with_route(route_21, our_payment_hash_21, onion, id).unwrap();
check_added_monitors(&nodes[0], 0);
@@ -310,7 +310,7 @@ pub fn test_channel_reserve_holding_cell_htlcs() {
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22);
route.paths[0].hops.last_mut().unwrap().fee_msat += 1;
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, route.get_total_amount());
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -320,7 +320,7 @@ pub fn test_channel_reserve_holding_cell_htlcs() {
let (route_22, our_payment_hash_22, our_payment_preimage_22, our_payment_secret_22) =
get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22);
// this will also stuck in the holding cell
- let onion = RecipientOnionFields::secret_only(our_payment_secret_22);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret_22, recv_value_22);
let id = PaymentId(our_payment_hash_22.0);
nodes[0].node.send_payment_with_route(route_22, our_payment_hash_22, onion, id).unwrap();
check_added_monitors(&nodes[0], 0);
@@ -496,7 +496,7 @@ pub fn channel_reserve_in_flight_removes() {
let (route, payment_hash_3, payment_preimage_3, payment_secret_3) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
let send_1 = {
- let onion = RecipientOnionFields::secret_only(payment_secret_3);
+ let onion = RecipientOnionFields::secret_only(payment_secret_3, 100000);
let id = PaymentId(payment_hash_3.0);
nodes[0].node.send_payment_with_route(route, payment_hash_3, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -573,7 +573,7 @@ pub fn channel_reserve_in_flight_removes() {
let (route, payment_hash_4, payment_preimage_4, payment_secret_4) =
get_route_and_payment_hash!(nodes[1], nodes[0], 10000);
let send_2 = {
- let onion = RecipientOnionFields::secret_only(payment_secret_4);
+ let onion = RecipientOnionFields::secret_only(payment_secret_4, 10000);
let id = PaymentId(payment_hash_4.0);
nodes[1].node.send_payment_with_route(route, payment_hash_4, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -640,7 +640,7 @@ pub fn holding_cell_htlc_counting() {
for _ in 0..50 {
let (route, payment_hash, payment_preimage, payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100000);
let id = PaymentId(payment_hash.0);
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
payments.push((payment_preimage, payment_hash));
@@ -656,7 +656,7 @@ pub fn holding_cell_htlc_counting() {
// the holding cell waiting on B's RAA to send. At this point we should not be able to add
// another HTLC.
{
- let onion = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1, 100000);
let id = PaymentId(payment_hash_1.0);
let res = nodes[1].node.send_payment_with_route(route, payment_hash_1, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -666,7 +666,7 @@ pub fn holding_cell_htlc_counting() {
// This should also be true if we try to forward a payment.
let (route, payment_hash_2, _, payment_secret_2) =
get_route_and_payment_hash!(nodes[0], nodes[2], 100000);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 100000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -772,7 +772,7 @@ pub fn test_basic_channel_reserve() {
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send);
route.paths[0].hops.last_mut().unwrap().fee_msat += 1;
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, max_can_send + 1);
let id = PaymentId(our_payment_hash.0);
let err = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], err, true, APIError::ChannelUnavailable { .. }, {});
@@ -820,7 +820,8 @@ pub fn do_test_fee_spike_buffer(cfg: Option<UserConfig>, htlc_fails: bool) {
let payment_amt_msat = 3460001;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv);
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields =
+ RecipientOnionFields::secret_only(payment_secret, payment_amt_msat);
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(
&route.paths[0],
payment_amt_msat,
@@ -1021,7 +1022,7 @@ pub fn test_chan_reserve_violation_outbound_htlc_inbound_chan() {
}
// However one more HTLC should be significantly over the reserve amount and fail.
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1_000_000);
let id = PaymentId(our_payment_hash.0);
let res = nodes[1].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -1068,7 +1069,7 @@ pub fn test_chan_reserve_violation_inbound_htlc_outbound_channel() {
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let cur_height = nodes[1].node.best_block.read().unwrap().height + 1;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv);
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret, 700_000);
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(
&route.paths[0],
700_000,
@@ -1153,7 +1154,7 @@ pub fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() {
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;
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, dust_amt + 1);
let id = PaymentId(our_payment_hash.0);
let res = nodes[1].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -1224,7 +1225,7 @@ pub fn test_chan_reserve_violation_inbound_htlc_inbound_chan() {
let (route_1, our_payment_hash_1, _, our_payment_secret_1) =
get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_1);
let payment_event_1 = {
- let onion = RecipientOnionFields::secret_only(our_payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret_1, amt_msat_1);
let id = PaymentId(our_payment_hash_1.0);
let route = route_1.clone();
nodes[0].node.send_payment_with_route(route, our_payment_hash_1, onion, id).unwrap();
@@ -1253,7 +1254,7 @@ pub fn test_chan_reserve_violation_inbound_htlc_inbound_chan() {
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
let cur_height = nodes[0].node.best_block.read().unwrap().height + 1;
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv);
- let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_onion_fields = RecipientOnionFields::spontaneous_empty(recv_value_2);
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(
&route_2.paths[0],
recv_value_2,
@@ -1323,7 +1324,7 @@ pub fn test_payment_route_reaching_same_channel_twice() {
route.paths[0].hops.extend_from_slice(&cloned_hops);
unwrap_send_err!(nodes[0], nodes[0].node.send_payment_with_route(route, our_payment_hash,
- RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)
+ RecipientOnionFields::secret_only(our_payment_secret, 100000000), PaymentId(our_payment_hash.0)
), false, APIError::InvalidRoute { ref err },
assert_eq!(err, &"Path went through the same channel twice"));
assert!(nodes[0].node.list_recent_payments().is_empty());
@@ -1347,7 +1348,7 @@ pub fn test_update_add_htlc_bolt2_sender_value_below_minimum_msat() {
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
route.paths[0].hops[0].fee_msat = 100;
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -1367,7 +1368,7 @@ pub fn test_update_add_htlc_bolt2_sender_zero_value_msat() {
let (mut route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
route.paths[0].hops[0].fee_msat = 0;
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 0);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res,
@@ -1397,7 +1398,7 @@ pub fn test_update_add_htlc_bolt2_receiver_zero_value_msat() {
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1438,7 +1439,7 @@ pub fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() {
get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000);
route.paths[0].hops.last_mut().unwrap().cltv_expiry_delta = 500000001;
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000000);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::InvalidRoute { ref err },
@@ -1473,7 +1474,7 @@ pub fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increme
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
let payment_event = {
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1499,7 +1500,7 @@ pub fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increme
expect_and_process_pending_htlcs(&nodes[1], false);
expect_payment_claimable!(nodes[1], our_payment_hash, our_payment_secret, 100000);
}
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 100000);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -1527,7 +1528,7 @@ pub fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_value_in_flight() {
// Manually create a route over our max in flight (which our router normally automatically
// limits us to.
route.paths[0].hops[0].fee_msat = max_in_flight + 1;
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, max_in_flight + 1);
let id = PaymentId(our_payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -1559,7 +1560,7 @@ pub fn test_update_add_htlc_bolt2_receiver_check_amount_received_more_than_min()
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], htlc_minimum_msat);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, htlc_minimum_msat);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1599,7 +1600,7 @@ pub fn test_update_add_htlc_bolt2_receiver_sender_can_afford_amount_sent() {
let max_can_send = 5000000 - channel_reserve - commit_tx_fee_outbound;
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], max_can_send);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, max_can_send);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1643,7 +1644,7 @@ pub fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() {
&route.paths[0],
&session_priv,
);
- let recipient_onion_fields = RecipientOnionFields::secret_only(our_payment_secret);
+ let recipient_onion_fields = RecipientOnionFields::secret_only(our_payment_secret, send_amt);
let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(
&route.paths[0],
send_amt,
@@ -1703,7 +1704,7 @@ pub fn test_update_add_htlc_bolt2_receiver_check_max_in_flight_msat() {
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1737,7 +1738,7 @@ pub fn test_update_add_htlc_bolt2_receiver_check_cltv_expiry() {
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let reason = RecipientOnionFields::secret_only(our_payment_secret);
+ let reason = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, reason, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1769,7 +1770,7 @@ pub fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() {
create_announced_chan_between_nodes(&nodes, 0, 1);
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
@@ -1834,7 +1835,7 @@ pub fn test_update_fulfill_htlc_bolt2_update_fulfill_htlc_before_commitment() {
let chan = create_announced_chan_between_nodes(&nodes, 0, 1);
let (route, our_payment_hash, our_payment_preimage, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
@@ -1879,7 +1880,7 @@ pub fn test_update_fulfill_htlc_bolt2_update_fail_htlc_before_commitment() {
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1923,7 +1924,7 @@ pub fn test_update_fulfill_htlc_bolt2_update_fail_malformed_htlc_before_commitme
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -2086,7 +2087,7 @@ pub fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_me
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1000000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 1000000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -2244,7 +2245,8 @@ pub fn do_test_dust_limit_fee_accounting(can_afford: bool) {
let onion_keys =
onion_utils::construct_onion_keys(&secp_ctx, &route_0_1.paths[0], &session_priv);
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret_0_1);
+ let recipient_onion_fields =
+ RecipientOnionFields::secret_only(payment_secret_0_1, HTLC_AMT_SAT * 1000);
let (onion_payloads, amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(
&route_0_1.paths[0],
HTLC_AMT_SAT * 1000,
diff --git a/lightning/src/ln/interception_tests.rs b/lightning/src/ln/interception_tests.rs
index c3cd52a..5fece51 100644
--- a/lightning/src/ln/interception_tests.rs
+++ b/lightning/src/ln/interception_tests.rs
@@ -163,7 +163,7 @@ fn do_test_htlc_interception_flags(
None => {},
}
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let payment_id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
diff --git a/lightning/src/ln/invoice_utils.rs b/lightning/src/ln/invoice_utils.rs
index 1503a9a..ae87307 100644
--- a/lightning/src/ln/invoice_utils.rs
+++ b/lightning/src/ln/invoice_utils.rs
@@ -1284,7 +1284,10 @@ mod test {
let payment_hash = invoice.payment_hash();
let id = PaymentId(payment_hash.0);
- let onion = RecipientOnionFields::secret_only(*invoice.payment_secret());
+ let onion = RecipientOnionFields::secret_only(
+ *invoice.payment_secret(),
+ invoice.amount_milli_satoshis().unwrap(),
+ );
nodes[0].node.send_payment(payment_hash, onion, id, params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
diff --git a/lightning/src/ln/max_payment_path_len_tests.rs b/lightning/src/ln/max_payment_path_len_tests.rs
index b947273..ea78449 100644
--- a/lightning/src/ln/max_payment_path_len_tests.rs
+++ b/lightning/src/ln/max_payment_path_len_tests.rs
@@ -87,6 +87,7 @@ fn large_payment_metadata() {
payment_secret: Some(payment_secret),
payment_metadata: Some(payment_metadata.clone()),
custom_tlvs: Vec::new(),
+ total_mpp_amount_msat: amt_msat,
};
let route_params = route_0_1.route_params.clone().unwrap();
let id = PaymentId(payment_hash.0);
@@ -128,6 +129,7 @@ fn large_payment_metadata() {
// If our payment_metadata contains 1 additional byte, we'll fail prior to pathfinding.
let mut too_large_onion = max_sized_onion.clone();
too_large_onion.payment_metadata.as_mut().map(|mut md| md.push(42));
+ too_large_onion.total_mpp_amount_msat = MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY;
// First confirm we'll fail to create the onion packet directly.
let secp_ctx = Secp256k1::signing_only();
@@ -167,6 +169,7 @@ fn large_payment_metadata() {
payment_secret: Some(payment_secret_2),
payment_metadata: Some(two_hop_metadata.clone()),
custom_tlvs: Vec::new(),
+ total_mpp_amount_msat: amt_msat,
};
let mut route_params_0_2 = route_0_2.route_params.clone().unwrap();
route_params_0_2.payment_params.max_path_length = 2;
@@ -261,7 +264,7 @@ fn one_hop_blinded_path_with_custom_tlv() {
- final_payload_len_without_custom_tlv;
// Check that we can send the maximum custom TLV with 1 blinded hop.
- let max_sized_onion = RecipientOnionFields::spontaneous_empty().with_custom_tlvs(
+ let max_sized_onion = RecipientOnionFields::spontaneous_empty(amt_msat).with_custom_tlvs(
RecipientCustomTlvs::new(vec![(CUSTOM_TLV_TYPE, vec![42; max_custom_tlv_len])]).unwrap(),
);
let id = PaymentId(payment_hash.0);
@@ -369,7 +372,7 @@ fn blinded_path_with_custom_tlv() {
let reserved_packet_bytes_without_custom_tlv: usize = onion_utils::build_onion_payloads(
&route.paths[0],
MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY,
- &RecipientOnionFields::spontaneous_empty(),
+ &RecipientOnionFields::spontaneous_empty(MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY),
nodes[0].best_block_info().1 + DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
&None,
None,
@@ -387,7 +390,7 @@ fn blinded_path_with_custom_tlv() {
- reserved_packet_bytes_without_custom_tlv;
// Check that we can send the maximum custom TLV size with 0 intermediate unblinded hops.
- let max_sized_onion = RecipientOnionFields::spontaneous_empty().with_custom_tlvs(
+ let max_sized_onion = RecipientOnionFields::spontaneous_empty(amt_msat).with_custom_tlvs(
RecipientCustomTlvs::new(vec![(CUSTOM_TLV_TYPE, vec![42; max_custom_tlv_len])]).unwrap(),
);
let no_retry = Retry::Attempts(0);
@@ -420,10 +423,12 @@ fn blinded_path_with_custom_tlv() {
.unwrap_err();
assert_eq!(err, RetryableSendFailure::OnionPacketSizeExceeded);
- // Confirm that we can't construct an onion packet given this too-large custom TLV.
+ // Confirm that we can't construct an onion packet given this too-large custom TLV (as long as
+ // we actually use the amount the payment logic uses when validating).
let secp_ctx = Secp256k1::signing_only();
route.paths[0].hops[0].fee_msat = MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY;
route.paths[0].hops[0].cltv_expiry_delta = DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA;
+ too_large_onion.total_mpp_amount_msat = MIN_FINAL_VALUE_ESTIMATE_WITH_OVERPAY;
let err = onion_utils::create_payment_onion(
&secp_ctx,
&route.paths[0],
diff --git a/lightning/src/ln/monitor_tests.rs b/lightning/src/ln/monitor_tests.rs
index 1574458..18a9768 100644
--- a/lightning/src/ln/monitor_tests.rs
+++ b/lightning/src/ln/monitor_tests.rs
@@ -68,7 +68,7 @@ fn chanmon_fail_from_stale_commitment() {
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000);
nodes[0].node.send_payment_with_route(route, payment_hash,
- RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 1_000_000), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let bs_txn = get_local_commitment_txn!(nodes[1], chan_id_2);
@@ -881,7 +881,7 @@ fn do_test_balances_on_local_commitment_htlcs(keyed_anchors: bool, p2a_anchor: b
let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 10_000_000);
let htlc_cltv_timeout = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 1; // Note ChannelManager adds one to CLTV timeouts for safety
nodes[0].node.send_payment_with_route(route, payment_hash,
- RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 10_000_000), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
@@ -893,7 +893,7 @@ fn do_test_balances_on_local_commitment_htlcs(keyed_anchors: bool, p2a_anchor: b
let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[1], 20_000_000);
nodes[0].node.send_payment_with_route(route_2, payment_hash_2,
- RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap();
+ RecipientOnionFields::secret_only(payment_secret_2, 20_000_000), PaymentId(payment_hash_2.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
@@ -3630,7 +3630,7 @@ fn do_test_lost_timeout_monitor_events(confirm_tx: CommitmentType, dust_htlcs: b
let (route, hash_b, _, payment_secret_b) =
get_route_and_payment_hash!(nodes[1], nodes[2], amt);
- let onion = RecipientOnionFields::secret_only(payment_secret_b);
+ let onion = RecipientOnionFields::secret_only(payment_secret_b, amt);
nodes[1].node.send_payment_with_route(route, hash_b, onion, PaymentId(hash_b.0)).unwrap();
check_added_monitors(&nodes[1], 1);
diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs
index a4a09dd..de08af5 100644
--- a/lightning/src/ln/offers_tests.rs
+++ b/lightning/src/ln/offers_tests.rs
@@ -2469,7 +2469,7 @@ fn rejects_keysend_to_non_static_invoice_path() {
let route_params = RouteParameters::from_payment_params_and_value(pay_params, amt_msat);
let keysend_payment_id = PaymentId([2; 32]);
let payment_hash = nodes[0].node.send_spontaneous_payment(
- Some(payment_preimage), RecipientOnionFields::spontaneous_empty(), keysend_payment_id,
+ Some(payment_preimage), RecipientOnionFields::spontaneous_empty(amt_msat), keysend_payment_id,
route_params, Retry::Attempts(0)
).unwrap();
check_added_monitors(&nodes[0], 1);
diff --git a/lightning/src/ln/onion_payment.rs b/lightning/src/ln/onion_payment.rs
index 555cc7a..d0d50c6 100644
--- a/lightning/src/ln/onion_payment.rs
+++ b/lightning/src/ln/onion_payment.rs
@@ -879,7 +879,7 @@ mod tests {
let total_amt_msat = 1000;
let cur_height = 1000;
let pay_secret = PaymentSecret([99; 32]);
- let recipient_onion = RecipientOnionFields::secret_only(pay_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(pay_secret, total_amt_msat);
let preimage_bytes = [43; 32];
let preimage = PaymentPreimage(preimage_bytes);
let rhash_bytes = Sha256::hash(&preimage_bytes).to_byte_array();
diff --git a/lightning/src/ln/onion_route_tests.rs b/lightning/src/ln/onion_route_tests.rs
index fe7d833..74c76ee 100644
--- a/lightning/src/ln/onion_route_tests.rs
+++ b/lightning/src/ln/onion_route_tests.rs
@@ -128,7 +128,8 @@ fn run_onion_failure_test_with_fail_intercept<F1, F2, F3>(
// 0 ~~> 2 send payment
let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
- let recipient_onion = RecipientOnionFields::secret_only(*payment_secret);
+ let recipient_onion =
+ RecipientOnionFields::secret_only(*payment_secret, route.get_total_amount());
nodes[0]
.node
.send_payment_with_route(route.clone(), *payment_hash, recipient_onion, payment_id)
@@ -399,7 +400,7 @@ fn test_fee_failures() {
// positive case
let (route, payment_hash_success, payment_preimage_success, payment_secret_success) =
get_route_and_payment_hash!(nodes[0], nodes[2], 40_000);
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret_success);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret_success, 40_000);
let payment_id = PaymentId(payment_hash_success.0);
nodes[0]
.node
@@ -450,7 +451,7 @@ fn test_fee_failures() {
let (payment_preimage_success, payment_hash_success, payment_secret_success) =
get_payment_preimage_hash(&nodes[2], None, None);
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret_success);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret_success, 40_000);
let payment_id = PaymentId(payment_hash_success.0);
nodes[0]
.node
@@ -523,7 +524,7 @@ fn test_onion_failure() {
let cur_height = nodes[0].best_block_info().1 + 1;
let onion_keys =
construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv);
- let recipient_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_fields = RecipientOnionFields::spontaneous_empty(40000);
let path = &route.paths[0];
let (mut onion_payloads, _htlc_msat, _htlc_cltv) =
build_onion_payloads(path, 40000, &recipient_fields, cur_height, &None, None, None)
@@ -565,7 +566,7 @@ fn test_onion_failure() {
let cur_height = nodes[0].best_block_info().1 + 1;
let onion_keys =
construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv);
- let recipient_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_fields = RecipientOnionFields::spontaneous_empty(40000);
let path = &route.paths[0];
let (mut onion_payloads, _htlc_msat, _htlc_cltv) =
build_onion_payloads(path, 40000, &recipient_fields, cur_height, &None, None, None)
@@ -1284,7 +1285,7 @@ fn test_onion_failure() {
CLTV_FAR_FAR_AWAY + route.paths[0].hops[0].cltv_expiry_delta + 1;
let onion_keys =
construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv);
- let recipient_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_fields = RecipientOnionFields::spontaneous_empty(40000);
let path = &route.paths[0];
let (onion_payloads, _, htlc_cltv) =
build_onion_payloads(path, 40000, &recipient_fields, height, &None, None, None)
@@ -1542,7 +1543,7 @@ fn test_overshoot_final_cltv() {
get_route_and_payment_hash!(nodes[0], nodes[2], 40000);
let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, 40000);
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, payment_id)
@@ -1837,7 +1838,7 @@ fn test_always_create_tlv_format_onion_payloads() {
assert!(!hops[1].node_features.supports_variable_length_onion());
let cur_height = nodes[0].best_block_info().1 + 1;
- let recipient_fields = RecipientOnionFields::spontaneous_empty();
+ let recipient_fields = RecipientOnionFields::spontaneous_empty(40000);
let path = &route.paths[0];
let (onion_payloads, _htlc_msat, _htlc_cltv) =
build_onion_payloads(path, 40000, &recipient_fields, cur_height, &None, None, None)
@@ -1973,7 +1974,7 @@ fn test_trampoline_onion_payload_assembly_values() {
let payment_secret = PaymentSecret(
SecretKey::from_slice(&<Vec<u8>>::from_hex(SECRET_HEX).unwrap()).unwrap().secret_bytes(),
);
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let (trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) =
onion_utils::build_trampoline_onion_payloads(
&path.blinded_tail.as_ref().unwrap(),
@@ -2038,6 +2039,8 @@ fn test_trampoline_onion_payload_assembly_values() {
)
.unwrap();
+ let recipient_onion_fields =
+ RecipientOnionFields::secret_only(payment_secret, outer_total_msat);
let (outer_payloads, total_msat, total_htlc_offset) = build_onion_payloads(
&path,
outer_total_msat,
@@ -2072,6 +2075,7 @@ fn test_trampoline_onion_payload_assembly_values() {
panic!("Bob payload must be Forward");
}
+ let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let (_, total_msat_combined, total_htlc_offset_combined) = onion_utils::create_payment_onion(
&Secp256k1::new(),
&path,
@@ -2280,7 +2284,7 @@ fn do_test_fail_htlc_backwards_with_reason(failure_code: FailureCode) {
let payment_amount = 100_000;
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], payment_amount);
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, payment_amount);
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, PaymentId(payment_hash.0))
@@ -2430,7 +2434,7 @@ fn test_phantom_onion_hmac_failure() {
let (route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel);
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, recv_value_msat);
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, PaymentId(payment_hash.0))
@@ -2502,7 +2506,7 @@ fn test_phantom_invalid_onion_payload() {
// We'll use the session priv later when constructing an invalid onion packet.
let session_priv = [3; 32];
*nodes[0].keys_manager.override_random_bytes.lock().unwrap() = Some(session_priv);
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, recv_value_msat);
let payment_id = PaymentId(payment_hash.0);
nodes[0]
.node
@@ -2534,7 +2538,8 @@ fn test_phantom_invalid_onion_payload() {
let session_priv = SecretKey::from_slice(&session_priv).unwrap();
let mut onion_keys =
construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv);
- let recipient_onion_fields = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion_fields =
+ RecipientOnionFields::secret_only(payment_secret, msgs::MAX_VALUE_MSAT + 1);
let (mut onion_payloads, _, _) = build_onion_payloads(
&route.paths[0],
msgs::MAX_VALUE_MSAT + 1,
@@ -2602,7 +2607,7 @@ fn test_phantom_final_incorrect_cltv_expiry() {
let (route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel);
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, recv_value_msat);
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, PaymentId(payment_hash.0))
@@ -2671,7 +2676,7 @@ fn test_phantom_failure_too_low_cltv() {
route.paths[0].hops[1].cltv_expiry_delta = 5;
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, recv_value_msat);
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, PaymentId(payment_hash.0))
@@ -2724,7 +2729,7 @@ fn test_phantom_failure_modified_cltv() {
let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel);
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, recv_value_msat);
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, PaymentId(payment_hash.0))
@@ -2779,7 +2784,7 @@ fn test_phantom_failure_expires_too_soon() {
let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_value_msat, channel);
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, recv_value_msat);
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, PaymentId(payment_hash.0))
@@ -2829,7 +2834,8 @@ fn test_phantom_failure_too_low_recv_amt() {
let (mut route, phantom_scid) = get_phantom_route!(nodes, bad_recv_amt_msat, channel);
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion =
+ RecipientOnionFields::secret_only(payment_secret, route.get_total_amount());
nodes[0]
.node
.send_payment_with_route(route, payment_hash, recipient_onion, PaymentId(payment_hash.0))
@@ -2898,7 +2904,7 @@ fn do_test_phantom_dust_exposure_failure(multiplier_dust_limit: bool) {
let (mut route, phantom_scid) = get_phantom_route!(nodes, max_dust_exposure + 1, channel);
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, max_dust_exposure + 1);
let payment_id = PaymentId(payment_hash.0);
nodes[0]
.node
@@ -2948,7 +2954,7 @@ fn test_phantom_failure_reject_payment() {
let (mut route, phantom_scid) = get_phantom_route!(nodes, recv_amt_msat, channel);
// Route the HTLC through to the destination.
- let recipient_onion = RecipientOnionFields::secret_only(payment_secret);
+ let recipient_onion = RecipientOnionFields::secret_only(payment_secret, recv_amt_msat);
let payment_id = PaymentId(payment_hash.0);
nodes[0]
.node
diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs
index 605f27e..22cb758 100644
--- a/lightning/src/ln/onion_utils.rs
+++ b/lightning/src/ln/onion_utils.rs
@@ -219,6 +219,7 @@ impl<'a, 'b> OnionPayload<'a, 'b> for msgs::OutboundOnionPayload<'a> {
recipient_onion: &'a RecipientOnionFields, keysend_preimage: Option<PaymentPreimage>,
sender_intended_htlc_amt_msat: u64, total_msat: u64, cltv_expiry_height: u32,
) -> Result<Self::ReceiveType, APIError> {
+ debug_assert_eq!(total_msat, recipient_onion.total_mpp_amount_msat);
Ok(Self::Receive {
payment_data: recipient_onion
.payment_secret
@@ -257,6 +258,7 @@ impl<'a, 'b> OnionPayload<'a, 'b> for msgs::OutboundOnionPayload<'a> {
total_msat: u64, amt_to_forward: u64, outgoing_cltv_value: u32,
recipient_onion: &'a RecipientOnionFields, packet: msgs::TrampolineOnionPacket,
) -> Result<Self, APIError> {
+ debug_assert_eq!(total_msat, recipient_onion.total_mpp_amount_msat);
Ok(Self::TrampolineEntrypoint {
amt_to_forward,
outgoing_cltv_value,
@@ -443,6 +445,8 @@ pub(super) fn build_onion_payloads<'a>(
invoice_request: Option<&'a InvoiceRequest>,
trampoline_packet: Option<msgs::TrampolineOnionPacket>,
) -> Result<(Vec<msgs::OutboundOnionPayload<'a>>, u64, u32), APIError> {
+ debug_assert_eq!(total_msat, recipient_onion.total_mpp_amount_msat);
+
let mut res: Vec<msgs::OutboundOnionPayload> = Vec::with_capacity(
path.hops.len() + path.blinded_tail.as_ref().map_or(0, |t| t.hops.len()),
);
@@ -514,6 +518,8 @@ where
let mut cur_cltv = starting_htlc_offset;
let mut last_hop_id = None;
+ debug_assert_eq!(total_msat, recipient_onion.total_mpp_amount_msat);
+
for (idx, hop) in hops.rev().enumerate() {
// First hop gets special values so that it can check, on receipt, that everything is
// exactly as it should be (and the next hop isn't trying to probe to find out if we're
@@ -661,11 +667,15 @@ pub(crate) fn set_max_path_length(
maybe_announced_channel: false,
};
let mut num_reserved_bytes: usize = 0;
+ // TODO: Find a way to avoid `clone`ing the whole recipient onion without re-adding the
+ // explicit amount parameter to build_onion_payloads_callback.
+ let mut recipient_onion_with_excess_value = recipient_onion.clone();
+ recipient_onion_with_excess_value.total_mpp_amount_msat = final_value_msat_with_overpay_buffer;
let build_payloads_res = build_onion_payloads_callback(
core::iter::once(&unblinded_route_hop),
blinded_tail_opt,
final_value_msat_with_overpay_buffer,
- &recipient_onion,
+ &recipient_onion_with_excess_value,
best_block_height,
&keysend_preimage,
invoice_request,
@@ -2623,11 +2633,29 @@ pub(crate) fn create_payment_onion_internal<T: secp256k1::Signing>(
prng_seed: [u8; 32], trampoline_session_priv_override: Option<SecretKey>,
trampoline_prng_seed_override: Option<[u8; 32]>,
) -> Result<(msgs::OnionPacket, u64, u32), APIError> {
+ debug_assert_eq!(total_msat, recipient_onion.total_mpp_amount_msat);
+
let mut outer_total_msat = total_msat;
let mut outer_starting_htlc_offset = cur_block_height;
- let mut trampoline_packet_option = None;
- if let Some(blinded_tail) = &path.blinded_tail {
+ // If we're paying to a recipient through a trampoline, we use the `payment_secret` provided in
+ // `recipient_onion` as the MPP identifier for the trampoline entry point, allowing it to
+ // detect when when it has received all the MPP parts.
+ // A `total_mpp_amount_msat` is also provided to the trampoline entry point, but set in the
+ // below `if` block.
+ let mut trampoline_outer_onion = RecipientOnionFields {
+ payment_secret: recipient_onion.payment_secret,
+ total_mpp_amount_msat: 0,
+ payment_metadata: None,
+ custom_tlvs: Vec::new(),
+ };
+ let (outer_onion, trampoline_packet_option) = if let Some(blinded_tail) = &path.blinded_tail {
+ if recipient_onion.payment_metadata.is_some() {
+ return Err(APIError::InvalidRoute {
+ err: "Cannot pass payment_metadata to a blinded recipient".to_owned(),
+ });
+ }
+
if !blinded_tail.trampoline_hops.is_empty() {
let trampoline_payloads;
(trampoline_payloads, outer_total_msat, outer_starting_htlc_offset) =
@@ -2638,6 +2666,7 @@ pub(crate) fn create_payment_onion_internal<T: secp256k1::Signing>(
cur_block_height,
keysend_preimage,
)?;
+ trampoline_outer_onion.total_mpp_amount_msat = outer_total_msat;
let trampoline_session_priv = trampoline_session_priv_override
.unwrap_or_else(|| compute_trampoline_session_priv(session_priv));
@@ -2656,14 +2685,18 @@ pub(crate) fn create_payment_onion_internal<T: secp256k1::Signing>(
err: "Route size too large considering onion data".to_owned(),
})?;
- trampoline_packet_option = Some(trampoline_packet);
+ (&trampoline_outer_onion, Some(trampoline_packet))
+ } else {
+ (recipient_onion, None)
}
- }
+ } else {
+ (recipient_onion, None)
+ };
let (onion_payloads, htlc_msat, htlc_cltv) = build_onion_payloads(
&path,
outer_total_msat,
- recipient_onion,
+ outer_onion,
outer_starting_htlc_offset,
keysend_preimage,
invoice_request,
@@ -4029,7 +4062,7 @@ mod tests {
max_total_routing_fee_msat: Some(u64::MAX),
};
route_params.payment_params.max_total_cltv_expiry_delta = u32::MAX;
- let recipient_onion = RecipientOnionFields::spontaneous_empty();
+ let recipient_onion = RecipientOnionFields::spontaneous_empty(u64::MAX);
set_max_path_length(&mut route_params, &recipient_onion, None, None, 42).unwrap();
}
diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs
index 64f9f64..b9a5884 100644
--- a/lightning/src/ln/outbound_payment.rs
+++ b/lightning/src/ln/outbound_payment.rs
@@ -21,6 +21,7 @@ use crate::ln::channelmanager::{
EventCompletionAction, HTLCSource, OptionalBolt11PaymentParams, PaymentCompleteUpdate,
PaymentId,
};
+use crate::ln::msgs::DecodeError;
use crate::ln::onion_utils;
use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason};
use crate::offers::invoice::{Bolt12Invoice, DerivedSigningPubkey, InvoiceBuilder};
@@ -44,8 +45,10 @@ use core::fmt::{self, Display, Formatter};
use core::sync::atomic::{AtomicBool, Ordering};
use core::time::Duration;
+use crate::io;
use crate::prelude::*;
use crate::sync::Mutex;
+use crate::util::ser;
/// The number of ticks of [`ChannelManager::timer_tick_occurred`] until we time-out the idempotency
/// of payments by [`PaymentId`]. See [`OutboundPayments::remove_stale_payments`].
@@ -758,33 +761,83 @@ pub struct RecipientOnionFields {
pub payment_metadata: Option<Vec<u8>>,
/// See [`Self::custom_tlvs`] for more info.
pub(super) custom_tlvs: Vec<(u64, Vec<u8>)>,
+ /// The total payment amount which is being sent.
+ ///
+ /// This is communicated to the recipient as an indication that they should delay claiming the
+ /// payment until they've received multiple payment parts totaling at least this amount.
+ ///
+ /// Note that in order to properly communicate this, the recipient must either be paid using
+ /// blinded paths or a [`Self::payment_secret`] must be set.
+ pub total_mpp_amount_msat: u64,
}
-impl_writeable_tlv_based!(RecipientOnionFields, {
- (0, payment_secret, option),
- (1, custom_tlvs, optional_vec),
- (2, payment_metadata, option),
-});
+impl ser::Writeable for RecipientOnionFields {
+ fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ write_tlv_fields!(writer, {
+ (0, self.payment_secret, option),
+ (1, self.custom_tlvs, optional_vec),
+ (2, self.payment_metadata, option),
+ (3, self.total_mpp_amount_msat, required),
+ });
+ Ok(())
+ }
+}
+
+impl ser::ReadableArgs<u64> for RecipientOnionFields {
+ fn read<R: io::Read>(
+ reader: &mut R, default_total_mpp_amount_msat: u64,
+ ) -> Result<Self, DecodeError> {
+ _init_and_read_len_prefixed_tlv_fields!(reader, {
+ (0, payment_secret, option),
+ (1, custom_tlvs, optional_vec),
+ (2, payment_metadata, option),
+ // Added and always written in LDK 0.3
+ (3, total_mpp_amount_msat, option),
+ });
+ Ok(Self {
+ payment_secret,
+ custom_tlvs: custom_tlvs.unwrap_or(Vec::new()),
+ payment_metadata,
+ total_mpp_amount_msat: total_mpp_amount_msat.unwrap_or(default_total_mpp_amount_msat),
+ })
+ }
+}
impl RecipientOnionFields {
- /// Creates a [`RecipientOnionFields`] from only a [`PaymentSecret`]. This is the most common
- /// set of onion fields for today's BOLT11 invoices - most nodes require a [`PaymentSecret`]
- /// but do not require or provide any further data.
+ /// Creates a [`RecipientOnionFields`] from only a [`PaymentSecret`] and total MPP amount. This
+ /// is the most common set of onion fields for today's BOLT11 invoices - most nodes require a
+ /// [`PaymentSecret`] but do not require or provide any further data.
#[rustfmt::skip]
- pub fn secret_only(payment_secret: PaymentSecret) -> Self {
- Self { payment_secret: Some(payment_secret), payment_metadata: None, custom_tlvs: Vec::new() }
+ pub fn secret_only(payment_secret: PaymentSecret, total_mpp_amount_msat: u64) -> Self {
+ Self {
+ payment_secret: Some(payment_secret),
+ payment_metadata: None,
+ custom_tlvs: Vec::new(),
+ total_mpp_amount_msat,
+ }
}
- /// Creates a new [`RecipientOnionFields`] with no fields. This generally does not create
- /// payable HTLCs except for single-path spontaneous payments, i.e. this should generally
- /// only be used for calls to [`ChannelManager::send_spontaneous_payment`]. If you are sending
- /// a spontaneous MPP this will not work as all MPP require payment secrets; you may
- /// instead want to use [`RecipientOnionFields::secret_only`].
+ /// Creates a new [`RecipientOnionFields`] with no fields but the total MPP amount. This is
+ /// useful when paying a blinded path, where the `payment_secret` and `payment_metadata` are
+ /// not provided but rather stored transparently in the blinded path itself.
+ ///
+ /// Otherwise, this generally does not create payable HTLCs except for single-path spontaneous
+ /// payments, i.e. those for calls to [`ChannelManager::send_spontaneous_payment`].
+ ///
+ /// Note that due to protocol limitations, in non-blinded-path cases, you cannot make an MPP
+ /// payment without a `payment_secret`. Thus, in such cases `total_mpp_amount_msat` is ignored.
+ /// If you intend to send a spontaneous MPP you may instead want to use
+ /// [`RecipientOnionFields::secret_only`].
///
/// [`ChannelManager::send_spontaneous_payment`]: super::channelmanager::ChannelManager::send_spontaneous_payment
/// [`RecipientOnionFields::secret_only`]: RecipientOnionFields::secret_only
- pub fn spontaneous_empty() -> Self {
- Self { payment_secret: None, payment_metadata: None, custom_tlvs: Vec::new() }
+ pub fn spontaneous_empty(total_mpp_amount_msat: u64) -> Self {
+ Self {
+ payment_secret: None,
+ payment_metadata: None,
+ custom_tlvs: Vec::new(),
+ total_mpp_amount_msat,
+ }
}
/// Creates a new [`RecipientOnionFields`] from an existing one, adding validated custom TLVs.
@@ -837,6 +890,9 @@ impl RecipientOnionFields {
pub(super) fn check_merge(&mut self, further_htlc_fields: &mut Self) -> Result<(), ()> {
if self.payment_secret != further_htlc_fields.payment_secret { return Err(()); }
if self.payment_metadata != further_htlc_fields.payment_metadata { return Err(()); }
+ if self.total_mpp_amount_msat != further_htlc_fields.total_mpp_amount_msat {
+ return Err(());
+ }
let tlvs = &mut self.custom_tlvs;
let further_tlvs = &mut further_htlc_fields.custom_tlvs;
@@ -984,8 +1040,9 @@ impl OutboundPayments {
(None, None) => return Err(Bolt11PaymentError::InvalidAmount),
};
- let mut recipient_onion = RecipientOnionFields::secret_only(*invoice.payment_secret())
- .with_custom_tlvs(optional_params.custom_tlvs);
+ let mut recipient_onion =
+ RecipientOnionFields::secret_only(*invoice.payment_secret(), amount)
+ .with_custom_tlvs(optional_params.custom_tlvs);
recipient_onion.payment_metadata = invoice.payment_metadata().map(|v| v.clone());
let payment_params = PaymentParameters::from_bolt11_invoice(invoice)
@@ -1084,6 +1141,7 @@ impl OutboundPayments {
payment_secret: None,
payment_metadata: None,
custom_tlvs: vec![],
+ total_mpp_amount_msat: route_params.final_value_msat,
};
let route = match self.find_initial_route(
payment_id, payment_hash, &recipient_onion, keysend_preimage, invoice_request,
@@ -1224,7 +1282,7 @@ impl OutboundPayments {
if let Err(()) = onion_utils::set_max_path_length(
&mut route_params,
- &RecipientOnionFields::spontaneous_empty(),
+ &RecipientOnionFields::spontaneous_empty(amount_msat),
Some(keysend_preimage),
Some(invreq),
best_block_height,
@@ -1620,6 +1678,7 @@ impl OutboundPayments {
payment_secret: *payment_secret,
payment_metadata: payment_metadata.clone(),
custom_tlvs: custom_tlvs.clone(),
+ total_mpp_amount_msat: total_msat,
};
let keysend_preimage = *keysend_preimage;
let invoice_request = invoice_request.clone();
@@ -1824,15 +1883,16 @@ impl OutboundPayments {
}
let route = Route { paths: vec![path], route_params: None };
+ let recipient_onion_fields =
+ RecipientOnionFields::secret_only(payment_secret, route.get_total_amount());
let onion_session_privs = self.add_new_pending_payment(payment_hash,
- RecipientOnionFields::secret_only(payment_secret), payment_id, None, &route, None, None,
+ recipient_onion_fields.clone(), payment_id, None, &route, None, None,
entropy_source, best_block_height, None
).map_err(|e| {
debug_assert!(matches!(e, PaymentSendFailure::DuplicatePayment));
ProbeSendFailure::DuplicateProbe
})?;
- let recipient_onion_fields = RecipientOnionFields::spontaneous_empty();
match self.pay_route_internal(&route, payment_hash, &recipient_onion_fields,
None, None, None, payment_id, None, &onion_session_privs, false, node_signer,
best_block_height, &send_payment_along_path
@@ -2847,7 +2907,7 @@ mod tests {
#[test]
#[rustfmt::skip]
fn test_recipient_onion_fields_with_custom_tlvs() {
- let onion_fields = RecipientOnionFields::spontaneous_empty();
+ let onion_fields = RecipientOnionFields::spontaneous_empty(42);
let bad_type_range_tlvs = RecipientCustomTlvs::new(vec![
(0, vec![42]),
@@ -2895,7 +2955,7 @@ mod tests {
let expired_route_params = RouteParameters::from_payment_params_and_value(payment_params, 0);
let pending_events = Mutex::new(VecDeque::new());
if on_retry {
- outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(),
+ outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(0),
PaymentId([0; 32]), None, &Route { paths: vec![], route_params: None },
Some(Retry::Attempts(1)), Some(expired_route_params.payment_params.clone()),
&&keys_manager, 0, None).unwrap();
@@ -2910,7 +2970,7 @@ mod tests {
} else { panic!("Unexpected event"); }
} else {
let err = outbound_payments.send_payment(
- PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]),
+ PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(0), PaymentId([0; 32]),
Retry::Attempts(0), expired_route_params, &&router, vec![], || InFlightHtlcs::new(),
&&keys_manager, &&keys_manager, 0, &pending_events, |_| Ok(()), &log).unwrap_err();
if let RetryableSendFailure::PaymentExpired = err { } else { panic!("Unexpected error"); }
@@ -2941,7 +3001,7 @@ mod tests {
let pending_events = Mutex::new(VecDeque::new());
if on_retry {
- outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(),
+ outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(0),
PaymentId([0; 32]), None, &Route { paths: vec![], route_params: None },
Some(Retry::Attempts(1)), Some(route_params.payment_params.clone()),
&&keys_manager, 0, None).unwrap();
@@ -2954,7 +3014,7 @@ mod tests {
if let Event::PaymentFailed { .. } = events[0].0 { } else { panic!("Unexpected event"); }
} else {
let err = outbound_payments.send_payment(
- PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]),
+ PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(0), PaymentId([0; 32]),
Retry::Attempts(0), route_params, &&router, vec![], || InFlightHtlcs::new(),
&&keys_manager, &&keys_manager, 0, &pending_events, |_| Ok(()), &log).unwrap_err();
if let RetryableSendFailure::RouteNotFound = err {
@@ -3005,7 +3065,7 @@ mod tests {
// PaymentPathFailed event.
let pending_events = Mutex::new(VecDeque::new());
outbound_payments.send_payment(
- PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]),
+ PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(1), PaymentId([0; 32]),
Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(),
&&keys_manager, &&keys_manager, 0, &pending_events,
|_| Err(APIError::ChannelUnavailable { err: "test".to_owned() }), &log).unwrap();
@@ -3023,7 +3083,7 @@ mod tests {
// Ensure that a MonitorUpdateInProgress "error" will not result in a PaymentPathFailed event.
outbound_payments.send_payment(
- PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]),
+ PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(1), PaymentId([0; 32]),
Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(),
&&keys_manager, &&keys_manager, 0, &pending_events,
|_| Err(APIError::MonitorUpdateInProgress), &log).unwrap();
@@ -3031,7 +3091,7 @@ mod tests {
// Ensure that any other error will result in a PaymentPathFailed event but no blamed scid.
outbound_payments.send_payment(
- PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(), PaymentId([1; 32]),
+ PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(1), PaymentId([1; 32]),
Retry::Attempts(0), route_params.clone(), &&router, vec![], || InFlightHtlcs::new(),
&&keys_manager, &&keys_manager, 0, &pending_events,
|_| Err(APIError::APIMisuseError { err: "test".to_owned() }), &log).unwrap();
diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs
index aa4bf96..1a01358 100644
--- a/lightning/src/ln/payment_tests.rs
+++ b/lightning/src/ln/payment_tests.rs
@@ -146,7 +146,7 @@ fn mpp_retry() {
let mut route_params = route.route_params.clone().unwrap();
nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
- let onion = RecipientOnionFields::secret_only(pay_secret);
+ let onion = RecipientOnionFields::secret_only(pay_secret, amt_msat * 2);
let retry = Retry::Attempts(1);
nodes[0].node.send_payment(hash, onion, id, route_params.clone(), retry).unwrap();
check_added_monitors(&nodes[0], 2); // one monitor per path
@@ -264,7 +264,7 @@ fn mpp_retry_overpay() {
let mut route_params = route.route_params.clone().unwrap();
nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
- let onion = RecipientOnionFields::secret_only(pay_secret);
+ let onion = RecipientOnionFields::secret_only(pay_secret, amt_msat);
let retry = Retry::Attempts(1);
nodes[0].node.send_payment(hash, onion, id, route_params.clone(), retry).unwrap();
check_added_monitors(&nodes[0], 2); // one monitor per path
@@ -366,7 +366,7 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) {
route.route_params.as_mut().unwrap().final_value_msat *= 2;
// Initiate the MPP payment.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 200_000);
nodes[0].node.send_payment_with_route(route, hash, onion, PaymentId(hash.0)).unwrap();
check_added_monitors(&nodes[0], 2); // one monitor per path
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -461,7 +461,7 @@ fn do_test_keysend_payments(public_node: bool) {
{
let preimage = Some(PaymentPreimage([42; 32]));
- let onion = RecipientOnionFields::spontaneous_empty();
+ let onion = RecipientOnionFields::spontaneous_empty(10000);
let retry = Retry::Attempts(1);
let id = PaymentId([42; 32]);
nodes[0].node.send_spontaneous_payment(preimage, onion, id, route_params, retry).unwrap();
@@ -511,7 +511,7 @@ fn test_mpp_keysend() {
let preimage = Some(PaymentPreimage([42; 32]));
let payment_secret = PaymentSecret([42; 32]);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, recv_value);
let retry = Retry::Attempts(0);
let id = PaymentId([42; 32]);
let hash =
@@ -554,7 +554,7 @@ fn test_fulfill_hold_times() {
let preimage = Some(PaymentPreimage([42; 32]));
let payment_secret = PaymentSecret([42; 32]);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, recv_value);
let retry = Retry::Attempts(0);
let id = PaymentId([42; 32]);
let hash =
@@ -624,7 +624,7 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() {
let payment_id_0 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
nodes[0].router.expect_find_route(route.route_params.clone().unwrap(), Ok(route.clone()));
let params = route.route_params.clone().unwrap();
- let onion = RecipientOnionFields::spontaneous_empty();
+ let onion = RecipientOnionFields::spontaneous_empty(amount);
let retry = Retry::Attempts(0);
nodes[0].node.send_spontaneous_payment(preimage, onion, payment_id_0, params, retry).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -672,7 +672,7 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() {
let payment_id_1 = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
nodes[0].router.expect_find_route(route.route_params.clone().unwrap(), Ok(route.clone()));
- let onion = RecipientOnionFields::spontaneous_empty();
+ let onion = RecipientOnionFields::spontaneous_empty(amount);
let params = route.route_params.clone().unwrap();
let retry = Retry::Attempts(0);
nodes[0].node.send_spontaneous_payment(preimage, onion, payment_id_1, params, retry).unwrap();
@@ -761,7 +761,7 @@ fn no_pending_leak_on_initial_send_failure() {
nodes[0].node.peer_disconnected(node_b_id);
nodes[1].node.peer_disconnected(node_a_id);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100_000);
let payment_id = PaymentId(payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route, payment_hash, onion, payment_id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { ref err },
@@ -814,7 +814,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
send_along_route(&nodes[0], route.clone(), &[&nodes[1], &nodes[2]], 1_000_000);
let route_params = route.route_params.unwrap().clone();
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -996,7 +996,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
nodes[1].node.timer_tick_occurred();
}
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
// Check that we cannot retry a fulfilled payment
nodes[0]
.node
@@ -1004,7 +1004,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
.unwrap_err();
// ...but if we send with a different PaymentId the payment should fly
let id = PaymentId(payment_hash.0);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
nodes[0].node.send_payment_with_route(new_route.clone(), payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1173,7 +1173,7 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
// If we attempt to retry prior to the HTLC-Timeout (or commitment transaction, for dust HTLCs)
// confirming, we will fail as it's considered still-pending...
let (new_route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], amt);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
match nodes[0].node.send_payment_with_route(new_route.clone(), hash, onion, payment_id) {
Err(RetryableSendFailure::DuplicatePayment) => {},
_ => panic!("Unexpected error"),
@@ -1193,7 +1193,7 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
node_a_ser = nodes[0].node.encode();
// After the payment failed, we're free to send it again.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
nodes[0].node.send_payment_with_route(new_route.clone(), hash, onion, payment_id).unwrap();
assert!(!nodes[0].node.get_and_clear_pending_msg_events().is_empty());
@@ -1210,13 +1210,13 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
// Now resend the payment, delivering the HTLC and actually claiming it this time. This ensures
// the payment is not (spuriously) listed as still pending.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
nodes[0].node.send_payment_with_route(new_route.clone(), hash, onion, payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt, hash, payment_secret);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
match nodes[0].node.send_payment_with_route(new_route.clone(), hash, onion, payment_id) {
Err(RetryableSendFailure::DuplicatePayment) => {},
_ => panic!("Unexpected error"),
@@ -1238,7 +1238,7 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) {
reconnect_nodes(ReconnectArgs::new(&nodes[0], &nodes[1]));
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt);
match nodes[0].node.send_payment_with_route(new_route, hash, onion, payment_id) {
Err(RetryableSendFailure::DuplicatePayment) => {},
_ => panic!("Unexpected error"),
@@ -1531,7 +1531,7 @@ fn get_ldk_payment_preimage() {
&Default::default(),
&random_seed_bytes,
);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route.unwrap(), payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1884,7 +1884,7 @@ fn claimed_send_payment_idempotent() {
() => {
// If we try to resend a new payment with a different payment_hash but with the same
// payment_id, it should be rejected.
- let onion = RecipientOnionFields::secret_only(second_payment_secret);
+ let onion = RecipientOnionFields::secret_only(second_payment_secret, 100_000);
let send_result =
nodes[0].node.send_payment_with_route(route.clone(), hash_b, onion, payment_id);
match send_result {
@@ -1896,7 +1896,7 @@ fn claimed_send_payment_idempotent() {
// also be rejected.
let send_result = nodes[0].node.send_spontaneous_payment(
None,
- RecipientOnionFields::spontaneous_empty(),
+ RecipientOnionFields::spontaneous_empty(100_000),
payment_id,
route.route_params.clone().unwrap(),
Retry::Attempts(0),
@@ -1940,7 +1940,7 @@ fn claimed_send_payment_idempotent() {
nodes[0].node.timer_tick_occurred();
}
- let onion = RecipientOnionFields::secret_only(second_payment_secret);
+ let onion = RecipientOnionFields::secret_only(second_payment_secret, 100_000);
nodes[0].node.send_payment_with_route(route, hash_b, onion, payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1]]], 100_000, hash_b, second_payment_secret);
@@ -1967,7 +1967,7 @@ fn abandoned_send_payment_idempotent() {
() => {
// If we try to resend a new payment with a different payment_hash but with the same
// payment_id, it should be rejected.
- let onion = RecipientOnionFields::secret_only(second_payment_secret);
+ let onion = RecipientOnionFields::secret_only(second_payment_secret, 100_000);
let send_result =
nodes[0].node.send_payment_with_route(route.clone(), hash_b, onion, payment_id);
match send_result {
@@ -1979,7 +1979,7 @@ fn abandoned_send_payment_idempotent() {
// also be rejected.
let send_result = nodes[0].node.send_spontaneous_payment(
None,
- RecipientOnionFields::spontaneous_empty(),
+ RecipientOnionFields::spontaneous_empty(100_000),
payment_id,
route.route_params.clone().unwrap(),
Retry::Attempts(0),
@@ -2009,7 +2009,7 @@ fn abandoned_send_payment_idempotent() {
// However, we can reuse the PaymentId immediately after we `abandon_payment` upon passing the
// failed payment back.
- let onion = RecipientOnionFields::secret_only(second_payment_secret);
+ let onion = RecipientOnionFields::secret_only(second_payment_secret, 100_000);
nodes[0].node.send_payment_with_route(route, hash_b, onion, payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
pass_along_route(&nodes[0], &[&[&nodes[1]]], 100_000, hash_b, second_payment_secret);
@@ -2177,12 +2177,12 @@ fn test_holding_cell_inflight_htlcs() {
// Queue up two payments - one will be delivered right away, one immediately goes into the
// holding cell as nodes[0] is AwaitingRAA.
{
- let onion = RecipientOnionFields::secret_only(payment_secret_1);
+ let onion = RecipientOnionFields::secret_only(payment_secret_1, 1000000);
let id = PaymentId(payment_hash_1.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash_1, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 1000000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[0], 0);
@@ -2272,7 +2272,7 @@ fn do_test_intercepted_payment(test: InterceptTest) {
let (hash, payment_secret) =
nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
nodes[0].node.send_payment_with_route(route.clone(), hash, onion, id).unwrap();
let payment_event = {
@@ -2508,7 +2508,7 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) {
let (payment_hash, payment_secret) =
nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(0)).unwrap();
@@ -2720,7 +2720,7 @@ fn do_automatic_retries(test: AutoRetry) {
if test == AutoRetry::Success {
// Test that we can succeed on the first retry.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
let retry = Retry::Attempts(1);
nodes[0].node.send_payment(hash, onion, id, route_params, retry).unwrap();
@@ -2746,7 +2746,7 @@ fn do_automatic_retries(test: AutoRetry) {
preimage,
));
} else if test == AutoRetry::Spontaneous {
- let onion = RecipientOnionFields::spontaneous_empty();
+ let onion = RecipientOnionFields::spontaneous_empty(amt_msat);
let id = PaymentId(hash.0);
nodes[0]
.node
@@ -2771,7 +2771,7 @@ fn do_automatic_retries(test: AutoRetry) {
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], &[path], preimage));
} else if test == AutoRetry::FailAttempts {
// Ensure ChannelManager will not retry a payment if it has run out of payment attempts.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
nodes[0].node.send_payment(hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
@@ -2792,7 +2792,7 @@ fn do_automatic_retries(test: AutoRetry) {
#[cfg(feature = "std")]
{
// Ensure ChannelManager will not retry a payment if it times out due to Retry::Timeout.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
let retry = Retry::Timeout(Duration::from_secs(60));
nodes[0].node.send_payment(hash, onion, id, route_params, retry).unwrap();
@@ -2820,7 +2820,7 @@ fn do_automatic_retries(test: AutoRetry) {
} else if test == AutoRetry::FailOnRestart {
// Ensure ChannelManager will not retry a payment after restart, even if there were retry
// attempts remaining prior to restart.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
nodes[0].node.send_payment(hash, onion, id, route_params, Retry::Attempts(2)).unwrap();
pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
@@ -2854,7 +2854,7 @@ fn do_automatic_retries(test: AutoRetry) {
_ => panic!("Unexpected event"),
}
} else if test == AutoRetry::FailOnRetry {
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
nodes[0].node.send_payment(hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
pass_failed_attempt_with_retry_along_path!(channel_id_2, true);
@@ -3016,7 +3016,7 @@ fn auto_retry_partial_failure() {
nodes[0].router.expect_find_route(retry_2_params, Ok(retry_2_route));
// Send a payment that will partially fail on send, then partially fail on retry, then succeed.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(3)).unwrap();
@@ -3178,7 +3178,7 @@ fn auto_retry_zero_attempts_send_error() {
};
nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route));
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(0)).unwrap();
@@ -3226,7 +3226,7 @@ fn fails_paying_after_rejected_by_payee() {
.unwrap();
let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -3342,7 +3342,9 @@ fn retry_multi_path_single_failed_payment() {
scorer.expect_usage(chans[1].short_channel_id.unwrap(), usage);
}
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ // Note that while we actaully pay amt_msat + 1, we should really set the onion amount to
+ // amt_msat as that's what we built a route for.
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat + 1);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
let events = nodes[0].node.get_and_clear_pending_events();
@@ -3423,7 +3425,7 @@ fn immediate_retry_on_failure() {
route.route_params = Some(retry_params.clone());
nodes[0].router.expect_find_route(retry_params, Ok(route.clone()));
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
let events = nodes[0].node.get_and_clear_pending_events();
@@ -3562,7 +3564,7 @@ fn no_extra_retries_on_back_to_back_fail() {
// We can't use the commitment_signed_dance macro helper because in this test we'll be sending
// two HTLCs back-to-back on the same channel, and the macro only expects to handle one at a
// time.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
@@ -3807,7 +3809,7 @@ fn test_simple_partial_retry() {
// We can't use the commitment_signed_dance macro helper because in this test we'll be sending
// two HTLCs back-to-back on the same channel, and the macro only expects to handle one at a
// time.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment(payment_hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
let first_htlc = SendEvent::from_node(&nodes[0]);
@@ -4009,7 +4011,7 @@ fn test_threaded_payment_retries() {
};
nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(payment_hash.0);
let retry = Retry::Attempts(0xdeadbeef);
nodes[0].node.send_payment(payment_hash, onion, id, route_params.clone(), retry).unwrap();
@@ -4320,7 +4322,7 @@ fn do_claim_from_closed_chan(fail_payment: bool) {
let final_cltv = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 8 + 1;
nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
nodes[0].node.send_payment(hash, onion, id, route_params, Retry::Attempts(1)).unwrap();
@@ -4489,6 +4491,7 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) {
payment_secret: if spontaneous { None } else { Some(payment_secret) },
payment_metadata: None,
custom_tlvs: custom_tlvs.clone(),
+ total_mpp_amount_msat: amt_msat,
};
if spontaneous {
let params = route.route_params.unwrap();
@@ -4569,7 +4572,7 @@ fn test_retry_custom_tlvs() {
let mut route_params = route.route_params.clone().unwrap();
let custom_tlvs = vec![((1 << 16) + 1, vec![0x42u8; 16])];
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let onion = onion.with_custom_tlvs(RecipientCustomTlvs::new(custom_tlvs.clone()).unwrap());
nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
@@ -4701,6 +4704,7 @@ fn do_test_custom_tlvs_consistency(
payment_secret: Some(payment_secret),
payment_metadata: None,
custom_tlvs: first_tlvs,
+ total_mpp_amount_msat: amt_msat,
};
let session_privs =
nodes[0].node.test_add_new_pending_payment(hash, onion.clone(), id, &route).unwrap();
@@ -4726,6 +4730,7 @@ fn do_test_custom_tlvs_consistency(
payment_secret: Some(payment_secret),
payment_metadata: None,
custom_tlvs: second_tlvs,
+ total_mpp_amount_msat: amt_msat,
};
let path_b = &route.paths[1];
let priv_b = session_privs[1];
@@ -4850,6 +4855,7 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) {
payment_secret: Some(payment_secret),
payment_metadata: Some(payment_metadata),
custom_tlvs: vec![],
+ total_mpp_amount_msat: amt_msat,
};
let retry = Retry::Attempts(1);
nodes[0].node.send_payment(payment_hash, onion, payment_id, route_params, retry).unwrap();
@@ -5043,7 +5049,10 @@ fn test_htlc_forward_considers_anchor_outputs_value() {
nodes[2],
sendable_balance_msat + anchor_outpus_value_msat
);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(
+ payment_secret,
+ sendable_balance_msat + anchor_outpus_value_msat,
+ );
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -5108,7 +5117,7 @@ fn peel_payment_onion_custom_tlvs() {
let payment_params = PaymentParameters::for_keysend(node_b_id, TEST_FINAL_CLTV, false);
let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
let route = functional_test_utils::get_route(&nodes[0], &route_params).unwrap();
- let mut recipient_onion = RecipientOnionFields::spontaneous_empty()
+ let mut recipient_onion = RecipientOnionFields::spontaneous_empty(amt_msat)
.with_custom_tlvs(RecipientCustomTlvs::new(vec![(414141, vec![42; 1200])]).unwrap());
let prng_seed = chanmon_cfgs[0].keys_manager.get_secure_random_bytes();
let session_priv = SecretKey::from_slice(&prng_seed[..]).expect("RNG is busted");
@@ -5203,7 +5212,7 @@ fn test_non_strict_forwarding() {
for i in 0..4 {
let (payment_preimage, payment_hash, payment_secret) =
get_payment_preimage_hash(&nodes[2], Some(payment_value), None);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, payment_value);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -5242,7 +5251,7 @@ fn test_non_strict_forwarding() {
// Send a 5th payment which will fail.
let (_, payment_hash, payment_secret) =
get_payment_preimage_hash(&nodes[2], Some(payment_value), None);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, payment_value);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, onion, id).unwrap();
@@ -5303,7 +5312,7 @@ fn remove_pending_outbounds_on_buggy_router() {
nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
// Send the payment with one retry allowed, but the payment should still fail
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let retry = Retry::Attempts(1);
nodes[0].node.send_payment(payment_hash, onion, payment_id, route_params, retry).unwrap();
let events = nodes[0].node.get_and_clear_pending_events();
@@ -5379,7 +5388,7 @@ fn pay_route_without_params() {
get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, amt_msat);
route.route_params.take();
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
let id = PaymentId(hash.0);
nodes[0].node.send_payment_with_route(route, hash, onion, id).unwrap();
diff --git a/lightning/src/ln/priv_short_conf_tests.rs b/lightning/src/ln/priv_short_conf_tests.rs
index a5ccac7..ffe5ea6 100644
--- a/lightning/src/ln/priv_short_conf_tests.rs
+++ b/lightning/src/ln/priv_short_conf_tests.rs
@@ -81,7 +81,7 @@ fn test_priv_forwarding_rejection() {
let (route, our_payment_hash, our_payment_preimage, our_payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 10_000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -164,7 +164,7 @@ fn test_priv_forwarding_rejection() {
get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, node_c_id);
get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, node_b_id);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 10_000);
let id = PaymentId(our_payment_hash.0);
nodes[0].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -348,7 +348,7 @@ fn test_routed_scid_alias() {
get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000);
assert_eq!(route.paths[0].hops[1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap());
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100_000);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -578,7 +578,7 @@ fn test_inbound_scid_privacy() {
get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000);
assert_eq!(route.paths[0].hops[1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap());
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100_000);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -599,7 +599,7 @@ fn test_inbound_scid_privacy() {
get_route_and_payment_hash!(nodes[0], nodes[2], payment_params_2, 100_000);
assert_eq!(route_2.paths[0].hops[1].short_channel_id, last_hop[0].short_channel_id.unwrap());
- let onion = RecipientOnionFields::secret_only(payment_secret_2);
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, 100_000);
let id = PaymentId(payment_hash_2.0);
nodes[0].node.send_payment_with_route(route_2, payment_hash_2, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -695,7 +695,7 @@ fn test_scid_alias_returned() {
route.paths[0].hops[1].fee_msat = 10_000_000; // Overshoot the last channel's value
// Route the HTLC through to the destination.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, route.get_total_amount());
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, onion, id).unwrap();
@@ -732,7 +732,7 @@ fn test_scid_alias_returned() {
route.paths[0].hops[0].fee_msat = 0; // But set fee paid to the middle hop to 0
// Route the HTLC through to the destination.
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 10_000);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
@@ -934,7 +934,7 @@ fn test_0conf_channel_with_async_monitor() {
let (route, payment_hash, payment_preimage, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -1283,7 +1283,7 @@ fn test_0conf_channel_reorg() {
);
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 10_000);
let id = PaymentId([0; 32]);
nodes[1].node.send_payment_with_route(route, payment_hash, onion.clone(), id).unwrap();
let mut conditions = PaymentFailedConditions::new();
diff --git a/lightning/src/ln/quiescence_tests.rs b/lightning/src/ln/quiescence_tests.rs
index d972fb6..3557b03 100644
--- a/lightning/src/ln/quiescence_tests.rs
+++ b/lightning/src/ln/quiescence_tests.rs
@@ -98,7 +98,7 @@ fn allow_shutdown_while_awaiting_quiescence(local_shutdown: bool) {
let payment_amount = 1_000_000;
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(local_node, remote_node, payment_amount);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, payment_amount);
let payment_id = PaymentId(payment_hash.0);
local_node.node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
check_added_monitors(&local_node, 1);
@@ -304,7 +304,7 @@ fn test_quiescence_on_final_revoke_and_ack_pending_monitor_update() {
let payment_amount = 1_000_000;
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(&nodes[0], &nodes[1], payment_amount);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, payment_amount);
let payment_id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -370,7 +370,7 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
let (route1, payment_hash1, payment_preimage1, payment_secret1) =
get_route_and_payment_hash!(&nodes[1], &nodes[0], payment_amount);
- let onion1 = RecipientOnionFields::secret_only(payment_secret1);
+ let onion1 = RecipientOnionFields::secret_only(payment_secret1, payment_amount);
let payment_id1 = PaymentId(payment_hash1.0);
nodes[1].node.send_payment_with_route(route1, payment_hash1, onion1, payment_id1).unwrap();
check_added_monitors(&nodes[1], 0);
@@ -380,7 +380,7 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
// allowed to make updates.
let (route2, payment_hash2, payment_preimage2, payment_secret2) =
get_route_and_payment_hash!(&nodes[0], &nodes[1], payment_amount);
- let onion2 = RecipientOnionFields::secret_only(payment_secret2);
+ let onion2 = RecipientOnionFields::secret_only(payment_secret2, payment_amount);
let payment_id2 = PaymentId(payment_hash2.0);
nodes[0].node.send_payment_with_route(route2, payment_hash2, onion2, payment_id2).unwrap();
check_added_monitors(&nodes[0], 1);
diff --git a/lightning/src/ln/reload_tests.rs b/lightning/src/ln/reload_tests.rs
index cc5eac6..2e8a060 100644
--- a/lightning/src/ln/reload_tests.rs
+++ b/lightning/src/ln/reload_tests.rs
@@ -545,7 +545,7 @@ fn do_test_data_loss_protect(reconnect_panicing: bool, substantially_old: bool,
// `not_stale` to test the boundary condition.
let pay_params = PaymentParameters::for_keysend(nodes[1].node.get_our_node_id(), 100, false);
let route_params = RouteParameters::from_payment_params_and_value(pay_params, 40000);
- nodes[0].node.send_spontaneous_payment(None, RecipientOnionFields::spontaneous_empty(), PaymentId([0; 32]), route_params, Retry::Attempts(0)).unwrap();
+ nodes[0].node.send_spontaneous_payment(None, RecipientOnionFields::spontaneous_empty(40000), PaymentId([0; 32]), route_params, Retry::Attempts(0)).unwrap();
check_added_monitors(&nodes[0], 1);
let update_add_commit = SendEvent::from_node(&nodes[0]);
@@ -766,7 +766,7 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool, double_rest
});
nodes[0].node.send_payment_with_route(route, payment_hash,
- RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 15_000_000), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 2);
// Send the payment through to nodes[3] *without* clearing the PaymentClaimable event
@@ -964,7 +964,7 @@ fn do_forwarded_payment_no_manager_persistence(use_cs_commitment: bool, claim_ht
let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
let htlc_expiry = nodes[0].best_block_info().1 + TEST_FINAL_CLTV;
nodes[0].node.send_payment_with_route(route, payment_hash,
- RecipientOnionFields::secret_only(payment_secret), payment_id).unwrap();
+ RecipientOnionFields::secret_only(payment_secret, 1_000_000), payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
let payment_event = SendEvent::from_node(&nodes[0]);
@@ -1219,7 +1219,7 @@ fn do_manager_persisted_pre_outbound_edge_forward(intercept_htlc: bool) {
if intercept_htlc {
route.paths[0].hops[1].short_channel_id = nodes[1].node.get_intercept_scid();
}
- nodes[0].node.send_payment_with_route(route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
+ nodes[0].node.send_payment_with_route(route, payment_hash, RecipientOnionFields::secret_only(payment_secret, amt_msat), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
@@ -1312,7 +1312,7 @@ fn test_manager_persisted_post_outbound_edge_forward() {
// Lock in the HTLC from node_a <> node_b.
let amt_msat = 5000;
let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
- nodes[0].node.send_payment_with_route(route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
+ nodes[0].node.send_payment_with_route(route, payment_hash, RecipientOnionFields::secret_only(payment_secret, amt_msat), PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
@@ -1371,7 +1371,8 @@ fn test_manager_persisted_post_outbound_edge_holding_cell() {
// Lock in the HTLC from node_a <> node_b.
let amt_msat = 1000;
let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
- nodes[0].node.send_payment_with_route(route, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
+ nodes[0].node.send_payment_with_route(route, payment_hash, onion, PaymentId(payment_hash.0)).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
nodes[1].node.handle_update_add_htlc(nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
@@ -1380,7 +1381,8 @@ fn test_manager_persisted_post_outbound_edge_holding_cell() {
// Send a 2nd HTLC node_c -> node_b, to force the first HTLC into the holding cell.
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
let (route_2, payment_hash_2, payment_preimage_2, payment_secret_2) = get_route_and_payment_hash!(nodes[2], nodes[1], amt_msat);
- nodes[2].node.send_payment_with_route(route_2, payment_hash_2, RecipientOnionFields::secret_only(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap();
+ let onion = RecipientOnionFields::secret_only(payment_secret_2, amt_msat);
+ nodes[2].node.send_payment_with_route(route_2, payment_hash_2, onion, PaymentId(payment_hash_2.0)).unwrap();
let send_event =
SendEvent::from_event(nodes[2].node.get_and_clear_pending_msg_events().remove(0));
nodes[1].node.handle_update_add_htlc(nodes[2].node.get_our_node_id(), &send_event.msgs[0]);
@@ -1554,9 +1556,9 @@ fn test_htlc_localremoved_persistence() {
let test_preimage = PaymentPreimage([42; 32]);
let mismatch_payment_hash = PaymentHash([43; 32]);
let session_privs = nodes[0].node.test_add_new_pending_payment(mismatch_payment_hash,
- RecipientOnionFields::spontaneous_empty(), PaymentId(mismatch_payment_hash.0), &route).unwrap();
+ RecipientOnionFields::spontaneous_empty(10_000), PaymentId(mismatch_payment_hash.0), &route).unwrap();
nodes[0].node.test_send_payment_internal(&route, mismatch_payment_hash,
- RecipientOnionFields::spontaneous_empty(), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap();
+ RecipientOnionFields::spontaneous_empty(10_000), Some(test_preimage), PaymentId(mismatch_payment_hash.0), None, session_privs).unwrap();
check_added_monitors(&nodes[0], 1);
let updates = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
@@ -1741,7 +1743,7 @@ fn test_hold_completed_inflight_monitor_updates_upon_manager_reload() {
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[0], nodes[1], 1_000_000);
let payment_id = PaymentId(payment_hash.0);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
nodes[0].node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
@@ -2127,9 +2129,8 @@ fn test_reload_with_mpp_claims_on_same_channel() {
get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
let payment_id = PaymentId(nodes[0].keys_manager.backing.get_secure_random_bytes());
- nodes[0].node.send_payment_with_route(
- route, payment_hash, RecipientOnionFields::secret_only(payment_secret), payment_id,
- ).unwrap();
+ let onion = RecipientOnionFields::secret_only(payment_secret, amt_msat);
+ nodes[0].node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
check_added_monitors(&nodes[0], 1);
// Forward the first HTLC nodes[0] -> nodes[1] -> nodes[2]. Note that the second HTLC is released
diff --git a/lightning/src/ln/shutdown_tests.rs b/lightning/src/ln/shutdown_tests.rs
index 474b422..d70b240 100644
--- a/lightning/src/ln/shutdown_tests.rs
+++ b/lightning/src/ln/shutdown_tests.rs
@@ -443,12 +443,12 @@ fn updates_shutdown_wait() {
)
.unwrap();
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100_000);
let id = PaymentId(payment_hash.0);
let res = nodes[0].node.send_payment_with_route(route_1, payment_hash, onion, id);
unwrap_send_err!(nodes[0], res, true, APIError::ChannelUnavailable { .. }, {});
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 100_000);
let res = nodes[1].node.send_payment_with_route(route_2, payment_hash, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
@@ -544,7 +544,7 @@ fn do_htlc_fail_async_shutdown(blinded_recipient: bool) {
amt_msat,
)
};
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, amt_msat);
let id = PaymentId(our_payment_hash.0);
nodes[0]
.node
@@ -1903,7 +1903,7 @@ fn test_pending_htlcs_arent_lost_on_mon_delay() {
// moment `cs_last_raa` is received by B.
let (route_b, payment_hash_b, _preimage, payment_secret_b) =
get_route_and_payment_hash!(&nodes[0], nodes[2], 900_000);
- let onion = RecipientOnionFields::secret_only(payment_secret_b);
+ let onion = RecipientOnionFields::secret_only(payment_secret_b, 900_000);
let id = PaymentId(payment_hash_b.0);
nodes[0].node.send_payment_with_route(route_b, payment_hash_b, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
diff --git a/lightning/src/ln/splicing_tests.rs b/lightning/src/ln/splicing_tests.rs
index 92a298f..409ab3e 100644
--- a/lightning/src/ln/splicing_tests.rs
+++ b/lightning/src/ln/splicing_tests.rs
@@ -1980,7 +1980,7 @@ fn fail_splice_on_interactive_tx_error() {
// Queue an outgoing HTLC to the holding cell. It should be freed once we exit quiescence.
let (route, payment_hash, _payment_preimage, payment_secret) =
get_route_and_payment_hash!(initiator, acceptor, 1_000_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
let payment_id = PaymentId(payment_hash.0);
initiator.node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
@@ -2055,7 +2055,7 @@ fn fail_splice_on_tx_abort() {
// Queue an outgoing HTLC to the holding cell. It should be freed once we exit quiescence.
let (route, payment_hash, _payment_preimage, payment_secret) =
get_route_and_payment_hash!(initiator, acceptor, 1_000_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
let payment_id = PaymentId(payment_hash.0);
initiator.node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
@@ -2124,7 +2124,7 @@ fn fail_splice_on_tx_complete_error() {
// Queue an outgoing HTLC to the holding cell. It should be freed once we exit quiescence.
let (route, payment_hash, _payment_preimage, payment_secret) =
get_route_and_payment_hash!(initiator, acceptor, 1_000_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
let payment_id = PaymentId(payment_hash.0);
acceptor.node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
@@ -2208,7 +2208,7 @@ fn free_holding_cell_on_tx_signatures_quiescence_exit() {
// Queue an outgoing HTLC to the holding cell. It should be freed once we exit quiescence.
let (route, payment_hash, _payment_preimage, payment_secret) =
get_route_and_payment_hash!(initiator, acceptor, 1_000_000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 1_000_000);
let payment_id = PaymentId(payment_hash.0);
initiator.node.send_payment_with_route(route, payment_hash, onion, payment_id).unwrap();
assert!(initiator.node.get_and_clear_pending_msg_events().is_empty());
@@ -2402,7 +2402,7 @@ fn do_test_splice_with_inflight_htlc_forward_and_resolution(expire_scid_pre_forw
let route = get_route(&nodes[0], &route_params).unwrap();
let (_, payment_hash, payment_secret) =
get_payment_preimage_hash(&nodes[2], Some(payment_amount), None);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, payment_amount);
let id = PaymentId(payment_hash.0);
nodes[0].node.send_payment_with_route(route.clone(), payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[0], 1);
diff --git a/lightning/src/ln/update_fee_tests.rs b/lightning/src/ln/update_fee_tests.rs
index ff3e2a0..1886b0f 100644
--- a/lightning/src/ln/update_fee_tests.rs
+++ b/lightning/src/ln/update_fee_tests.rs
@@ -80,7 +80,7 @@ pub fn test_async_inbound_update_fee() {
// ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], 40000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 40000);
let id = PaymentId(our_payment_hash.0);
nodes[1].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -181,7 +181,7 @@ pub fn test_update_fee_unordered_raa() {
// ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
let (route, our_payment_hash, _, our_payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], 40000);
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 40000);
let id = PaymentId(our_payment_hash.0);
nodes[1].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
@@ -665,7 +665,7 @@ pub fn test_update_fee_with_fundee_update_add_htlc() {
get_route_and_payment_hash!(nodes[1], nodes[0], 800000);
// nothing happens since node[1] is in AwaitingRemoteRevoke
- let onion = RecipientOnionFields::secret_only(our_payment_secret);
+ let onion = RecipientOnionFields::secret_only(our_payment_secret, 800000);
let id = PaymentId(our_payment_hash.0);
nodes[1].node.send_payment_with_route(route, our_payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 0);
@@ -1101,7 +1101,7 @@ pub fn do_cannot_afford_on_holding_cell_release(
let (route, payment_hash, _, payment_secret) =
get_route_and_payment_hash!(nodes[1], nodes[0], 5000 * 1000);
- let onion = RecipientOnionFields::secret_only(payment_secret);
+ let onion = RecipientOnionFields::secret_only(payment_secret, 5000 * 1000);
let id = PaymentId(payment_hash.0);
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
check_added_monitors(&nodes[1], 1);
Why this scored 36/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.