Skip to content

Commit 937f854

Browse files
committed
Start publishing PersistClaimInfo event.
Indicates that [`ClaimInfo`] may be durably persisted to reduce `ChannelMonitor` in-memory size.
1 parent 3dab464 commit 937f854

6 files changed

Lines changed: 126 additions & 11 deletions

File tree

lightning/src/chain/chainmonitor.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,15 @@ where
841841
self.event_notifier.notify();
842842
}
843843

844+
#[cfg(any(test, feature = "_test_utils"))]
845+
pub fn get_and_clear_claim_info_events(&self) -> Vec<events::Event> {
846+
let mut res = Vec::new();
847+
for (_, monitor) in self.monitors.read().unwrap().iter() {
848+
res.append(&mut monitor.monitor.get_and_clear_claim_info_events());
849+
}
850+
res
851+
}
852+
844853
#[cfg(any(test, feature = "_test_utils"))]
845854
pub fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
846855
use crate::events::EventsProvider;

lightning/src/chain/channelmonitor.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,6 +2320,21 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
23202320
ret
23212321
}
23222322

2323+
#[cfg(any(test, feature = "_test_utils"))]
2324+
pub fn get_and_clear_claim_info_events(&self) -> Vec<Event> {
2325+
let mut res = Vec::new();
2326+
let mut inner = self.inner.lock().unwrap();
2327+
inner.pending_events.retain(|ev| {
2328+
if let Event::PersistClaimInfo { .. } = ev {
2329+
res.push(ev.clone());
2330+
false
2331+
} else {
2332+
true
2333+
}
2334+
});
2335+
res
2336+
}
2337+
23232338
/// Gets the counterparty's initial commitment transaction. The returned commitment
23242339
/// transaction is unsigned. This is intended to be called during the initial persistence of
23252340
/// the monitor (inside an implementation of [`Persist::persist_new_channel`]), to allow for
@@ -3557,6 +3572,13 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
35573572
} else {
35583573
assert!(cfg!(fuzzing), "Commitment txids are unique outside of fuzzing, where hashes can collide");
35593574
}
3575+
let htlcs = funding.counterparty_claimable_outpoints.get(&txid).unwrap().iter().map(|(htlc, _)| htlc.clone()).collect();
3576+
self.pending_events.push(Event::PersistClaimInfo {
3577+
funding_txo: funding.funding_outpoint().into_bitcoin_outpoint(),
3578+
channel_id: self.channel_id,
3579+
claim_key: ClaimKey(txid),
3580+
claim_info: ClaimInfo { htlcs },
3581+
})
35603582
}
35613583
};
35623584
core::iter::once(&mut self.funding).chain(&mut self.pending_funding).for_each(prune_htlc_sources);

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ fn test_monitor_and_persister_update_fail() {
9494
(nodes[0].keys_manager, nodes[0].keys_manager),
9595
)
9696
.unwrap();
97+
// Compare events separately since we don't ever persist [`Event::PersistClaimInfo`] event.
98+
let events = monitor.get_and_clear_pending_events();
99+
let new_events = new_monitor.get_and_clear_pending_events();
100+
assert_eq!(new_events, events);
97101
assert!(new_monitor == *monitor);
98102
new_monitor
99103
};
@@ -3546,7 +3550,7 @@ fn do_test_blocked_chan_preimage_release(completion_mode: BlockedUpdateComplMode
35463550

35473551
// The event processing should release the last RAA update.
35483552
// It should also generate the next update for nodes[2].
3549-
check_added_monitors(&nodes[1], 2);
3553+
check_added_monitors_with_claim_info_events(&nodes[1], 2, 1);
35503554
let mut bs_htlc_fulfill = get_htlc_update_msgs(&nodes[1], &node_c_id);
35513555
check_added_monitors(&nodes[1], 0);
35523556

lightning/src/ln/functional_test_utils.rs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! nodes for functional tests.
1212
1313
use crate::blinded_path::payment::DummyTlvs;
14-
use crate::chain::channelmonitor::{ChannelMonitor, HTLC_FAIL_BACK_BUFFER};
14+
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER};
1515
use crate::chain::transaction::OutPoint;
1616
use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
1717
use crate::events::bump_transaction::sync::BumpTransactionEventHandlerSync;
@@ -1267,11 +1267,72 @@ pub fn commit_tx_fee_msat(
12671267

12681268
/// Check whether N channel monitor(s) have been added.
12691269
pub fn check_added_monitors<CM: AChannelManager, H: NodeHolder<CM = CM>>(node: &H, count: usize) {
1270+
do_check_added_monitors(node, count, None);
1271+
}
1272+
1273+
pub fn check_added_monitors_with_claim_info_events<CM: AChannelManager, H: NodeHolder<CM = CM>>(
1274+
node: &H, count: usize, expected_claim_info_events: usize,
1275+
) {
1276+
do_check_added_monitors(node, count, Some(expected_claim_info_events));
1277+
}
1278+
1279+
pub fn do_check_added_monitors<CM: AChannelManager, H: NodeHolder<CM = CM>>(
1280+
node: &H, count: usize, expected_claim_info_events: Option<usize>,
1281+
) {
12701282
if let Some(chain_monitor) = node.chain_monitor() {
1271-
let mut added_monitors = chain_monitor.added_monitors.lock().unwrap();
1283+
let added_monitors = chain_monitor.added_monitors.lock().unwrap().split_off(0);
12721284
let n = added_monitors.len();
1285+
let mut channels_with_commitment_secrets = new_hash_set();
1286+
let commitment_secret_updates = added_monitors
1287+
.iter()
1288+
.map(|(channel_id, _, updates_opt)| {
1289+
if let Some(updates) = updates_opt {
1290+
let is_commitment_secret = |update: &&ChannelMonitorUpdateStep| {
1291+
matches!(update, ChannelMonitorUpdateStep::CommitmentSecret { .. })
1292+
};
1293+
let count = updates.updates.iter().filter(is_commitment_secret).count();
1294+
if count > 0 {
1295+
channels_with_commitment_secrets.insert(*channel_id);
1296+
}
1297+
count
1298+
} else {
1299+
0
1300+
}
1301+
})
1302+
.sum();
1303+
let mut added_claim_info_events: usize = 0;
1304+
if commitment_secret_updates > 0 {
1305+
let persist_claim_info_events =
1306+
chain_monitor.chain_monitor.get_and_clear_claim_info_events();
1307+
added_claim_info_events += persist_claim_info_events.len();
1308+
1309+
let mut seen_channel_fundings = new_hash_set();
1310+
let mut claim_info_channel_ids = new_hash_set();
1311+
for event in persist_claim_info_events {
1312+
match event {
1313+
Event::PersistClaimInfo { channel_id, funding_txo, claim_key, claim_info } => {
1314+
assert!(seen_channel_fundings.insert(funding_txo));
1315+
claim_info_channel_ids.insert(channel_id);
1316+
let mut persisted_claim_infos =
1317+
chain_monitor.persisted_claim_infos.lock().unwrap();
1318+
let persist_key = (channel_id, claim_key);
1319+
persisted_claim_infos.insert(persist_key, claim_info);
1320+
},
1321+
_ => panic!(),
1322+
}
1323+
}
1324+
assert_eq!(claim_info_channel_ids, channels_with_commitment_secrets);
1325+
}
1326+
1327+
if let Some(expected_claim_info_events) = expected_claim_info_events {
1328+
assert_eq!(added_claim_info_events, expected_claim_info_events);
1329+
} else {
1330+
// Each CommitmentSecret update produces one PersistClaimInfo event per
1331+
// active funding. For spliced channels with a pending funding, this means
1332+
// more claim info events than commitment secret updates.
1333+
assert!(added_claim_info_events >= commitment_secret_updates);
1334+
}
12731335
assert_eq!(n, count, "expected {} monitors to be added, not {}", count, n);
1274-
added_monitors.clear();
12751336
}
12761337
}
12771338

lightning/src/ln/functional_tests.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7385,6 +7385,10 @@ pub fn test_update_err_monitor_lockdown() {
73857385
)
73867386
.unwrap()
73877387
.1;
7388+
// Compare events separately since we don't ever persist [`Event::PersistClaimInfo`] event.
7389+
let events = monitor.get_and_clear_pending_events();
7390+
let new_events = new_monitor.get_and_clear_pending_events();
7391+
assert_eq!(new_events, events);
73887392
assert!(new_monitor == *monitor);
73897393
new_monitor
73907394
};
@@ -7493,6 +7497,10 @@ pub fn test_concurrent_monitor_claim() {
74937497
)
74947498
.unwrap()
74957499
.1;
7500+
// Compare events separately since we don't ever persist [`Event::PersistClaimInfo`] event.
7501+
let events = monitor.get_and_clear_pending_events();
7502+
let new_events = new_monitor.get_and_clear_pending_events();
7503+
assert_eq!(new_events, events);
74967504
assert!(new_monitor == *monitor);
74977505
new_monitor
74987506
};
@@ -7543,6 +7551,10 @@ pub fn test_concurrent_monitor_claim() {
75437551
)
75447552
.unwrap()
75457553
.1;
7554+
// Compare events separately since we don't ever persist [`Event::PersistClaimInfo`] event.
7555+
let events = monitor.get_and_clear_pending_events();
7556+
let new_events = new_monitor.get_and_clear_pending_events();
7557+
assert_eq!(new_events, events);
75467558
assert!(new_monitor == *monitor);
75477559
new_monitor
75487560
};
@@ -10010,7 +10022,7 @@ fn do_test_multi_post_event_actions(do_reload: bool) {
1001010022
// After the events are processed, the ChannelMonitorUpdates will be released and, upon their
1001110023
// completion, we'll respond to nodes[1] with an RAA + CS.
1001210024
get_revoke_commit_msgs(&nodes[0], &node_b_id);
10013-
check_added_monitors(&nodes[0], 3);
10025+
check_added_monitors_with_claim_info_events(&nodes[0], 3, 2);
1001410026
}
1001510027

