Skip to content

Commit efcaf4f

Browse files
committed
code refactor for trampoline routing
1 parent 03aa736 commit efcaf4f

File tree

7 files changed

+280
-57
lines changed

7 files changed

+280
-57
lines changed

crates/fiber-lib/src/fiber/network.rs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ use crate::fiber::gossip::{GossipConfig, GossipService, SubscribableGossipMessag
9292
use crate::fiber::payment::SessionRoute;
9393
use crate::fiber::payment::{
9494
AttemptStatus, PaymentActor, PaymentActorArguments, PaymentActorMessage, PaymentCustomRecords,
95-
PaymentStatus, SendPaymentCommand, SendPaymentWithRouterCommand,
95+
PaymentStatus, SendPaymentCommand, SendPaymentWithRouterCommand, TrampolineContext,
9696
};
9797
use crate::fiber::serde_utils::EntityHex;
9898
use crate::fiber::types::{
@@ -2474,19 +2474,21 @@ where
24742474
));
24752475
}
24762476

2477-
let remaining_trampoline_onion = peeled_trampoline.next.map(|p| p.into_bytes());
2477+
let (Some(remaining_trampoline_onion), Some(mut prev_tlc)) =
2478+
(peeled_trampoline.next.map(|p| p.into_bytes()), previous_tlc)
2479+
else {
2480+
return Err(TlcErr::new_node_fail(
2481+
TlcErrorCode::InvalidOnionPayload,
2482+
state.get_public_key(),
2483+
));
2484+
};
24782485

2479-
if let Some(mut prev_tlc) = previous_tlc {
2480-
if let Some(shared_secret) = trampoline_outer_shared_secret {
2481-
prev_tlc.shared_secret = Some(shared_secret);
2482-
}
2483-
state
2484-
.trampoline_forwarding_tlcs
2485-
.entry(payment_hash)
2486-
.or_default()
2487-
.push(prev_tlc);
2486+
if let Some(shared_secret) = trampoline_outer_shared_secret {
2487+
prev_tlc.shared_secret = Some(shared_secret);
24882488
}
2489-
2489+
// currently we only support single previous tlc in trampoline forwarding,
2490+
// maybe we need to support multiple previous tlcs in the future
2491+
let previous_tlcs = vec![prev_tlc];
24902492
let command = SendPaymentCommand {
24912493
target_pubkey: Some(next_node_id),
24922494
amount: Some(amount_to_forward),
@@ -2497,7 +2499,10 @@ where
24972499
max_parts: Some(1),
24982500
udt_type_script,
24992501
allow_self_payment: true,
2500-
final_trampoline_onion: remaining_trampoline_onion,
2502+
trampoline_context: Some(TrampolineContext {
2503+
remaining_trampoline_onion,
2504+
previous_tlcs,
2505+
}),
25012506
..Default::default()
25022507
};
25032508

@@ -2811,9 +2816,6 @@ pub struct NetworkActorState<S, C> {
28112816

28122817
// Inflight payment actors
28132818
inflight_payments: HashMap<Hash256, ActorRef<PaymentActorMessage>>,
2814-
2815-
// Trampoline forwarding map: payment_hash -> Vec<PrevTlcInfo>
2816-
trampoline_forwarding_tlcs: HashMap<Hash256, Vec<PrevTlcInfo>>,
28172819
}
28182820

28192821
#[derive(Debug, Clone)]
@@ -3968,19 +3970,25 @@ where
39683970
error!("Can't find inflight payment actor");
39693971
}
39703972

