Skip to content

Commit 1c6073b

Browse files
WIP: Test static invoice server
1 parent 8493fa0 commit 1c6073b

File tree

2 files changed

+222
-3
lines changed

2 files changed

+222
-3
lines changed

lightning/src/ln/async_payments_tests.rs

Lines changed: 221 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ use crate::offers::invoice_request::InvoiceRequest;
2828
use crate::offers::nonce::Nonce;
2929
use crate::offers::offer::Offer;
3030
use 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+
};
3338
use crate::onion_message::offers::OffersMessage;
3439
use crate::onion_message::packet::ParsedOnionMessageContents;
3540
use 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+
}

lightning/src/onion_message/messenger.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ where
15271527
}
15281528

15291529
#[cfg(test)]
1530-
pub(super) fn release_pending_msgs(&self) -> HashMap<PublicKey, VecDeque<OnionMessage>> {
1530+
pub(crate) fn release_pending_msgs(&self) -> HashMap<PublicKey, VecDeque<OnionMessage>> {
15311531
let mut message_recipients = self.message_recipients.lock().unwrap();
15321532
let mut msgs = new_hash_map();
15331533
// We don't want to disconnect the peers by removing them entirely from the original map, so we

0 commit comments

Comments
 (0)