@@ -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,244 @@ 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
+ david. node . pending_offers_messages . lock ( ) . unwrap ( ) . first_mut ( ) . unwrap ( ) . destination =
1131
+ Destination :: Node ( alice_id) ;
1132
+
1133
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
1134
+ alice. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
1135
+
1136
+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
1137
+ assert_eq ! ( invoice_request. amount_msats( ) , None ) ;
1138
+ assert_ne ! ( invoice_request. payer_id( ) , david_id) ;
1139
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
1140
+
1141
+ assert_eq ! ( alice. onion_messenger. next_onion_message_for_peer( charlie_id) , None ) ;
1142
+ }
1143
+
1144
+ /// Check that authentication fails when an invoice is handled using the wrong context (i.e., was
1145
+ /// sent over an unexpected blinded path).
1146
+ #[ test]
1147
+ fn fails_authentication_when_handling_invoice_for_offer ( ) {
1148
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
1149
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
1150
+
1151
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
1152
+ features. set_onion_messages_optional ( ) ;
1153
+ features. set_route_blinding_optional ( ) ;
1154
+
1155
+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
1156
+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
1157
+
1158
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
1159
+
1160
+ let node_chanmgrs = create_node_chanmgrs (
1161
+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
1162
+ ) ;
1163
+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
1164
+
1165
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
1166
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
1167
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
1168
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
1169
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
1170
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
1171
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
1172
+
1173
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
1174
+ let alice_id = alice. node . get_our_node_id ( ) ;
1175
+ let bob_id = bob. node . get_our_node_id ( ) ;
1176
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
1177
+ let david_id = david. node . get_our_node_id ( ) ;
1178
+
1179
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1180
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1181
+
1182
+ let offer = alice. node
1183
+ . create_offer_builder ( None )
1184
+ . unwrap ( )
1185
+ . amount_msats ( 10_000_000 )
1186
+ . build ( ) . unwrap ( ) ;
1187
+ assert_ne ! ( offer. signing_pubkey( ) , Some ( alice_id) ) ;
1188
+ assert ! ( !offer. paths( ) . is_empty( ) ) ;
1189
+ for path in offer. paths ( ) {
1190
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( bob_id) ) ;
1191
+ }
1192
+
1193
+ // Initiate an invoice request, but abandon tracking it.
1194
+ let payment_id_255 = PaymentId ( [ 255 ; 32 ] ) ;
1195
+ david. node . pay_for_offer ( & offer, None , None , None , payment_id_255, Retry :: Attempts ( 0 ) , None )
1196
+ . unwrap ( ) ;
1197
+ david. node . abandon_payment ( payment_id_255) ;
1198
+ get_event ! ( david, Event :: InvoiceRequestFailed ) ;
1199
+
1200
+ // Don't send the invoice request, but grab its reply path to use with a different request.
1201
+ let invalid_reply_path = {
1202
+ let mut penidng_offers_messages = david. node . pending_offers_messages . lock ( ) . unwrap ( ) ;
1203
+ let pending_invoice_request = penidng_offers_messages. pop ( ) . unwrap ( ) ;
1204
+ penidng_offers_messages. clear ( ) ;
1205
+ pending_invoice_request. reply_path
1206
+ } ;
1207
+
1208
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1209
+ david. node . pay_for_offer ( & offer, None , None , None , payment_id, Retry :: Attempts ( 0 ) , None )
1210
+ . unwrap ( ) ;
1211
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1212
+
1213
+ // Swap out the reply path to force authentication to fail when handling the invoice since it
1214
+ // will be sent over the wrong blinded path.
1215
+ {
1216
+ let mut penidng_offers_messages = david. node . pending_offers_messages . lock ( ) . unwrap ( ) ;
1217
+ let mut pending_invoice_request = penidng_offers_messages. first_mut ( ) . unwrap ( ) ;
1218
+ pending_invoice_request. reply_path = invalid_reply_path;
1219
+ }
1220
+
1221
+ connect_peers ( david, bob) ;
1222
+
1223
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
1224
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
1225
+
1226
+ connect_peers ( alice, charlie) ;
1227
+
1228
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
1229
+ alice. onion_messenger . handle_onion_message ( & bob_id, & onion_message) ;
1230
+
1231
+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
1232
+ assert_eq ! ( invoice_request. amount_msats( ) , None ) ;
1233
+ assert_ne ! ( invoice_request. payer_id( ) , david_id) ;
1234
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
1235
+
1236
+ let onion_message = alice. onion_messenger . next_onion_message_for_peer ( charlie_id) . unwrap ( ) ;
1237
+ charlie. onion_messenger . handle_onion_message ( & alice_id, & onion_message) ;
1238
+
1239
+ let onion_message = charlie. onion_messenger . next_onion_message_for_peer ( david_id) . unwrap ( ) ;
1240
+ david. onion_messenger . handle_onion_message ( & charlie_id, & onion_message) ;
1241
+
1242
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1243
+ }
1244
+
1245
+ /// Check that authentication fails when an invoice is handled using the wrong context (i.e., was
1246
+ /// sent directly or over an unexpected blinded path).
1247
+ #[ test]
1248
+ fn fails_authentication_when_handling_invoice_for_refund ( ) {
1249
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
1250
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
1251
+
1252
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
1253
+ features. set_onion_messages_optional ( ) ;
1254
+ features. set_route_blinding_optional ( ) ;
1255
+
1256
+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
1257
+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
1258
+
1259
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
1260
+
1261
+ let node_chanmgrs = create_node_chanmgrs (
1262
+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
1263
+ ) ;
1264
+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
1265
+
1266
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
1267
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
1268
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
1269
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
1270
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
1271
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
1272
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
1273
+
1274
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
1275
+ let alice_id = alice. node . get_our_node_id ( ) ;
1276
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
1277
+ let david_id = david. node . get_our_node_id ( ) ;
1278
+
1279
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1280
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1281
+
1282
+ let absolute_expiry = Duration :: from_secs ( u64:: MAX ) ;
1283
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1284
+ let refund = david. node
1285
+ . create_refund_builder ( 10_000_000 , absolute_expiry, payment_id, Retry :: Attempts ( 0 ) , None )
1286
+ . unwrap ( )
1287
+ . build ( ) . unwrap ( ) ;
1288
+ assert_ne ! ( refund. payer_id( ) , david_id) ;
1289
+ assert ! ( !refund. paths( ) . is_empty( ) ) ;
1290
+ for path in refund. paths ( ) {
1291
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
1292
+ }
1293
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1294
+
1295
+ let expected_invoice = alice. node . request_refund_payment ( & refund) . unwrap ( ) ;
1296
+
1297
+ // Send the invoice directly to David instead of using a blinded path.
1298
+ connect_peers ( david, alice) ;
1299
+ alice. node . pending_offers_messages . lock ( ) . unwrap ( ) . first_mut ( ) . unwrap ( ) . destination =
1300
+ Destination :: Node ( david_id) ;
1301
+
1302
+ let onion_message = alice. onion_messenger . next_onion_message_for_peer ( david_id) . unwrap ( ) ;
1303
+ david. onion_messenger . handle_onion_message ( & alice_id, & onion_message) ;
1304
+
1305
+ let invoice = extract_invoice ( david, & onion_message) ;
1306
+ assert_eq ! ( invoice, expected_invoice) ;
1307
+
1308
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1309
+ }
1310
+
1073
1311
/// Fails creating or paying an offer when a blinded path cannot be created because no peers are
1074
1312
/// connected.
1075
1313
#[ test]
0 commit comments