3971-
if let Some(prev_tlcs) = self.trampoline_forwarding_tlcs.remove(&payment_hash) {
3972-
let session = self.store.get_payment_session(payment_hash);
3973-
match session {
3974-
Some(session) if session.status == PaymentStatus::Success => {
3973+
// If this payment has associated previous TLCs,
3974+
// meaning it's a trampoline forwarding payment,
3975+
// we need to resolve those upstream TLCs based on the payment outcome.
3976+
let Some(session) = self.store.get_payment_session(payment_hash) else {
3977+
return;
3978+
};
3979+
let trampoline_context = session.request.trampoline_context.as_ref();
3980+
3981+
if let Some(context) = trampoline_context {
3982+
match session.status {
3983+
PaymentStatus::Success => {
39753984
let preimage = session
39763985
.attempts()
39773986
.find(|a| a.is_success())
39783987
.and_then(|a| a.preimage);
39793988

39803989
if let Some(preimage) = preimage {
3981-
// Store preimage globally
39823990
self.store.insert_preimage(payment_hash, preimage);
3983-
for prev_tlc in prev_tlcs {
3991+
for prev_tlc in &context.previous_tlcs {
39843992
let (send, _recv) = oneshot::channel();
39853993
let rpc_reply = RpcReplyPort::from(send);
39863994
let command = ChannelCommand::RemoveTlc(
@@ -4003,8 +4011,8 @@ where
40034011
error!("Payment success but no preimage found for {payment_hash}");
40044012
}
40054013
}
4006-
Some(session) if session.status == PaymentStatus::Failed => {
4007-
for prev_tlc in prev_tlcs {
4014+
PaymentStatus::Failed => {
4015+
for prev_tlc in &context.previous_tlcs {
40084016
let (send, _recv) = oneshot::channel();
40094017
let rpc_reply = RpcReplyPort::from(send);
40104018
let shared_secret = prev_tlc.shared_secret.unwrap_or([0u8; 32]);
@@ -4346,7 +4354,6 @@ where
43464354
funding_timeout_seconds: config.funding_timeout_seconds,
43474355
},
43484356
inflight_payments: Default::default(),
4349-
trampoline_forwarding_tlcs: Default::default(),
43504357
};
43514358

43524359
let node_announcement = state.get_or_create_new_node_announcement_message();

crates/fiber-lib/src/fiber/payment.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::Arc;
33

44
use super::network::{SendOnionPacketCommand, SendPaymentResponse, ASSUME_NETWORK_MYSELF_ALIVE};
55
use super::types::{Hash256, Privkey, Pubkey, TlcErrData};
6-
use crate::fiber::channel::{ChannelActorStateStore, ProcessingChannelError};
6+
use crate::fiber::channel::{ChannelActorStateStore, PrevTlcInfo, ProcessingChannelError};
77
use crate::fiber::config::{
88
DEFAULT_FINAL_TLC_EXPIRY_DELTA, DEFAULT_MAX_PARTS, MAX_PAYMENT_TLC_EXPIRY_LIMIT,
99
MIN_TLC_EXPIRY_DELTA, PAYMENT_MAX_PARTS_LIMIT,
@@ -170,7 +170,8 @@ pub struct SendPaymentData {
170170
/// When set to a non-empty list `[t1, t2, ...]`, routing will only find a path from the
171171
/// payer to `t1`, and the inner trampoline onion will encode `t1 -> t2 -> ... -> final`.
172172
pub trampoline_hops: Option<Vec<TrampolineHop>>,
173-
pub final_trampoline_onion: Option<Vec<u8>>,
173+
#[serde(default)]
174+
pub trampoline_context: Option<TrampolineContext>,
174175
#[serde(skip)]
175176
pub channel_stats: GraphChannelStat,
176177
}
@@ -196,7 +197,7 @@ pub struct SendPaymentDataBuilder {
196197
allow_mpp: bool,
197198
dry_run: bool,
198199
trampoline_hops: Option<Vec<TrampolineHop>>,
199-
final_trampoline_onion: Option<Vec<u8>>,
200+
trampoline_context: Option<TrampolineContext>,
200201
channel_stats: GraphChannelStat,
201202
}
202203

@@ -308,8 +309,8 @@ impl SendPaymentDataBuilder {
308309
self
309310
}
310311

311-
pub fn final_trampoline_onion(mut self, final_trampoline_onion: Option<Vec<u8>>) -> Self {
312-
self.final_trampoline_onion = final_trampoline_onion;
312+
pub fn trampoline_context(mut self, trampoline_context: Option<TrampolineContext>) -> Self {
313+
self.trampoline_context = trampoline_context;
313314
self
314315
}
315316

@@ -453,8 +454,8 @@ impl SendPaymentDataBuilder {
453454
allow_mpp: self.allow_mpp,
454455
dry_run: self.dry_run,
455456
trampoline_hops: self.trampoline_hops,
456-
final_trampoline_onion: self.final_trampoline_onion,
457457
channel_stats: self.channel_stats,
458+
trampoline_context: self.trampoline_context,
458459
})
459460
}
460461
}
@@ -609,7 +610,7 @@ impl SendPaymentData {
609610
.allow_mpp(allow_mpp)
610611
.dry_run(command.dry_run)
611612
.trampoline_hops(command.trampoline_hops)
612-
.final_trampoline_onion(command.final_trampoline_onion)
613+
.trampoline_context(command.trampoline_context)
613614
.channel_stats(Default::default())
614615
.build()
615616
}
@@ -1129,12 +1130,21 @@ pub struct SendPaymentCommand {
11291130
/// When set to a non-empty list `[t1, t2, ...]`, routing will only find a path from the
11301131
/// payer to `t1`, and the inner trampoline onion will encode `t1 -> t2 -> ... -> final`.
11311132
pub trampoline_hops: Option<Vec<TrampolineHop>>,
1133+
1134+
/// Context for trampoline routing.
1135+
pub trampoline_context: Option<TrampolineContext>,
1136+
}
1137+
1138+
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
1139+
pub struct TrampolineContext {
11321140
/// Optional final trampoline onion packet.
11331141
///
1134-
/// When provided, this onion packet will be attached to the payload of the final hop
1142+
/// When provided, this onion packet will be attached to the payload of the next hop
11351143
/// (which in this context is the next trampoline node).
1136-
#[serde(skip)]
1137-
pub final_trampoline_onion: Option<Vec<u8>>,
1144+
pub remaining_trampoline_onion: Vec<u8>,
1145+
/// Previous TLCs information for the payment session.
1146+
/// This is used to associate the outgoing payment with the incoming payment.
1147+
pub previous_tlcs: Vec<PrevTlcInfo>,
11381148
}
11391149

11401150
impl SendPaymentCommand {
@@ -1713,9 +1723,10 @@ where
17131723
Ok(mut hops) => {
17141724
assert_ne!(hops[0].funding_tx_hash, Hash256::default());
17151725

1716-
if let Some(trampoline_onion) = &session.request.final_trampoline_onion {
1726+
if let Some(trampoline) = &session.request.trampoline_context {
17171727
if let Some(last_hop) = hops.last_mut() {
1718-
last_hop.trampoline_onion = Some(trampoline_onion.clone());
1728+
last_hop.trampoline_onion =
1729+
Some(trampoline.remaining_trampoline_onion.clone());
17191730
}
17201731
}
17211732

crates/fiber-lib/src/fiber/tests/network.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ fn test_send_payment_data_trampoline_hops_validation_errors() {
131131
target_pubkey: Some(target),
132132
allow_self_payment: false,
133133
payment_hash: Some(payment_hash),
134+
trampoline_context: None,
134135
final_tlc_expiry_delta: None,
135136
tlc_expiry_limit: None,
136137
timeout: None,
@@ -142,7 +143,6 @@ fn test_send_payment_data_trampoline_hops_validation_errors() {
142143
dry_run: false,
143144
hop_hints: None,
144145
custom_records: None,
145-
final_trampoline_onion: None,
146146
};
147147

148148
// Provided but empty.

crates/fiber-lib/src/fiber/tests/payment.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5247,6 +5247,7 @@ async fn test_send_payment_no_preimage_invoice_will_make_payment_failed() {
52475247
target_pubkey: None,
52485248
allow_self_payment: true,
52495249
payment_hash: None,
5250+
trampoline_context: None,
52505251
final_tlc_expiry_delta: None,
52515252
tlc_expiry_limit: None,
52525253
timeout: None,
@@ -5258,7 +5259,6 @@ async fn test_send_payment_no_preimage_invoice_will_make_payment_failed() {
52585259
dry_run: false,
52595260
hop_hints: None,
52605261
custom_records: None,
5261-
final_trampoline_onion: None,
52625262
})
52635263
.await
52645264
.unwrap();

0 commit comments

Comments
 (0)