1001610028
#[xtest(feature = "_externalize_tests")]

lightning/src/util/test_utils.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use crate::chain::chaininterface::FEERATE_FLOOR_SATS_PER_KW;
1717
use crate::chain::chaininterface::{ConfirmationTarget, TransactionType};
1818
use crate::chain::chainmonitor::{ChainMonitor, Persist};
1919
use crate::chain::channelmonitor::{
20-
ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, MonitorEvent,
20+
ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, ClaimInfo, ClaimKey,
21+
MonitorEvent,
2122
};
2223
use crate::chain::transaction::OutPoint;
2324
use crate::chain::WatchedOutput;
@@ -495,7 +496,8 @@ impl<T: chaininterface::BroadcasterInterface> SyncBroadcaster for T {}
495496
impl<T: Persist<TestChannelSigner>> SyncPersist for T {}
496497

497498
pub struct TestChainMonitor<'a> {
498-
pub added_monitors: Mutex<Vec<(ChannelId, ChannelMonitor<TestChannelSigner>)>>,
499+
pub added_monitors:
500+
Mutex<Vec<(ChannelId, ChannelMonitor<TestChannelSigner>, Option<ChannelMonitorUpdate>)>>,
499501
pub monitor_updates: Mutex<HashMap<ChannelId, Vec<ChannelMonitorUpdate>>>,
500502
pub latest_monitor_update_id: Mutex<HashMap<ChannelId, (u64, u64)>>,
501503
pub chain_monitor: ChainMonitor<
@@ -507,6 +509,7 @@ pub struct TestChainMonitor<'a> {
507509
&'a dyn SyncPersist,
508510
&'a TestKeysInterface,
509511
>,
512+
pub persisted_claim_infos: Mutex<HashMap<(ChannelId, ClaimKey), ClaimInfo>>,
510513
pub keys_manager: &'a TestKeysInterface,
511514
/// If this is set to Some(), the next update_channel call (not watch_channel) must be a
512515
/// ChannelForceClosed event for the given channel_id with should_broadcast set to the given
@@ -537,6 +540,7 @@ impl<'a> TestChainMonitor<'a> {
537540
keys_manager,
538541
keys_manager.get_peer_storage_key(),
539542
),
543+
persisted_claim_infos: Mutex::new(new_hash_map()),
540544
keys_manager,
541545
expect_channel_force_closed: Mutex::new(None),
542546
expect_monitor_round_trip_fail: Mutex::new(None),
@@ -577,7 +581,7 @@ impl<'a> TestChainMonitor<'a> {
577581
.lock()
578582
.unwrap()
579583
.insert(channel_id, (monitor.get_latest_update_id(), monitor.get_latest_update_id()));
580-
self.added_monitors.lock().unwrap().push((channel_id, monitor));
584+
self.added_monitors.lock().unwrap().push((channel_id, monitor, None));
581585
self.chain_monitor.load_existing_monitor(channel_id, new_monitor)
582586
}
583587

