@@ -518,6 +518,12 @@ pub(super) enum HTLCFailReason {
518
518
}
519
519
}
520
520
521
+ struct ReceiveError {
522
+ err_code : u16 ,
523
+ err_data : Vec < u8 > ,
524
+ msg : & ' static str ,
525
+ }
526
+
521
527
/// Return value for claim_funds_from_hop
522
528
enum ClaimFundsFromHop {
523
529
PrevHopForceClosed ,
@@ -2043,6 +2049,102 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2043
2049
}
2044
2050
}
2045
2051
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
+
2046
2148
fn decode_update_add_htlc_onion ( & self , msg : & msgs:: UpdateAddHTLC ) -> ( PendingHTLCStatus , MutexGuard < ChannelHolder < Signer > > ) {
2047
2149
macro_rules! return_malformed_err {
2048
2150
( $msg: expr, $err_code: expr) => {
@@ -2108,68 +2210,16 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2108
2210
let pending_forward_info = match next_hop {
2109
2211
onion_utils:: Hop :: Receive ( next_hop_data) => {
2110
2212
// 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)
2158
2220
} ,
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
+ }
2173
2223
} ,
2174
2224
onion_utils:: Hop :: Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
2175
2225
let mut new_pubkey = msg. onion_routing_packet . public_key . unwrap ( ) ;
0 commit comments