Skip to content

Commit 4e4ca11

Browse files
Add phantom invoice route hints filtering tests
1 parent 34167d1 commit 4e4ca11

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

lightning-invoice/src/utils.rs

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,4 +737,194 @@ mod test {
737737
_ => panic!("Unexpected event")
738738
}
739739
}
740+
741+
#[test]
742+
fn test_multi_node_hints_includes_single_public_channels_to_participating_nodes() {
743+
let mut chanmon_cfgs = create_chanmon_cfgs(3);
744+
let seed_1 = [42 as u8; 32];
745+
let seed_2 = [43 as u8; 32];
746+
let cross_node_seed = [44 as u8; 32];
747+
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed);
748+
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
749+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
750+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
751+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
752+
let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
753+
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_0_1.1);
754+
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_1.0);
755+
let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
756+
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_0_2.1);
757+
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_2.0);
758+
759+
let payment_amt = 10_000;
760+
let (_, payment_hash, payment_secret) = {
761+
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
762+
let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
763+
(payment_preimage, payment_hash, payment_secret)
764+
};
765+
let route_hints = vec![
766+
nodes[1].node.get_phantom_route_hints(),
767+
nodes[2].node.get_phantom_route_hints(),
768+
];
769+
let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt), "test".to_string(), payment_hash, payment_secret, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
770+
771+
let hints = invoice.private_routes();
772+
assert_eq!(hints.len(), 2);
773+
774+
let mut short_chan_ids = HashSet::new();
775+
short_chan_ids.insert(chan_0_1.0.contents.short_channel_id.clone());
776+
short_chan_ids.insert(chan_0_2.0.contents.short_channel_id.clone());
777+
for hint in hints {
778+
let hint_short_chan_id = hint.0.0[0].short_channel_id;
779+
assert!(short_chan_ids.contains(&hint_short_chan_id));
780+
short_chan_ids.remove(&hint_short_chan_id);
781+
}
782+
}
783+
784+
#[test]
785+
fn test_multi_node_hints_has_only_highest_inbound_capacity_channel() {
786+
let mut chanmon_cfgs = create_chanmon_cfgs(3);
787+
let seed_1 = [42 as u8; 32];
788+
let seed_2 = [43 as u8; 32];
789+
let cross_node_seed = [44 as u8; 32];
790+
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed);
791+
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
792+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
793+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
794+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
795+
let chan_0_1_low_inbound_capacity = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
796+
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_0_1_low_inbound_capacity.1);
797+
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_1_low_inbound_capacity.0);
798+
let chan_0_1_high_inbound_capacity = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 0, InitFeatures::known(), InitFeatures::known());
799+
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_0_1_high_inbound_capacity.1);
800+
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_1_high_inbound_capacity.0);
801+
let chan_0_1_medium_inbound_capacity = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
802+
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_0_1_medium_inbound_capacity.1);
803+
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_1_medium_inbound_capacity.0);
804+
let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
805+
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_0_2.1);
806+
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_2.0);
807+
808+
let payment_amt = 10_000;
809+
let (_, payment_hash, payment_secret) = {
810+
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
811+
let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
812+
(payment_preimage, payment_hash, payment_secret)
813+
};
814+
let route_hints = vec![
815+
nodes[1].node.get_phantom_route_hints(),
816+
nodes[2].node.get_phantom_route_hints(),
817+
];
818+
let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt), "test".to_string(), payment_hash, payment_secret, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
819+
820+
let hints = invoice.private_routes();
821+
assert_eq!(hints.len(), 2);
822+
823+
let mut short_chan_ids = HashSet::new();
824+
short_chan_ids.insert(chan_0_1_high_inbound_capacity.0.contents.short_channel_id.clone());
825+
short_chan_ids.insert(chan_0_2.0.contents.short_channel_id.clone());
826+
for hint in hints {
827+
let hint_short_chan_id = hint.0.0[0].short_channel_id;
828+
assert!(short_chan_ids.contains(&hint_short_chan_id));
829+
short_chan_ids.remove(&hint_short_chan_id);
830+
}
831+
}
832+
833+
#[test]
834+
fn test_multi_node_hints_has_no_channels_with_lower_inbound_capacity_than_invoice_amt() {
835+
let mut chanmon_cfgs = create_chanmon_cfgs(3);
836+
let seed_1 = [42 as u8; 32];
837+
let seed_2 = [43 as u8; 32];
838+
let cross_node_seed = [44 as u8; 32];
839+
chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed);
840+
chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
841+
let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
842+
let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
843+
let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
844+
let chan_0_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 0, InitFeatures::known(), InitFeatures::known());
845+
nodes[0].node.handle_channel_update(&nodes[1].node.get_our_node_id(), &chan_0_1.1);
846+
nodes[1].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_1.0);
847+
let chan_0_2 = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1_000_000, 0, InitFeatures::known(), InitFeatures::known());
848+
nodes[0].node.handle_channel_update(&nodes[2].node.get_our_node_id(), &chan_0_2.1);
849+
nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_2.0);
850+
851+
// 1 msat above chan_0_1's inbound capacity
852+
let payment_amt_99_000_001_msat = 99_000_001;
853+
let (_, payment_hash_99_000_001_msat, payment_secret_99_000_001_msat) = {
854+
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt_99_000_001_msat), 3600).unwrap();
855+
let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
856+
(payment_preimage, payment_hash, payment_secret)
857+
};
858+
859+
let route_hints_99_000_001_msat = vec![
860+
nodes[1].node.get_phantom_route_hints(),
861+
nodes[2].node.get_phantom_route_hints(),
862+
];
863+
864+
let invoice_99_000_001_msat = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt_99_000_001_msat), "test".to_string(), payment_hash_99_000_001_msat, payment_secret_99_000_001_msat, route_hints_99_000_001_msat, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
865+
866+
let hints_99_000_001_msat = invoice_99_000_001_msat.private_routes();
867+
assert_eq!(hints_99_000_001_msat.len(), 1);
868+
869+
let mut short_chan_ids_99_000_001_msat = HashSet::new();
870+
short_chan_ids_99_000_001_msat.insert(chan_0_2.0.contents.short_channel_id.clone());
871+
for hint in hints_99_000_001_msat {
872+
let hint_short_chan_id = hint.0.0[0].short_channel_id;
873+
assert!(short_chan_ids_99_000_001_msat.contains(&hint_short_chan_id));
874+
short_chan_ids_99_000_001_msat.remove(&hint_short_chan_id);
875+
}
876+
877+
// Exactly at chan_0_1's inbound capacity
878+
let payment_amt_99_000_000_msat = 99_000_000;
879+
let (_, payment_hash_99_000_000_msat, payment_secret_99_000_000_msat) = {
880+
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt_99_000_000_msat), 3600).unwrap();
881+
let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
882+
(payment_preimage, payment_hash, payment_secret)
883+
};
884+
885+
let route_hints_99_000_000_msat = vec![
886+
nodes[1].node.get_phantom_route_hints(),
887+
nodes[2].node.get_phantom_route_hints(),
888+
];
889+
890+
let invoice_99_000_000_msat = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt_99_000_000_msat), "test".to_string(), payment_hash_99_000_000_msat, payment_secret_99_000_000_msat, route_hints_99_000_000_msat, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
891+
892+
let hints_99_000_000_msat = invoice_99_000_000_msat.private_routes();
893+
assert_eq!(hints_99_000_000_msat.len(), 2);
894+
895+
let mut short_chan_ids_99_000_000_msat = HashSet::new();
896+
short_chan_ids_99_000_000_msat.insert(chan_0_1.0.contents.short_channel_id.clone());
897+
short_chan_ids_99_000_000_msat.insert(chan_0_2.0.contents.short_channel_id.clone());
898+
for hint in hints_99_000_000_msat {
899+
let hint_short_chan_id = hint.0.0[0].short_channel_id;
900+
assert!(short_chan_ids_99_000_000_msat.contains(&hint_short_chan_id));
901+
short_chan_ids_99_000_000_msat.remove(&hint_short_chan_id);
902+
}
903+
904+
// An invoice with no specified amount should include all participating nodes in the hints.
905+
let (_, payment_hash_no_specified_amount, payment_secret_no_specified_amount) = {
906+
let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(None, 3600).unwrap();
907+
let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
908+
(payment_preimage, payment_hash, payment_secret)
909+
};
910+
911+
let route_hints_no_specified_amount = vec![
912+
nodes[1].node.get_phantom_route_hints(),
913+
nodes[2].node.get_phantom_route_hints(),
914+
];
915+
916+
let invoice_no_specified_amount = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(None, "test".to_string(), payment_hash_no_specified_amount, payment_secret_no_specified_amount, route_hints_no_specified_amount, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
917+
918+
let hints_no_specified_amount = invoice_no_specified_amount.private_routes();
919+
assert_eq!(hints_no_specified_amount.len(), 2);
920+
921+
let mut short_chan_ids_no_specified_amount = HashSet::new();
922+
short_chan_ids_no_specified_amount.insert(chan_0_1.0.contents.short_channel_id.clone());
923+
short_chan_ids_no_specified_amount.insert(chan_0_2.0.contents.short_channel_id.clone());
924+
for hint in hints_no_specified_amount {
925+
let hint_short_chan_id = hint.0.0[0].short_channel_id;
926+
assert!(short_chan_ids_no_specified_amount.contains(&hint_short_chan_id));
927+
short_chan_ids_no_specified_amount.remove(&hint_short_chan_id);
928+
}
929+
}
740930
}

0 commit comments

Comments
 (0)