Skip to content

Commit 37beb4c

Browse files
committed
(XXX: fuzz) Rm ChannelMonitor merge capabilities in favor of explicit add/update
This removes the ability to merge ChannelMonitors in favor of explicit ChannelMonitorUpdates. It further removes ChannelManager::test_restore_channel_monitor in favor of the new ChannelManager::channel_monitor_updated method, which explicitly confirms a set of updates instead of providing the latest copy of each ChannelMonitor to the user. This removes almost all need for Channels to have the latest channel_monitor, except for broadcasting the latest local state.
1 parent c25cd7c commit 37beb4c

7 files changed

+112
-263
lines changed

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 81 additions & 60 deletions
Large diffs are not rendered by default.

lightning/src/ln/channelmanager.rs

Lines changed: 5 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ pub type SimpleRefChannelManager<'a, M> = ChannelManager<InMemoryChannelKeys, &'
336336
///
337337
/// Note that you can be a bit lazier about writing out ChannelManager than you can be with
338338
/// ChannelMonitors. With ChannelMonitors you MUST write each monitor update out to disk before
339-
/// returning from ManyChannelMonitor::add_update_monitor, with ChannelManagers, writing updates
339+
/// returning from ManyChannelMonitor::add_/update_monitor, with ChannelManagers, writing updates
340340
/// happens out-of-band (and will prevent any other ChannelManager operations from occurring during
341341
/// the serialization process). If the deserialized version is out-of-date compared to the
342342
/// ChannelMonitors passed by reference to read(), those channels will be force-closed based on the
@@ -1388,8 +1388,8 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
13881388
}
13891389
};
13901390
// Because we have exclusive ownership of the channel here we can release the channel_state
1391-
// lock before add_update_monitor
1392-
if let Err(e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
1391+
// lock before add_monitor
1392+
if let Err(e) = self.monitor.add_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
13931393
match e {
13941394
ChannelMonitorUpdateErr::PermanentFailure => {
13951395
match handle_error!(self, Err(MsgHandleErrInternal::from_finish_shutdown("ChannelMonitor storage failure", *temporary_channel_id, chan.force_shutdown(), None)), chan.get_their_node_id()) {
@@ -2081,117 +2081,6 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
20812081
}
20822082
}
20832083

2084-
/// Used to restore channels to normal operation after a
2085-
/// ChannelMonitorUpdateErr::TemporaryFailure was returned from a channel monitor update
2086-
/// operation.
2087-
pub fn test_restore_channel_monitor(&self) {
2088-
let mut close_results = Vec::new();
2089-
let mut htlc_forwards = Vec::new();
2090-
let mut htlc_failures = Vec::new();
2091-
let mut pending_events = Vec::new();
2092-
let _ = self.total_consistency_lock.read().unwrap();
2093-
2094-
{
2095-
let mut channel_lock = self.channel_state.lock().unwrap();
2096-
let channel_state = &mut *channel_lock;
2097-
let short_to_id = &mut channel_state.short_to_id;
2098-
let pending_msg_events = &mut channel_state.pending_msg_events;
2099-
channel_state.by_id.retain(|_, channel| {
2100-
if channel.is_awaiting_monitor_update() {
2101-
let chan_monitor = channel.channel_monitor().clone();
2102-
if let Err(e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
2103-
match e {
2104-
ChannelMonitorUpdateErr::PermanentFailure => {
2105-
// TODO: There may be some pending HTLCs that we intended to fail
2106-
// backwards when a monitor update failed. We should make sure
2107-
// knowledge of those gets moved into the appropriate in-memory
2108-
// ChannelMonitor and they get failed backwards once we get
2109-
// on-chain confirmations.
2110-
// Note I think #198 addresses this, so once it's merged a test
2111-
// should be written.
2112-
if let Some(short_id) = channel.get_short_channel_id() {
2113-
short_to_id.remove(&short_id);
2114-
}
2115-
close_results.push(channel.force_shutdown());
2116-
if let Ok(update) = self.get_channel_update(&channel) {
2117-
pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
2118-
msg: update
2119-
});
2120-
}
2121-
false
2122-
},
2123-
ChannelMonitorUpdateErr::TemporaryFailure => true,
2124-
}
2125-
} else {
2126-
let (raa, commitment_update, order, pending_forwards, mut pending_failures, needs_broadcast_safe, funding_locked) = channel.monitor_updating_restored();
2127-
if !pending_forwards.is_empty() {
2128-
htlc_forwards.push((channel.get_short_channel_id().expect("We can't have pending forwards before funding confirmation"), pending_forwards));
2129-
}
2130-
htlc_failures.append(&mut pending_failures);
2131-
2132-
macro_rules! handle_cs { () => {
2133-
if let Some(update) = commitment_update {
2134-
pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
2135-
node_id: channel.get_their_node_id(),
2136-
updates: update,
2137-
});
2138-
}
2139-
} }
2140-
macro_rules! handle_raa { () => {
2141-
if let Some(revoke_and_ack) = raa {
2142-
pending_msg_events.push(events::MessageSendEvent::SendRevokeAndACK {
2143-
node_id: channel.get_their_node_id(),
2144-
msg: revoke_and_ack,
2145-
});
2146-
}
2147-
} }
2148-
match order {
2149-
RAACommitmentOrder::CommitmentFirst => {
2150-
handle_cs!();
2151-
handle_raa!();
2152-
},
2153-
RAACommitmentOrder::RevokeAndACKFirst => {
2154-
handle_raa!();
2155-
handle_cs!();
2156-
},
2157-
}
2158-
if needs_broadcast_safe {
2159-
pending_events.push(events::Event::FundingBroadcastSafe {
2160-
funding_txo: channel.get_funding_txo().unwrap(),
2161-
user_channel_id: channel.get_user_id(),
2162-
});
2163-
}
2164-
if let Some(msg) = funding_locked {
2165-
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
2166-
node_id: channel.get_their_node_id(),
2167-
msg,
2168-
});
2169-
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
2170-
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
2171-
node_id: channel.get_their_node_id(),
2172-
msg: announcement_sigs,
2173-
});
2174-
}
2175-
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
2176-
}
2177-
true
2178-
}
2179-
} else { true }
2180-
});
2181-
}
2182-
2183-
self.pending_events.lock().unwrap().append(&mut pending_events);
2184-
2185-
for failure in htlc_failures.drain(..) {
2186-
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), failure.0, &failure.1, failure.2);
2187-
}
2188-
self.forward_htlcs(&mut htlc_forwards[..]);
2189-
2190-
for res in close_results.drain(..) {
2191-
self.finish_force_close_channel(res);
2192-
}
2193-
}
2194-
21952084
fn internal_open_channel(&self, their_node_id: &PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> {
21962085
if msg.chain_hash != self.genesis_hash {
21972086
return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash", msg.temporary_channel_id.clone()));
@@ -2254,8 +2143,8 @@ impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::T
22542143
}
22552144
};
22562145
// Because we have exclusive ownership of the channel here we can release the channel_state
2257-
// lock before add_update_monitor
2258-
if let Err(e) = self.monitor.add_update_monitor(monitor_update.get_funding_txo().unwrap(), monitor_update) {
2146+
// lock before add_monitor
2147+
if let Err(e) = self.monitor.add_monitor(monitor_update.get_funding_txo().unwrap(), monitor_update) {
22592148
match e {
22602149
ChannelMonitorUpdateErr::PermanentFailure => {
22612150
// Note that we reply with the new channel_id in error messages if we gave up on the

lightning/src/ln/channelmonitor.rs

Lines changed: 14 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ pub enum ChannelMonitorUpdateErr {
130130
}
131131

132132
/// General Err type for ChannelMonitor actions. Generally, this implies that the data provided is
133-
/// inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::insert_combine this
134-
/// means you tried to merge two monitors for different channels or for a channel which was
135-
/// restored from a backup and then generated new commitment updates.
133+
/// inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::update_monitor this
134+
/// means you tried to update a monitor for a different channel or the ChannelMonitorUpdate was
135+
/// corrupted.
136136
/// Contains a human-readable error message.
137137
#[derive(Debug)]
138138
pub struct MonitorUpdateError(pub &'static str);
@@ -147,7 +147,7 @@ pub struct HTLCUpdate {
147147

148148
/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
149149
/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
150-
/// events to it, while also taking any add_update_monitor events and passing them to some remote
150+
/// events to it, while also taking any add/update_monitor events and passing them to some remote
151151
/// server(s).
152152
///
153153
/// Note that any updates to a channel's monitor *must* be applied to each instance of the
@@ -161,7 +161,7 @@ pub struct HTLCUpdate {
161161
/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
162162
/// all registered listeners in one go.
163163
pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
164-
/// Adds or updates a monitor for the given `funding_txo`.
164+
/// Adds a monitor for the given `funding_txo`.
165165
///
166166
/// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
167167
/// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
@@ -170,7 +170,7 @@ pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
170170
/// Further, the implementer must also ensure that each output returned in
171171
/// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about
172172
/// any spends of any of the outputs.
173-
fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
173+
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
174174

175175
/// Updates a monitor for the given `funding_txo`.
176176
///
@@ -266,14 +266,11 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl
266266
}
267267

268268
/// Adds or updates the monitor which monitors the channel referred to by the given key.
269-
pub fn add_update_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
269+
pub fn add_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
270270
let mut monitors = self.monitors.lock().unwrap();
271-
match monitors.get_mut(&key) {
272-
Some(orig_monitor) => {
273-
log_trace!(self, "Updating Channel Monitor for channel {}", log_funding_info!(monitor.key_storage));
274-
return orig_monitor.insert_combine(monitor);
275-
},
276-
None => {}
271+
let entry = match monitors.entry(key) {
272+
hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
273+
hash_map::Entry::Vacant(e) => e,
277274
};
278275
match monitor.key_storage {
279276
Storage::Local { ref funding_info, .. } => {
@@ -297,7 +294,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl
297294
self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
298295
}
299296
}
300-
monitors.insert(key, monitor);
297+
entry.insert(monitor);
301298
Ok(())
302299
}
303300

@@ -315,8 +312,8 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl
315312
}
316313

317314
impl<ChanSigner: ChannelKeys> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner> {
318-
fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
319-
match self.add_update_monitor_by_key(funding_txo, monitor) {
315+
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
316+
match self.add_monitor_by_key(funding_txo, monitor) {
320317
Ok(_) => Ok(()),
321318
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
322319
}
@@ -859,7 +856,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
859856

860857
// We simply modify last_block_hash in Channel's block_connected so that serialization is
861858
// consistent but hopefully the users' copy handles block_connected in a consistent way.
862-
// (we do *not*, however, update them in insert_combine to ensure any local user copies keep
859+
// (we do *not*, however, update them in update_monitor to ensure any local user copies keep
863860
// their last_block_hash from its state and not based on updated copies that didn't run through
864861
// the full block_connected).
865862
pub(crate) last_block_hash: Sha256dHash,
@@ -1494,68 +1491,6 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14941491
Ok(())
14951492
}
14961493

1497-
/// Combines this ChannelMonitor with the information contained in the other ChannelMonitor.
1498-
/// After a successful call this ChannelMonitor is up-to-date and is safe to use to monitor the
1499-
/// chain for new blocks/transactions.
1500-
pub fn insert_combine(&mut self, mut other: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
1501-
match self.key_storage {
1502-
Storage::Local { ref funding_info, .. } => {
1503-
if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
1504-
let our_funding_info = funding_info;
1505-
if let Storage::Local { ref funding_info, .. } = other.key_storage {
1506-
if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
1507-
// We should be able to compare the entire funding_txo, but in fuzztarget it's trivially
1508-
// easy to collide the funding_txo hash and have a different scriptPubKey.
1509-
if funding_info.as_ref().unwrap().0 != our_funding_info.as_ref().unwrap().0 {
1510-
return Err(MonitorUpdateError("Funding transaction outputs are not identical!"));
1511-
}
1512-
} else {
1513-
return Err(MonitorUpdateError("Try to combine a Local monitor with a Watchtower one !"));
1514-
}
1515-
},
1516-
Storage::Watchtower { .. } => {
1517-
if let Storage::Watchtower { .. } = other.key_storage {
1518-
unimplemented!();
1519-
} else {
1520-
return Err(MonitorUpdateError("Try to combine a Watchtower monitor with a Local one !"));
1521-
}
1522-
},
1523-
}
1524-
let other_min_secret = other.get_min_seen_secret();
1525-
let our_min_secret = self.get_min_seen_secret();
1526-
if our_min_secret > other_min_secret {
1527-
self.provide_secret(other_min_secret, other.get_secret(other_min_secret).unwrap())?;
1528-
}
1529-
if let Some(ref local_tx) = self.current_local_signed_commitment_tx {
1530-
if let Some(ref other_local_tx) = other.current_local_signed_commitment_tx {
1531-
let our_commitment_number = 0xffffffffffff - ((((local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
1532-
let other_commitment_number = 0xffffffffffff - ((((other_local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (other_local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ other.commitment_transaction_number_obscure_factor);
1533-
if our_commitment_number >= other_commitment_number {
1534-
self.key_storage = other.key_storage;
1535-
}
1536-
}
1537-
}
1538-
// TODO: We should use current_remote_commitment_number and the commitment number out of
1539-
// local transactions to decide how to merge
1540-
if our_min_secret >= other_min_secret {
1541-
self.their_cur_revocation_points = other.their_cur_revocation_points;
1542-
for (txid, htlcs) in other.remote_claimable_outpoints.drain() {
1543-
self.remote_claimable_outpoints.insert(txid, htlcs);
1544-
}
1545-
if let Some(local_tx) = other.prev_local_signed_commitment_tx {
1546-
self.prev_local_signed_commitment_tx = Some(local_tx);
1547-
}
1548-
if let Some(local_tx) = other.current_local_signed_commitment_tx {
1549-
self.current_local_signed_commitment_tx = Some(local_tx);
1550-
}
1551-
self.payment_preimages = other.payment_preimages;
1552-
self.to_remote_rescue = other.to_remote_rescue;
1553-
}
1554-
1555-
self.current_remote_commitment_number = cmp::min(self.current_remote_commitment_number, other.current_remote_commitment_number);
1556-
Ok(())
1557-
}
1558-
15591494
/// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
15601495
/// ChannelMonitor.
15611496
pub fn get_latest_update_id(&self) -> u64 {

lightning/src/ln/functional_test_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl<'a, 'b> Drop for Node<'a, 'b> {
104104
monitor.write_for_disk(&mut w).unwrap();
105105
let (_, new_mon) = <(Sha256d, ChannelMonitor<EnforcingChannelKeys>)>::read(
106106
&mut ::std::io::Cursor::new(&w.0), Arc::clone(&self.logger) as Arc<Logger>).unwrap();
107-
if let Err(_) = new_monitor.add_update_monitor(new_mon.get_funding_txo().unwrap(), new_mon) {
107+
if let Err(_) = new_monitor.add_monitor(new_mon.get_funding_txo().unwrap(), new_mon) {
108108
panic!();
109109
}
110110
}

lightning/src/ln/functional_tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3616,7 +3616,7 @@ fn test_no_txn_manager_serialize_deserialize() {
36163616
nodes_0_deserialized = nodes_0_deserialized_tmp;
36173617
assert!(nodes_0_read.is_empty());
36183618

3619-
assert!(nodes[0].chan_monitor.add_update_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
3619+
assert!(nodes[0].chan_monitor.add_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
36203620
nodes[0].node = &nodes_0_deserialized;
36213621
nodes[0].block_notifier.register_listener(nodes[0].node);
36223622
assert_eq!(nodes[0].node.list_channels().len(), 1);
@@ -3685,7 +3685,7 @@ fn test_simple_manager_serialize_deserialize() {
36853685
nodes_0_deserialized = nodes_0_deserialized_tmp;
36863686
assert!(nodes_0_read.is_empty());
36873687

3688-
assert!(nodes[0].chan_monitor.add_update_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
3688+
assert!(nodes[0].chan_monitor.add_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
36893689
nodes[0].node = &nodes_0_deserialized;
36903690
check_added_monitors!(nodes[0], 1);
36913691

@@ -3758,7 +3758,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
37583758
}
37593759

37603760
for monitor in node_0_monitors.drain(..) {
3761-
assert!(nodes[0].chan_monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor).is_ok());
3761+
assert!(nodes[0].chan_monitor.add_monitor(monitor.get_funding_txo().unwrap(), monitor).is_ok());
37623762
check_added_monitors!(nodes[0], 1);
37633763
}
37643764
nodes[0].node = &nodes_0_deserialized;
@@ -6420,7 +6420,7 @@ fn test_data_loss_protect() {
64206420
}).unwrap().1
64216421
};
64226422
nodes[0].node = &node_state_0;
6423-
assert!(monitor.add_update_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok());
6423+
assert!(monitor.add_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok());
64246424
nodes[0].chan_monitor = &monitor;
64256425
nodes[0].chain_monitor = chain_monitor;
64266426

lightning/src/util/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub enum APIError {
3333
/// A human-readable error message
3434
err: &'static str
3535
},
36-
/// An attempt to call add_update_monitor returned an Err (ie you did this!), causing the
36+
/// An attempt to call add/update_monitor returned an Err (ie you did this!), causing the
3737
/// attempted action to fail.
3838
MonitorUpdateFailed,
3939
}

0 commit comments

Comments
 (0)