@@ -518,6 +518,12 @@ pub(super) enum HTLCFailReason {
518518 }
519519}
520520
521+ struct ReceiveError {
522+ err_code : u16 ,
523+ err_data : Vec < u8 > ,
524+ msg : & ' static str ,
525+ }
526+
521527/// Return value for claim_funds_from_hop
522528enum ClaimFundsFromHop {
523529 PrevHopForceClosed ,
@@ -2043,6 +2049,102 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
20432049 }
20442050 }
20452051
2052+ fn construct_recv_pending_htlc_info ( & self , hop_data : msgs:: OnionHopData , shared_secret : [ u8 ; 32 ] ,
2053+ payment_hash : PaymentHash , amt_msat : u64 , cltv_expiry : u32 ) -> Result < PendingHTLCInfo , ReceiveError >
2054+ {
2055+ // final_incorrect_cltv_expiry
2056+ if hop_data. outgoing_cltv_value != cltv_expiry {
2057+ return Err ( ReceiveError {
2058+ msg : "Upstream node set CLTV to the wrong value" ,
2059+ err_code : 18 ,
2060+ err_data : byte_utils:: be32_to_array ( cltv_expiry) . to_vec ( )
2061+ } )
2062+ }
2063+ // final_expiry_too_soon
2064+ // We have to have some headroom to broadcast on chain if we have the preimage, so make sure
2065+ // we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
2066+ // Also, ensure that, in the case of an unknown preimage for the received payment hash, our
2067+ // payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
2068+ // channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
2069+ if ( hop_data. outgoing_cltv_value as u64 ) <= self . best_block . read ( ) . unwrap ( ) . height ( ) as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
2070+ return Err ( ReceiveError {
2071+ err_code : 17 ,
2072+ err_data : Vec :: new ( ) ,
2073+ msg : "The final CLTV expiry is too soon to handle" ,
2074+ } ) ;
2075+ }
2076+ if hop_data. amt_to_forward > amt_msat {
2077+ return Err ( ReceiveError {
2078+ err_code : 19 ,
2079+ err_data : byte_utils:: be64_to_array ( amt_msat) . to_vec ( ) ,
2080+ msg : "Upstream node sent less than we were supposed to receive in payment" ,
2081+ } ) ;
2082+ }
2083+
2084+ let routing = match hop_data. format {
2085+ msgs:: OnionHopDataFormat :: Legacy { .. } => {
2086+ return Err ( ReceiveError {
2087+ err_code : 0x4000 |0x2000 |3 ,
2088+ err_data : Vec :: new ( ) ,
2089+ msg : "We require payment_secrets" ,
2090+ } ) ;
2091+ } ,
2092+ msgs:: OnionHopDataFormat :: NonFinalNode { .. } => {
2093+ return Err ( ReceiveError {
2094+ err_code : 0x4000 |22 ,
2095+ err_data : Vec :: new ( ) ,
2096+ msg : "Got non final data with an HMAC of 0" ,
2097+ } ) ;
2098+ } ,
2099+ msgs:: OnionHopDataFormat :: FinalNode { payment_data, keysend_preimage } => {
2100+ if payment_data. is_some ( ) && keysend_preimage. is_some ( ) {
2101+ return Err ( ReceiveError {
2102+ err_code : 0x4000 |22 ,
2103+ err_data : Vec :: new ( ) ,
2104+ msg : "We don't support MPP keysend payments" ,
2105+ } ) ;
2106+ } else if let Some ( data) = payment_data {
2107+ PendingHTLCRouting :: Receive {
2108+ payment_data : data,
2109+ incoming_cltv_expiry : hop_data. outgoing_cltv_value ,
2110+ }
2111+ } else if let Some ( payment_preimage) = keysend_preimage {
2112+ // We need to check that the sender knows the keysend preimage before processing this
2113+ // payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
2114+ // could discover the final destination of X, by probing the adjacent nodes on the route
2115+ // with a keysend payment of identical payment hash to X and observing the processing
2116+ // time discrepancies due to a hash collision with X.
2117+ let hashed_preimage = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
2118+ if hashed_preimage != payment_hash {
2119+ return Err ( ReceiveError {
2120+ err_code : 0x4000 |22 ,
2121+ err_data : Vec :: new ( ) ,
2122+ msg : "Payment preimage didn't match payment hash" ,
2123+ } ) ;
2124+ }
2125+
2126+ PendingHTLCRouting :: ReceiveKeysend {
2127+ payment_preimage,
2128+ incoming_cltv_expiry : hop_data. outgoing_cltv_value ,
2129+ }
2130+ } else {
2131+ return Err ( ReceiveError {
2132+ err_code : 0x4000 |0x2000 |3 ,
2133+ err_data : Vec :: new ( ) ,
2134+ msg : "We require payment_secrets" ,
2135+ } ) ;
2136+ }
2137+ } ,
2138+ } ;
2139+ Ok ( PendingHTLCInfo {
2140+ routing,
2141+ payment_hash,
2142+ incoming_shared_secret : shared_secret,
2143+ amt_to_forward : amt_msat,
2144+ outgoing_cltv_value : hop_data. outgoing_cltv_value ,
2145+ } )
2146+ }
2147+
20462148 fn decode_update_add_htlc_onion ( & self , msg : & msgs:: UpdateAddHTLC ) -> ( PendingHTLCStatus , MutexGuard < ChannelHolder < Signer > > ) {
20472149 macro_rules! return_malformed_err {
20482150 ( $msg: expr, $err_code: expr) => {
@@ -2108,68 +2210,16 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
21082210 let pending_forward_info = match next_hop {
21092211 onion_utils:: Hop :: Receive ( next_hop_data) => {
21102212 // OUR PAYMENT!
2111- // final_expiry_too_soon
2112- // We have to have some headroom to broadcast on chain if we have the preimage, so make sure
2113- // we have at least HTLC_FAIL_BACK_BUFFER blocks to go.
2114- // Also, ensure that, in the case of an unknown preimage for the received payment hash, our
2115- // payment logic has enough time to fail the HTLC backward before our onchain logic triggers a
2116- // channel closure (see HTLC_FAIL_BACK_BUFFER rationale).
2117- if ( msg. cltv_expiry as u64 ) <= self . best_block . read ( ) . unwrap ( ) . height ( ) as u64 + HTLC_FAIL_BACK_BUFFER as u64 + 1 {
2118- return_err ! ( "The final CLTV expiry is too soon to handle" , 17 , & [ 0 ; 0 ] ) ;
2119- }
2120- // final_incorrect_htlc_amount
2121- if next_hop_data. amt_to_forward > msg. amount_msat {
2122- return_err ! ( "Upstream node sent less than we were supposed to receive in payment" , 19 , & byte_utils:: be64_to_array( msg. amount_msat) ) ;
2123- }
2124- // final_incorrect_cltv_expiry
2125- if next_hop_data. outgoing_cltv_value != msg. cltv_expiry {
2126- return_err ! ( "Upstream node set CLTV to the wrong value" , 18 , & byte_utils:: be32_to_array( msg. cltv_expiry) ) ;
2127- }
2128-
2129- let routing = match next_hop_data. format {
2130- msgs:: OnionHopDataFormat :: Legacy { .. } => return_err ! ( "We require payment_secrets" , 0x4000 |0x2000 |3 , & [ 0 ; 0 ] ) ,
2131- msgs:: OnionHopDataFormat :: NonFinalNode { .. } => return_err ! ( "Got non final data with an HMAC of 0" , 0x4000 | 22 , & [ 0 ; 0 ] ) ,
2132- msgs:: OnionHopDataFormat :: FinalNode { payment_data, keysend_preimage } => {
2133- if payment_data. is_some ( ) && keysend_preimage. is_some ( ) {
2134- return_err ! ( "We don't support MPP keysend payments" , 0x4000 |22 , & [ 0 ; 0 ] ) ;
2135- } else if let Some ( data) = payment_data {
2136- PendingHTLCRouting :: Receive {
2137- payment_data : data,
2138- incoming_cltv_expiry : msg. cltv_expiry ,
2139- }
2140- } else if let Some ( payment_preimage) = keysend_preimage {
2141- // We need to check that the sender knows the keysend preimage before processing this
2142- // payment further. Otherwise, an intermediary routing hop forwarding non-keysend-HTLC X
2143- // could discover the final destination of X, by probing the adjacent nodes on the route
2144- // with a keysend payment of identical payment hash to X and observing the processing
2145- // time discrepancies due to a hash collision with X.
2146- let hashed_preimage = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
2147- if hashed_preimage != msg. payment_hash {
2148- return_err ! ( "Payment preimage didn't match payment hash" , 0x4000 |22 , & [ 0 ; 0 ] ) ;
2149- }
2150-
2151- PendingHTLCRouting :: ReceiveKeysend {
2152- payment_preimage,
2153- incoming_cltv_expiry : msg. cltv_expiry ,
2154- }
2155- } else {
2156- return_err ! ( "We require payment_secrets" , 0x4000 |0x2000 |3 , & [ 0 ; 0 ] ) ;
2157- }
2213+ match self . construct_recv_pending_htlc_info ( next_hop_data, shared_secret, msg. payment_hash , msg. amount_msat , msg. cltv_expiry ) {
2214+ Ok ( info) => {
2215+ // Note that we could obviously respond immediately with an update_fulfill_htlc
2216+ // message, however that would leak that we are the recipient of this payment, so
2217+ // instead we stay symmetric with the forwarding case, only responding (after a
2218+ // delay) once they've send us a commitment_signed!
2219+ PendingHTLCStatus :: Forward ( info)
21582220 } ,
2159- } ;
2160-
2161- // Note that we could obviously respond immediately with an update_fulfill_htlc
2162- // message, however that would leak that we are the recipient of this payment, so
2163- // instead we stay symmetric with the forwarding case, only responding (after a
2164- // delay) once they've send us a commitment_signed!
2165-
2166- PendingHTLCStatus :: Forward ( PendingHTLCInfo {
2167- routing,
2168- payment_hash : msg. payment_hash . clone ( ) ,
2169- incoming_shared_secret : shared_secret,
2170- amt_to_forward : next_hop_data. amt_to_forward ,
2171- outgoing_cltv_value : next_hop_data. outgoing_cltv_value ,
2172- } )
2221+ Err ( ReceiveError { err_code, err_data, msg } ) => return_err ! ( msg, err_code, & err_data)
2222+ }
21732223 } ,
21742224 onion_utils:: Hop :: Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
21752225 let mut new_pubkey = msg. onion_routing_packet . public_key . unwrap ( ) ;
0 commit comments