Skip to content

Commit 4dfe046

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 8a02797 commit 4dfe046

File tree

7 files changed

+112
-263
lines changed

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);
@@ -149,7 +149,7 @@ impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
149149

150150
/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
151151
/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
152-
/// events to it, while also taking any add_update_monitor events and passing them to some remote
152+
/// events to it, while also taking any add/update_monitor events and passing them to some remote
153153
/// server(s).
154154
///
155155
/// Note that any updates to a channel's monitor *must* be applied to each instance of the
@@ -163,7 +163,7 @@ impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
163163
/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
164164
/// all registered listeners in one go.
165165
pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
166-
/// Adds or updates a monitor for the given `funding_txo`.
166+
/// Adds a monitor for the given `funding_txo`.
167167
///
168168
/// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
169169
/// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
@@ -175,7 +175,7 @@ pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
175175
///
176176
/// Any spends of outputs which should have been registered which aren't passed to
177177
/// ChannelMonitors via block_connected may result in funds loss.
178-
fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
178+
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
179179

180180
/// Updates a monitor for the given `funding_txo`.
181181
///
@@ -274,14 +274,11 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl
274274
}
275275

276276
/// Adds or updates the monitor which monitors the channel referred to by the given key.
277-
pub fn add_update_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
277+
pub fn add_monitor_by_key(&self, key: Key, monitor: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
278278
let mut monitors = self.monitors.lock().unwrap();
279-
match monitors.get_mut(&key) {
280-
Some(orig_monitor) => {
281-
log_trace!(self, "Updating Channel Monitor for channel {}", log_funding_info!(monitor.key_storage));
282-
return orig_monitor.insert_combine(monitor);
283-
},
284-
None => {}
279+
let entry = match monitors.entry(key) {
280+
hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
281+
hash_map::Entry::Vacant(e) => e,
285282
};
286283
match monitor.key_storage {
287284
Storage::Local { ref funding_info, .. } => {
@@ -305,7 +302,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl
305302
self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
306303
}
307304
}
308-
monitors.insert(key, monitor);
305+
entry.insert(monitor);
309306
Ok(())
310307
}
311308

@@ -323,8 +320,8 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys> Simpl
323320
}
324321

