Skip to content

Hold times for successful payments #3801

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
15 changes: 13 additions & 2 deletions fuzz/src/process_onion_failure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
let path = Path { hops, blinded_tail };

let htlc_source = HTLCSource::OutboundRoute {
path,
path: path.clone(),
session_priv,
first_hop_htlc_msat: 0,
payment_id,
Expand All @@ -133,8 +133,19 @@ fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
} else {
None
};
let encrypted_packet = OnionErrorPacket { data: failure_data.into(), attribution_data };
let encrypted_packet =
OnionErrorPacket { data: failure_data.into(), attribution_data: attribution_data.clone() };
lightning::ln::process_onion_failure(&secp_ctx, &logger, &htlc_source, encrypted_packet);

if let Some(attribution_data) = attribution_data {
lightning::ln::decode_fulfill_attribution_data(
&secp_ctx,
&logger,
&path,
&session_priv,
attribution_data,
);
}
}

/// Method that needs to be added manually, {name}_test
Expand Down
1 change: 1 addition & 0 deletions lightning-background-processor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2732,6 +2732,7 @@ mod tests {
payment_id: PaymentId([42; 32]),
payment_hash: None,
path: path.clone(),
hold_times: None,
});
let event = $receive.expect("PaymentPathSuccessful not handled within deadline");
match event {
Expand Down
12 changes: 11 additions & 1 deletion lightning/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,8 @@ pub enum Event {
///
/// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
path: Path,
/// The hold times as reported by each hop.
hold_times: Option<Vec<u32>>,
},
/// Indicates an outbound HTLC we sent failed, likely due to an intermediary node being unable to
/// handle the HTLC.
Expand Down Expand Up @@ -1888,10 +1890,16 @@ impl Writeable for Event {
(4, funding_info, required),
})
},
&Event::PaymentPathSuccessful { ref payment_id, ref payment_hash, ref path } => {
&Event::PaymentPathSuccessful {
ref payment_id,
ref payment_hash,
ref path,
ref hold_times,
} => {
13u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_id, required),
(1, hold_times, option),
(2, payment_hash, option),
(4, path.hops, required_vec),
(6, path.blinded_tail, option),
Expand Down Expand Up @@ -2391,6 +2399,7 @@ impl MaybeReadable for Event {
let mut f = || {
_init_and_read_len_prefixed_tlv_fields!(reader, {
(0, payment_id, required),
(1, hold_times, option),
(2, payment_hash, option),
(4, path, required_vec),
(6, blinded_tail, option),
Expand All @@ -2399,6 +2408,7 @@ impl MaybeReadable for Event {
payment_id: payment_id.0.unwrap(),
payment_hash,
path: Path { hops: path, blinded_tail },
hold_times,
}))
};
f()
Expand Down
2 changes: 1 addition & 1 deletion lightning/src/ln/async_payments_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ fn async_receive_flow_success() {
let args = PassAlongPathArgs::new(&nodes[0], route[0], amt_msat, payment_hash, ev);
let claimable_ev = do_pass_along_path(args).unwrap();
let keysend_preimage = extract_payment_preimage(&claimable_ev);
let res =
let (res, _) =
claim_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], route, keysend_preimage));
assert_eq!(res, Some(PaidBolt12Invoice::StaticInvoice(static_invoice)));
}
Expand Down
2 changes: 2 additions & 0 deletions lightning/src/ln/blinded_payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2333,6 +2333,8 @@ fn test_trampoline_unblinded_receive() {
None,
).unwrap();

// 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 outer_session_priv = secret_from_hex("e52c20461ed7acd46c4e7b591a37610519179482887bd73bf3b94617f8f03677");

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();
Expand Down
21 changes: 17 additions & 4 deletions lightning/src/ln/chanmon_update_fail_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2887,8 +2887,12 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
as_raa = Some(get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, node_b_id));
}

let fulfill_msg =
msgs::UpdateFulfillHTLC { channel_id: chan_id_2, htlc_id: 0, payment_preimage };
let mut fulfill_msg = msgs::UpdateFulfillHTLC {
channel_id: chan_id_2,
htlc_id: 0,
payment_preimage,
attribution_data: None,
};
if second_fails {
nodes[2].node.fail_htlc_backwards(&payment_hash);
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(
Expand All @@ -2897,15 +2901,24 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
);
check_added_monitors!(nodes[2], 1);
get_htlc_update_msgs!(nodes[2], node_b_id);
// Note that we don't populate fulfill_msg.attribution_data here, which will lead to hold times being
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rustfmt 🤷‍♂️

// unavailable.
} else {
nodes[2].node.claim_funds(payment_preimage);
check_added_monitors!(nodes[2], 1);
expect_payment_claimed!(nodes[2], payment_hash, 100_000);

let cs_updates = get_htlc_update_msgs!(nodes[2], node_b_id);
assert_eq!(cs_updates.update_fulfill_htlcs.len(), 1);
// Check that the message we're about to deliver matches the one generated:
assert_eq!(fulfill_msg, cs_updates.update_fulfill_htlcs[0]);

// Check that the message we're about to deliver matches the one generated. Ignore attribution data.
assert_eq!(fulfill_msg.channel_id, cs_updates.update_fulfill_htlcs[0].channel_id);
assert_eq!(fulfill_msg.htlc_id, cs_updates.update_fulfill_htlcs[0].htlc_id);
assert_eq!(
fulfill_msg.payment_preimage,
cs_updates.update_fulfill_htlcs[0].payment_preimage
);
fulfill_msg.attribution_data = cs_updates.update_fulfill_htlcs[0].attribution_data.clone();
}
nodes[1].node.handle_update_fulfill_htlc(node_c_id, &fulfill_msg);
expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], Some(1000), false, false);
Expand Down
Loading
Loading