7
7
// You may not use this file except in accordance with one or both of these
8
8
// licenses.
9
9
10
- use bitcoin:: secp256k1:: Secp256k1 ;
10
+ use bitcoin:: secp256k1:: { Secp256k1 , SecretKey } ;
11
11
use crate :: blinded_path:: BlindedPath ;
12
12
use crate :: blinded_path:: payment:: { ForwardNode , ForwardTlvs , PaymentConstraints , PaymentRelay , ReceiveTlvs } ;
13
13
use crate :: events:: MessageSendEventsProvider ;
@@ -16,6 +16,7 @@ use crate::ln::channelmanager::{PaymentId, RecipientOnionFields};
16
16
use crate :: ln:: features:: BlindedHopFeatures ;
17
17
use crate :: ln:: functional_test_utils:: * ;
18
18
use crate :: ln:: msgs:: ChannelMessageHandler ;
19
+ use crate :: ln:: onion_utils;
19
20
use crate :: ln:: onion_utils:: INVALID_ONION_BLINDING ;
20
21
use crate :: ln:: outbound_payment:: Retry ;
21
22
use crate :: prelude:: * ;
@@ -113,14 +114,29 @@ fn mpp_to_one_hop_blinded_path() {
113
114
claim_payment_along_route ( & nodes[ 0 ] , expected_route, false , payment_preimage) ;
114
115
}
115
116
117
+ enum ForwardCheckFail {
118
+ // Fail a check on the inbound onion payload. In this case, we underflow when calculating the
119
+ // outgoing cltv_expiry.
120
+ InboundOnionCheck ,
121
+ // The forwarding node's payload is encoded as a receive, i.e. the next hop HMAC is [0; 32].
122
+ ForwardPayloadEncodedAsReceive ,
123
+ }
124
+
116
125
#[ test]
117
126
fn forward_checks_failure ( ) {
127
+ do_forward_checks_failure ( ForwardCheckFail :: InboundOnionCheck ) ;
128
+ do_forward_checks_failure ( ForwardCheckFail :: ForwardPayloadEncodedAsReceive ) ;
129
+ }
130
+
131
+ fn do_forward_checks_failure ( check : ForwardCheckFail ) {
118
132
// Ensure we'll fail backwards properly if a forwarding check fails on initial update_add
119
133
// receipt.
120
134
let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
121
135
let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
122
136
let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
123
- let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
137
+ let mut nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
138
+ // We need the session priv to construct a bogus onion packet later.
139
+ * nodes[ 0 ] . keys_manager . override_random_bytes . lock ( ) . unwrap ( ) = Some ( [ 3 ; 32 ] ) ;
124
140
create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
125
141
let chan_upd_1_2 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) . 0 . contents ;
126
142
@@ -158,6 +174,8 @@ fn forward_checks_failure() {
158
174
159
175
let route_params = RouteParameters :: from_payment_params_and_value (
160
176
PaymentParameters :: blinded ( vec ! [ blinded_path] ) , amt_msat) ;
177
+ let route = get_route ( & nodes[ 0 ] , & route_params) . unwrap ( ) ;
178
+ node_cfgs[ 0 ] . router . expect_find_route ( route_params. clone ( ) , Ok ( route. clone ( ) ) ) ;
161
179
nodes[ 0 ] . node . send_payment ( payment_hash, RecipientOnionFields :: spontaneous_empty ( ) , PaymentId ( payment_hash. 0 ) , route_params, Retry :: Attempts ( 0 ) ) . unwrap ( ) ;
162
180
check_added_monitors ( & nodes[ 0 ] , 1 ) ;
163
181
@@ -167,7 +185,22 @@ fn forward_checks_failure() {
167
185
let mut payment_event = SendEvent :: from_event ( ev) ;
168
186
169
187
let mut update_add = & mut payment_event. msgs [ 0 ] ;
170
- update_add. cltv_expiry = 10 ; // causes outbound CLTV expiry to underflow
188
+ match check {
189
+ ForwardCheckFail :: InboundOnionCheck => {
190
+ update_add. cltv_expiry = 10 ; // causes outbound CLTV expiry to underflow
191
+ } ,
192
+ ForwardCheckFail :: ForwardPayloadEncodedAsReceive => {
193
+ let session_priv = SecretKey :: from_slice ( & [ 3 ; 32 ] ) . unwrap ( ) ;
194
+ let onion_keys = onion_utils:: construct_onion_keys ( & Secp256k1 :: new ( ) , & route. paths [ 0 ] , & session_priv) . unwrap ( ) ;
195
+ let cur_height = nodes[ 0 ] . best_block_info ( ) . 1 ;
196
+ let ( mut onion_payloads, ..) = onion_utils:: build_onion_payloads (
197
+ & route. paths [ 0 ] , amt_msat, RecipientOnionFields :: spontaneous_empty ( ) , cur_height, & None ) . unwrap ( ) ;
198
+ // Remove the receive payload so the blinded forward payload is encoded as a final payload
199
+ // (i.e. next_hop_hmac == [0; 32])
200
+ onion_payloads. pop ( ) ;
201
+ update_add. onion_routing_packet = onion_utils:: construct_onion_packet ( onion_payloads, onion_keys, [ 0 ; 32 ] , & payment_hash) . unwrap ( ) ;
202
+ } ,
203
+ }
171
204
nodes[ 1 ] . node . handle_update_add_htlc ( & nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event. msgs [ 0 ] ) ;
172
205
check_added_monitors ! ( nodes[ 1 ] , 0 ) ;
173
206
do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 0 ] , & payment_event. commitment_msg , true , true ) ;
0 commit comments