@@ -28,8 +28,13 @@ use crate::offers::invoice_request::InvoiceRequest;
2828use crate :: offers:: nonce:: Nonce ;
2929use crate :: offers:: offer:: Offer ;
3030use crate :: offers:: static_invoice:: StaticInvoice ;
31- use crate :: onion_message:: async_payments:: { AsyncPaymentsMessage , AsyncPaymentsMessageHandler } ;
32- use crate :: onion_message:: messenger:: { Destination , MessageRouter , MessageSendInstructions } ;
31+ use crate :: onion_message:: async_payments:: {
32+ AsyncPaymentsMessage , AsyncPaymentsMessageHandler , DEFAULT_CONFIG_PATH_RELATIVE_EXPIRY ,
33+ REPLY_PATH_RELATIVE_EXPIRY ,
34+ } ;
35+ use crate :: onion_message:: messenger:: {
36+ Destination , MessageRouter , MessageSendInstructions , PeeledOnion ,
37+ } ;
3338use crate :: onion_message:: offers:: OffersMessage ;
3439use crate :: onion_message:: packet:: ParsedOnionMessageContents ;
3540use crate :: prelude:: * ;
@@ -1284,3 +1289,217 @@ fn expired_static_invoice_payment_path() {
12841289 1 ,
12851290 ) ;
12861291}
1292+
1293+ #[ cfg_attr( feature = "std" , ignore) ]
1294+ #[ test]
1295+ fn ignore_expired_static_invoice_server_message ( ) {
1296+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
1297+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
1298+ let new_persister_1;
1299+ let new_persister_2;
1300+ let new_chain_monitor_1;
1301+ let new_chain_monitor_2;
1302+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
1303+ let payee_node_deserialized_1;
1304+ let payee_node_deserialized_2;
1305+ let mut nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
1306+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 ) ;
1307+ let chan_id_1_2 =
1308+ create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 1_000_000 , 0 ) . 0 . channel_id ;
1309+
1310+ reload_payee_with_async_receive_cfg ! (
1311+ nodes[ 1 ] ,
1312+ nodes[ 2 ] ,
1313+ new_persister_1,
1314+ new_chain_monitor_1,
1315+ payee_node_deserialized_1,
1316+ & [ chan_id_1_2]
1317+ ) ;
1318+
1319+ // If we receive an offer_paths_request over an expired path, it should be ignored.
1320+ let offer_paths_req = nodes[ 2 ]
1321+ . onion_messenger
1322+ . next_onion_message_for_peer ( nodes[ 1 ] . node . get_our_node_id ( ) )
1323+ . unwrap ( ) ;
1324+ assert ! ( matches!(
1325+ nodes[ 1 ] . onion_messenger. peel_onion_message( & offer_paths_req) . unwrap( ) ,
1326+ PeeledOnion :: Receive (
1327+ ParsedOnionMessageContents :: AsyncPayments ( AsyncPaymentsMessage :: OfferPathsRequest ( _) ) ,
1328+ _,
1329+ _
1330+ )
1331+ ) ) ;
1332+ nodes[ 2 ] . onion_messenger . release_pending_msgs ( ) ; // Ignore redundant paths requests
1333+
1334+ let configured_path_absolute_expiry = ( nodes[ 1 ] . node . duration_since_epoch ( )
1335+ + DEFAULT_CONFIG_PATH_RELATIVE_EXPIRY )
1336+ . as_secs ( ) as u32 ;
1337+ let block = create_dummy_block (
1338+ nodes[ 1 ] . best_block_hash ( ) ,
1339+ configured_path_absolute_expiry + 1u32 ,
1340+ Vec :: new ( ) ,
1341+ ) ;
1342+ connect_block ( & nodes[ 1 ] , & block) ;
1343+ connect_block ( & nodes[ 2 ] , & block) ;
1344+
1345+ nodes[ 1 ]
1346+ . onion_messenger
1347+ . handle_onion_message ( nodes[ 2 ] . node . get_our_node_id ( ) , & offer_paths_req) ;
1348+ assert ! ( nodes[ 1 ]
1349+ . onion_messenger
1350+ . next_onion_message_for_peer( nodes[ 2 ] . node. get_our_node_id( ) )
1351+ . is_none( ) ) ;
1352+
1353+ // The payee's configured paths are expired, so reload them again with fresh paths.
1354+ reload_payee_with_async_receive_cfg ! (
1355+ nodes[ 1 ] ,
1356+ nodes[ 2 ] ,
1357+ new_persister_2,
1358+ new_chain_monitor_2,
1359+ payee_node_deserialized_2,
1360+ & [ chan_id_1_2]
1361+ ) ;
1362+
1363+ // If we receive an offer_paths message over an expired reply path, it should be ignored.
1364+ nodes[ 2 ] . node . timer_tick_occurred ( ) ;
1365+ let offer_paths_req = nodes[ 2 ]
1366+ . onion_messenger
1367+ . next_onion_message_for_peer ( nodes[ 1 ] . node . get_our_node_id ( ) )
1368+ . unwrap ( ) ;
1369+ nodes[ 2 ] . onion_messenger . release_pending_msgs ( ) ; // Ignore redundant paths requests
1370+ nodes[ 1 ]
1371+ . onion_messenger
1372+ . handle_onion_message ( nodes[ 2 ] . node . get_our_node_id ( ) , & offer_paths_req) ;
1373+ let offer_paths = nodes[ 1 ]
1374+ . onion_messenger
1375+ . next_onion_message_for_peer ( nodes[ 2 ] . node . get_our_node_id ( ) )
1376+ . unwrap ( ) ;
1377+ assert ! ( matches!(
1378+ nodes[ 2 ] . onion_messenger. peel_onion_message( & offer_paths) . unwrap( ) ,
1379+ PeeledOnion :: Receive (
1380+ ParsedOnionMessageContents :: AsyncPayments ( AsyncPaymentsMessage :: OfferPaths ( _) ) ,
1381+ _,
1382+ _
1383+ )
1384+ ) ) ;
1385+
1386+ let block = create_dummy_block (
1387+ nodes[ 2 ] . best_block_hash ( ) ,
1388+ ( nodes[ 2 ] . node . duration_since_epoch ( ) + REPLY_PATH_RELATIVE_EXPIRY ) . as_secs ( ) as u32 + 1u32 ,
1389+ Vec :: new ( ) ,
1390+ ) ;
1391+ connect_block ( & nodes[ 2 ] , & block) ;
1392+
1393+ nodes[ 2 ] . onion_messenger . handle_onion_message ( nodes[ 1 ] . node . get_our_node_id ( ) , & offer_paths) ;
1394+ assert ! ( nodes[ 2 ]
1395+ . onion_messenger
1396+ . next_onion_message_for_peer( nodes[ 1 ] . node. get_our_node_id( ) )
1397+ . is_none( ) ) ;
1398+
1399+ // If we receive a serve_static_invoice message over an expired reply path, it should be ignored.
1400+ nodes[ 2 ] . node . timer_tick_occurred ( ) ;
1401+ let offer_paths_req = nodes[ 2 ]
1402+ . onion_messenger
1403+ . next_onion_message_for_peer ( nodes[ 1 ] . node . get_our_node_id ( ) )
1404+ . unwrap ( ) ;
1405+ nodes[ 1 ]
1406+ . onion_messenger
1407+ . handle_onion_message ( nodes[ 2 ] . node . get_our_node_id ( ) , & offer_paths_req) ;
1408+ let offer_paths = nodes[ 1 ]
1409+ . onion_messenger
1410+ . next_onion_message_for_peer ( nodes[ 2 ] . node . get_our_node_id ( ) )
1411+ . unwrap ( ) ;
1412+ nodes[ 2 ] . onion_messenger . handle_onion_message ( nodes[ 1 ] . node . get_our_node_id ( ) , & offer_paths) ;
1413+ let serve_static_invoice = nodes[ 2 ]
1414+ . onion_messenger
1415+ . next_onion_message_for_peer ( nodes[ 1 ] . node . get_our_node_id ( ) )
1416+ . unwrap ( ) ;
1417+ assert ! ( matches!(
1418+ nodes[ 1 ] . onion_messenger. peel_onion_message( & serve_static_invoice) . unwrap( ) ,
1419+ PeeledOnion :: Receive (
1420+ ParsedOnionMessageContents :: AsyncPayments ( AsyncPaymentsMessage :: ServeStaticInvoice ( _) ) ,
1421+ _,
1422+ _
1423+ )
1424+ ) ) ;
1425+
1426+ let block = create_dummy_block (
1427+ nodes[ 1 ] . best_block_hash ( ) ,
1428+ ( nodes[ 1 ] . node . duration_since_epoch ( ) + REPLY_PATH_RELATIVE_EXPIRY ) . as_secs ( ) as u32 + 1u32 ,
1429+ Vec :: new ( ) ,
1430+ ) ;
1431+ connect_block ( & nodes[ 1 ] , & block) ;
1432+
1433+ nodes[ 1 ]
1434+ . onion_messenger
1435+ . handle_onion_message ( nodes[ 2 ] . node . get_our_node_id ( ) , & serve_static_invoice) ;
1436+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_events( ) . is_empty( ) ) ;
1437+ assert ! ( nodes[ 1 ]
1438+ . onion_messenger
1439+ . next_onion_message_for_peer( nodes[ 2 ] . node. get_our_node_id( ) )
1440+ . is_none( ) ) ;
1441+
1442+ // If we receive a static_invoice_persisted message to an expired path, it should be ignored.
1443+ nodes[ 2 ] . node . timer_tick_occurred ( ) ;
1444+ let offer_paths_req = nodes[ 2 ]
1445+ . onion_messenger
1446+ . next_onion_message_for_peer ( nodes[ 1 ] . node . get_our_node_id ( ) )
1447+ . unwrap ( ) ;
1448+ nodes[ 1 ]
1449+ . onion_messenger
1450+ . handle_onion_message ( nodes[ 2 ] . node . get_our_node_id ( ) , & offer_paths_req) ;
1451+ let offer_paths = nodes[ 1 ]
1452+ . onion_messenger
1453+ . next_onion_message_for_peer ( nodes[ 2 ] . node . get_our_node_id ( ) )
1454+ . unwrap ( ) ;
1455+ nodes[ 2 ] . onion_messenger . handle_onion_message ( nodes[ 1 ] . node . get_our_node_id ( ) , & offer_paths) ;
1456+ let serve_static_invoice = nodes[ 2 ]
1457+ . onion_messenger
1458+ . next_onion_message_for_peer ( nodes[ 1 ] . node . get_our_node_id ( ) )
1459+ . unwrap ( ) ;
1460+ nodes[ 1 ]
1461+ . onion_messenger
1462+ . handle_onion_message ( nodes[ 2 ] . node . get_our_node_id ( ) , & serve_static_invoice) ;
1463+ let mut events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
1464+ assert_eq ! ( events. len( ) , 1 ) ;
1465+ let ack_paths = match events. pop ( ) . unwrap ( ) {
1466+ Event :: PersistStaticInvoice { invoice_persisted_paths, .. } => invoice_persisted_paths,
1467+ _ => panic ! ( ) ,
1468+ } ;
1469+
1470+ nodes[ 1 ] . node . static_invoice_persisted ( ack_paths) . unwrap ( ) ;
1471+ let invoice_persisted = nodes[ 1 ]
1472+ . onion_messenger
1473+ . next_onion_message_for_peer ( nodes[ 2 ] . node . get_our_node_id ( ) )
1474+ . unwrap ( ) ;
1475+ assert ! ( matches!(
1476+ nodes[ 2 ] . onion_messenger. peel_onion_message( & invoice_persisted) . unwrap( ) ,
1477+ PeeledOnion :: Receive (
1478+ ParsedOnionMessageContents :: AsyncPayments (
1479+ AsyncPaymentsMessage :: StaticInvoicePersisted ( _)
1480+ ) ,
1481+ _,
1482+ _
1483+ )
1484+ ) ) ;
1485+
1486+ let block = create_dummy_block (
1487+ nodes[ 2 ] . best_block_hash ( ) ,
1488+ ( nodes[ 2 ] . node . duration_since_epoch ( ) + REPLY_PATH_RELATIVE_EXPIRY ) . as_secs ( ) as u32 + 1u32 ,
1489+ Vec :: new ( ) ,
1490+ ) ;
1491+ connect_block ( & nodes[ 1 ] , & block) ;
1492+ connect_block ( & nodes[ 2 ] , & block) ;
1493+ nodes[ 2 ]
1494+ . onion_messenger
1495+ . handle_onion_message ( nodes[ 1 ] . node . get_our_node_id ( ) , & invoice_persisted) ;
1496+ assert ! ( nodes[ 2 ] . node. get_cached_async_receive_offer( ) . is_none( ) ) ;
1497+
1498+ // The recipient won't try to ask for offer paths again as the maximum number of attempts has been
1499+ // exceeded.
1500+ nodes[ 2 ] . node . timer_tick_occurred ( ) ;
1501+ assert ! ( nodes[ 2 ]
1502+ . onion_messenger
1503+ . next_onion_message_for_peer( nodes[ 1 ] . node. get_our_node_id( ) )
1504+ . is_none( ) ) ;
1505+ }
0 commit comments