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