Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8925925
ln/refactor: use amount_msat and counterparty_skimmed_fee_msat vars
carlaKC Apr 14, 2026
6168bed
ln: remove incoming trampoline secret from HTLCSource
carlaKC Mar 12, 2026
b9c3601
ln: store incoming mpp data in PendingHTLCRouting
carlaKC Jan 27, 2026
d2ece0d
ln: use total_msat to calculate the amount for our next trampoline
carlaKC Feb 25, 2026
e253953
ln: use outer onion values in PendingHTLCInfo for trampoline
carlaKC May 12, 2026
3d0309f
ln: store next trampoline amount and cltv in PendingHTLCRouting
carlaKC May 12, 2026
0cae5b5
ln: use outer onion values for trampoline NextPacketDetails
carlaKC Feb 12, 2026
07d3248
ln: add awaiting_trampoline_forwards to accumulate inbound MPP
carlaKC Mar 30, 2026
f25382b
ln: add trampoline mpp accumulation with rejection on completion
carlaKC Apr 10, 2026
163da0a
ln: double encrypt errors received from downstream failures
carlaKC Mar 12, 2026
8bc2e85
ln: handle DecodedOnionFailure for local trampoline failures
carlaKC Mar 12, 2026
764458a
ln: process added trampoline htlcs with CLTV validation in tests
carlaKC Feb 25, 2026
7fce959
ln/test: add test coverage for MPP trampoline
carlaKC Mar 17, 2026
33a2e6e
ln/test: add tests for mpp accumulation of trampoline forwards
carlaKC Apr 27, 2026
a72e72b
ln: add trampoline forward info to PendingOutboundPayment::Retryable
carlaKC Jan 16, 2026
e561664
ln: thread trampoline routing information through payment methods
carlaKC Feb 10, 2026
6f29fa4
ln: add blinding point to new_trampoline_entry
carlaKC Feb 10, 2026
10ea6b6
ln function to build trampoline forwarding onions
carlaKC Jan 28, 2026
aae0d08
ln: support trampoline in send_payment_along_path
carlaKC May 1, 2026
ca34a50
ln: add send trampoline payment functionality
carlaKC Jan 16, 2026
326dd57
[wip] Clauded error handling
carlaKC May 4, 2026
8d5da62
[wip] ln: add trampoline htlc failure logic to outbound payments
carlaKC Mar 17, 2026
0a6055d
ln: add claim_trampoline_forward to mark trampoline complete
carlaKC Feb 18, 2026
d3a8c79
ln: handle trampoline payments in finalize_claims
carlaKC Feb 18, 2026
50cf716
ln: only fail trampoline payments backwards when payment state ready
carlaKC Mar 12, 2026
8df6640
ln: claim trampoline payment on completion
carlaKC Feb 18, 2026
b65c990
ln: use correct blinding point for trampoline payload decodes
carlaKC Feb 2, 2026
3839863
ln: allow reading HTLCSource::TrampolineForward
carlaKC Feb 24, 2026
141bbcf
ln: add trampoline payment dispatch after inbound accumulation
carlaKC May 12, 2026
12061ee
ln/test: only use replacement onion in trampoline tests when needed
carlaKC Feb 10, 2026
7d46a2f
[wip]ln: pass trampoline secret to construct_pending_htlc_fail_msg
carlaKC Mar 17, 2026
9472914
[wip]: forwarding tests with messy replacement onion code
carlaKC May 12, 2026
3dfa5fc
[wip]: track already_forwarded_htlcs by full HTLCSource
carlaKC Mar 4, 2026
f6ef7f8
[wip]: support muti-out sources in inbound_forwarded_htlcs
carlaKC Mar 4, 2026
fbfd75d
[wip]: pass full HTLCSource through in committed_outbound_htlc_sources
carlaKC Mar 4, 2026
8f87e4e
[wip] dedup trampoline forwards with failed_htlcs
carlaKC Mar 4, 2026
c10d3d3
[wip] persist trampoline information in InboundUpdateAdd
carlaKC Mar 4, 2026
b646942
[wip] return trampoline forwards in inbound_forwarded_htlcs
carlaKC Mar 4, 2026
49a2797
[wip]: return trampoline forwards from outbound_htlc_forwards
carlaKC Mar 4, 2026
2593ba6
[temp] Turn on trampoline forwards for testing and signal feature
carlaKC May 20, 2026
493e6a9
[Temp] Surface ability to make blinded trampoline path for interop
carlaKC Jun 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 81 additions & 2 deletions lightning/src/blinded_path/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ impl BlindedPaymentPath {
}

