Skip to content

Commit 95830ed

Browse files
author
Antoine Riard
committed
Add test_update_err_monitor_lockdown
This test tries the new lockdown logic in case of a signed-and-broadcast local commitment transaction while a concurrent ChannelMonitorUpdate for a next _local_ commitment is submitted from offchain. Update is rejected as expected with a ChannelMonitorUpdateErr.
1 parent 851ab92 commit 95830ed

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

lightning/src/ln/functional_tests.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
55
use chain::transaction::OutPoint;
66
use chain::keysinterface::{ChannelKeys, KeysInterface, SpendableOutputDescriptor};
7+
use chain::chaininterface;
78
use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil, BlockNotifier};
89
use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
910
use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure, BREAKDOWN_TIMEOUT};
1011
use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
12+
use ln::channelmonitor;
1113
use ln::channel::{Channel, ChannelError};
1214
use ln::{chan_utils, onion_utils};
1315
use ln::router::{Route, RouteHop};
@@ -7581,3 +7583,64 @@ fn test_simple_mpp() {
75817583
// ...but with the right secret we should be able to claim all the way back
75827584
claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage, Some(payment_secret), 200_000);
75837585
}
7586+
7587+
#[test]
7588+
fn test_update_err_monitor_lockdown() {
7589+
// Our monitor will lock update of local commitment transaction if a broadcastion condition
7590+
// has been fulfilled (either force-close from Channel or block height requiring a HTLC-
7591+
// timeout). Trying to update monitor after lockdown should return a ChannelMonitorUpdateErr.
7592+
//
7593+
// This scenario may happen in a watchtower setup, where watchtower process a block height
7594+
// triggering a timeout while a slow-block-processing ChannelManager receives a local signed
7595+
// commitment at same time.
7596+
7597+
let chanmon_cfgs = create_chanmon_cfgs(2);
7598+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
7599+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
7600+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
7601+
7602+
// Create some initial channel
7603+
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported());
7604+
let outpoint = OutPoint { txid: chan_1.3.txid(), index: 0 };
7605+
7606+
// Rebalance the network to generate htlc in the two directions
7607+
send_payment(&nodes[0], &vec!(&nodes[1])[..], 10_000_000, 10_000_000);
7608+
7609+
// Route a HTLC from node 0 to node 1 (but don't settle)
7610+
let preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
7611+
7612+
// Copy SimpleManyChannelMonitor to simulate a watchtower and update block height of node 0 until its ChannelMonitor timeout HTLC onchain
7613+
let logger = Arc::new(test_utils::TestLogger::with_id(format!("node {}", 0)));
7614+
let watchtower = {
7615+
let monitors = nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap();
7616+
let monitor = monitors.get(&outpoint).unwrap();
7617+
let mut w = test_utils::TestVecWriter(Vec::new());
7618+
monitor.write_for_disk(&mut w).unwrap();
7619+
let new_monitor = <(Sha256dHash, channelmonitor::ChannelMonitor<EnforcingChannelKeys>)>::read(
7620+
&mut ::std::io::Cursor::new(&w.0), Arc::new(test_utils::TestLogger::new())).unwrap().1;
7621+
assert!(new_monitor == *monitor);
7622+
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, logger.clone() as Arc<Logger>));
7623+
let watchtower = test_utils::TestChannelMonitor::new(chain_monitor, &chanmon_cfgs[0].tx_broadcaster, logger.clone(), &chanmon_cfgs[0].fee_estimator);
7624+
assert!(watchtower.add_monitor(outpoint, new_monitor).is_ok());
7625+
watchtower
7626+
};
7627+
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
7628+
watchtower.simple_monitor.block_connected(&header, 200, &vec![], &vec![]);
7629+
7630+
// Try to update ChannelMonitor
7631+
assert!(nodes[1].node.claim_funds(preimage, &None, 9_000_000));
7632+
check_added_monitors!(nodes[1], 1);
7633+
let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
7634+
assert_eq!(updates.update_fulfill_htlcs.len(), 1);
7635+
nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
7636+
if let Some(ref mut channel) = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2) {
7637+
if let Ok((_, _, _, update)) = channel.commitment_signed(&updates.commitment_signed, &node_cfgs[0].fee_estimator) {
7638+
if let Err(_) = watchtower.simple_monitor.update_monitor(outpoint, update.clone()) {} else { assert!(false); }
7639+
if let Ok(_) = nodes[0].chan_monitor.update_monitor(outpoint, update) {} else { assert!(false); }
7640+
} else { assert!(false); }
7641+
} else { assert!(false); };
7642+
// Our local monitor is in-sync and hasn't processed yet timeout
7643+
check_added_monitors!(nodes[0], 1);
7644+
let events = nodes[0].node.get_and_clear_pending_events();
7645+
assert_eq!(events.len(), 1);
7646+
}

0 commit comments

Comments
 (0)