@@ -517,6 +517,12 @@ pub(super) enum HTLCFailReason {
517
517
}
518
518
}
519
519
520
+ struct ReceiveError {
521
+ err_code : u16 ,
522
+ err_data : Vec < u8 > ,
523
+ msg : & ' static str ,
524
+ }
525
+
520
526
/// Return value for claim_funds_from_hop
521
527
enum ClaimFundsFromHop {
522
528
PrevHopForceClosed ,
@@ -2038,6 +2044,102 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2038
2044
}
2039
2045
}
2040
2046
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
+
2041
2143
fn decode_update_add_htlc_onion ( & self , msg : & msgs:: UpdateAddHTLC ) -> ( PendingHTLCStatus , MutexGuard < ChannelHolder < Signer > > ) {
2042
2144
macro_rules! return_malformed_err {
2043
2145
( $msg: expr, $err_code: expr) => {
@@ -2103,68 +2205,16 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2103
2205
let pending_forward_info = match next_hop {
2104
2206
onion_utils:: Hop :: Receive ( next_hop_data) => {
2105
2207
// 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)
2153
2215
} ,
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
+ }
2168
2218
} ,
2169
2219
onion_utils:: Hop :: Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
2170
2220
let mut new_pubkey = msg. onion_routing_packet . public_key . unwrap ( ) ;
0 commit comments