5
5
6
6
use bitcoin:: hashes:: Hash ;
7
7
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
8
- use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 } ;
8
+ use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 , ecdh :: SharedSecret } ;
9
9
10
10
use crate :: blinded_path;
11
11
use crate :: blinded_path:: payment:: { PaymentConstraints , PaymentRelay } ;
@@ -15,7 +15,7 @@ use crate::ln::channelmanager::{BlindedFailure, BlindedForward, CLTV_FAR_FAR_AWA
15
15
use crate :: types:: features:: BlindedHopFeatures ;
16
16
use crate :: ln:: msgs;
17
17
use crate :: ln:: onion_utils;
18
- use crate :: ln:: onion_utils:: { HTLCFailReason , INVALID_ONION_BLINDING } ;
18
+ use crate :: ln:: onion_utils:: { HTLCFailReason , INVALID_ONION_BLINDING , ONION_DATA_LEN } ;
19
19
use crate :: routing:: gossip:: NodeId ;
20
20
use crate :: sign:: { NodeSigner , Recipient } ;
21
21
use crate :: util:: logger:: Logger ;
@@ -61,20 +61,36 @@ fn check_blinded_forward(
61
61
Ok ( ( amt_to_forward, outgoing_cltv_value) )
62
62
}
63
63
64
+ enum RoutingInfo {
65
+ Direct {
66
+ short_channel_id : u64 ,
67
+ new_packet_bytes : [ u8 ; ONION_DATA_LEN ] ,
68
+ next_hop_hmac : [ u8 ; 32 ]
69
+ } ,
70
+ #[ cfg( trampoline) ]
71
+ Trampoline {
72
+ outgoing_node_id : NodeId ,
73
+ // Trampoline onions are currently variable length
74
+ new_packet_bytes : Vec < u8 > ,
75
+ next_hop_hmac : [ u8 ; 32 ] ,
76
+ shared_secret : SharedSecret
77
+ }
78
+ }
79
+
64
80
pub ( super ) fn create_fwd_pending_htlc_info (
65
81
msg : & msgs:: UpdateAddHTLC , hop_data : onion_utils:: Hop , shared_secret : [ u8 ; 32 ] ,
66
82
next_packet_pubkey_opt : Option < Result < PublicKey , secp256k1:: Error > >
67
83
) -> Result < PendingHTLCInfo , InboundHTLCErr > {
68
84
debug_assert ! ( next_packet_pubkey_opt. is_some( ) ) ;
69
85
70
86
let (
71
- short_channel_id , amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
72
- next_blinding_override, new_packet_bytes , next_hop_hmac
87
+ routing_info , amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
88
+ next_blinding_override
73
89
) = match hop_data {
74
90
onion_utils:: Hop :: Forward { next_hop_data : msgs:: InboundOnionForwardPayload {
75
91
short_channel_id, amt_to_forward, outgoing_cltv_value
76
92
} , new_packet_bytes, next_hop_hmac, .. } =>
77
- ( short_channel_id, amt_to_forward , outgoing_cltv_value , None , None , new_packet_bytes , next_hop_hmac ) ,
93
+ ( RoutingInfo :: Direct { short_channel_id, new_packet_bytes , next_hop_hmac } , amt_to_forward , outgoing_cltv_value , None , None ) ,
78
94
onion_utils:: Hop :: BlindedForward { next_hop_data : msgs:: InboundOnionBlindedForwardPayload {
79
95
short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features,
80
96
next_blinding_override,
@@ -90,38 +106,115 @@ pub(super) fn create_fwd_pending_htlc_info(
90
106
err_data : vec ! [ 0 ; 32 ] ,
91
107
}
92
108
} ) ?;
93
- ( short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
94
- next_blinding_override, new_packet_bytes , next_hop_hmac )
109
+ ( RoutingInfo :: Direct { short_channel_id, new_packet_bytes , next_hop_hmac } , amt_to_forward, outgoing_cltv_value, intro_node_blinding_point,
110
+ next_blinding_override)
95
111
} ,
96
112
onion_utils:: Hop :: Receive { .. } | onion_utils:: Hop :: BlindedReceive { .. } =>
97
113
return Err ( InboundHTLCErr {
98
114
msg : "Final Node OnionHopData provided for us as an intermediary node" ,
99
115
err_code : 0x4000 | 22 ,
100
116
err_data : Vec :: new ( ) ,
101
117
} ) ,
118
+ #[ cfg( trampoline) ]
119
+ onion_utils:: Hop :: TrampolineReceive { .. } =>
120
+ return Err ( InboundHTLCErr {
121
+ msg : "Final Node OnionHopData provided for us as an intermediary node" ,
122
+ err_code : 0x4000 | 22 ,
123
+ err_data : Vec :: new ( ) ,
124
+ } ) ,
125
+ #[ cfg( trampoline) ]
126
+ onion_utils:: Hop :: TrampolineForward { next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
127
+ (
128
+ RoutingInfo :: Trampoline {
129
+ outgoing_node_id : next_trampoline_hop_data. outgoing_node_id ,
130
+ new_packet_bytes : new_trampoline_packet_bytes,
131
+ next_hop_hmac : next_trampoline_hop_hmac,
132
+ shared_secret : trampoline_shared_secret
133
+ } ,
134
+ next_trampoline_hop_data. amt_to_forward ,
135
+ next_trampoline_hop_data. outgoing_cltv_value ,
136
+ None ,
137
+ None
138
+ )
139
+ } ,
140
+ #[ cfg( trampoline) ]
141
+ onion_utils:: Hop :: TrampolineBlindedForward { next_trampoline_hop_data, next_trampoline_hop_hmac, new_trampoline_packet_bytes, trampoline_shared_secret, .. } => {
142
+ let ( amt_to_forward, outgoing_cltv_value) = check_blinded_forward (
143
+ msg. amount_msat , msg. cltv_expiry , & next_trampoline_hop_data. payment_relay , & next_trampoline_hop_data. payment_constraints , & next_trampoline_hop_data. features
144
+ ) . map_err ( |( ) | {
145
+ // We should be returning malformed here if `msg.blinding_point` is set, but this is
146
+ // unreachable right now since we checked it in `decode_update_add_htlc_onion`.
147
+ InboundHTLCErr {
148
+ msg : "Underflow calculating outbound amount or cltv value for blinded forward" ,
149
+ err_code : INVALID_ONION_BLINDING ,
150
+ err_data : vec ! [ 0 ; 32 ] ,
151
+ }
152
+ } ) ?;
153
+ (
154
+ RoutingInfo :: Trampoline {
155
+ outgoing_node_id : next_trampoline_hop_data. outgoing_node_id ,
156
+ new_packet_bytes : new_trampoline_packet_bytes,
157
+ next_hop_hmac : next_trampoline_hop_hmac,
158
+ shared_secret : trampoline_shared_secret
159
+ } ,
160
+ amt_to_forward,
161
+ outgoing_cltv_value,
162
+ next_trampoline_hop_data. intro_node_blinding_point ,
163
+ next_trampoline_hop_data. next_blinding_override
164
+ )
165
+ } ,
102
166
} ;
103
167
104
- let outgoing_packet = msgs:: OnionPacket {
105
- version : 0 ,
106
- public_key : next_packet_pubkey_opt. unwrap_or ( Err ( secp256k1:: Error :: InvalidPublicKey ) ) ,
107
- hop_data : new_packet_bytes,
108
- hmac : next_hop_hmac,
168
+ let routing = match routing_info {
169
+ RoutingInfo :: Direct { short_channel_id, new_packet_bytes, next_hop_hmac } => {
170
+ let outgoing_packet = msgs:: OnionPacket {
171
+ version : 0 ,
172
+ public_key : next_packet_pubkey_opt. unwrap_or ( Err ( secp256k1:: Error :: InvalidPublicKey ) ) ,
173
+ hop_data : new_packet_bytes,
174
+ hmac : next_hop_hmac,
175
+ } ;
176
+ PendingHTLCRouting :: Forward {
177
+ onion_packet : outgoing_packet,
178
+ short_channel_id,
179
+ incoming_cltv_expiry : Some ( msg. cltv_expiry ) ,
180
+ blinded : intro_node_blinding_point. or ( msg. blinding_point )
181
+ . map ( |bp| BlindedForward {
182
+ inbound_blinding_point : bp,
183
+ next_blinding_override,
184
+ failure : intro_node_blinding_point
185
+ . map ( |_| BlindedFailure :: FromIntroductionNode )
186
+ . unwrap_or ( BlindedFailure :: FromBlindedNode ) ,
187
+ } ) ,
188
+ }
189
+ }
190
+ #[ cfg( trampoline) ]
191
+ RoutingInfo :: Trampoline { outgoing_node_id, new_packet_bytes, next_hop_hmac, shared_secret } => {
192
+ let next_trampoline_packet_pubkey = match next_packet_pubkey_opt {
193
+ Some ( Ok ( pubkey) ) => pubkey,
194
+ _ => return Err ( InboundHTLCErr {
195
+ msg : "Missing next Trampoline hop pubkey from intermediate Trampoline forwarding data" ,
196
+ err_code : 0x4000 | 22 ,
197
+ err_data : Vec :: new ( ) ,
198
+ } ) ,
199
+ } ;
200
+ let outgoing_packet = msgs:: TrampolineOnionPacket {
201
+ version : 0 ,
202
+ public_key : next_trampoline_packet_pubkey,
203
+ hop_data : new_packet_bytes,
204
+ hmac : next_hop_hmac,
205
+ } ;
206
+ PendingHTLCRouting :: TrampolineForward {
207
+ incoming_shared_secret : shared_secret. secret_bytes ( ) ,
208
+ onion_packet : outgoing_packet,
209
+ node_id : outgoing_node_id,
210
+ incoming_cltv_expiry : msg. cltv_expiry ,
211
+ blinded : None
212
+ }
213
+ }
109
214
} ;
110
215
111
216
Ok ( PendingHTLCInfo {
112
- routing : PendingHTLCRouting :: Forward {
113
- onion_packet : outgoing_packet,
114
- short_channel_id,
115
- incoming_cltv_expiry : Some ( msg. cltv_expiry ) ,
116
- blinded : intro_node_blinding_point. or ( msg. blinding_point )
117
- . map ( |bp| BlindedForward {
118
- inbound_blinding_point : bp,
119
- next_blinding_override,
120
- failure : intro_node_blinding_point
121
- . map ( |_| BlindedFailure :: FromIntroductionNode )
122
- . unwrap_or ( BlindedFailure :: FromBlindedNode ) ,
123
- } ) ,
124
- } ,
217
+ routing,
125
218
payment_hash : msg. payment_hash ,
126
219
incoming_shared_secret : shared_secret,
127
220
incoming_amt_msat : Some ( msg. amount_msat ) ,
@@ -167,6 +260,8 @@ pub(super) fn create_recv_pending_htlc_info(
167
260
sender_intended_htlc_amt_msat, cltv_expiry_height, None , Some ( payment_context) ,
168
261
intro_node_blinding_point. is_none ( ) , true , invoice_request)
169
262
}
263
+ #[ cfg( trampoline) ]
264
+ onion_utils:: Hop :: TrampolineReceive { .. } => todo ! ( ) ,
170
265
onion_utils:: Hop :: Forward { .. } => {
171
266
return Err ( InboundHTLCErr {
172
267
err_code : 0x4000 |22 ,
@@ -181,6 +276,14 @@ pub(super) fn create_recv_pending_htlc_info(
181
276
msg : "Got blinded non final data with an HMAC of 0" ,
182
277
} )
183
278
} ,
279
+ #[ cfg( trampoline) ]
280
+ onion_utils:: Hop :: TrampolineForward { .. } | onion_utils:: Hop :: TrampolineBlindedForward { .. } => {
281
+ return Err ( InboundHTLCErr {
282
+ err_code : 0x4000 |22 ,
283
+ err_data : Vec :: new ( ) ,
284
+ msg : "Got Trampoline non final data with an HMAC of 0" ,
285
+ } )
286
+ } ,
184
287
} ;
185
288
// final_incorrect_cltv_expiry
186
289
if onion_cltv_expiry > cltv_expiry {
@@ -391,7 +494,7 @@ where
391
494
return_malformed_err ! ( "Unknown onion packet version" , 0x8000 | 0x4000 | 4 ) ;
392
495
}
393
496
394
- let encode_relay_error = |message : & str , err_code : u16 , shared_secret : [ u8 ; 32 ] , data : & [ u8 ] | {
497
+ let encode_relay_error = |message : & str , err_code : u16 , shared_secret : [ u8 ; 32 ] , trampoline_shared_secret : Option < [ u8 ; 32 ] > , data : & [ u8 ] | {
395
498
if msg. blinding_point . is_some ( ) {
396
499
return_malformed_err ! ( message, INVALID_ONION_BLINDING )
397
500
}
@@ -401,7 +504,7 @@ where
401
504
channel_id : msg. channel_id ,
402
505
htlc_id : msg. htlc_id ,
403
506
reason : HTLCFailReason :: reason ( err_code, data. to_vec ( ) )
404
- . get_encrypted_failure_packet ( & shared_secret, & None ) ,
507
+ . get_encrypted_failure_packet ( & shared_secret, & trampoline_shared_secret ) ,
405
508
} ) ) ;
406
509
} ;
407
510
@@ -413,8 +516,8 @@ where
413
516
Err ( onion_utils:: OnionDecodeErr :: Malformed { err_msg, err_code } ) => {
414
517
return_malformed_err ! ( err_msg, err_code) ;
415
518
} ,
416
- Err ( onion_utils:: OnionDecodeErr :: Relay { err_msg, err_code, shared_secret } ) => {
417
- return encode_relay_error ( err_msg, err_code, shared_secret. secret_bytes ( ) , & [ 0 ; 0 ] ) ;
519
+ Err ( onion_utils:: OnionDecodeErr :: Relay { err_msg, err_code, shared_secret, trampoline_shared_secret } ) => {
520
+ return encode_relay_error ( err_msg, err_code, shared_secret. secret_bytes ( ) , trampoline_shared_secret . map ( |tss| tss . secret_bytes ( ) ) , & [ 0 ; 0 ] ) ;
418
521
} ,
419
522
} ;
420
523
@@ -434,7 +537,7 @@ where
434
537
Ok ( ( amt, cltv) ) => ( amt, cltv) ,
435
538
Err ( ( ) ) => {
436
539
return encode_relay_error ( "Underflow calculating outbound amount or cltv value for blinded forward" ,
437
- INVALID_ONION_BLINDING , shared_secret. secret_bytes ( ) , & [ 0 ; 32 ] ) ;
540
+ INVALID_ONION_BLINDING , shared_secret. secret_bytes ( ) , None , & [ 0 ; 32 ] ) ;
438
541
}
439
542
} ;
440
543
let next_packet_pubkey = onion_utils:: next_hop_pubkey ( & secp_ctx,
@@ -444,6 +547,17 @@ where
444
547
outgoing_cltv_value
445
548
} )
446
549
}
550
+ #[ cfg( trampoline) ]
551
+ onion_utils:: Hop :: TrampolineForward { next_trampoline_hop_data : msgs:: InboundTrampolineForwardPayload { amt_to_forward, outgoing_cltv_value, outgoing_node_id } , trampoline_shared_secret, incoming_trampoline_public_key, .. } => {
552
+ let next_trampoline_packet_pubkey = onion_utils:: next_hop_pubkey ( secp_ctx,
553
+ incoming_trampoline_public_key, & trampoline_shared_secret. secret_bytes ( ) ) ;
554
+ Some ( NextPacketDetails {
555
+ next_packet_pubkey : next_trampoline_packet_pubkey,
556
+ outgoing_connector : HopConnector :: Trampoline ( outgoing_node_id) ,
557
+ outgoing_amt_msat : amt_to_forward,
558
+ outgoing_cltv_value,
559
+ } )
560
+ }
447
561
_ => None
448
562
} ;
449
563
0 commit comments