@@ -6,9 +6,12 @@ use bitcoin::hashes::Hash;
66use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
77use bitcoin:: secp256k1:: { self , Secp256k1 , PublicKey } ;
88
9+ use crate :: blinded_path;
10+ use crate :: blinded_path:: payment:: { PaymentConstraints , PaymentRelay } ;
911use crate :: chain:: channelmonitor:: { HTLC_FAIL_BACK_BUFFER , LATENCY_GRACE_PERIOD_BLOCKS } ;
1012use crate :: ln:: PaymentHash ;
11- use crate :: ln:: channelmanager:: { CLTV_FAR_FAR_AWAY , HTLCFailureMsg , MIN_CLTV_EXPIRY_DELTA , PendingHTLCInfo , PendingHTLCRouting } ;
13+ use crate :: ln:: channelmanager:: { BlindedForward , CLTV_FAR_FAR_AWAY , HTLCFailureMsg , MIN_CLTV_EXPIRY_DELTA , PendingHTLCInfo , PendingHTLCRouting } ;
14+ use crate :: ln:: features:: BlindedHopFeatures ;
1215use crate :: ln:: msgs;
1316use crate :: ln:: onion_utils;
1417use crate :: ln:: onion_utils:: { HTLCFailReason , INVALID_ONION_BLINDING } ;
@@ -28,6 +31,23 @@ pub struct InboundOnionErr {
2831 pub msg : & ' static str ,
2932}
3033
34+ fn check_blinded_forward (
35+ inbound_amt_msat : u64 , inbound_cltv_expiry : u32 , payment_relay : & PaymentRelay ,
36+ payment_constraints : & PaymentConstraints , features : & BlindedHopFeatures
37+ ) -> Result < ( u64 , u32 ) , ( ) > {
38+ let amt_to_forward = blinded_path:: payment:: amt_to_forward_msat (
39+ inbound_amt_msat, payment_relay
40+ ) . ok_or ( ( ) ) ?;
41+ let outgoing_cltv_value = inbound_cltv_expiry. checked_sub (
42+ payment_relay. cltv_expiry_delta as u32
43+ ) . ok_or ( ( ) ) ?;
44+ if inbound_amt_msat < payment_constraints. htlc_minimum_msat ||
45+ outgoing_cltv_value > payment_constraints. max_cltv_expiry
46+ { return Err ( ( ) ) }
47+ if features. requires_unknown_bits_from ( & BlindedHopFeatures :: empty ( ) ) { return Err ( ( ) ) }
48+ Ok ( ( amt_to_forward, outgoing_cltv_value) )
49+ }
50+
3151pub ( super ) fn create_fwd_pending_htlc_info (
3252 msg : & msgs:: UpdateAddHTLC , hop_data : msgs:: InboundOnionPayload , hop_hmac : [ u8 ; 32 ] ,
3353 new_packet_bytes : [ u8 ; onion_utils:: ONION_DATA_LEN ] , shared_secret : [ u8 ; 32 ] ,
@@ -41,10 +61,27 @@ pub(super) fn create_fwd_pending_htlc_info(
4161 hmac : hop_hmac,
4262 } ;
4363
44- let ( short_channel_id, amt_to_forward, outgoing_cltv_value) = match hop_data {
64+ let (
65+ short_channel_id, amt_to_forward, outgoing_cltv_value, inbound_blinding_point
66+ ) = match hop_data {
4567 msgs:: InboundOnionPayload :: Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } =>
46- ( short_channel_id, amt_to_forward, outgoing_cltv_value) ,
47- msgs:: InboundOnionPayload :: BlindedForward { .. } => todo ! ( ) ,
68+ ( short_channel_id, amt_to_forward, outgoing_cltv_value, None ) ,
69+ msgs:: InboundOnionPayload :: BlindedForward {
70+ short_channel_id, payment_relay, payment_constraints, intro_node_blinding_point, features,
71+ } => {
72+ let ( amt_to_forward, outgoing_cltv_value) = check_blinded_forward (
73+ msg. amount_msat , msg. cltv_expiry , & payment_relay, & payment_constraints, & features
74+ ) . map_err ( |( ) | {
75+ // We should be returning malformed here if `msg.blinding_point` is set, but this is
76+ // unreachable right now since we checked it in `decode_update_add_htlc_onion`.
77+ InboundOnionErr {
78+ msg : "Underflow calculating outbound amount or cltv value for blinded forward" ,
79+ err_code : INVALID_ONION_BLINDING ,
80+ err_data : vec ! [ 0 ; 32 ] ,
81+ }
82+ } ) ?;
83+ ( short_channel_id, amt_to_forward, outgoing_cltv_value, Some ( intro_node_blinding_point) )
84+ } ,
4885 msgs:: InboundOnionPayload :: Receive { .. } | msgs:: InboundOnionPayload :: BlindedReceive { .. } =>
4986 return Err ( InboundOnionErr {
5087 msg : "Final Node OnionHopData provided for us as an intermediary node" ,
@@ -57,7 +94,7 @@ pub(super) fn create_fwd_pending_htlc_info(
5794 routing : PendingHTLCRouting :: Forward {
5895 onion_packet : outgoing_packet,
5996 short_channel_id,
60- blinded : None ,
97+ blinded : inbound_blinding_point . map ( |bp| BlindedForward { inbound_blinding_point : bp } ) ,
6198 } ,
6299 payment_hash : msg. payment_hash ,
63100 incoming_shared_secret : shared_secret,
@@ -336,9 +373,25 @@ where
336373 }
337374 } ,
338375 onion_utils:: Hop :: Forward {
339- next_hop_data : msgs:: InboundOnionPayload :: BlindedForward { .. } , ..
376+ next_hop_data : msgs:: InboundOnionPayload :: BlindedForward {
377+ short_channel_id, ref payment_relay, ref payment_constraints, ref features, ..
378+ } , ..
340379 } => {
341- todo ! ( )
380+ let ( amt_to_forward, outgoing_cltv_value) = match check_blinded_forward (
381+ msg. amount_msat , msg. cltv_expiry , & payment_relay, & payment_constraints, & features
382+ ) {
383+ Ok ( ( amt, cltv) ) => ( amt, cltv) ,
384+ Err ( ( ) ) => {
385+ return_err ! ( "Underflow calculating outbound amount or cltv value for blinded forward" ,
386+ INVALID_ONION_BLINDING , & [ 0 ; 32 ] ) ;
387+ }
388+ } ;
389+ let next_packet_pubkey = onion_utils:: next_hop_pubkey ( & secp_ctx,
390+ msg. onion_routing_packet . public_key . unwrap ( ) , & shared_secret) ;
391+ NextPacketDetails {
392+ next_packet_pubkey, outgoing_scid : short_channel_id, outgoing_amt_msat : amt_to_forward,
393+ outgoing_cltv_value
394+ }
342395 } ,
343396 onion_utils:: Hop :: Receive { .. } => return Ok ( ( next_hop, shared_secret, None ) ) ,
344397 onion_utils:: Hop :: Forward { next_hop_data : msgs:: InboundOnionPayload :: Receive { .. } , .. } |
0 commit comments