Merge PR 'Fix payment attribution edge cases and simplify claiming' (#5021)
What changed, and why it matters
This commit refactors how LDK nodes claim incoming Lightning payments. It replaces a separate 'claim with known custom TLVs' method with an options struct passed to the normal claim call, and fixes two edge cases in payment attribution data used for timing analysis: it caps failure-packet size to prevent oversized messages and ensures trampoline-style forwarded claims start fresh attribution rather than reusing downstream data. The changes are mostly defensive correctness fixes rather than an active vulnerability patch.
Review downstream callers that previously used claim_funds_with_known_custom_tlvs and migrate them to claim_funds with ClaimFundsOptions { custom_tlvs_known: true }. Monitor for any protocol or compatibility issues arising from the new failure-packet size cap and the changed trampoline attribution behavior.
Security signals we found
API change: claim_funds now takes ClaimFundsOptions, consolidating TLV-known behavior into one path
Failure-packet length bound added to prevent oversized onion error messages
Incoming failure packet truncated at 32 KiB before processing
Trampoline/delegated forward claims no longer propagate downstream attribution upstream
New regression test delegated_trampoline_claim_starts_new_attribution
Attribution HMAC computation optimized by cloning a precomputed message HMAC engine
Evidence from the diff
The patch introduces ClaimFundsOptions and makes claim_funds accept it, removing claim_funds_with_known_custom_tlvs. It also adjusts attribution handling: build_unencrypted_failure_packet now truncates failure data so the total onion error packet stays within MAX_ATTRIBUTABLE_RETURN_FIELD_LEN (32 KiB), and process_failure_packet truncates incoming error data to the same limit. In addition, when a TrampolineForward HTLC source is claimed, the code now passes None for upstream attribution data instead of cloning downstream attribution, and a new unit test verifies that delegated trampoline claims generate fresh attribution. The commit also removes a now-unneeded session-priv hashing step when decoding outbound attribution hold times.
Changed components
lightning/src/ln/channelmanager.rslightning/src/ln/onion_utils.rslightning/src/events/mod.rslightning/src/ln/blinded_payment_tests.rsFuzz and integration test suitesInspect captured patch +256 / −173
### fuzz/src/chanmon_consistency.rs
@@ -2671,7 +2671,7 @@ impl PaymentTracker {
.payment_preimages
.get(&payment_hash)
.expect("PaymentClaimable for unknown payment hash");
- node.claim_funds(payment_preimage);
+ node.claim_funds(payment_preimage, Default::default());
self.claimed_payment_hashes.insert(payment_hash);
}
}
### fuzz/src/full_stack.rs
@@ -845,7 +845,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger + MaybeSend + MaybeSync>
} else {
let mut payment_preimage = PaymentPreimage([0; 32]);
payment_preimage.0[0] = payment.0[0];
- channelmanager.claim_funds(payment_preimage);
+ channelmanager.claim_funds(payment_preimage, Default::default());
}
}
},
### lightning-liquidity/tests/lsps2_integration_tests.rs
@@ -1547,7 +1547,7 @@ fn client_trusts_lsp_end_to_end_test() {
assert!(broadcasted.is_empty(), "There should be no broadcasted txs yet");
drop(broadcasted);
- client_node.inner.node.claim_funds(preimage.unwrap());
+ client_node.inner.node.claim_funds(preimage.unwrap(), Default::default());
claim_and_assert_forwarded_only(
&payer_node,
@@ -1987,7 +1987,7 @@ fn late_payment_forwarded_and_safe_after_force_close_does_not_broadcast() {
other => panic!("Expected PaymentClaimable, got {:?}", other),
};
- client_node.inner.node.claim_funds(preimage);
+ client_node.inner.node.claim_funds(preimage, Default::default());
claim_and_assert_forwarded_only(&payer_node, &service_node.inner, &client_node.inner, preimage);
// Service now has PaymentForwarded. Record in JIT state but still not safe to broadcast.
@@ -2198,7 +2198,7 @@ fn htlc_timeout_before_client_claim_results_in_handling_failed() {
assert!(closed_on_service, "Expected service->client channel to close due to HTLC timeout");
// Client tries to claim but should fail since HTLC timed out
- client_node.inner.node.claim_funds(preimage);
+ client_node.inner.node.claim_funds(preimage, Default::default());
let client_events = client_node.inner.node.get_and_clear_pending_events();
assert_eq!(client_events.len(), 1);
match &client_events[0] {
### lightning/src/chain/chainmonitor.rs
@@ -1818,9 +1818,9 @@ mod tests {
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
- nodes[1].node.claim_funds(payment_preimage_2);
+ nodes[1].node.claim_funds(payment_preimage_2, Default::default());
check_added_monitors(&nodes[1], 1);
let persistences =
### lightning/src/events/mod.rs
@@ -1094,12 +1094,13 @@ pub enum Event {
/// If [`Event::PaymentClaimable::onion_fields`] is `Some`, and includes custom TLVs with even type
/// numbers, you should use [`ChannelManager::fail_htlc_backwards_with_reason`] with
/// [`FailureCode::InvalidOnionPayload`] if you fail to understand and handle the contents, or
- /// [`ChannelManager::claim_funds_with_known_custom_tlvs`] upon successful handling.
+ /// [`ChannelManager::claim_funds`] with [`ClaimFundsOptions::custom_tlvs_known`] set to true upon
+ /// successful handling.
/// If you don't intend to check for custom TLVs, you can simply use
- /// [`ChannelManager::claim_funds`], which will automatically fail back even custom TLVs.
+ /// [`ChannelManager::claim_funds`] with default options, which will automatically fail back even
+ /// custom TLVs.
///
/// If you fail to call [`ChannelManager::claim_funds`],
- /// [`ChannelManager::claim_funds_with_known_custom_tlvs`],
/// [`ChannelManager::fail_htlc_backwards`], or
/// [`ChannelManager::fail_htlc_backwards_with_reason`] within the HTLC's timeout, the HTLC will
/// be automatically failed.
@@ -1118,7 +1119,7 @@ pub enum Event {
/// returning `Err(ReplayEvent ())`) and will be persisted across restarts.
///
/// [`ChannelManager::claim_funds`]: crate::ln::channelmanager::ChannelManager::claim_funds
- /// [`ChannelManager::claim_funds_with_known_custom_tlvs`]: crate::ln::channelmanager::ChannelManager::claim_funds_with_known_custom_tlvs
+ /// [`ClaimFundsOptions::custom_tlvs_known`]: crate::ln::channelmanager::ClaimFundsOptions::custom_tlvs_known
/// [`FailureCode::InvalidOnionPayload`]: crate::ln::channelmanager::FailureCode::InvalidOnionPayload
/// [`ChannelManager::fail_htlc_backwards`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards
/// [`ChannelManager::fail_htlc_backwards_with_reason`]: crate::ln::channelmanager::ChannelManager::fail_htlc_backwards_with_reason
### lightning/src/ln/async_signer_tests.rs
@@ -1022,7 +1022,7 @@ fn do_test_async_commitment_signature_ordering(monitor_update_failure: bool) {
get_htlc_update_msgs(&nodes[0], &node_b_id);
// Send back update_fulfill_htlc + commitment_signed for the first payment.
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
check_added_monitors(&nodes[1], 1);
@@ -1615,7 +1615,7 @@ fn test_no_disconnect_while_async_commitment_signed_expecting_remote_revoke_and_
// Route a payment and attempt to claim it.
let payment_amount = 1_000_000;
let (preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], payment_amount);
- nodes[1].node.claim_funds(preimage);
+ nodes[1].node.claim_funds(preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, payment_amount);
### lightning/src/ln/blinded_payment_tests.rs
@@ -1473,7 +1473,7 @@ fn conditionally_round_fwd_amt() {
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);
+ nodes[4].node.claim_funds(payment_preimage, Default::default());
let expected_path = &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]];
let expected_route = &[&expected_path[..]];
let mut args = ClaimAlongRouteArgs::new(&nodes[0], &expected_route[..], payment_preimage)
@@ -2537,7 +2537,22 @@ fn do_test_trampoline_single_hop_receive(success: bool) {
pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], amt_msat, payment_hash, payment_secret);
if success {
- claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
+ let expected_path = &[&nodes[1], &nodes[2]];
+ let expected_route = &[&expected_path[..]];
+ let expected_fee = pass_claimed_payment_along_route(ClaimAlongRouteArgs::new(
+ &nodes[0], &expected_route[..], payment_preimage,
+ ));
+ let (_, path_events) = expect_payment_sent(
+ &nodes[0], payment_preimage, Some(Some(expected_fee)), true, true,
+ );
+ assert_eq!(path_events.len(), 1);
+ match &path_events[0] {
+ Event::PaymentPathSuccessful { hold_times, .. } => {
+ assert_eq!(hold_times, &[0, 0]);
+ },
+ _ => panic!("Unexpected event"),
+ }
} else {
fail_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_hash);
}
### lightning/src/ln/chanmon_update_fail_tests.rs
@@ -117,7 +117,7 @@ fn test_monitor_and_persister_update_fail() {
.block_connected(&create_dummy_block(BlockHash::all_zeros(), 42, Vec::new()), 200);
// Try to update ChannelMonitor
- nodes[1].node.claim_funds(preimage);
+ nodes[1].node.claim_funds(preimage, Default::default());
expect_payment_claimed!(nodes[1], payment_hash, 9_000_000);
check_added_monitors(&nodes[1], 1);
@@ -344,7 +344,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
// Claim the previous payment, which will result in a update_fulfill_htlc/CS from nodes[1]
// but nodes[0] won't respond since it is frozen.
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
@@ -1290,7 +1290,7 @@ fn test_monitor_update_fail_reestablish() {
nodes[1].node.peer_disconnected(node_a_id);
nodes[0].node.peer_disconnected(node_b_id);
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
@@ -1518,7 +1518,7 @@ fn claim_while_disconnected_monitor_update_fail() {
nodes[0].node.peer_disconnected(node_b_id);
nodes[1].node.peer_disconnected(node_a_id);
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
@@ -1848,7 +1848,7 @@ fn test_monitor_update_fail_claim() {
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
// As long as the preimage isn't on-chain, we shouldn't expose the `PaymentClaimed` event to
// users nor send the preimage to peers in the new commitment update.
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
check_added_monitors(&nodes[1], 1);
@@ -2088,7 +2088,7 @@ fn monitor_update_claim_fail_no_response() {
let as_raa = commitment_signed_dance_return_raa(&nodes[1], &nodes[0], &commitment, false);
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@@ -2503,7 +2503,7 @@ fn test_fail_htlc_on_broadcast_after_claim() {
let bs_txn = get_local_commitment_txn!(nodes[2], chan_id_2);
assert_eq!(bs_txn.len(), 1);
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 2000);
@@ -2709,7 +2709,7 @@ fn do_channel_holding_cell_serialize(disconnect: bool, reload_a: bool) {
let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode();
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- nodes[0].node.claim_funds(payment_preimage_0);
+ nodes[0].node.claim_funds(payment_preimage_0, Default::default());
check_added_monitors(&nodes[0], 1);
nodes[1].node.handle_update_add_htlc(node_a_id, &send.msgs[0]);
@@ -2915,7 +2915,7 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
// Note that we don't populate fulfill_msg.attribution_data here, which will lead to hold times being
// unavailable.
} else {
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 100_000);
@@ -3092,14 +3092,14 @@ fn double_temp_error() {
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
// `claim_funds` results in a ChannelMonitorUpdate.
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
let (latest_update_1, _) = nodes[1].chain_monitor.get_latest_mon_update_id(channel_id);
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
// Previously, this would've panicked due to a double-call to `Channel::monitor_update_failed`,
// which had some asserts that prevented it from being called twice.
- nodes[1].node.claim_funds(payment_preimage_2);
+ nodes[1].node.claim_funds(payment_preimage_2, Default::default());
check_added_monitors(&nodes[1], 1);
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed);
@@ -3471,7 +3471,7 @@ fn do_test_blocked_chan_preimage_release(completion_mode: BlockedUpdateComplMode
route_payment(&nodes[2], &[&nodes[1], &nodes[0]], 1_000_000);
// Claim the first payment to get a `PaymentSent` event (but don't handle it yet).
- nodes[2].node.claim_funds(payment_preimage_1);
+ nodes[2].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash_1, 1_000_000);
@@ -3486,7 +3486,7 @@ fn do_test_blocked_chan_preimage_release(completion_mode: BlockedUpdateComplMode
// Now claim the second payment on nodes[0], which will ultimately result in nodes[1] trying to
// claim an HTLC on its channel with nodes[2], but that channel is blocked on the above
// `PaymentSent` event.
- nodes[0].node.claim_funds(payment_preimage_2);
+ nodes[0].node.claim_funds(payment_preimage_2, Default::default());
check_added_monitors(&nodes[0], 1);
expect_payment_claimed!(nodes[0], payment_hash_2, 1_000_000);
@@ -3623,7 +3623,7 @@ fn do_test_inverted_mon_completion_order(
manager_b = nodes[1].node.encode();
}
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 100_000);
@@ -3816,7 +3816,7 @@ fn do_test_durable_preimages_on_closed_channel(
let mon_ab = get_monitor!(nodes[1], chan_id_ab).encode();
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
@@ -4051,7 +4051,7 @@ fn do_test_reload_mon_update_completion_actions(close_during_reload: bool) {
let (payment_preimage, payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
@@ -4168,7 +4168,7 @@ fn do_test_glacial_peer_cant_hang(hold_chan_a: bool) {
let (payment_preimage, payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
@@ -4325,7 +4325,7 @@ fn do_test_partial_claim_mon_update_compl_actions(reload_a: bool, reload_b: bool
// Claim along both paths, but only complete one of the two monitor updates.
chanmon_cfgs[3].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
chanmon_cfgs[3].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- nodes[3].node.claim_funds(preimage);
+ nodes[3].node.claim_funds(preimage, Default::default());
assert_eq!(nodes[3].node.get_and_clear_pending_msg_events(), Vec::new());
assert_eq!(nodes[3].node.get_and_clear_pending_events(), Vec::new());
check_added_monitors(&nodes[3], 2);
@@ -4563,7 +4563,7 @@ fn test_claim_to_closed_channel_blocks_forwarded_preimage_removal() {
// Now that B has a pending forwarded payment across it with the inbound edge on-chain, claim
// the payment on C and give B the preimage for it.
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
@@ -4643,7 +4643,7 @@ fn test_claim_to_closed_channel_blocks_claimed_event() {
// payment on disk, but don't let the `ChannelMonitorUpdate` complete. This should prevent the
// `Event::PaymentClaimed` from being generated.
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
@@ -4760,7 +4760,7 @@ fn test_single_channel_multiple_mpp() {
let thrd = std::thread::spawn(move || {
// Initiate the claim in a background thread as it will immediately block waiting on the
// `write_blocker` we set above.
- claim_node.claim_funds(payment_preimage);
+ claim_node.claim_funds(payment_preimage, Default::default());
});
// First unlock one monitor so that we have a pending
@@ -5189,7 +5189,7 @@ fn test_mpp_claim_to_holding_cell() {
// improving coverage somewhat but it isn't strictly critical to the test.
chanmon_cfgs[3].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
chanmon_cfgs[3].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- nodes[3].node.claim_funds(preimage_1);
+ nodes[3].node.claim_funds(preimage_1, Default::default());
check_added_monitors(&nodes[3], 2);
// Complete the B <-> D monitor update, freeing the first fulfill.
@@ -5540,7 +5540,7 @@ fn test_monitor_update_after_funding_spend() {
// B claims payment 1. The preimage monitor update also returns InProgress (deferred),
// so no Completed-while-InProgress assertion fires.
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
// First event cycle: the force-close MonitorEvent (CommitmentTxConfirmed) fires first,
### lightning/src/ln/channelmanager.rs
@@ -750,6 +750,18 @@ impl Readable for InterceptId {
}
}
+/// Optional arguments to [`ChannelManager::claim_funds`].
+///
+/// These fields will often not need to be set, and the provided [`Self::default`] can be used.
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub struct ClaimFundsOptions {
+ /// Whether custom TLVs with even type numbers in the received payment are known to you.
+ ///
+ /// You MUST check you've understood all even TLVs before setting this to true, otherwise you may
+ /// unintentionally agree to some protocol you do not understand.
+ pub custom_tlvs_known: bool,
+}
+
/// Optional arguments to [`ChannelManager::pay_for_bolt11_invoice`]
///
/// These fields will often not need to be set, and the provided [`Self::default`] can be used.
@@ -2550,15 +2562,15 @@ impl<
/// PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
/// assert_eq!(payment_hash, invoice.payment_hash());
/// println!("Claiming payment {}", payment_hash);
-/// channel_manager.claim_funds(payment_preimage);
+/// channel_manager.claim_funds(payment_preimage, Default::default());
/// },
/// PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => {
/// println!("Unknown payment hash: {}", payment_hash);
/// },
/// PaymentPurpose::SpontaneousPayment(payment_preimage) => {
/// assert_ne!(payment_hash, invoice.payment_hash());
/// println!("Claiming spontaneous payment {}", payment_hash);
-/// channel_manager.claim_funds(payment_preimage);
+/// channel_manager.claim_funds(payment_preimage, Default::default());
/// },
/// // ...
/// # _ => {},
@@ -2659,7 +2671,7 @@ impl<
/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
/// PaymentPurpose::Bolt12OfferPayment { payment_preimage: Some(payment_preimage), .. } => {
/// println!("Claiming payment {}", payment_hash);
-/// channel_manager.claim_funds(payment_preimage);
+/// channel_manager.claim_funds(payment_preimage, Default::default());
/// },
/// PaymentPurpose::Bolt12OfferPayment { payment_preimage: None, .. } => {
/// println!("Unknown payment hash: {}", payment_hash);
@@ -2819,7 +2831,7 @@ impl<
/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(payment_preimage), .. } => {
/// assert_eq!(payment_hash, known_payment_hash);
/// println!("Claiming payment {}", payment_hash);
-/// channel_manager.claim_funds(payment_preimage);
+/// channel_manager.claim_funds(payment_preimage, Default::default());
/// },
/// PaymentPurpose::Bolt12RefundPayment { payment_preimage: None, .. } => {
/// println!("Unknown payment hash: {}", payment_hash);
@@ -10128,35 +10140,17 @@ impl<
/// event matches your expectation. If you fail to do so and call this method, you may provide
/// the sender "proof-of-payment" when they did not fulfill the full expected payment.
///
- /// This function will fail the payment if it has custom TLVs with even type numbers, as we
- /// will assume they are unknown. If you intend to accept even custom TLVs, you should use
- /// [`claim_funds_with_known_custom_tlvs`].
+ /// With default options, this function will fail the payment if it has custom TLVs with even
+ /// type numbers, as we will assume they are unknown. To accept even custom TLVs, set
+ /// [`ClaimFundsOptions::custom_tlvs_known`] to true after checking you've understood them all.
///
/// [`Event::PaymentClaimable`]: crate::events::Event::PaymentClaimable
/// [`Event::PaymentClaimable::claim_deadline`]: crate::events::Event::PaymentClaimable::claim_deadline
/// [`Event::PaymentClaimed`]: crate::events::Event::PaymentClaimed
/// [`process_pending_events`]: EventsProvider::process_pending_events
/// [`create_inbound_payment`]: Self::create_inbound_payment
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
- /// [`claim_funds_with_known_custom_tlvs`]: Self::claim_funds_with_known_custom_tlvs
- pub fn claim_funds(&self, payment_preimage: PaymentPreimage) {
- self.claim_payment_internal(payment_preimage, false);
- }
-
- /// This is a variant of [`claim_funds`] that allows accepting a payment with custom TLVs with
- /// even type numbers.
- ///
- /// # Note
- ///
- /// You MUST check you've understood all even TLVs before using this to
- /// claim, otherwise you may unintentionally agree to some protocol you do not understand.
- ///
- /// [`claim_funds`]: Self::claim_funds
- pub fn claim_funds_with_known_custom_tlvs(&self, payment_preimage: PaymentPreimage) {
- self.claim_payment_internal(payment_preimage, true);
- }
-
- fn claim_payment_internal(&self, payment_preimage: PaymentPreimage, custom_tlvs_known: bool) {
+ pub fn claim_funds(&self, payment_preimage: PaymentPreimage, options: ClaimFundsOptions) {
let payment_hash: PaymentHash = payment_preimage.into();
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
@@ -10167,7 +10161,7 @@ impl<
&self.node_signer,
&self.logger,
&self.inbound_payment_id_secret,
- custom_tlvs_known,
+ options.custom_tlvs_known,
);
match res {
@@ -10766,17 +10760,6 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
// Decode attribution data to hold times.
let hold_times = sources.into_iter().filter_map(|(source, attribution_data)| {
if let HTLCSource::OutboundRoute { ref session_priv, ref path, .. } = source {
- // If the path has trampoline hops, we need to hash the session private key to get the outer session key.
- let derived_key;
- let session_priv = if path.has_trampoline_hops() {
- let session_priv_hash =
- <Sha256 as CryptoHash>::hash(&session_priv.secret_bytes()).to_byte_array();
- derived_key = SecretKey::from_slice(&session_priv_hash[..]).unwrap();
- &derived_key
- } else {
- session_priv
- };
-
let hold_times = attribution_data.map_or(Vec::new(), |attribution_data| {
decode_fulfill_attribution_data(
&self.secp_ctx,
@@ -10903,7 +10886,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
send_timestamp,
);
},
- HTLCSource::TrampolineForward { previous_hop_data, .. } => {
+ HTLCSource::TrampolineForward { previous_hop_data, outbound_payment } => {
+ debug_assert!(outbound_payment.is_some());
// Only emit a single event for trampoline claims.
let mut event_prev_htlcs = Some(
previous_hop_data.iter().map(|hop| hop.htlc_locator(hop.amount_msat)).collect(),
@@ -10951,7 +10935,8 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
next_channel_outpoint,
next_channel_id,
current_previous_hop_data,
- attribution_data.clone(),
+ // The upstream sender cannot verify an independently dispatched route.
+ None,
send_timestamp,
);
}
@@ -21702,7 +21687,7 @@ mod tests {
use crate::ln::outbound_payment::Retry;
use crate::ln::types::ChannelId;
use crate::prelude::*;
- use crate::routing::router::{find_route, PaymentParameters, RouteParameters};
+ use crate::routing::router::{find_route, Path, PaymentParameters, RouteParameters};
use crate::sign::EntropySource;
use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
use crate::util::config::{ChannelConfig, ChannelConfigUpdate};
@@ -21712,6 +21697,67 @@ mod tests {
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use core::sync::atomic::Ordering;
+ #[test]
+ fn delegated_trampoline_claim_starts_new_attribution() {
+ let chanmon_cfgs = create_chanmon_cfgs(2);
+ let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+ let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+ let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+ create_announced_chan_between_nodes(&nodes, 0, 1);
+ let (payment_preimage, payment_hash, _, _) =
+ route_payment(&nodes[0], &[&nodes[1]], 100_000);
+ let previous_hop = {
+ let claimable_payments = nodes[1].node.claimable_payments.lock().unwrap();
+ claimable_payments.claimable_payments.get(&payment_hash).unwrap().htlcs[0]
+ .mpp_part
+ .prev_hop
+ .clone()
+ };
+
+ let downstream_attribution =
+ onion_utils::process_fulfill_attribution_data(None, &[42; 32], 7);
+ let expected_attribution = onion_utils::process_fulfill_attribution_data(
+ None,
+ &previous_hop.incoming_packet_shared_secret,
+ 0,
+ );
+ assert_ne!(downstream_attribution, expected_attribution);
+
+ // Delegated trampoline forwarding is not enabled yet, so construct its source manually
+ // and call the claim path directly to verify that downstream attribution is replaced.
+ let session_priv = SecretKey::from_slice(&[43; 32]).unwrap();
+ nodes[1].node.claim_funds_internal(
+ super::HTLCSource::TrampolineForward {
+ previous_hop_data: vec![previous_hop.clone()],
+ outbound_payment: Some(super::TrampolineDispatch {
+ payment_id: PaymentId([44; 32]),
+ path: Path { hops: Vec::new(), blinded_tail: None },
+ session_priv,
+ }),
+ },
+ payment_preimage,
+ 100_000,
+ None,
+ false,
+ nodes[0].node.get_our_node_id(),
+ previous_hop.outpoint,
+ previous_hop.channel_id,
+ None,
+ Some(downstream_attribution),
+ None,
+ );
+ check_added_monitors(&nodes[1], 1);
+
+ let updates = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id());
+ assert_eq!(updates.update_fulfill_htlcs.len(), 1);
+ assert_eq!(updates.update_fulfill_htlcs[0].attribution_data, Some(expected_attribution));
+ assert!(matches!(
+ nodes[1].node.get_and_clear_pending_events().as_slice(),
+ [Event::PaymentForwarded { .. }]
+ ));
+ }
+
#[test]
#[rustfmt::skip]
fn test_notify_limits() {
@@ -21862,7 +21908,7 @@ mod tests {
// claim_funds_along_route because the ordering of the messages causes the second half of the
// payment to be put in the holding cell, which confuses the test utilities. So we exchange the
// lightning messages manually.
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], our_payment_hash, 200_000);
check_added_monitors(&nodes[1], 2);
@@ -23007,7 +23053,7 @@ pub mod bench {
$node_b.process_pending_htlc_forwards();
expect_payment_claimable!(ANodeHolder { node: &$node_b }, payment_hash, payment_secret, 10_000);
- $node_b.claim_funds(payment_preimage);
+ $node_b.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(ANodeHolder { node: &$node_b }, payment_hash, 10_000);
match $node_b.get_and_clear_pending_msg_events().pop().unwrap() {
### lightning/src/ln/functional_test_utils.rs
@@ -3986,7 +3986,11 @@ pub fn do_claim_payment_along_route(args: ClaimAlongRouteArgs) -> u64 {
args.expected_paths[0].last().unwrap().node.get_our_node_id()
);
}
- args.expected_paths[0].last().unwrap().node.claim_funds(args.payment_preimage);
+ args.expected_paths[0]
+ .last()
+ .unwrap()
+ .node
+ .claim_funds(args.payment_preimage, Default::default());
pass_claimed_payment_along_route(args)
}
@@ -4348,7 +4352,7 @@ pub fn pass_claimed_payment_along_route_from_ev(
}
// Ensure that claim_funds is idempotent.
- expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage);
+ expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage, Default::default());
assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events().is_empty());
check_added_monitors(&expected_paths[0].last().unwrap(), 0);
### lightning/src/ln/functional_tests.rs
@@ -355,7 +355,7 @@ pub fn test_duplicate_htlc_different_direction_onchain() {
);
// Provide preimage to node 0 by claiming payment
- nodes[0].node.claim_funds(payment_preimage);
+ nodes[0].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[0], payment_hash, payment_value_msats);
check_added_monitors(&nodes[0], 1);
@@ -572,7 +572,7 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
},
PostFailBackAction::ClaimOnChain => {
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[2], payment_hash, 3_000_000);
check_added_monitors(&nodes[2], 1);
get_htlc_update_msgs(&nodes[2], &node_b_id);
@@ -605,7 +605,7 @@ fn do_test_fail_back_before_backwards_timeout(post_fail_back_action: PostFailBac
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
},
PostFailBackAction::ClaimOffChain => {
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[2], payment_hash, 3_000_000);
check_added_monitors(&nodes[2], 1);
let mut commitment_update = get_htlc_update_msgs(&nodes[2], &node_b_id);
@@ -641,7 +641,7 @@ fn test_preimage_claim_reconfirmed_before_event_handled() {
// B claims the payment but A never receives the off-chain fulfill. B then goes on chain with an
// HTLC-Success transaction as the HTLC nears expiry.
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], payment_hash, 3_000_000);
check_added_monitors(&nodes[1], 1);
let _ = get_htlc_update_msgs(&nodes[1], &node_a_id);
@@ -784,7 +784,7 @@ pub fn channel_monitor_network_test() {
macro_rules! claim_funds {
($node: expr, $prev_node: expr, $preimage: expr, $payment_hash: expr) => {{
- $node.node.claim_funds($preimage);
+ $node.node.claim_funds($preimage, Default::default());
expect_payment_claimed!($node, $payment_hash, 3_000_000);
check_added_monitors(&$node, 1);
@@ -1561,9 +1561,9 @@ pub fn test_htlc_on_chain_success() {
let commitment_tx = get_local_commitment_txn!(nodes[2], chan_2.2);
assert_eq!(commitment_tx.len(), 1);
check_spends!(commitment_tx[0], chan_2.3);
- nodes[2].node.claim_funds(our_payment_preimage);
+ nodes[2].node.claim_funds(our_payment_preimage, Default::default());
expect_payment_claimed!(nodes[2], payment_hash_1, 3_000_000);
- nodes[2].node.claim_funds(our_payment_preimage_2);
+ nodes[2].node.claim_funds(our_payment_preimage_2, Default::default());
expect_payment_claimed!(nodes[2], payment_hash_2, 3_000_000);
check_added_monitors(&nodes[2], 2);
let updates = get_htlc_update_msgs(&nodes[2], &node_b_id);
@@ -2625,7 +2625,7 @@ pub fn test_dup_events_on_peer_disconnect() {
let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], payment_hash, 1_000_000);
check_added_monitors(&nodes[1], 1);
let mut claim_msgs = get_htlc_update_msgs(&nodes[1], &node_a_id);
@@ -2959,7 +2959,7 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8, simulate_broken
_ => panic!("Unexpected event"),
}
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
@@ -3259,7 +3259,7 @@ pub fn test_drop_messages_peer_disconnect_dual_htlc() {
_ => panic!("Unexpected event"),
}
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
check_added_monitors(&nodes[1], 1);
@@ -3803,7 +3803,7 @@ pub fn test_static_spendable_outputs_preimage_tx() {
assert_eq!(commitment_tx[0].input[0].previous_output.txid, chan_1.3.compute_txid());
// Settle A's commitment tx on B's chain
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], payment_hash, 3_000_000);
check_added_monitors(&nodes[1], 1);
mine_transaction(&nodes[1], &commitment_tx[0]);
@@ -4152,7 +4152,7 @@ pub fn test_onchain_to_onchain_claim() {
route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3_000_000);
let commitment_tx = get_local_commitment_txn!(nodes[2], chan_2.2);
check_spends!(commitment_tx[0], chan_2.3);
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[2], payment_hash, 3_000_000);
check_added_monitors(&nodes[2], 1);
let updates = get_htlc_update_msgs(&nodes[2], &node_b_id);
@@ -4362,7 +4362,7 @@ pub fn test_duplicate_payment_hash_one_failure_one_success() {
};
// Now give node E the payment preimage and pass it back to C.
- nodes[4].node.claim_funds(our_payment_preimage);
+ nodes[4].node.claim_funds(our_payment_preimage, Default::default());
expect_payment_claimed!(nodes[4], dup_payment_hash, 800_000);
check_added_monitors(&nodes[4], 1);
let mut updates = get_htlc_update_msgs(&nodes[4], &node_c_id);
@@ -4473,7 +4473,7 @@ pub fn test_dynamic_spendable_outputs_local_htlc_success_tx() {
check_spends!(local_txn[0], chan_1.3);
// Give B knowledge of preimage to be able to generate a local HTLC-Success Tx
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], payment_hash, 9_000_000);
check_added_monitors(&nodes[1], 1);
@@ -5177,7 +5177,7 @@ fn do_htlc_claim_local_commitment_only(use_dust: bool) {
// Claim the payment, but don't deliver A's commitment_signed, resulting in the HTLC only being
// present in B's local commitment transaction, but none of A's commitment transactions.
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, if use_dust { 50000 } else { 3_000_000 });
@@ -5574,7 +5574,7 @@ pub fn test_free_and_fail_holding_cell_htlcs() {
Event::PaymentClaimable { .. } => {},
_ => panic!("Unexpected event"),
}
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_1, amt_1);
@@ -6716,7 +6716,7 @@ pub fn test_bump_penalty_txn_on_remote_commitment() {
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.compute_txid());
// Claim a HTLC without revocation (provide B monitor with preimage)
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], payment_hash, htlc_value_a_msats);
let _ = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id());
mine_transaction(&nodes[1], &remote_txn[0]);
@@ -7605,7 +7605,7 @@ pub fn test_update_err_monitor_lockdown() {
watchtower.chain_monitor.block_connected(&block, 200);
// Try to update ChannelMonitor
- nodes[1].node.claim_funds(preimage);
+ nodes[1].node.claim_funds(preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, 9_000_000);
@@ -8039,7 +8039,7 @@ fn do_test_onchain_htlc_settlement_after_close(
// Step (5):
// Carol then claims the funds and sends an update_fulfill message to Bob, and they go through the
// process of removing the HTLC from their commitment transactions.
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 3_000_000);
@@ -8841,7 +8841,7 @@ pub fn test_double_partial_claim() {
// At this point nodes[3] has received one half of the payment, and the user goes to handle
// that PaymentClaimable event they got hours ago and never handled...we should refuse to claim.
- nodes[3].node.claim_funds(payment_preimage);
+ nodes[3].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[3], 0);
assert!(nodes[3].node.get_and_clear_pending_msg_events().is_empty());
}
@@ -10157,11 +10157,11 @@ fn do_test_multi_post_event_actions(do_reload: bool) {
let (payment_preimage_2, payment_hash_2, ..) =
route_payment(&nodes[0], &[&nodes[2]], 1_000_000);
- nodes[1].node.claim_funds(our_payment_preimage);
+ nodes[1].node.claim_funds(our_payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], our_payment_hash, 1_000_000);
- nodes[2].node.claim_funds(payment_preimage_2);
+ nodes[2].node.claim_funds(payment_preimage_2, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash_2, 1_000_000);
@@ -10414,7 +10414,7 @@ fn test_dup_htlc_claim_onchain_and_offchain() {
route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
// C claims the payment.
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
check_added_monitors(&nodes[2], 1);
### lightning/src/ln/htlc_reserve_unit_tests.rs
@@ -512,14 +512,14 @@ pub fn channel_reserve_in_flight_removes() {
// Now claim both of the first two HTLCs on B's end, putting B in AwaitingRAA and generating an
// initial fulfill/CS.
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_1, payment_value_1);
check_added_monitors(&nodes[1], 1);
let mut bs_removes = get_htlc_update_msgs(&nodes[1], &node_a_id);
// This claim goes in B's holding cell, allowing us to have a pending B->A RAA which does not
// remove the second HTLC when we send the HTLC back from B to A.
- nodes[1].node.claim_funds(payment_preimage_2);
+ nodes[1].node.claim_funds(payment_preimage_2, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_2, 20_000);
check_added_monitors(&nodes[1], 1);
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@@ -1884,7 +1884,7 @@ pub fn test_update_fulfill_htlc_bolt2_incorrect_htlc_id() {
let (our_payment_preimage, our_payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1]], 100_000);
- nodes[1].node.claim_funds(our_payment_preimage);
+ nodes[1].node.claim_funds(our_payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], our_payment_hash, 100_000);
@@ -1943,7 +1943,7 @@ pub fn test_update_fulfill_htlc_bolt2_wrong_preimage() {
let (our_payment_preimage, our_payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1]], 100_000);
- nodes[1].node.claim_funds(our_payment_preimage);
+ nodes[1].node.claim_funds(our_payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], our_payment_hash, 100_000);
### lightning/src/ln/monitor_tests.rs
@@ -223,7 +223,7 @@ fn archive_fully_resolved_monitors() {
nodes[1].chain_monitor.chain_monitor.archive_fully_resolved_channel_monitors();
assert_eq!(nodes[1].chain_monitor.chain_monitor.list_monitors().len(), 1);
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, 10_000_000);
let htlc_claim_tx = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
@@ -669,18 +669,18 @@ fn do_test_claim_value_force_close(keyed_anchors: bool, p2a_anchor: bool, prev_c
}, received_htlc_balance.clone(), received_htlc_timeout_balance.clone()]),
sorted_vec(nodes[1].chain_monitor.chain_monitor.get_monitor(chan_id).unwrap().get_claimable_balances()));
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, 3_000_100);
let mut b_htlc_msgs = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id());
// We claim the dust payment here as well, but it won't impact our claimable balances as its
// dust and thus doesn't appear on chain at all.
- nodes[1].node.claim_funds(dust_payment_preimage);
+ nodes[1].node.claim_funds(dust_payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], dust_payment_hash, 3_000);
- nodes[1].node.claim_funds(timeout_payment_preimage);
+ nodes[1].node.claim_funds(timeout_payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], timeout_payment_hash, 4_000_200);
@@ -1009,7 +1009,7 @@ fn do_test_balances_on_local_commitment_htlcs(keyed_anchors: bool, p2a_anchor: b
expect_and_process_pending_htlcs(&nodes[1], false);
expect_payment_claimable!(nodes[1], payment_hash_2, payment_secret_2, 20_000_000);
- nodes[1].node.claim_funds(payment_preimage_2);
+ nodes[1].node.claim_funds(payment_preimage_2, Default::default());
get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_2, 20_000_000);
@@ -1529,7 +1529,7 @@ fn do_test_revoked_counterparty_commitment_balances(keyed_anchors: bool, p2a_anc
let missing_htlc_cltv_timeout = nodes[0].best_block_info().1 + TEST_FINAL_CLTV + 1; // Note ChannelManager adds one to CLTV timeouts for safety
let missing_htlc_payment_hash = route_payment(&nodes[1], &[&nodes[0]], 2_000_000).1;
- nodes[1].node.claim_funds(claimed_payment_preimage);
+ nodes[1].node.claim_funds(claimed_payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], claimed_payment_hash, 3_000_100);
check_added_monitors(&nodes[1], 1);
let _b_htlc_msgs = get_htlc_update_msgs(&nodes[1], &nodes[0].node.get_our_node_id());
@@ -2120,7 +2120,7 @@ fn do_test_revoked_counterparty_aggregated_claims(keyed_anchors: bool, p2a_ancho
const DUMMY_HTLC_AMT: u64 = 1000;
route_payment(&nodes[0], &[&nodes[1]], DUMMY_HTLC_AMT);
- nodes[0].node.claim_funds(claimed_payment_preimage);
+ nodes[0].node.claim_funds(claimed_payment_preimage, Default::default());
expect_payment_claimed!(nodes[0], claimed_payment_hash, 3_000_100);
check_added_monitors(&nodes[0], 1);
let _a_htlc_msgs = get_htlc_update_msgs(&nodes[0], &nodes[1].node.get_our_node_id());
@@ -3390,11 +3390,11 @@ fn test_update_replay_panics() {
check_closed_broadcast(&nodes[1], 1, true);
check_added_monitors(&nodes[1], 1);
- nodes[1].node.claim_funds(payment_preimage_1);
+ nodes[1].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_1, 1_000_000);
- nodes[1].node.claim_funds(payment_preimage_2);
+ nodes[1].node.claim_funds(payment_preimage_2, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash_2, 1_000_000);
@@ -3468,7 +3468,7 @@ fn test_claim_event_never_handled() {
// Send the payment we'll ultimately test the PaymentClaimed event for.
let (preimage_a, payment_hash_a, ..) = route_payment(&nodes[0], &[&nodes[1]], 1_000_000);
- nodes[1].node.claim_funds(preimage_a);
+ nodes[1].node.claim_funds(preimage_a, Default::default());
check_added_monitors(&nodes[1], 1);
let mut updates = get_htlc_update_msgs(&nodes[1], &node_a_id);
@@ -3546,10 +3546,10 @@ fn do_test_lost_preimage_monitor_events(on_counterparty_tx: bool, p2a_anchor: bo
nodes[1].node.peer_disconnected(nodes[2].node.get_our_node_id());
nodes[2].node.peer_disconnected(nodes[1].node.get_our_node_id());
- nodes[2].node.claim_funds(preimage_a);
+ nodes[2].node.claim_funds(preimage_a, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], hash_a, 1_000_000);
- nodes[2].node.claim_funds(preimage_b);
+ nodes[2].node.claim_funds(preimage_b, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], hash_b, 1_000_000);
@@ -3974,7 +3974,7 @@ fn test_ladder_preimage_htlc_claims() {
check_added_monitors(&nodes[1], 1);
check_closed_event(&nodes[1], 1, ClosureReason::CommitmentTxConfirmed, &[node_id_0], 1_000_000);
- nodes[1].node.claim_funds(payment_preimage1);
+ nodes[1].node.claim_funds(payment_preimage1, Default::default());
expect_payment_claimed!(&nodes[1], payment_hash1, 1_000_000);
check_added_monitors(&nodes[1], 1);
@@ -3995,7 +3995,7 @@ fn test_ladder_preimage_htlc_claims() {
expect_payment_sent(&nodes[0], payment_preimage1, None, true, false);
check_added_monitors(&nodes[0], 1);
- nodes[1].node.claim_funds(payment_preimage2);
+ nodes[1].node.claim_funds(payment_preimage2, Default::default());
expect_payment_claimed!(&nodes[1], payment_hash2, 1_000_000);
check_added_monitors(&nodes[1], 1);
### lightning/src/ln/offers_tests.rs
@@ -3164,7 +3164,7 @@ fn pay_for_bolt12_invoice_partial_amount_multi_payer() {
};
// Claiming releases a fulfill to each payer, and each payer sees PaymentSent.
- alice.node.claim_funds(payment_preimage);
+ alice.node.claim_funds(payment_preimage, Default::default());
check_added_monitors(alice, 2);
expect_payment_claimed!(alice, payment_hash, invoice_amount + 20);
### lightning/src/ln/onion_utils.rs
@@ -50,7 +50,10 @@ use crate::io::{Cursor, Read};
use crate::prelude::*;
const DEFAULT_MIN_FAILURE_PACKET_LEN: usize = 256;
-
+const MAX_ATTRIBUTABLE_RETURN_FIELD_LEN: usize = 32 * 1024;
+// Failure packets contain a 32-byte HMAC, 2-byte failure length, 2-byte
+// failure code, and 2-byte padding length in addition to the failure data.
+const FAILURE_PACKET_BASE_LEN: usize = 32 + 2 + 2 + 2;
/// The unit size of the hold time. This is used to reduce the hold time resolution to improve privacy.
pub(crate) const HOLD_TIME_UNIT_MILLIS: u128 = 100;
@@ -958,6 +961,9 @@ fn build_unencrypted_failure_packet(
) -> OnionErrorPacket {
assert_eq!(shared_secret.len(), 32);
+ let max_failure_data_len = MAX_ATTRIBUTABLE_RETURN_FIELD_LEN - FAILURE_PACKET_BASE_LEN;
+ let failure_data = &failure_data[..core::cmp::min(failure_data.len(), max_failure_data_len)];
+
// Failure len is 2 bytes type plus the data.
let failure_len = 2 + failure_data.len();
@@ -3053,6 +3059,8 @@ impl AttributionData {
/// Adds the current node's HMACs for all possible positions to this packet.
pub(crate) fn add_hmacs(&mut self, shared_secret: &[u8], message: &[u8]) {
let um: [u8; 32] = gen_um_from_shared_secret(&shared_secret);
+ let mut message_hmac = HmacEngine::<Sha256>::new(&um);
+ message_hmac.input(&message);
// Iterate over all possible positions that this hop could be on the path. An intermediate node does not have this
// information, so it is up to the sender to verify the HMAC that corresponds to the actual position.
@@ -3062,8 +3070,7 @@ impl AttributionData {
// The HMAC covers the original message and - for the assumed position - all the hold times and downstream
// HMACs. As position decreases, fewer downstream HMACs are included.
- let mut hmac_engine = HmacEngine::<Sha256>::new(&um);
- hmac_engine.input(&message);
+ let mut hmac_engine = message_hmac.clone();
hmac_engine.input(&self.hold_times[..(position + 1) * HOLD_TIME_LEN]);
self.write_downstream_hmacs(position, &mut hmac_engine);
@@ -3196,6 +3203,8 @@ impl AttributionData {
fn process_failure_packet(
onion_error: &mut OnionErrorPacket, shared_secret: &[u8], hold_time: u32,
) {
+ onion_error.data.truncate(MAX_ATTRIBUTABLE_RETURN_FIELD_LEN);
+
// Process received attribution data if present.
if let Some(ref mut attribution_data) = onion_error.attribution_data {
attribution_data.shift_right();
@@ -4514,7 +4523,8 @@ mod tests {
let reason = LocalHTLCFailureReason::TemporaryNodeFailure;
let empty = super::build_unencrypted_failure_packet(&shared_secret, reason, &[], 0, 0);
- let failure_data = vec![0; LN_MAX_MSG_LEN - update_fail_htlc_wire_len(&empty)];
+ let max_failure_data_len = MAX_ATTRIBUTABLE_RETURN_FIELD_LEN - empty.data.len();
+ let failure_data = vec![0; max_failure_data_len + 1];
let onion_error = super::build_unencrypted_failure_packet(
&shared_secret,
@@ -4524,6 +4534,9 @@ mod tests {
DEFAULT_MIN_FAILURE_PACKET_LEN,
);
assert!(onion_error.attribution_data.is_some());
+ assert_eq!(onion_error.data.len(), MAX_ATTRIBUTABLE_RETURN_FIELD_LEN);
+ let failure_len = u16::from_be_bytes(onion_error.data[32..34].try_into().unwrap());
+ assert_eq!(failure_len as usize, 2 + max_failure_data_len);
let msg = UpdateFailHTLC {
channel_id: ChannelId([0; 32]),
@@ -4535,7 +4548,7 @@ mod tests {
let mut buffer = Vec::new();
msgs::UpdateFailHTLC::TYPE.write(&mut buffer).unwrap();
msg.write(&mut buffer).unwrap();
- assert_eq!(buffer.len(), LN_MAX_MSG_LEN);
+ assert!(buffer.len() < LN_MAX_MSG_LEN);
assert_eq!(update_fail_htlc_wire_len(&msg.into()), buffer.len());
}
@@ -4551,9 +4564,10 @@ mod tests {
let onion_error =
HTLCFailReason::from_msg(&msg).get_encrypted_failure_packet(&[1; 32], &None);
- assert!(onion_error.attribution_data.is_none());
+ assert!(onion_error.attribution_data.is_some());
+ assert_eq!(onion_error.data.len(), MAX_ATTRIBUTABLE_RETURN_FIELD_LEN);
- assert_eq!(update_fail_htlc_wire_len(&onion_error), LN_MAX_MSG_LEN);
+ assert!(update_fail_htlc_wire_len(&onion_error) < LN_MAX_MSG_LEN);
}
#[test]
### lightning/src/ln/payment_tests.rs
@@ -334,7 +334,7 @@ fn mpp_retry_overpay() {
// Can't use claim_payment_along_route as it doesn't support overpayment, so we break out the
// individual steps here.
- nodes[3].node.claim_funds(payment_preimage);
+ nodes[3].node.claim_funds(payment_preimage, Default::default());
let extra_fees = vec![0, total_overpaid_amount];
let expected_route = &[&[&nodes[1], &nodes[3]][..], &[&nodes[2], &nodes[3]][..]];
let args = ClaimAlongRouteArgs::new(&nodes[0], &expected_route[..], payment_preimage)
@@ -962,7 +962,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
// Now claim the first payment, which should allow nodes[1] to claim the payment on-chain when
// we close in a moment.
- nodes[2].node.claim_funds(payment_preimage_1);
+ nodes[2].node.claim_funds(payment_preimage_1, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash_1, 1_000_000);
@@ -1351,7 +1351,7 @@ fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(
(txn.remove(0), txn.remove(0))
};
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, 10_000_000);
@@ -1512,7 +1512,7 @@ fn test_fulfill_restart_failure() {
let node_b_ser = nodes[1].node.encode();
let mon_ser = get_monitor!(nodes[1], chan_id).encode();
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, 100_000);
@@ -2875,7 +2875,7 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) {
for i in 0..num_mpp_parts {
expected_paths.push(&expected_paths_vecs[i][..]);
}
- expected_paths[0].last().unwrap().node.claim_funds(payment_preimage);
+ expected_paths[0].last().unwrap().node.claim_funds(payment_preimage, Default::default());
let args = ClaimAlongRouteArgs::new(&nodes[0], &expected_paths[..], payment_preimage)
.with_expected_extra_fees(vec![skimmed_fee_msat as u32; num_mpp_parts]);
let total_fee_msat = pass_claimed_payment_along_route(args);
@@ -3349,7 +3349,7 @@ fn auto_retry_partial_failure() {
expect_htlc_failure_conditions(nodes[1].node.get_and_clear_pending_events(), &[]);
nodes[1].node.process_pending_htlc_forwards();
expect_payment_claimable!(nodes[1], payment_hash, payment_secret, amt_msat);
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[1], payment_hash, amt_msat);
let mut bs_claim = get_htlc_update_msgs(&nodes[1], &node_a_id);
assert_eq!(bs_claim.update_fulfill_htlcs.len(), 1);
@@ -4436,7 +4436,7 @@ fn do_no_missing_sent_on_reload(persist_manager_with_payment: bool, at_midpoint:
node_a_ser = nodes[0].node.encode();
}
- nodes[1].node.claim_funds(our_payment_preimage);
+ nodes[1].node.claim_funds(our_payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], our_payment_hash, 1_000_000);
@@ -4671,7 +4671,7 @@ fn do_claim_from_closed_chan(fail_payment: bool) {
let reason = ClosureReason::CommitmentTxConfirmed;
check_closed_event(&nodes[3], 1, reason, &[node_b_id], 1000000);
- nodes[3].node.claim_funds(payment_preimage);
+ nodes[3].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[3], 2);
expect_payment_claimed!(nodes[3], hash, 10_000_000);
@@ -4801,7 +4801,10 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) {
match (known_tlvs, even_tlvs) {
(true, _) => {
- nodes[1].node.claim_funds_with_known_custom_tlvs(preimage);
+ nodes[1].node.claim_funds(
+ preimage,
+ crate::ln::channelmanager::ClaimFundsOptions { custom_tlvs_known: true },
+ );
let expected_total_fee_msat = pass_claimed_payment_along_route(
ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], preimage)
.with_custom_tlvs(custom_tlvs),
@@ -4815,7 +4818,7 @@ fn do_test_custom_tlvs(spontaneous: bool, even_tlvs: bool, known_tlvs: bool) {
);
},
(false, true) => {
- nodes[1].node.claim_funds(preimage);
+ nodes[1].node.claim_funds(preimage, Default::default());
let fail_type = HTLCHandlingFailureType::Receive { payment_hash: hash };
expect_and_process_pending_htlcs_and_htlc_handling_failed(&nodes[1], &[fail_type]);
let reason = PaymentFailureReason::RecipientRejected;
@@ -5805,7 +5808,7 @@ fn do_bolt11_multi_node_mpp(use_bolt11_pay: bool) {
_ => panic!("Unexpected event: {:?}", events[0]),
};
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[2], invoice.payment_hash(), invoice_amt_msat);
check_added_monitors(&nodes[2], 2);
@@ -6070,7 +6073,7 @@ fn bolt11_multi_node_mpp_with_retry() {
_ => panic!("Unexpected event: {:?}", events[0]),
};
- nodes[3].node.claim_funds(payment_preimage);
+ nodes[3].node.claim_funds(payment_preimage, Default::default());
expect_payment_claimed!(nodes[3], invoice.payment_hash(), invoice_amt_msat);
check_added_monitors(&nodes[3], 2);
### lightning/src/ln/quiescence_tests.rs
@@ -212,7 +212,7 @@ fn test_quiescence_waits_for_async_signer_and_monitor_update() {
let payment_amount = 1_000_000;
let (preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], payment_amount);
- nodes[1].node.claim_funds(preimage);
+ nodes[1].node.claim_funds(preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(&nodes[1], payment_hash, payment_amount);
@@ -413,7 +413,7 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
let failed_payment = HTLCHandlingFailureType::Receive { payment_hash: payment_hash2 };
expect_and_process_pending_htlcs_and_htlc_handling_failed(&nodes[1], &[failed_payment]);
} else {
- nodes[1].node.claim_funds(payment_preimage2);
+ nodes[1].node.claim_funds(payment_preimage2, Default::default());
check_added_monitors(&nodes[1], 1);
}
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
@@ -459,7 +459,7 @@ fn quiescence_updates_go_to_holding_cell(fail_htlc: bool) {
let failed_payment = HTLCHandlingFailureType::Receive { payment_hash: payment_hash1 };
expect_and_process_pending_htlcs_and_htlc_handling_failed(&nodes[0], &[failed_payment]);
} else {
- nodes[0].node.claim_funds(payment_preimage1);
+ nodes[0].node.claim_funds(payment_preimage1, Default::default());
}
check_added_monitors(&nodes[0], 1);
@@ -627,7 +627,7 @@ fn do_test_quiescence_during_disconnection(with_pending_claim: bool, propose_dis
if with_pending_claim {
// Optionally reconnect with pending quiescence while there's some pending messages to
// deliver.
- nodes[1].node.claim_funds(preimage);
+ nodes[1].node.claim_funds(preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, 100_000);
let _ = get_htlc_update_msgs(&nodes[1], &node_a_id);
### lightning/src/ln/reload_tests.rs
@@ -851,7 +851,7 @@ fn do_test_partial_claim_before_restart(persist_both_monitors: bool, double_rest
expect_payment_claimable!(nodes[3], payment_hash, payment_secret, 15_000_000);
- nodes[3].node.claim_funds(payment_preimage);
+ nodes[3].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[3], 2);
expect_payment_claimed!(nodes[3], payment_hash, 15_000_000);
@@ -1095,7 +1095,7 @@ fn test_mpp_claim_htlc_fulfills_unblocked_on_reload() {
// preimage durably persisted.
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
chanmon_cfgs[1].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 2);
// Complete only channel A's preimage update. Channel B will be reloaded from the stale snapshot
@@ -1886,7 +1886,7 @@ fn test_manager_persisted_post_outbound_edge_holding_cell() {
expect_payment_sent(&nodes[0], payment_preimage, None, true, true);
// Claim the c->b payment on node_b.
- nodes[1].node.claim_funds(payment_preimage_2);
+ nodes[1].node.claim_funds(payment_preimage_2, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_2, amt_msat);
check_added_monitors(&nodes[1], 1);
let mut update = get_htlc_update_msgs(&nodes[1], &nodes[2].node.get_our_node_id());
@@ -2257,7 +2257,7 @@ fn outbound_removed_holding_cell_resolved_no_double_forward() {
);
// Claim the payment on nodes[2].
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
@@ -2350,7 +2350,7 @@ fn test_reload_node_with_preimage_in_monitor_claims_htlc() {
);
// Claim the payment on nodes[2].
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
@@ -2601,7 +2601,7 @@ fn test_reload_with_mpp_claims_on_same_channel() {
// Claim the HTLCs such that they're fully removed from the outbound edge, but disconnect
// node_0<>node_1 so that they can't be claimed backwards by node_1.
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 2);
expect_payment_claimed!(nodes[2], payment_hash, amt_msat);
### lightning/src/ln/reorg_tests.rs
@@ -69,7 +69,7 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) {
route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000);
// Provide preimage to node 2 by claiming payment
- nodes[2].node.claim_funds(our_payment_preimage);
+ nodes[2].node.claim_funds(our_payment_preimage, Default::default());
expect_payment_claimed!(nodes[2], our_payment_hash, 1_000_000);
check_added_monitors(&nodes[2], 1);
get_htlc_update_msgs(&nodes[2], &node_id_1);
@@ -214,7 +214,7 @@ fn test_counterparty_revoked_reorg() {
route_payment(&nodes[1], &[&nodes[0]], 4_000_000);
let payment_hash_4 = route_payment(&nodes[1], &[&nodes[0]], 4_000).1;
- nodes[0].node.claim_funds(payment_preimage_3);
+ nodes[0].node.claim_funds(payment_preimage_3, Default::default());
let _ = get_htlc_update_msgs(&nodes[0], &node_id_1);
check_added_monitors(&nodes[0], 1);
expect_payment_claimed!(nodes[0], payment_hash_3, 4_000_000);
@@ -639,9 +639,9 @@ fn test_set_outpoints_partial_claiming() {
// Connect blocks on node A to advance height towards TEST_FINAL_CLTV
// Provide node A with both preimage
- nodes[0].node.claim_funds(payment_preimage_1);
+ nodes[0].node.claim_funds(payment_preimage_1, Default::default());
expect_payment_claimed!(nodes[0], payment_hash_1, 3_000_000);
- nodes[0].node.claim_funds(payment_preimage_2);
+ nodes[0].node.claim_funds(payment_preimage_2, Default::default());
expect_payment_claimed!(nodes[0], payment_hash_2, 3_000_000);
check_added_monitors(&nodes[0], 2);
nodes[0].node.get_and_clear_pending_msg_events();
@@ -1245,9 +1245,9 @@ fn do_test_split_htlc_expiry_tracking(use_third_htlc: bool, reorg_out: bool, p2a
nodes[1].node.peer_disconnected(node_id_0);
// Give node B preimages so that it will claim the first two HTLCs on-chain.
- nodes[1].node.claim_funds(preimage_a);
+ nodes[1].node.claim_funds(preimage_a, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_a, 100_000_000);
- nodes[1].node.claim_funds(preimage_b);
+ nodes[1].node.claim_funds(preimage_b, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_b, 100_000_000);
check_added_monitors(&nodes[1], 2);
@@ -1515,9 +1515,9 @@ fn do_test_reorg_resurrect_split_htlc_package_with_future_locktime(style: Connec
nodes[1].node.peer_disconnected(node_id_0);
// Give node B both preimages so it will claim both HTLCs on-chain.
- nodes[1].node.claim_funds(preimage_a);
+ nodes[1].node.claim_funds(preimage_a, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_a, amt_a_msat);
- nodes[1].node.claim_funds(preimage_b);
+ nodes[1].node.claim_funds(preimage_b, Default::default());
expect_payment_claimed!(nodes[1], payment_hash_b, amt_b_msat);
check_added_monitors(&nodes[1], 2);
### lightning/src/ln/shutdown_tests.rs
@@ -175,7 +175,7 @@ fn expect_channel_shutdown_state_with_htlc() {
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
// Claim Funds on Node2
- nodes[2].node.claim_funds(payment_preimage_0);
+ nodes[2].node.claim_funds(payment_preimage_0, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash_0, 100_000);
@@ -452,7 +452,7 @@ fn updates_shutdown_wait() {
let res = nodes[1].node.send_payment_with_route(route_2, payment_hash, onion, id);
unwrap_send_err!(nodes[1], res, true, APIError::ChannelUnavailable { .. }, {});
- nodes[2].node.claim_funds(payment_preimage_0);
+ nodes[2].node.claim_funds(payment_preimage_0, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash_0, 100_000);
@@ -718,7 +718,7 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) {
assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 100_000);
@@ -1878,7 +1878,7 @@ fn test_pending_htlcs_arent_lost_on_mon_delay() {
// by not processing the `PaymentSent` event upon claim.
let (preimage_a, payment_hash_a, ..) = route_payment(&nodes[1], &[&nodes[2]], 500_000);
- nodes[2].node.claim_funds(preimage_a);
+ nodes[2].node.claim_funds(preimage_a, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash_a, 500_000);
### lightning/src/ln/splicing_tests.rs
@@ -1476,7 +1476,7 @@ fn test_queued_splice_contribution_fails_on_stale_reload() {
let encoded_node_0 = nodes[0].node.encode();
// Claiming the payment while disconnected persists the preimage to the monitor.
- nodes[0].node.claim_funds(preimage);
+ nodes[0].node.claim_funds(preimage, Default::default());
expect_payment_claimed!(nodes[0], payment_hash, payment_amount);
check_added_monitors(&nodes[0], 1);
@@ -2558,9 +2558,9 @@ fn do_test_splice_commitment_broadcast(splice_status: SpliceStatus, claim_htlcs:
if claim_htlcs {
// Claim both HTLCs, but don't do anything with the update message sent since we want to
// resolve the HTLCs onchain instead with a single transaction (thanks to anchors).
- nodes[1].node.claim_funds(preimage1);
+ nodes[1].node.claim_funds(preimage1, Default::default());
expect_payment_claimed!(&nodes[1], payment_hash1, payment_amount);
- nodes[1].node.claim_funds(preimage2);
+ nodes[1].node.claim_funds(preimage2, Default::default());
expect_payment_claimed!(&nodes[1], payment_hash2, payment_amount);
check_added_monitors(&nodes[1], 2);
let _ = get_htlc_update_msgs(&nodes[1], &node_id_0);
@@ -3699,7 +3699,7 @@ fn test_holding_cell_claim_freed_after_inferred_splice_locked() {
nodes[0].node.peer_disconnected(node_id_1);
nodes[1].node.peer_disconnected(node_id_0);
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, 1_000_000);
@@ -14389,7 +14389,7 @@ fn test_splice_out_maximum_includes_pending_claimed_inbound_htlc() {
let (payment_preimage, payment_hash, ..) =
route_payment(&nodes[0], &[&nodes[1]], PENDING_CLAIMED_INBOUND_HTLC_MSAT);
- nodes[1].node.claim_funds(payment_preimage);
+ nodes[1].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, PENDING_CLAIMED_INBOUND_HTLC_MSAT);
@@ -14514,7 +14514,7 @@ fn test_async_splice_receives_tx_signatures_while_unrelated_monitor_update_pendi
// Claiming the forwarded payment at C creates an HTLC fulfill that B must
// propagate backward over the same A-B channel that is being spliced.
- nodes[2].node.claim_funds(payment_preimage);
+ nodes[2].node.claim_funds(payment_preimage, Default::default());
check_added_monitors(&nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 1_000_000);
### lightning/src/ln/zero_fee_commitment_tests.rs
@@ -155,7 +155,7 @@ fn test_htlc_claim_chunking() {
assert_eq!(node_1_commit_tx[0].output.len(), 75 + 2 + 1);
for (preimage, payment_hash) in node_1_preimages {
- nodes[1].node.claim_funds(preimage);
+ nodes[1].node.claim_funds(preimage, Default::default());
check_added_monitors(&nodes[1], 1);
expect_payment_claimed!(nodes[1], payment_hash, NONDUST_HTLC_AMT_MSAT);
}Why this scored 47/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.