From f827adda8d57d1548d683afba961cd65f615823f Mon Sep 17 00:00:00 2001 From: jurvis Date: Wed, 17 Aug 2022 22:51:36 -0700 Subject: [PATCH] [wip] Add multihop correctness test for correct_inflight_map_from_path --- lightning-invoice/src/payment.rs | 79 +++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/lightning-invoice/src/payment.rs b/lightning-invoice/src/payment.rs index 07c89bccb25..bf386b48113 100644 --- a/lightning-invoice/src/payment.rs +++ b/lightning-invoice/src/payment.rs @@ -682,8 +682,8 @@ where // hardcoded with an inflight value of 0 so that we can correctly represent the first hop // in our sliding window of two. let our_node_id: PublicKey = self.payer.node_id(); - let reversed_hops_with_payer = core::iter::once((0u64, our_node_id)).chain( - path.split_last().unwrap().1.iter().map(|hop| (hop.fee_msat, hop.pubkey))).rev(); + let reversed_hops_with_payer: Vec<(u64, PublicKey)> = core::iter::once((0u64, our_node_id)).chain( + path.split_last().unwrap().1.iter().map(|hop| (hop.fee_msat, hop.pubkey))).rev().collect(); let mut cumulative_msat = path.last().unwrap().fee_msat; // Taking the reversed vector from above, we zip it with just the reversed hops list to @@ -1555,6 +1555,32 @@ mod tests { invoice_payer.handle_event(&event); } + #[test] + fn correct_inflight_map_from_path() { + let event_handled = core::cell::RefCell::new(false); + let event_handler = |_: &_| { *event_handled.borrow_mut() = true; }; + + let final_value_msat = 128u64; + let payer = TestPayer::new() + .expect_send(Amount::ForInvoice(final_value_msat)); + let router = TestMultiHopRouter {}; + let scorer = RefCell::new(TestScorer::new()); + let logger = TestLogger::new(); + let invoice_payer = + InvoicePayer::new(&payer, router, &scorer, &logger, event_handler, Retry::Attempts(2)); + + let payment_preimage = PaymentPreimage([1; 32]); + let invoice = invoice(payment_preimage); + let payment_hash = PaymentHash(invoice.payment_hash().clone().into_inner()); + + let payment_id = Some(invoice_payer.pay_invoice(&invoice).unwrap()); + + let inflight_map = invoice_payer.create_inflight_map(&payment_hash); + assert_eq!(inflight_map.get(&(0u64, true)).unwrap().clone(), 158u64); + assert_eq!(inflight_map.get(&(1u64, true)).unwrap().clone(), 148u64); + assert_eq!(inflight_map.get(&(2u64, true)).unwrap().clone(), 128u64); + } + struct TestRouter; impl TestRouter { @@ -1620,6 +1646,55 @@ mod tests { } } + struct TestMultiHopRouter; + + impl TestMultiHopRouter { + // Constructs the following route: + // Alice -(0,10)-> Bob -(0, 20)-> Charlie -(0, 130)-> Dina + fn route_for_value(final_value_msat: u64) -> Route { + Route { + paths: vec![vec![ + RouteHop{ + pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(), + channel_features: ChannelFeatures::empty(), + node_features: NodeFeatures::empty(), + short_channel_id: 0, + fee_msat: 10, + cltv_expiry_delta: 0 + }, + RouteHop{ + pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(), + channel_features: ChannelFeatures::empty(), + node_features: NodeFeatures::empty(), + short_channel_id: 1, + fee_msat: 20, + cltv_expiry_delta: 0 + }, + RouteHop{ + pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(), + channel_features: ChannelFeatures::empty(), + node_features: NodeFeatures::empty(), + short_channel_id: 2, + fee_msat: final_value_msat, + cltv_expiry_delta: 0 + }, + ]], + payment_params: None, + } + } + } + + impl Router for TestMultiHopRouter { + fn find_route( + &self, _payer: &PublicKey, route_params: &RouteParameters, _payment_hash: &PaymentHash, + _first_hops: Option<&[&ChannelDetails]>, _scorer: &S + ) -> Result { + Ok(Route { + payment_params: Some(route_params.payment_params.clone()), ..Self::route_for_value(route_params.final_value_msat) + }) + } + } + struct TestScorer { expectations: Option>, }