Skip to content

Commit b3ff257

Browse files
committed
Rework chain::Watch return types to make async updates less scary
When a `chain::Watch` `ChannelMonitor` update method is called, the user has three options: (a) persist the monitor update immediately and return success, (b) fail to persist the monitor update immediately and return failure, (c) return a flag indicating the monitor update is in progress and will complete in the future. (c) is rather harmless, and in some deployments should be expected to be the return value for all monitor update calls, but currently requires returning `Err(ChannelMonitorUpdateErr::TemporaryFailure)` which isn't very descriptive and sounds scarier than it is. Instead, here, we change the return type used to be a single enum (rather than a Result) and rename `TemporaryFailure` `UpdateInProgress`.
1 parent 1fdfc7f commit b3ff257

16 files changed

+421
-361
lines changed

fuzz/src/chanmon_consistency.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
3030
use bitcoin::hash_types::{BlockHash, WPubkeyHash};
3131

3232
use lightning::chain;
33-
use lightning::chain::{BestBlock, ChannelMonitorUpdateErr, chainmonitor, channelmonitor, Confirm, Watch};
33+
use lightning::chain::{BestBlock, ChannelMonitorUpdateResult, chainmonitor, channelmonitor, Confirm, Watch};
3434
use lightning::chain::channelmonitor::{ChannelMonitor, MonitorEvent};
3535
use lightning::chain::transaction::OutPoint;
3636
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
@@ -122,7 +122,7 @@ impl TestChainMonitor {
122122
}
123123
}
124124
impl chain::Watch<EnforcingSigner> for TestChainMonitor {
125-
fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<EnforcingSigner>) -> Result<(), chain::ChannelMonitorUpdateErr> {
125+
fn watch_channel(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor<EnforcingSigner>) -> chain::ChannelMonitorUpdateResult {
126126
let mut ser = VecWriter(Vec::new());
127127
monitor.write(&mut ser).unwrap();
128128
if let Some(_) = self.latest_monitors.lock().unwrap().insert(funding_txo, (monitor.get_latest_update_id(), ser.0)) {
@@ -132,7 +132,7 @@ impl chain::Watch<EnforcingSigner> for TestChainMonitor {
132132
self.chain_monitor.watch_channel(funding_txo, monitor)
133133
}
134134

135-
fn update_channel(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), chain::ChannelMonitorUpdateErr> {
135+
fn update_channel(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> chain::ChannelMonitorUpdateResult {
136136
let mut map_lock = self.latest_monitors.lock().unwrap();
137137
let mut map_entry = match map_lock.entry(funding_txo) {
138138
hash_map::Entry::Occupied(entry) => entry,
@@ -353,7 +353,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
353353
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
354354
let keys_manager = Arc::new(KeyProvider { node_id: $node_id, rand_bytes_id: atomic::AtomicU32::new(0), enforcement_states: Mutex::new(HashMap::new()) });
355355
let monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), $fee_estimator.clone(),
356-
Arc::new(TestPersister { update_ret: Mutex::new(Ok(())) }), Arc::clone(&keys_manager)));
356+
Arc::new(TestPersister {
357+
update_ret: Mutex::new(ChannelMonitorUpdateResult::UpdateComplete)
358+
}), Arc::clone(&keys_manager)));
357359

358360
let mut config = UserConfig::default();
359361
config.channel_config.forwarding_fee_proportional_millionths = 0;
@@ -373,7 +375,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
373375
let keys_manager = Arc::clone(& $keys_manager);
374376
let logger: Arc<dyn Logger> = Arc::new(test_logger::TestLogger::new($node_id.to_string(), out.clone()));
375377
let chain_monitor = Arc::new(TestChainMonitor::new(broadcast.clone(), logger.clone(), $fee_estimator.clone(),
376-
Arc::new(TestPersister { update_ret: Mutex::new(Ok(())) }), Arc::clone(& $keys_manager)));
378+
Arc::new(TestPersister {
379+
update_ret: Mutex::new(ChannelMonitorUpdateResult::UpdateComplete)
380+
}), Arc::clone(& $keys_manager)));
377381

378382
let mut config = UserConfig::default();
379383
config.channel_config.forwarding_fee_proportional_millionths = 0;
@@ -402,7 +406,8 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
402406

403407
let res = (<(BlockHash, ChanMan)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, chain_monitor.clone());
404408
for (funding_txo, mon) in monitors.drain() {
405-
assert!(chain_monitor.chain_monitor.watch_channel(funding_txo, mon).is_ok());
409+
assert_eq!(chain_monitor.chain_monitor.watch_channel(funding_txo, mon),
410+
ChannelMonitorUpdateResult::UpdateComplete);
406411
}
407412
res
408413
} }
@@ -878,12 +883,12 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
878883
// bit-twiddling mutations to have similar effects. This is probably overkill, but no
879884
// harm in doing so.
880885