@@ -611,7 +615,7 @@ impl<'a> chain::Watch<TestChannelSigner> for TestChainMonitor<'a> {
611615
.lock()
612616
.unwrap()
613617
.insert(channel_id, (monitor.get_latest_update_id(), monitor.get_latest_update_id()));
614-
self.added_monitors.lock().unwrap().push((channel_id, monitor));
618+
self.added_monitors.lock().unwrap().push((channel_id, monitor, None));
615619
self.chain_monitor.watch_channel(channel_id, new_monitor)
616620
}
617621

@@ -666,9 +670,12 @@ impl<'a> chain::Watch<TestChannelSigner> for TestChainMonitor<'a> {
666670
assert_eq!(chan_id, channel_id);
667671
assert!(new_monitor != *monitor);
668672
} else {
669-
assert!(new_monitor == *monitor);
673+
let expected_monitor = monitor.clone();
674+
// Compare without [`Event::PersistClaimInfo`] events since we don't persist them.
675+
expected_monitor.get_and_clear_claim_info_events();
676+
assert!(new_monitor == expected_monitor);
670677
}
671-
self.added_monitors.lock().unwrap().push((channel_id, new_monitor));
678+
self.added_monitors.lock().unwrap().push((channel_id, new_monitor, Some(update.clone())));
672679
update_res
673680
}
674681

0 commit comments

Comments
 (0)