325322
impl<ChanSigner: ChannelKeys> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner> {
326-
fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
327-
match self.add_update_monitor_by_key(funding_txo, monitor) {
323+
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
324+
match self.add_monitor_by_key(funding_txo, monitor) {
328325
Ok(_) => Ok(()),
329326
Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
330327
}
@@ -867,7 +864,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
867864

868865
// We simply modify last_block_hash in Channel's block_connected so that serialization is
869866
// consistent but hopefully the users' copy handles block_connected in a consistent way.
870-
// (we do *not*, however, update them in insert_combine to ensure any local user copies keep
867+
// (we do *not*, however, update them in update_monitor to ensure any local user copies keep
871868
// their last_block_hash from its state and not based on updated copies that didn't run through
872869
// the full block_connected).
873870
pub(crate) last_block_hash: Sha256dHash,
@@ -1497,68 +1494,6 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14971494
Ok(())
14981495
}
14991496

1500-
/// Combines this ChannelMonitor with the information contained in the other ChannelMonitor.
1501-
/// After a successful call this ChannelMonitor is up-to-date and is safe to use to monitor the
1502-
/// chain for new blocks/transactions.
1503-
pub fn insert_combine(&mut self, mut other: ChannelMonitor<ChanSigner>) -> Result<(), MonitorUpdateError> {
1504-
match self.key_storage {
1505-
Storage::Local { ref funding_info, .. } => {
1506-
if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
1507-
let our_funding_info = funding_info;
1508-
if let Storage::Local { ref funding_info, .. } = other.key_storage {
1509-
if funding_info.is_none() { return Err(MonitorUpdateError("Try to combine a Local monitor without funding_info")); }
1510-
// We should be able to compare the entire funding_txo, but in fuzztarget it's trivially
1511-
// easy to collide the funding_txo hash and have a different scriptPubKey.
1512-
if funding_info.as_ref().unwrap().0 != our_funding_info.as_ref().unwrap().0 {
1513-
return Err(MonitorUpdateError("Funding transaction outputs are not identical!"));
1514-
}
1515-
} else {
1516-
return Err(MonitorUpdateError("Try to combine a Local monitor with a Watchtower one !"));
1517-
}
1518-
},
1519-
Storage::Watchtower { .. } => {
1520-
if let Storage::Watchtower { .. } = other.key_storage {
1521-
unimplemented!();
1522-
} else {
1523-
return Err(MonitorUpdateError("Try to combine a Watchtower monitor with a Local one !"));
1524-
}
1525-
},
1526-
}
1527-
let other_min_secret = other.get_min_seen_secret();
1528-
let our_min_secret = self.get_min_seen_secret();
1529-
if our_min_secret > other_min_secret {
1530-
self.provide_secret(other_min_secret, other.get_secret(other_min_secret).unwrap())?;
1531-
}
1532-
if let Some(ref local_tx) = self.current_local_signed_commitment_tx {
1533-
if let Some(ref other_local_tx) = other.current_local_signed_commitment_tx {
1534-
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);
1535-
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);
1536-
if our_commitment_number >= other_commitment_number {
1537-
self.key_storage = other.key_storage;
1538-
}
1539-
}
1540-
}
1541-
// TODO: We should use current_remote_commitment_number and the commitment number out of
1542-
// local transactions to decide how to merge
1543-
if our_min_secret >= other_min_secret {
1544-
self.their_cur_revocation_points = other.their_cur_revocation_points;
1545-
for (txid, htlcs) in other.remote_claimable_outpoints.drain() {
1546-
self.remote_claimable_outpoints.insert(txid, htlcs);
1547-
}
1548-
if let Some(local_tx) = other.prev_local_signed_commitment_tx {
1549-
self.prev_local_signed_commitment_tx = Some(local_tx);
1550-
}
1551-
if let Some(local_tx) = other.current_local_signed_commitment_tx {
1552-
self.current_local_signed_commitment_tx = Some(local_tx);
1553-
}
1554-
self.payment_preimages = other.payment_preimages;
1555-
self.to_remote_rescue = other.to_remote_rescue;
1556-
}
1557-
1558-
self.current_remote_commitment_number = cmp::min(self.current_remote_commitment_number, other.current_remote_commitment_number);
1559-
Ok(())
1560-
}
1561-
15621497
/// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
15631498
/// ChannelMonitor.
15641499
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
@@ -130,7 +130,7 @@ impl<'a, 'b> Drop for Node<'a, 'b> {
130130
let chain_watch = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&self.logger) as Arc<Logger>));
131131
let channel_monitor = test_utils::TestChannelMonitor::new(chain_watch.clone(), self.tx_broadcaster.clone(), self.logger.clone(), feeest);
132132
for deserialized_monitor in deserialized_monitors.drain(..) {
133-
if let Err(_) = channel_monitor.add_update_monitor(deserialized_monitor.get_funding_txo().unwrap(), deserialized_monitor) {
133+
if let Err(_) = channel_monitor.add_monitor(deserialized_monitor.get_funding_txo().unwrap(), deserialized_monitor) {
134134
panic!();
135135
}
136136
}

lightning/src/ln/functional_tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3714,7 +3714,7 @@ fn test_no_txn_manager_serialize_deserialize() {
37143714
nodes_0_deserialized = nodes_0_deserialized_tmp;
37153715
assert!(nodes_0_read.is_empty());
37163716

3717-
assert!(nodes[0].chan_monitor.add_update_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
3717+
assert!(nodes[0].chan_monitor.add_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
37183718
nodes[0].node = &nodes_0_deserialized;
37193719
nodes[0].block_notifier.register_listener(nodes[0].node);
37203720
assert_eq!(nodes[0].node.list_channels().len(), 1);
@@ -3783,7 +3783,7 @@ fn test_simple_manager_serialize_deserialize() {
37833783
nodes_0_deserialized = nodes_0_deserialized_tmp;
37843784
assert!(nodes_0_read.is_empty());
37853785

3786-
assert!(nodes[0].chan_monitor.add_update_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
3786+
assert!(nodes[0].chan_monitor.add_monitor(chan_0_monitor.get_funding_txo().unwrap(), chan_0_monitor).is_ok());
37873787
nodes[0].node = &nodes_0_deserialized;
37883788
check_added_monitors!(nodes[0], 1);
37893789

@@ -3856,7 +3856,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
38563856
}
38573857

38583858
for monitor in node_0_monitors.drain(..) {
3859-
assert!(nodes[0].chan_monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor).is_ok());
3859+
assert!(nodes[0].chan_monitor.add_monitor(monitor.get_funding_txo().unwrap(), monitor).is_ok());
38603860
check_added_monitors!(nodes[0], 1);
38613861
}
38623862
nodes[0].node = &nodes_0_deserialized;
@@ -6518,7 +6518,7 @@ fn test_data_loss_protect() {
65186518
}).unwrap().1
65196519
};
65206520
nodes[0].node = &node_state_0;
6521-
assert!(monitor.add_update_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok());
6521+
assert!(monitor.add_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok());
65226522
nodes[0].chan_monitor = &monitor;
65236523
nodes[0].chain_monitor = chain_monitor;
65246524

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)