Skip to content

Commit 27aced9

Browse files
committed
Add test for partial-send MPP due to monitor update failure
Relatively simple test that, after a monitor update fails, we get the right return value and continue with the bits of the MPP that did not send after the monitor updating is restored.
1 parent 6a6b17b commit 27aced9

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! here. See also the chanmon_fail_consistency fuzz test.
55
66
use chain::transaction::OutPoint;
7-
use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSendFailure};
7+
use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure};
88
use ln::channelmonitor::ChannelMonitorUpdateErr;
99
use ln::features::InitFeatures;
1010
use ln::msgs;
@@ -1762,3 +1762,53 @@ fn during_funding_monitor_fail() {
17621762
do_during_funding_monitor_fail(true, true, true, true, false);
17631763
do_during_funding_monitor_fail(true, true, false, false, false);
17641764
}
1765+
1766+
#[test]
1767+
fn test_path_paused_mpp() {
1768+
// Simple test of sending a multi-path payment where one path is currently blocked awaiting
1769+
// monitor update
1770+
let chanmon_cfgs = create_chanmon_cfgs(4);
1771+
let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
1772+
let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
1773+
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
1774+
1775+
let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
1776+
let (chan_2_ann, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::supported(), InitFeatures::supported());
1777+
let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
1778+
let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
1779+
1780+
let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
1781+
let payment_secret = PaymentSecret([0xdb; 32]);
1782+
let mut route = nodes[0].router.get_route(&nodes[3].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
1783+
let path = route.paths[0].clone();
1784+
route.paths.push(path);
1785+
route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
1786+
route.paths[0][0].short_channel_id = chan_1_id;
1787+
route.paths[0][1].short_channel_id = chan_3_id;
1788+
route.paths[1][0].pubkey = nodes[2].node.get_our_node_id();
1789+
route.paths[1][0].short_channel_id = chan_2_ann.contents.short_channel_id;
1790+
route.paths[1][1].short_channel_id = chan_4_id;
1791+
1792+
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
1793+
*nodes[0].chan_monitor.next_update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
1794+
1795+
if let Err(PaymentSendFailure::PartialFailure(fails)) = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)) {
1796+
assert_eq!(fails.len(), 2);
1797+
if let Ok(()) = fails[0] {} else { panic!(); }
1798+
if let Err(APIError::MonitorUpdateFailed) = fails[1] {} else { panic!(); }
1799+
} else { panic!(); }
1800+
check_added_monitors!(nodes[0], 2);
1801+
*nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(());
1802+
1803+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
1804+
assert_eq!(events.len(), 1);
1805+
pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 0, payment_hash.clone(), Some(payment_secret), events.pop().unwrap(), false);
1806+
1807+
let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2_id).unwrap().clone();
1808+
nodes[0].node.channel_monitor_updated(&outpoint, latest_update);
1809+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
1810+
assert_eq!(events.len(), 1);
1811+
pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash.clone(), Some(payment_secret), events.pop().unwrap(), true);
1812+
1813+
claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage, Some(payment_secret), 200_000);
1814+
}

lightning/src/util/test_utils.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub struct TestChannelMonitor<'a> {
5151
pub latest_monitor_update_id: Mutex<HashMap<[u8; 32], (OutPoint, u64)>>,
5252
pub simple_monitor: channelmonitor::SimpleManyChannelMonitor<OutPoint, EnforcingChannelKeys, &'a chaininterface::BroadcasterInterface, &'a TestFeeEstimator>,
5353
pub update_ret: Mutex<Result<(), channelmonitor::ChannelMonitorUpdateErr>>,
54+
// If this is set to Some(), after the next return, we'll always return this until update_ret
55+
// is changed:
56+
pub next_update_ret: Mutex<Option<Result<(), channelmonitor::ChannelMonitorUpdateErr>>>,
5457
}
5558
impl<'a> TestChannelMonitor<'a> {
5659
pub fn new(chain_monitor: Arc<chaininterface::ChainWatchInterface>, broadcaster: &'a chaininterface::BroadcasterInterface, logger: Arc<Logger>, fee_estimator: &'a TestFeeEstimator) -> Self {
@@ -59,6 +62,7 @@ impl<'a> TestChannelMonitor<'a> {
5962
latest_monitor_update_id: Mutex::new(HashMap::new()),
6063
simple_monitor: channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, fee_estimator),
6164
update_ret: Mutex::new(Ok(())),
65+
next_update_ret: Mutex::new(None),
6266
}
6367
}
6468
}
@@ -76,7 +80,12 @@ impl<'a> channelmonitor::ManyChannelMonitor<EnforcingChannelKeys> for TestChanne
7680
self.latest_monitor_update_id.lock().unwrap().insert(funding_txo.to_channel_id(), (funding_txo, monitor.get_latest_update_id()));
7781
self.added_monitors.lock().unwrap().push((funding_txo, monitor));
7882
assert!(self.simple_monitor.add_monitor(funding_txo, new_monitor).is_ok());
79-
self.update_ret.lock().unwrap().clone()
83+
84+
let ret = self.update_ret.lock().unwrap().clone();
85+
if let Some(next_ret) = self.next_update_ret.lock().unwrap().take() {
86+
*self.update_ret.lock().unwrap() = next_ret;
87+
}
88+
ret
8089
}
8190

8291
fn update_monitor(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
@@ -100,7 +109,12 @@ impl<'a> channelmonitor::ManyChannelMonitor<EnforcingChannelKeys> for TestChanne
100109
w.0.clear();
101110
monitor.write_for_watchtower(&mut w).unwrap(); // This at least shouldn't crash...
102111
self.added_monitors.lock().unwrap().push((funding_txo, new_monitor));
103-
self.update_ret.lock().unwrap().clone()
112+
113+
let ret = self.update_ret.lock().unwrap().clone();
114+
if let Some(next_ret) = self.next_update_ret.lock().unwrap().take() {
115+
*self.update_ret.lock().unwrap() = next_ret;
116+
}
117+
ret
104118
}
105119

106120
fn get_and_clear_pending_htlcs_updated(&self) -> Vec<HTLCUpdate> {

0 commit comments

Comments
 (0)