@@ -32,6 +32,8 @@ use bitcoin::script::ScriptBuf;
32
32
use bitcoin:: hash_types:: Txid ;
33
33
34
34
use crate :: blinded_path:: payment:: { BlindedPaymentTlvs , ForwardTlvs , ReceiveTlvs , UnauthenticatedReceiveTlvs } ;
35
+ #[ cfg( trampoline) ]
36
+ use crate :: blinded_path:: payment:: { BlindedTrampolineTlvs , TrampolineForwardTlvs } ;
35
37
use crate :: ln:: channelmanager:: Verification ;
36
38
use crate :: ln:: types:: ChannelId ;
37
39
use crate :: types:: payment:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
@@ -2074,6 +2076,7 @@ mod fuzzy_internal_msgs {
2074
2076
}
2075
2077
2076
2078
#[ cfg( trampoline) ]
2079
+ #[ cfg_attr( trampoline, allow( unused) ) ]
2077
2080
pub struct InboundTrampolineEntrypointPayload {
2078
2081
pub amt_to_forward : u64 ,
2079
2082
pub outgoing_cltv_value : u32 ,
@@ -2116,12 +2119,42 @@ mod fuzzy_internal_msgs {
2116
2119
pub enum InboundOnionPayload {
2117
2120
Forward ( InboundOnionForwardPayload ) ,
2118
2121
#[ cfg( trampoline) ]
2122
+ #[ cfg_attr( trampoline, allow( unused) ) ]
2119
2123
TrampolineEntrypoint ( InboundTrampolineEntrypointPayload ) ,
2120
2124
Receive ( InboundOnionReceivePayload ) ,
2121
2125
BlindedForward ( InboundOnionBlindedForwardPayload ) ,
2122
2126
BlindedReceive ( InboundOnionBlindedReceivePayload ) ,
2123
2127
}
2124
2128
2129
+ #[ cfg( trampoline) ]
2130
+ #[ cfg_attr( trampoline, allow( unused) ) ]
2131
+ pub struct InboundTrampolineForwardPayload {
2132
+ pub next_trampoline : PublicKey ,
2133
+ /// The value, in msat, of the payment after this hop's fee is deducted.
2134
+ pub amt_to_forward : u64 ,
2135
+ pub outgoing_cltv_value : u32 ,
2136
+ }
2137
+
2138
+ #[ cfg( trampoline) ]
2139
+ #[ cfg_attr( trampoline, allow( unused) ) ]
2140
+ pub struct InboundTrampolineBlindedForwardPayload {
2141
+ pub next_trampoline : PublicKey ,
2142
+ pub payment_relay : PaymentRelay ,
2143
+ pub payment_constraints : PaymentConstraints ,
2144
+ pub features : BlindedHopFeatures ,
2145
+ pub intro_node_blinding_point : Option < PublicKey > ,
2146
+ pub next_blinding_override : Option < PublicKey > ,
2147
+ }
2148
+
2149
+ #[ cfg( trampoline) ]
2150
+ #[ cfg_attr( trampoline, allow( unused) ) ]
2151
+ pub enum InboundTrampolinePayload {
2152
+ Forward ( InboundTrampolineForwardPayload ) ,
2153
+ BlindedForward ( InboundTrampolineBlindedForwardPayload ) ,
2154
+ Receive ( InboundOnionReceivePayload ) ,
2155
+ BlindedReceive ( InboundOnionBlindedReceivePayload ) ,
2156
+ }
2157
+
2125
2158
pub ( crate ) enum OutboundOnionPayload < ' a > {
2126
2159
Forward {
2127
2160
short_channel_id : u64 ,
@@ -3359,6 +3392,134 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, NS)> for InboundOnionPayload wh
3359
3392
}
3360
3393
}
3361
3394
3395
+ #[ cfg( trampoline) ]
3396
+ impl < NS : Deref > ReadableArgs < ( Option < PublicKey > , NS ) > for InboundTrampolinePayload where NS :: Target : NodeSigner {
3397
+ fn read < R : Read > ( r : & mut R , args : ( Option < PublicKey > , NS ) ) -> Result < Self , DecodeError > {
3398
+ let ( update_add_blinding_point, node_signer) = args;
3399
+
3400
+ let mut amt = None ;
3401
+ let mut cltv_value = None ;
3402
+ let mut payment_data: Option < FinalOnionHopData > = None ;
3403
+ let mut encrypted_tlvs_opt: Option < WithoutLength < Vec < u8 > > > = None ;
3404
+ let mut intro_node_blinding_point = None ;
3405
+ let mut next_trampoline: Option < PublicKey > = None ;
3406
+ let mut payment_metadata: Option < WithoutLength < Vec < u8 > > > = None ;
3407
+ let mut total_msat = None ;
3408
+ let mut keysend_preimage: Option < PaymentPreimage > = None ;
3409
+ let mut invoice_request: Option < InvoiceRequest > = None ;
3410
+ let mut custom_tlvs = Vec :: new ( ) ;
3411
+
3412
+ let tlv_len = BigSize :: read ( r) ?;
3413
+ let mut rd = FixedLengthReader :: new ( r, tlv_len. 0 ) ;
3414
+ decode_tlv_stream_with_custom_tlv_decode ! ( & mut rd, {
3415
+ ( 2 , amt, ( option, encoding: ( u64 , HighZeroBytesDroppedBigSize ) ) ) ,
3416
+ ( 4 , cltv_value, ( option, encoding: ( u32 , HighZeroBytesDroppedBigSize ) ) ) ,
3417
+ ( 8 , payment_data, option) ,
3418
+ ( 10 , encrypted_tlvs_opt, option) ,
3419
+ ( 12 , intro_node_blinding_point, option) ,
3420
+ ( 14 , next_trampoline, option) ,
3421
+ ( 16 , payment_metadata, option) ,
3422
+ ( 18 , total_msat, ( option, encoding: ( u64 , HighZeroBytesDroppedBigSize ) ) ) ,
3423
+ ( 77_777 , invoice_request, option) ,
3424
+ // See https://github.com/lightning/blips/blob/master/blip-0003.md
3425
+ ( 5482373484 , keysend_preimage, option)
3426
+ } , |msg_type: u64 , msg_reader: & mut FixedLengthReader <_>| -> Result <bool , DecodeError > {
3427
+ if msg_type < 1 << 16 { return Ok ( false ) }
3428
+ let mut value = Vec :: new( ) ;
3429
+ msg_reader. read_to_limit( & mut value, u64 :: MAX ) ?;
3430
+ custom_tlvs. push( ( msg_type, value) ) ;
3431
+ Ok ( true )
3432
+ } ) ;
3433
+
3434
+ if amt. unwrap_or ( 0 ) > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
3435
+ if intro_node_blinding_point. is_some ( ) && update_add_blinding_point. is_some ( ) {
3436
+ return Err ( DecodeError :: InvalidValue )
3437
+ }
3438
+
3439
+ if let Some ( blinding_point) = intro_node_blinding_point. or ( update_add_blinding_point) {
3440
+ if next_trampoline. is_some ( ) || payment_data. is_some ( ) || payment_metadata. is_some ( ) {
3441
+ return Err ( DecodeError :: InvalidValue )
3442
+ }
3443
+ let enc_tlvs = encrypted_tlvs_opt. ok_or ( DecodeError :: InvalidValue ) ?. 0 ;
3444
+ let enc_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & blinding_point, None )
3445
+ . map_err ( |_| DecodeError :: InvalidValue ) ?;
3446
+ let rho = onion_utils:: gen_rho_from_shared_secret ( & enc_tlvs_ss. secret_bytes ( ) ) ;
3447
+ let mut s = Cursor :: new ( & enc_tlvs) ;
3448
+ let mut reader = FixedLengthReader :: new ( & mut s, enc_tlvs. len ( ) as u64 ) ;
3449
+ match ChaChaPolyReadAdapter :: read ( & mut reader, rho) ? {
3450
+ ChaChaPolyReadAdapter { readable : BlindedTrampolineTlvs :: Forward ( TrampolineForwardTlvs {
3451
+ next_trampoline, payment_relay, payment_constraints, features, next_blinding_override
3452
+ } ) } => {
3453
+ if amt. is_some ( ) || cltv_value. is_some ( ) || total_msat. is_some ( ) ||
3454
+ keysend_preimage. is_some ( ) || invoice_request. is_some ( )
3455
+ {
3456
+ return Err ( DecodeError :: InvalidValue )
3457
+ }
3458
+ Ok ( Self :: BlindedForward ( InboundTrampolineBlindedForwardPayload {
3459
+ next_trampoline,
3460
+ payment_relay,
3461
+ payment_constraints,
3462
+ features,
3463
+ intro_node_blinding_point,
3464
+ next_blinding_override,
3465
+ } ) )
3466
+ } ,
3467
+ ChaChaPolyReadAdapter { readable : BlindedTrampolineTlvs :: Receive ( receive_tlvs) } => {
3468
+ let ReceiveTlvs { tlvs, authentication : ( hmac, nonce) } = receive_tlvs;
3469
+ let expanded_key = node_signer. get_inbound_payment_key ( ) ;
3470
+ if tlvs. verify_for_offer_payment ( hmac, nonce, & expanded_key) . is_err ( ) {
3471
+ return Err ( DecodeError :: InvalidValue ) ;
3472
+ }
3473
+
3474
+ let UnauthenticatedReceiveTlvs {
3475
+ payment_secret, payment_constraints, payment_context,
3476
+ } = tlvs;
3477
+ if total_msat. unwrap_or ( 0 ) > MAX_VALUE_MSAT { return Err ( DecodeError :: InvalidValue ) }
3478
+ Ok ( Self :: BlindedReceive ( InboundOnionBlindedReceivePayload {
3479
+ sender_intended_htlc_amt_msat : amt. ok_or ( DecodeError :: InvalidValue ) ?,
3480
+ total_msat : total_msat. ok_or ( DecodeError :: InvalidValue ) ?,
3481
+ cltv_expiry_height : cltv_value. ok_or ( DecodeError :: InvalidValue ) ?,
3482
+ payment_secret,
3483
+ payment_constraints,
3484
+ payment_context,
3485
+ intro_node_blinding_point,
3486
+ keysend_preimage,
3487
+ invoice_request,
3488
+ custom_tlvs,
3489
+ } ) )
3490
+ } ,
3491
+ }
3492
+ } else if let Some ( next_trampoline) = next_trampoline {
3493
+ if payment_data. is_some ( ) || payment_metadata. is_some ( ) || encrypted_tlvs_opt. is_some ( ) ||
3494
+ total_msat. is_some ( ) || invoice_request. is_some ( )
3495
+ { return Err ( DecodeError :: InvalidValue ) }
3496
+ Ok ( Self :: Forward ( InboundTrampolineForwardPayload {
3497
+ next_trampoline,
3498
+ amt_to_forward : amt. ok_or ( DecodeError :: InvalidValue ) ?,
3499
+ outgoing_cltv_value : cltv_value. ok_or ( DecodeError :: InvalidValue ) ?,
3500
+ } ) )
3501
+ } else {
3502
+ if encrypted_tlvs_opt. is_some ( ) || total_msat. is_some ( ) || invoice_request. is_some ( ) {
3503
+ return Err ( DecodeError :: InvalidValue )
3504
+ }
3505
+ if let Some ( data) = & payment_data {
3506
+ if data. total_msat > MAX_VALUE_MSAT {
3507
+ return Err ( DecodeError :: InvalidValue ) ;
3508
+ }
3509
+ }
3510
+ Ok ( Self :: Receive ( InboundOnionReceivePayload {
3511
+ payment_data,
3512
+ payment_metadata : payment_metadata. map ( |w| w. 0 ) ,
3513
+ keysend_preimage,
3514
+ sender_intended_htlc_amt_msat : amt. ok_or ( DecodeError :: InvalidValue ) ?,
3515
+ cltv_expiry_height : cltv_value. ok_or ( DecodeError :: InvalidValue ) ?,
3516
+ custom_tlvs,
3517
+ } ) )
3518
+ }
3519
+ }
3520
+ }
3521
+
3522
+
3362
3523
impl Writeable for Ping {
3363
3524
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
3364
3525
self . ponglen . write ( w) ?;
0 commit comments