@@ -54,7 +54,7 @@ use crate::offers::invoice::Bolt12Invoice;
54
54
use crate :: offers:: invoice_error:: InvoiceError ;
55
55
use crate :: offers:: invoice_request:: { InvoiceRequest , InvoiceRequestFields } ;
56
56
use crate :: offers:: parse:: Bolt12SemanticError ;
57
- use crate :: onion_message:: messenger:: PeeledOnion ;
57
+ use crate :: onion_message:: messenger:: { Destination , PeeledOnion } ;
58
58
use crate :: onion_message:: offers:: OffersMessage ;
59
59
use crate :: onion_message:: packet:: ParsedOnionMessageContents ;
60
60
use crate :: routing:: gossip:: { NodeAlias , NodeId } ;
@@ -1070,6 +1070,266 @@ fn creates_refund_with_blinded_path_using_unannounced_introduction_node() {
1070
1070
}
1071
1071
}
1072
1072
1073
+ /// Check that authentication fails when an invoice request is handled using the wrong context
1074
+ /// (i.e., was sent directly or over an unexpected blinded path).
1075
+ #[ test]
1076
+ fn fails_authentication_when_handling_invoice_request ( ) {
1077
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
1078
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
1079
+
1080
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
1081
+ features. set_onion_messages_optional ( ) ;
1082
+ features. set_route_blinding_optional ( ) ;
1083
+
1084
+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
1085
+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
1086
+
1087
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
1088
+
1089
+ let node_chanmgrs = create_node_chanmgrs (
1090
+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
1091
+ ) ;
1092
+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
1093
+
1094
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
1095
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
1096
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
1097
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
1098
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
1099
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
1100
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
1101
+
1102
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
1103
+ let alice_id = alice. node . get_our_node_id ( ) ;
1104
+ let bob_id = bob. node . get_our_node_id ( ) ;
1105
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
1106
+ let david_id = david. node . get_our_node_id ( ) ;
1107
+
1108
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1109
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1110
+
1111
+ let offer = alice. node
1112
+ . create_offer_builder ( None )
1113
+ . unwrap ( )
1114
+ . amount_msats ( 10_000_000 )
1115
+ . build ( ) . unwrap ( ) ;
1116
+ assert_eq ! ( offer. metadata( ) , None ) ;
1117
+ assert_ne ! ( offer. signing_pubkey( ) , Some ( alice_id) ) ;
1118
+ assert ! ( !offer. paths( ) . is_empty( ) ) ;
1119
+ for path in offer. paths ( ) {
1120
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( bob_id) ) ;
1121
+ }
1122
+
1123
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1124
+ david. node . pay_for_offer ( & offer, None , None , None , payment_id, Retry :: Attempts ( 0 ) , None )
1125
+ . unwrap ( ) ;
1126
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1127
+
1128
+ // Send the invoice request directly to Alice instead of using a blinded path.
1129
+ connect_peers ( david, alice) ;
1130
+ #[ cfg( not( c_bindings) ) ] {
1131
+ david. node . pending_offers_messages . lock ( ) . unwrap ( ) . first_mut ( ) . unwrap ( ) . destination =
1132
+ Destination :: Node ( alice_id) ;
1133
+ }
1134
+ #[ cfg( c_bindings) ] {
1135
+ david. node . pending_offers_messages . lock ( ) . unwrap ( ) . first_mut ( ) . unwrap ( ) . 1 =
1136
+ Destination :: Node ( alice_id) ;
1137
+ }
1138
+
1139
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
1140
+ alice. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
1141
+
1142
+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
1143
+ assert_eq ! ( invoice_request. amount_msats( ) , None ) ;
1144
+ assert_ne ! ( invoice_request. payer_id( ) , david_id) ;
1145
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
1146
+
1147
+ assert_eq ! ( alice. onion_messenger. next_onion_message_for_peer( charlie_id) , None ) ;
1148
+ }
1149
+
1150
+ /// Check that authentication fails when an invoice is handled using the wrong context (i.e., was
1151
+ /// sent over an unexpected blinded path).
1152
+ #[ test]
1153
+ fn fails_authentication_when_handling_invoice_for_offer ( ) {
1154
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
1155
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
1156
+
1157
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
1158
+ features. set_onion_messages_optional ( ) ;
1159
+ features. set_route_blinding_optional ( ) ;
1160
+
1161
+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
1162
+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
1163
+
1164
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
1165
+
1166
+ let node_chanmgrs = create_node_chanmgrs (
1167
+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
1168
+ ) ;
1169
+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
1170
+
1171
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
1172
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
1173
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
1174
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
1175
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
1176
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
1177
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
1178
+
1179
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
1180
+ let alice_id = alice. node . get_our_node_id ( ) ;
1181
+ let bob_id = bob. node . get_our_node_id ( ) ;
1182
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
1183
+ let david_id = david. node . get_our_node_id ( ) ;
1184
+
1185
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1186
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1187
+
1188
+ let offer = alice. node
1189
+ . create_offer_builder ( None )
1190
+ . unwrap ( )
1191
+ . amount_msats ( 10_000_000 )
1192
+ . build ( ) . unwrap ( ) ;
1193
+ assert_ne ! ( offer. signing_pubkey( ) , Some ( alice_id) ) ;
1194
+ assert ! ( !offer. paths( ) . is_empty( ) ) ;
1195
+ for path in offer. paths ( ) {
1196
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( bob_id) ) ;
1197
+ }
1198
+
1199
+ // Initiate an invoice request, but abandon tracking it.
1200
+ let payment_id_255 = PaymentId ( [ 255 ; 32 ] ) ;
1201
+ david. node . pay_for_offer ( & offer, None , None , None , payment_id_255, Retry :: Attempts ( 0 ) , None )
1202
+ . unwrap ( ) ;
1203
+ david. node . abandon_payment ( payment_id_255) ;
1204
+ get_event ! ( david, Event :: InvoiceRequestFailed ) ;
1205
+
1206
+ // Don't send the invoice request, but grab its reply path to use with a different request.
1207
+ let invalid_reply_path = {
1208
+ let mut penidng_offers_messages = david. node . pending_offers_messages . lock ( ) . unwrap ( ) ;
1209
+ let pending_invoice_request = penidng_offers_messages. pop ( ) . unwrap ( ) ;
1210
+ penidng_offers_messages. clear ( ) ;
1211
+ #[ cfg( not( c_bindings) ) ] {
1212
+ pending_invoice_request. reply_path
1213
+ }
1214
+ #[ cfg( c_bindings) ] {
1215
+ pending_invoice_request. 2
1216
+ }
1217
+ } ;
1218
+
1219
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1220
+ david. node . pay_for_offer ( & offer, None , None , None , payment_id, Retry :: Attempts ( 0 ) , None )
1221
+ . unwrap ( ) ;
1222
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1223
+
1224
+ // Swap out the reply path to force authentication to fail when handling the invoice since it
1225
+ // will be sent over the wrong blinded path.
1226
+ {
1227
+ let mut penidng_offers_messages = david. node . pending_offers_messages . lock ( ) . unwrap ( ) ;
1228
+ let mut pending_invoice_request = penidng_offers_messages. first_mut ( ) . unwrap ( ) ;
1229
+ #[ cfg( not( c_bindings) ) ] {
1230
+ pending_invoice_request. reply_path = invalid_reply_path;
1231
+ }
1232
+ #[ cfg( c_bindings) ] {
1233
+ pending_invoice_request. 2 = invalid_reply_path;
1234
+ }
1235
+ }
1236
+
1237
+ connect_peers ( david, bob) ;
1238
+
1239
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
1240
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
1241
+
1242
+ connect_peers ( alice, charlie) ;
1243
+
1244
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
1245
+ alice. onion_messenger . handle_onion_message ( & bob_id, & onion_message) ;
1246
+
1247
+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
1248
+ assert_eq ! ( invoice_request. amount_msats( ) , None ) ;
1249
+ assert_ne ! ( invoice_request. payer_id( ) , david_id) ;
1250
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
1251
+
1252
+ let onion_message = alice. onion_messenger . next_onion_message_for_peer ( charlie_id) . unwrap ( ) ;
1253
+ charlie. onion_messenger . handle_onion_message ( & alice_id, & onion_message) ;
1254
+
1255
+ let onion_message = charlie. onion_messenger . next_onion_message_for_peer ( david_id) . unwrap ( ) ;
1256
+ david. onion_messenger . handle_onion_message ( & charlie_id, & onion_message) ;
1257
+
1258
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1259
+ }
1260
+
1261
+ /// Check that authentication fails when an invoice is handled using the wrong context (i.e., was
1262
+ /// sent directly or over an unexpected blinded path).
1263
+ #[ test]
1264
+ fn fails_authentication_when_handling_invoice_for_refund ( ) {
1265
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
1266
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
1267
+
1268
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
1269
+ features. set_onion_messages_optional ( ) ;
1270
+ features. set_route_blinding_optional ( ) ;
1271
+
1272
+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
1273
+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
1274
+
1275
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
1276
+
1277
+ let node_chanmgrs = create_node_chanmgrs (
1278
+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
1279
+ ) ;
1280
+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
1281
+
1282
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
1283
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
1284
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
1285
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
1286
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
1287
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
1288
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
1289
+
1290
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
1291
+ let alice_id = alice. node . get_our_node_id ( ) ;
1292
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
1293
+ let david_id = david. node . get_our_node_id ( ) ;
1294
+
1295
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1296
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1297
+
1298
+ let absolute_expiry = Duration :: from_secs ( u64:: MAX ) ;
1299
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1300
+ let refund = david. node
1301
+ . create_refund_builder ( 10_000_000 , absolute_expiry, payment_id, Retry :: Attempts ( 0 ) , None )
1302
+ . unwrap ( )
1303
+ . build ( ) . unwrap ( ) ;
1304
+ assert_ne ! ( refund. payer_id( ) , david_id) ;
1305
+ assert ! ( !refund. paths( ) . is_empty( ) ) ;
1306
+ for path in refund. paths ( ) {
1307
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
1308
+ }
1309
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1310
+
1311
+ let expected_invoice = alice. node . request_refund_payment ( & refund) . unwrap ( ) ;
1312
+
1313
+ // Send the invoice directly to David instead of using a blinded path.
1314
+ connect_peers ( david, alice) ;
1315
+ #[ cfg( not( c_bindings) ) ] {
1316
+ alice. node . pending_offers_messages . lock ( ) . unwrap ( ) . first_mut ( ) . unwrap ( ) . destination =
1317
+ Destination :: Node ( david_id) ;
1318
+ }
1319
+ #[ cfg( c_bindings) ] {
1320
+ alice. node . pending_offers_messages . lock ( ) . unwrap ( ) . first_mut ( ) . unwrap ( ) . 1 =
1321
+ Destination :: Node ( david_id) ;
1322
+ }
1323
+
1324
+ let onion_message = alice. onion_messenger . next_onion_message_for_peer ( david_id) . unwrap ( ) ;
1325
+ david. onion_messenger . handle_onion_message ( & alice_id, & onion_message) ;
1326
+
1327
+ let invoice = extract_invoice ( david, & onion_message) ;
1328
+ assert_eq ! ( invoice, expected_invoice) ;
1329
+
1330
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1331
+ }
1332
+
1073
1333
/// Fails creating or paying an offer when a blinded path cannot be created because no peers are
1074
1334
/// connected.
1075
1335
#[ test]
0 commit comments