Skip to content

Commit 2ee2a61

Browse files
committed
Add a test for asserting existing inflight amounts
1 parent 0dd6d73 commit 2ee2a61

File tree

1 file changed

+85
-7
lines changed

1 file changed

+85
-7
lines changed

lightning-invoice/src/payment.rs

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ mod tests {
801801
use lightning::ln::features::{ChannelFeatures, NodeFeatures, InitFeatures};
802802
use lightning::ln::functional_test_utils::*;
803803
use lightning::ln::msgs::{ChannelMessageHandler, ErrorAction, LightningError};
804-
use lightning::routing::gossip::NodeId;
804+
use lightning::routing::gossip::{EffectiveCapacity, NodeId};
805805
use lightning::routing::router::{PaymentParameters, Route, RouteHop};
806806
use lightning::routing::scoring::ChannelUsage;
807807
use lightning::util::test_utils::TestLogger;
@@ -1550,7 +1550,7 @@ mod tests {
15501550
}
15511551

15521552
#[test]
1553-
fn inflight_data_trivial_test() {
1553+
fn inflight_map_data_trivial_test() {
15541554
let event_handled = core::cell::RefCell::new(false);
15551555
let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
15561556

@@ -1590,7 +1590,57 @@ mod tests {
15901590
assert_eq!(inflight_map.get(&(2, true)), None);
15911591

15921592
// Second path should still be inflight
1593-
assert_eq!(inflight_map.get(&(1, true)).unwrap().clone(), 64);
1593+
assert_eq!(inflight_map.get(&(1, true)).unwrap().clone(), 64)
1594+
}
1595+
1596+
#[test]
1597+
fn inflight_usage_trivial_test() {
1598+
// First, let's just send a payment through, but only make sure one of the path completes
1599+
let event_handled = core::cell::RefCell::new(false);
1600+
let event_handler = |_: &_| { *event_handled.borrow_mut() = true; };
1601+
1602+
let payment_preimage = PaymentPreimage([1; 32]);
1603+
let payment_invoice = invoice(payment_preimage);
1604+
let payment_hash = Some(PaymentHash(payment_invoice.payment_hash().clone().into_inner()));
1605+
let final_value_msat = payment_invoice.amount_milli_satoshis().unwrap();
1606+
1607+
let payer = TestPayer::new()
1608+
.expect_send(Amount::ForInvoice(128))
1609+
.expect_send(Amount::ForInvoice(128));
1610+
let final_value_msat = payment_invoice.amount_milli_satoshis().unwrap();
1611+
let route = TestRouter::route_for_value(final_value_msat);
1612+
let router = TestRouter {};
1613+
let scorer = RefCell::new(TestScorer::new()
1614+
// 1st invoice, 1st path
1615+
.expect_usage(ChannelUsage { amount_msat: 10, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1616+
.expect_usage(ChannelUsage { amount_msat: 20, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1617+
.expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1618+
// 1st invoice, 2nd path
1619+
.expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1620+
// 2nd invoice, 1st path
1621+
.expect_usage(ChannelUsage { amount_msat: 10, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1622+
.expect_usage(ChannelUsage { amount_msat: 20, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1623+
.expect_usage(ChannelUsage { amount_msat: 64, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1624+
// 2nd invoice, 2nd path
1625+
.expect_usage(ChannelUsage { amount_msat: 128, inflight_htlc_msat: 0, effective_capacity: EffectiveCapacity::Unknown } )
1626+
);
1627+
let logger = TestLogger::new();
1628+
let invoice_payer =
1629+
InvoicePayer::new(&payer, router, &scorer, &logger, event_handler, Retry::Attempts(0));
1630+
1631+
// Succeed 1st path, leave 2nd path inflight
1632+
let payment_id = invoice_payer.pay_invoice(&payment_invoice).unwrap();
1633+
invoice_payer.handle_event(&Event::PaymentPathSuccessful {
1634+
payment_id, payment_hash, path: route.paths[0].clone()
1635+
});
1636+
1637+
// Let's pay a second invoice that will be using the same path. This should trigger the
1638+
// assertions that expect the last 4 ChannelUsage values above where TestScorer is initialized.
1639+
// Particularly, the 2nd path of the 1st payment, since it is not yet complete, should still
1640+
// have 64 msats inflight. Making the total inflight 128.
1641+
let payment_preimage_2 = PaymentPreimage([2; 32]);
1642+
let payment_invoice_2 = invoice(payment_preimage_2);
1643+
invoice_payer.pay_invoice(&payment_invoice_2).unwrap();
15941644
}
15951645

15961646
struct TestRouter;
@@ -1658,9 +1708,22 @@ mod tests {
16581708

16591709
impl Router for TestRouter {
16601710
fn find_route<S: Score>(
1661-
&self, _payer: &PublicKey, route_params: &RouteParameters, _payment_hash: &PaymentHash,
1662-
_first_hops: Option<&[&ChannelDetails]>, _scorer: &S
1711+
&self, payer: &PublicKey, route_params: &RouteParameters, _payment_hash: &PaymentHash,
1712+
_first_hops: Option<&[&ChannelDetails]>, scorer: &S
16631713
) -> Result<Route, LightningError> {
1714+
// Simulate calling the Scorer just as you would in find_route
1715+
let route = Self::route_for_value(route_params.final_value_msat);
1716+
for path in route.paths {
1717+
for hop in path {
1718+
let usage = ChannelUsage {
1719+
amount_msat: hop.fee_msat,
1720+
inflight_htlc_msat: 0,
1721+
effective_capacity: EffectiveCapacity::Unknown,
1722+
};
1723+
scorer.channel_penalty_msat(hop.short_channel_id, &NodeId::from_pubkey(payer), &NodeId::from_pubkey(&hop.pubkey), usage);
1724+
}
1725+
}
1726+
16641727
Ok(Route {
16651728
payment_params: Some(route_params.payment_params.clone()), ..Self::route_for_value(route_params.final_value_msat)
16661729
})
@@ -1680,6 +1743,7 @@ mod tests {
16801743

16811744
struct TestScorer {
16821745
expectations: Option<VecDeque<TestResult>>,
1746+
scorer_expectations: RefCell<VecDeque<ChannelUsage>>,
16831747
}
16841748

16851749
#[derive(Debug)]
@@ -1694,13 +1758,19 @@ mod tests {
16941758
fn new() -> Self {
16951759
Self {
16961760
expectations: None,
1761+
scorer_expectations: RefCell::new(VecDeque::new()),
16971762
}
16981763
}
16991764

17001765
fn expect(mut self, expectation: TestResult) -> Self {
17011766
self.expectations.get_or_insert_with(|| VecDeque::new()).push_back(expectation);
17021767
self
17031768
}
1769+
1770+
fn expect_usage(self, expectation: ChannelUsage) -> Self {
1771+
self.scorer_expectations.borrow_mut().push_back(expectation);
1772+
self
1773+
}
17041774
}
17051775

17061776
#[cfg(c_bindings)]
@@ -1710,8 +1780,16 @@ mod tests {
17101780

17111781
impl Score for TestScorer {
17121782
fn channel_penalty_msat(
1713-
&self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, _usage: ChannelUsage
1714-
) -> u64 { 0 }
1783+
&self, _short_channel_id: u64, _source: &NodeId, _target: &NodeId, usage: ChannelUsage
1784+
) -> u64 {
1785+
match self.scorer_expectations.borrow_mut().pop_front() {
1786+
Some(expectation) => {
1787+
assert_eq!(expectation.amount_msat, usage.amount_msat);
1788+
},
1789+
None => {},
1790+
}
1791+
0
1792+
}
17151793

17161794
fn payment_path_failed(&mut self, actual_path: &[&RouteHop], actual_short_channel_id: u64) {
17171795
if let Some(expectations) = &mut self.expectations {

0 commit comments

Comments
 (0)