881-
0x00 => *monitor_a.persister.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure),
882-
0x01 => *monitor_b.persister.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure),
883-
0x02 => *monitor_c.persister.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure),
884-
0x04 => *monitor_a.persister.update_ret.lock().unwrap() = Ok(()),
885-
0x05 => *monitor_b.persister.update_ret.lock().unwrap() = Ok(()),
886-
0x06 => *monitor_c.persister.update_ret.lock().unwrap() = Ok(()),
886+
0x00 => *monitor_a.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateInProgress,
887+
0x01 => *monitor_b.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateInProgress,
888+
0x02 => *monitor_c.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateInProgress,
889+
0x04 => *monitor_a.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateComplete,
890+
0x05 => *monitor_b.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateComplete,
891+
0x06 => *monitor_c.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateComplete,
887892

888893
0x08 => {
889894
if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) {
@@ -1108,9 +1113,9 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
11081113
// after we resolve all pending events.
11091114
// First make sure there are no pending monitor updates, resetting the error state
11101115
// and calling force_channel_monitor_updated for each monitor.
1111-
*monitor_a.persister.update_ret.lock().unwrap() = Ok(());
1112-
*monitor_b.persister.update_ret.lock().unwrap() = Ok(());
1113-
*monitor_c.persister.update_ret.lock().unwrap() = Ok(());
1116+
*monitor_a.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateComplete;
1117+
*monitor_b.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateComplete;
1118+
*monitor_c.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateResult::UpdateComplete;
11141119

11151120
if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) {
11161121
monitor_a.chain_monitor.force_channel_monitor_updated(chan_1_funding, *id);

fuzz/src/full_stack.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
2727
use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
2828

2929
use lightning::chain;
30-
use lightning::chain::{BestBlock, Confirm, Listen};
30+
use lightning::chain::{BestBlock, ChannelMonitorUpdateResult, Confirm, Listen};
3131
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
3232
use lightning::chain::chainmonitor;
3333
use lightning::chain::transaction::OutPoint;
@@ -378,7 +378,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
378378

379379
let broadcast = Arc::new(TestBroadcaster{ txn_broadcasted: Mutex::new(Vec::new()) });
380380
let monitor = Arc::new(chainmonitor::ChainMonitor::new(None, broadcast.clone(), Arc::clone(&logger), fee_est.clone(),
381-
Arc::new(TestPersister { update_ret: Mutex::new(Ok(())) })));
381+
Arc::new(TestPersister { update_ret: Mutex::new(ChannelMonitorUpdateResult::UpdateComplete) })));
382382

383383
let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone(), inbound_payment_key: KeyMaterial(inbound_payment_key.try_into().unwrap()), counter: AtomicU64::new(0) });
384384
let mut config = UserConfig::default();

fuzz/src/utils/test_persister.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ use lightning::util::enforcing_trait_impls::EnforcingSigner;
77
use std::sync::Mutex;
88

99
pub struct TestPersister {
10-
pub update_ret: Mutex<Result<(), chain::ChannelMonitorUpdateErr>>,
10+
pub update_ret: Mutex<chain::ChannelMonitorUpdateResult>,
1111
}
1212
impl chainmonitor::Persist<EnforcingSigner> for TestPersister {
13-
fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>, _update_id: MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> {
13+
fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateResult {
1414
self.update_ret.lock().unwrap().clone()
1515
}
1616

17-
fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: &Option<channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>, _update_id: MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> {
17+
fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: &Option<channelmonitor::ChannelMonitorUpdate>, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>, _update_id: MonitorUpdateId) -> chain::ChannelMonitorUpdateResult {
1818
self.update_ret.lock().unwrap().clone()
1919
}
2020
}

lightning-persister/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ mod tests {
135135
use bitcoin::blockdata::block::{Block, BlockHeader};
136136
use bitcoin::hashes::hex::FromHex;
137137
use bitcoin::Txid;
138-
use lightning::chain::ChannelMonitorUpdateErr;
138+
use lightning::chain::ChannelMonitorUpdateResult;
139139
use lightning::chain::chainmonitor::Persist;
140140
use lightning::chain::transaction::OutPoint;
141141
use lightning::{check_closed_broadcast, check_closed_event, check_added_monitors};
@@ -266,7 +266,7 @@ mod tests {
266266
index: 0
267267
};
268268
match persister.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) {
269-
Err(ChannelMonitorUpdateErr::PermanentFailure) => {},
269+
ChannelMonitorUpdateResult::PermanentFailure => {},
270270
_ => panic!("unexpected result from persisting new channel")
271271
}
272272

@@ -303,7 +303,7 @@ mod tests {
303303
index: 0
304304
};
305305
match persister.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) {
306-
Err(ChannelMonitorUpdateErr::PermanentFailure) => {},
306+
ChannelMonitorUpdateResult::PermanentFailure => {},
307307
_ => panic!("unexpected result from persisting new channel")
308308
}
309309

0 commit comments

Comments
 (0)