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