/// Create a blinded path for a trampoline payment, to be forwarded along `intermediate_nodes`.
#[cfg(any(test, feature = "_test_utils"))]
pub(crate) fn new_for_trampoline<
pub fn new_for_trampoline<
ES: EntropySource,
T: secp256k1::Signing + secp256k1::Verification,
>(
Expand Down Expand Up @@ -1322,4 +1321,84 @@ mod tests {
.unwrap();
assert_eq!(blinded_payinfo.htlc_maximum_msat, 3997);
}

#[test]
fn new_for_trampoline_path_structure() {
// Build a trampoline blinded path with a known ordered intermediate-node list and assert
// that (a) the introduction node is the first configured node and (b) the number of blinded
// hops equals (intermediates + 1) for the recipient.
use super::{BlindedPaymentPath, ForwardNode, TrampolineForwardTlvs};
use crate::blinded_path::IntroductionNode;
use crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA;
use crate::sign::ReceiveAuthKey;
use crate::util::test_utils::TestKeysInterface;
use bitcoin::network::Network;
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};

let secp_ctx = Secp256k1::new();
let entropy_source = TestKeysInterface::new(&[42; 32], Network::Testnet);

// Three distinct intermediate node ids (introduction first, then relays) plus a recipient.
let intro_node =
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[1; 32]).unwrap());
let relay_node =
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[2; 32]).unwrap());
let recipient =
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[3; 32]).unwrap());

let ordered_nodes = [intro_node, relay_node];

let forward_nodes: Vec<ForwardNode<TrampolineForwardTlvs>> = ordered_nodes
.iter()
.enumerate()
.map(|(i, node_id)| {
let next_trampoline = ordered_nodes.get(i + 1).copied().unwrap_or(recipient);
ForwardNode {
node_id: *node_id,
tlvs: TrampolineForwardTlvs {
next_trampoline,
payment_relay: PaymentRelay {
cltv_expiry_delta: 144,
fee_proportional_millionths: 0,
fee_base_msat: 0,
},
payment_constraints: PaymentConstraints {
max_cltv_expiry: 1_000_000,
htlc_minimum_msat: 0,
},
features: BlindedHopFeatures::empty(),
next_blinding_override: None,
},
htlc_maximum_msat: u64::MAX,
}
})
.collect();

let payee_tlvs = ReceiveTlvs {
payment_secret: PaymentSecret([0; 32]),
payment_constraints: PaymentConstraints {
max_cltv_expiry: 1_000_000,
htlc_minimum_msat: 1,
},
payment_context: PaymentContext::Bolt12Refund(Bolt12RefundContext {}),
};

let path = BlindedPaymentPath::new_for_trampoline(
&forward_nodes,
recipient,
ReceiveAuthKey([7; 32]),
payee_tlvs,
u64::MAX,
MIN_FINAL_CLTV_EXPIRY_DELTA,
&entropy_source,
&secp_ctx,
)
.unwrap();

// (a) The introduction node is the first configured (introduction) node.
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(intro_node));

// (b) One blinded hop per intermediate, plus one for the recipient.
assert_eq!(path.blinded_hops().len(), ordered_nodes.len() + 1);
}
}
Loading