diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index e180805f236..d6a106bb7d0 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -126,7 +126,7 @@ impl chain::Watch for TestChainMonitor { hash_map::Entry::Occupied(entry) => entry, hash_map::Entry::Vacant(_) => panic!("Didn't have monitor on update call"), }; - let mut deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>:: + let deserialized_monitor = <(BlockHash, channelmonitor::ChannelMonitor)>:: read(&mut Cursor::new(&map_entry.get().1), &OnlyReadsKeysInterface {}).unwrap().1; deserialized_monitor.update_monitor(&update, &&TestBroadcaster{}, &&FuzzEstimator{}, &self.logger).unwrap(); let mut ser = VecWriter(Vec::new()); diff --git a/lightning-block-sync/src/init.rs b/lightning-block-sync/src/init.rs index da9895ae721..24080b15acb 100644 --- a/lightning-block-sync/src/init.rs +++ b/lightning-block-sync/src/init.rs @@ -38,7 +38,6 @@ use lightning::chain; /// /// use lightning_block_sync::*; /// -/// use std::cell::RefCell; /// use std::io::Cursor; /// /// async fn init_sync< @@ -83,7 +82,7 @@ use lightning::chain; /// /// // Synchronize any channel monitors and the channel manager to be on the best block. /// let mut cache = UnboundedCache::new(); -/// let mut monitor_listener = (RefCell::new(monitor), &*tx_broadcaster, &*fee_estimator, &*logger); +/// let mut monitor_listener = (monitor, &*tx_broadcaster, &*fee_estimator, &*logger); /// let listeners = vec![ /// (monitor_block_hash, &mut monitor_listener as &mut dyn chain::Listen), /// (manager_block_hash, &mut manager as &mut dyn chain::Listen), @@ -92,7 +91,7 @@ use lightning::chain; /// block_source, Network::Bitcoin, &mut cache, listeners).await.unwrap(); /// /// // Allow the chain monitor to watch any channels. -/// let monitor = monitor_listener.0.into_inner(); +/// let monitor = monitor_listener.0; /// chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor); /// /// // Create an SPV client to notify the chain monitor and channel manager of block events. diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index 4cb9128d92f..de826d054d3 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -43,7 +43,7 @@ use util::events; use util::events::Event; use std::collections::{HashMap, hash_map}; -use std::sync::Mutex; +use std::sync::RwLock; use std::ops::Deref; /// An implementation of [`chain::Watch`] for monitoring channels. @@ -64,7 +64,7 @@ pub struct ChainMonitor, { /// The monitors - pub monitors: Mutex>>, + pub monitors: RwLock>>, chain_source: Option, broadcaster: T, logger: L, @@ -93,8 +93,8 @@ where C::Target: chain::Filter, /// [`chain::Watch::release_pending_monitor_events`]: ../trait.Watch.html#tymethod.release_pending_monitor_events /// [`chain::Filter`]: ../trait.Filter.html pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) { - let mut monitors = self.monitors.lock().unwrap(); - for monitor in monitors.values_mut() { + let monitors = self.monitors.read().unwrap(); + for monitor in monitors.values() { let mut txn_outputs = monitor.block_connected(header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger); if let Some(ref chain_source) = self.chain_source { @@ -113,8 +113,8 @@ where C::Target: chain::Filter, /// /// [`ChannelMonitor::block_disconnected`]: ../channelmonitor/struct.ChannelMonitor.html#method.block_disconnected pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) { - let mut monitors = self.monitors.lock().unwrap(); - for monitor in monitors.values_mut() { + let monitors = self.monitors.read().unwrap(); + for monitor in monitors.values() { monitor.block_disconnected(header, disconnected_height, &*self.broadcaster, &*self.fee_estimator, &*self.logger); } } @@ -130,7 +130,7 @@ where C::Target: chain::Filter, /// [`chain::Filter`]: ../trait.Filter.html pub fn new(chain_source: Option, broadcaster: T, logger: L, feeest: F, persister: P) -> Self { Self { - monitors: Mutex::new(HashMap::new()), + monitors: RwLock::new(HashMap::new()), chain_source, broadcaster, logger, @@ -177,7 +177,7 @@ where C::Target: chain::Filter, /// /// [`chain::Filter`]: ../trait.Filter.html fn watch_channel(&self, funding_outpoint: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { - let mut monitors = self.monitors.lock().unwrap(); + let mut monitors = self.monitors.write().unwrap(); let entry = match monitors.entry(funding_outpoint) { hash_map::Entry::Occupied(_) => { log_error!(self.logger, "Failed to add new channel data: channel monitor for given outpoint is already present"); @@ -209,8 +209,8 @@ where C::Target: chain::Filter, /// `ChainMonitor` monitors lock. fn update_channel(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr> { // Update the monitor that watches the channel referred to by the given outpoint. - let mut monitors = self.monitors.lock().unwrap(); - match monitors.get_mut(&funding_txo) { + let monitors = self.monitors.read().unwrap(); + match monitors.get(&funding_txo) { None => { log_error!(self.logger, "Failed to update channel monitor: no such monitor registered"); @@ -222,15 +222,15 @@ where C::Target: chain::Filter, #[cfg(not(any(test, feature = "fuzztarget")))] Err(ChannelMonitorUpdateErr::PermanentFailure) }, - Some(orig_monitor) => { - log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor)); - let update_res = orig_monitor.update_monitor(&update, &self.broadcaster, &self.fee_estimator, &self.logger); + Some(monitor) => { + log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(monitor)); + let update_res = monitor.update_monitor(&update, &self.broadcaster, &self.fee_estimator, &self.logger); if let Err(e) = &update_res { log_error!(self.logger, "Failed to update channel monitor: {:?}", e); } // Even if updating the monitor returns an error, the monitor's state will // still be changed. So, persist the updated monitor despite the error. - let persist_res = self.persister.update_persisted_channel(funding_txo, &update, orig_monitor); + let persist_res = self.persister.update_persisted_channel(funding_txo, &update, monitor); if let Err(ref e) = persist_res { log_error!(self.logger, "Failed to persist channel monitor update: {:?}", e); } @@ -245,8 +245,8 @@ where C::Target: chain::Filter, fn release_pending_monitor_events(&self) -> Vec { let mut pending_monitor_events = Vec::new(); - for chan in self.monitors.lock().unwrap().values_mut() { - pending_monitor_events.append(&mut chan.get_and_clear_pending_monitor_events()); + for monitor in self.monitors.read().unwrap().values() { + pending_monitor_events.append(&mut monitor.get_and_clear_pending_monitor_events()); } pending_monitor_events } @@ -261,8 +261,8 @@ impl even { fn get_and_clear_pending_events(&self) -> Vec { let mut pending_events = Vec::new(); - for chan in self.monitors.lock().unwrap().values_mut() { - pending_events.append(&mut chan.get_and_clear_pending_events()); + for monitor in self.monitors.read().unwrap().values() { + pending_events.append(&mut monitor.get_and_clear_pending_events()); } pending_events } diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index a830c8216a6..034854810c6 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -50,11 +50,11 @@ use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48}; use util::byte_utils; use util::events::Event; -use std::cell::RefCell; use std::collections::{HashMap, HashSet, hash_map}; use std::{cmp, mem}; -use std::ops::Deref; use std::io::Error; +use std::ops::Deref; +use std::sync::Mutex; /// An update generated by the underlying Channel itself which contains some new information the /// ChannelMonitor should be made aware of. @@ -626,6 +626,13 @@ impl Readable for ChannelMonitorUpdateStep { /// returned block hash and the the current chain and then reconnecting blocks to get to the /// best chain) upon deserializing the object! pub struct ChannelMonitor { + #[cfg(test)] + pub(crate) inner: Mutex>, + #[cfg(not(test))] + inner: Mutex>, +} + +pub(crate) struct ChannelMonitorImpl { latest_update_id: u64, commitment_transaction_number_obscure_factor: u64, @@ -724,6 +731,17 @@ pub struct ChannelMonitor { /// Used only in testing and fuzztarget to check serialization roundtrips don't change the /// underlying object impl PartialEq for ChannelMonitor { + fn eq(&self, other: &Self) -> bool { + let inner = self.inner.lock().unwrap(); + let other = other.inner.lock().unwrap(); + inner.eq(&other) + } +} + +#[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))] +/// Used only in testing and fuzztarget to check serialization roundtrips don't change the +/// underlying object +impl PartialEq for ChannelMonitorImpl { fn eq(&self, other: &Self) -> bool { if self.latest_update_id != other.latest_update_id || self.commitment_transaction_number_obscure_factor != other.commitment_transaction_number_obscure_factor || @@ -770,6 +788,12 @@ impl Writeable for ChannelMonitor { writer.write_all(&[SERIALIZATION_VERSION; 1])?; writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?; + self.inner.lock().unwrap().write(writer) + } +} + +impl Writeable for ChannelMonitorImpl { + fn write(&self, writer: &mut W) -> Result<(), Error> { self.latest_update_id.write(writer)?; // Set in initial Channel-object creation, so should always be set by now: @@ -999,54 +1023,255 @@ impl ChannelMonitor { outputs_to_watch.insert(funding_info.0.txid, vec![(funding_info.0.index as u32, funding_info.1.clone())]); ChannelMonitor { - latest_update_id: 0, - commitment_transaction_number_obscure_factor, + inner: Mutex::new(ChannelMonitorImpl { + latest_update_id: 0, + commitment_transaction_number_obscure_factor, - destination_script: destination_script.clone(), - broadcasted_holder_revokable_script: None, - counterparty_payment_script, - shutdown_script, + destination_script: destination_script.clone(), + broadcasted_holder_revokable_script: None, + counterparty_payment_script, + shutdown_script, - channel_keys_id, - holder_revocation_basepoint, - funding_info, - current_counterparty_commitment_txid: None, - prev_counterparty_commitment_txid: None, + channel_keys_id, + holder_revocation_basepoint, + funding_info, + current_counterparty_commitment_txid: None, + prev_counterparty_commitment_txid: None, - counterparty_tx_cache, - funding_redeemscript, - channel_value_satoshis, - their_cur_revocation_points: None, + counterparty_tx_cache, + funding_redeemscript, + channel_value_satoshis, + their_cur_revocation_points: None, - on_holder_tx_csv: counterparty_channel_parameters.selected_contest_delay, + on_holder_tx_csv: counterparty_channel_parameters.selected_contest_delay, - commitment_secrets: CounterpartyCommitmentSecrets::new(), - counterparty_claimable_outpoints: HashMap::new(), - counterparty_commitment_txn_on_chain: HashMap::new(), - counterparty_hash_commitment_number: HashMap::new(), + commitment_secrets: CounterpartyCommitmentSecrets::new(), + counterparty_claimable_outpoints: HashMap::new(), + counterparty_commitment_txn_on_chain: HashMap::new(), + counterparty_hash_commitment_number: HashMap::new(), - prev_holder_signed_commitment_tx: None, - current_holder_commitment_tx: holder_commitment_tx, - current_counterparty_commitment_number: 1 << 48, - current_holder_commitment_number, + prev_holder_signed_commitment_tx: None, + current_holder_commitment_tx: holder_commitment_tx, + current_counterparty_commitment_number: 1 << 48, + current_holder_commitment_number, - payment_preimages: HashMap::new(), - pending_monitor_events: Vec::new(), - pending_events: Vec::new(), + payment_preimages: HashMap::new(), + pending_monitor_events: Vec::new(), + pending_events: Vec::new(), - onchain_events_waiting_threshold_conf: HashMap::new(), - outputs_to_watch, + onchain_events_waiting_threshold_conf: HashMap::new(), + outputs_to_watch, - onchain_tx_handler, + onchain_tx_handler, - lockdown_from_offchain: false, - holder_tx_signed: false, + lockdown_from_offchain: false, + holder_tx_signed: false, - last_block_hash: Default::default(), - secp_ctx, + last_block_hash: Default::default(), + secp_ctx, + }), } } + #[cfg(test)] + fn provide_secret(&self, idx: u64, secret: [u8; 32]) -> Result<(), MonitorUpdateError> { + self.inner.lock().unwrap().provide_secret(idx, secret) + } + + /// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction. + /// The monitor watches for it to be broadcasted and then uses the HTLC information (and + /// possibly future revocation/preimage information) to claim outputs where possible. + /// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers. + pub(crate) fn provide_latest_counterparty_commitment_tx( + &self, + txid: Txid, + htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, + commitment_number: u64, + their_revocation_point: PublicKey, + logger: &L, + ) where L::Target: Logger { + self.inner.lock().unwrap().provide_latest_counterparty_commitment_tx( + txid, htlc_outputs, commitment_number, their_revocation_point, logger) + } + + #[cfg(test)] + fn provide_latest_holder_commitment_tx( + &self, + holder_commitment_tx: HolderCommitmentTransaction, + htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, + ) -> Result<(), MonitorUpdateError> { + self.inner.lock().unwrap().provide_latest_holder_commitment_tx( + holder_commitment_tx, htlc_outputs) + } + + #[cfg(test)] + pub(crate) fn provide_payment_preimage( + &self, + payment_hash: &PaymentHash, + payment_preimage: &PaymentPreimage, + broadcaster: &B, + fee_estimator: &F, + logger: &L, + ) where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.inner.lock().unwrap().provide_payment_preimage( + payment_hash, payment_preimage, broadcaster, fee_estimator, logger) + } + + pub(crate) fn broadcast_latest_holder_commitment_txn( + &self, + broadcaster: &B, + logger: &L, + ) where + B::Target: BroadcasterInterface, + L::Target: Logger, + { + self.inner.lock().unwrap().broadcast_latest_holder_commitment_txn(broadcaster, logger) + } + + /// Updates a ChannelMonitor on the basis of some new information provided by the Channel + /// itself. + /// + /// panics if the given update is not the next update by update_id. + pub fn update_monitor( + &self, + updates: &ChannelMonitorUpdate, + broadcaster: &B, + fee_estimator: &F, + logger: &L, + ) -> Result<(), MonitorUpdateError> + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.inner.lock().unwrap().update_monitor(updates, broadcaster, fee_estimator, logger) + } + + /// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this + /// ChannelMonitor. + pub fn get_latest_update_id(&self) -> u64 { + self.inner.lock().unwrap().get_latest_update_id() + } + + /// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for. + pub fn get_funding_txo(&self) -> (OutPoint, Script) { + self.inner.lock().unwrap().get_funding_txo().clone() + } + + /// Gets a list of txids, with their output scripts (in the order they appear in the + /// transaction), which we must learn about spends of via block_connected(). + /// + /// (C-not exported) because we have no HashMap bindings + pub fn get_outputs_to_watch(&self) -> HashMap> { + self.inner.lock().unwrap().get_outputs_to_watch().clone() + } + + /// Get the list of HTLCs who's status has been updated on chain. This should be called by + /// ChannelManager via [`chain::Watch::release_pending_monitor_events`]. + /// + /// [`chain::Watch::release_pending_monitor_events`]: ../trait.Watch.html#tymethod.release_pending_monitor_events + pub fn get_and_clear_pending_monitor_events(&self) -> Vec { + self.inner.lock().unwrap().get_and_clear_pending_monitor_events() + } + + /// Gets the list of pending events which were generated by previous actions, clearing the list + /// in the process. + /// + /// This is called by ChainMonitor::get_and_clear_pending_events() and is equivalent to + /// EventsProvider::get_and_clear_pending_events() except that it requires &mut self as we do + /// no internal locking in ChannelMonitors. + pub fn get_and_clear_pending_events(&self) -> Vec { + self.inner.lock().unwrap().get_and_clear_pending_events() + } + + pub(crate) fn get_min_seen_secret(&self) -> u64 { + self.inner.lock().unwrap().get_min_seen_secret() + } + + pub(crate) fn get_cur_counterparty_commitment_number(&self) -> u64 { + self.inner.lock().unwrap().get_cur_counterparty_commitment_number() + } + + pub(crate) fn get_cur_holder_commitment_number(&self) -> u64 { + self.inner.lock().unwrap().get_cur_holder_commitment_number() + } + + /// Used by ChannelManager deserialization to broadcast the latest holder state if its copy of + /// the Channel was out-of-date. You may use it to get a broadcastable holder toxic tx in case of + /// fallen-behind, i.e when receiving a channel_reestablish with a proof that our counterparty side knows + /// a higher revocation secret than the holder commitment number we are aware of. Broadcasting these + /// transactions are UNSAFE, as they allow counterparty side to punish you. Nevertheless you may want to + /// broadcast them if counterparty don't close channel with his higher commitment transaction after a + /// substantial amount of time (a month or even a year) to get back funds. Best may be to contact + /// out-of-band the other node operator to coordinate with him if option is available to you. + /// In any-case, choice is up to the user. + pub fn get_latest_holder_commitment_txn(&self, logger: &L) -> Vec + where L::Target: Logger { + self.inner.lock().unwrap().get_latest_holder_commitment_txn(logger) + } + + /// Unsafe test-only version of get_latest_holder_commitment_txn used by our test framework + /// to bypass HolderCommitmentTransaction state update lockdown after signature and generate + /// revoked commitment transaction. + #[cfg(any(test, feature = "unsafe_revoked_tx_signing"))] + pub fn unsafe_get_latest_holder_commitment_txn(&self, logger: &L) -> Vec + where L::Target: Logger { + self.inner.lock().unwrap().unsafe_get_latest_holder_commitment_txn(logger) + } + + /// Processes transactions in a newly connected block, which may result in any of the following: + /// - update the monitor's state against resolved HTLCs + /// - punish the counterparty in the case of seeing a revoked commitment transaction + /// - force close the channel and claim/timeout incoming/outgoing HTLCs if near expiration + /// - detect settled outputs for later spending + /// - schedule and bump any in-flight claims + /// + /// Returns any new outputs to watch from `txdata`; after called, these are also included in + /// [`get_outputs_to_watch`]. + /// + /// [`get_outputs_to_watch`]: #method.get_outputs_to_watch + pub fn block_connected( + &self, + header: &BlockHeader, + txdata: &TransactionData, + height: u32, + broadcaster: B, + fee_estimator: F, + logger: L, + ) -> Vec<(Txid, Vec<(u32, TxOut)>)> + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.inner.lock().unwrap().block_connected( + header, txdata, height, broadcaster, fee_estimator, logger) + } + + /// Determines if the disconnected block contained any transactions of interest and updates + /// appropriately. + pub fn block_disconnected( + &self, + header: &BlockHeader, + height: u32, + broadcaster: B, + fee_estimator: F, + logger: L, + ) where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.inner.lock().unwrap().block_disconnected( + header, height, broadcaster, fee_estimator, logger) + } +} + +impl ChannelMonitorImpl { /// Inserts a revocation secret into this channel monitor. Prunes old preimages if neither /// needed by holder commitment transactions HTCLs nor by counterparty ones. Unless we haven't already seen /// counterparty commitment transaction's secret, they are de facto pruned (we can use revocation key). @@ -1098,10 +1323,6 @@ impl ChannelMonitor { Ok(()) } - /// Informs this monitor of the latest counterparty (ie non-broadcastable) commitment transaction. - /// The monitor watches for it to be broadcasted and then uses the HTLC information (and - /// possibly future revocation/preimage information) to claim outputs where possible. - /// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers. pub(crate) fn provide_latest_counterparty_commitment_tx(&mut self, txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, commitment_number: u64, their_revocation_point: PublicKey, logger: &L) where L::Target: Logger { // TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction // so that a remote monitor doesn't learn anything unless there is a malicious close. @@ -1178,7 +1399,7 @@ impl ChannelMonitor { /// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all /// commitment_tx_infos which contain the payment hash have been revoked. - pub(crate) fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L) + fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, @@ -1231,10 +1452,6 @@ impl ChannelMonitor { self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0)); } - /// Updates a ChannelMonitor on the basis of some new information provided by the Channel - /// itself. - /// - /// panics if the given update is not the next update by update_id. pub fn update_monitor(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &L) -> Result<(), MonitorUpdateError> where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -1287,21 +1504,14 @@ impl ChannelMonitor { Ok(()) } - /// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this - /// ChannelMonitor. pub fn get_latest_update_id(&self) -> u64 { self.latest_update_id } - /// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for. pub fn get_funding_txo(&self) -> &(OutPoint, Script) { &self.funding_info } - /// Gets a list of txids, with their output scripts (in the order they appear in the - /// transaction), which we must learn about spends of via block_connected(). - /// - /// (C-not exported) because we have no HashMap bindings pub fn get_outputs_to_watch(&self) -> &HashMap> { // If we've detected a counterparty commitment tx on chain, we must include it in the set // of outputs to watch for spends of, otherwise we're likely to lose user funds. Because @@ -1312,22 +1522,12 @@ impl ChannelMonitor { &self.outputs_to_watch } - /// Get the list of HTLCs who's status has been updated on chain. This should be called by - /// ChannelManager via [`chain::Watch::release_pending_monitor_events`]. - /// - /// [`chain::Watch::release_pending_monitor_events`]: ../trait.Watch.html#tymethod.release_pending_monitor_events pub fn get_and_clear_pending_monitor_events(&mut self) -> Vec { let mut ret = Vec::new(); mem::swap(&mut ret, &mut self.pending_monitor_events); ret } - /// Gets the list of pending events which were generated by previous actions, clearing the list - /// in the process. - /// - /// This is called by ChainMonitor::get_and_clear_pending_events() and is equivalent to - /// EventsProvider::get_and_clear_pending_events() except that it requires &mut self as we do - /// no internal locking in ChannelMonitors. pub fn get_and_clear_pending_events(&mut self) -> Vec { let mut ret = Vec::new(); mem::swap(&mut ret, &mut self.pending_events); @@ -1715,15 +1915,6 @@ impl ChannelMonitor { (claim_requests, (commitment_txid, watch_outputs)) } - /// Used by ChannelManager deserialization to broadcast the latest holder state if its copy of - /// the Channel was out-of-date. You may use it to get a broadcastable holder toxic tx in case of - /// fallen-behind, i.e when receiving a channel_reestablish with a proof that our counterparty side knows - /// a higher revocation secret than the holder commitment number we are aware of. Broadcasting these - /// transactions are UNSAFE, as they allow counterparty side to punish you. Nevertheless you may want to - /// broadcast them if counterparty don't close channel with his higher commitment transaction after a - /// substantial amount of time (a month or even a year) to get back funds. Best may be to contact - /// out-of-band the other node operator to coordinate with him if option is available to you. - /// In any-case, choice is up to the user. pub fn get_latest_holder_commitment_txn(&mut self, logger: &L) -> Vec where L::Target: Logger { log_trace!(logger, "Getting signed latest holder commitment transaction!"); self.holder_tx_signed = true; @@ -1749,11 +1940,8 @@ impl ChannelMonitor { return res; } - /// Unsafe test-only version of get_latest_holder_commitment_txn used by our test framework - /// to bypass HolderCommitmentTransaction state update lockdown after signature and generate - /// revoked commitment transaction. #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))] - pub fn unsafe_get_latest_holder_commitment_txn(&mut self, logger: &L) -> Vec where L::Target: Logger { + fn unsafe_get_latest_holder_commitment_txn(&mut self, logger: &L) -> Vec where L::Target: Logger { log_trace!(logger, "Getting signed copy of latest holder commitment transaction!"); let commitment_tx = self.onchain_tx_handler.get_fully_signed_copy_holder_tx(&self.funding_redeemscript); let txid = commitment_tx.txid(); @@ -1775,17 +1963,6 @@ impl ChannelMonitor { return res } - /// Processes transactions in a newly connected block, which may result in any of the following: - /// - update the monitor's state against resolved HTLCs - /// - punish the counterparty in the case of seeing a revoked commitment transaction - /// - force close the channel and claim/timeout incoming/outgoing HTLCs if near expiration - /// - detect settled outputs for later spending - /// - schedule and bump any in-flight claims - /// - /// Returns any new outputs to watch from `txdata`; after called, these are also included in - /// [`get_outputs_to_watch`]. - /// - /// [`get_outputs_to_watch`]: #method.get_outputs_to_watch pub fn block_connected(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<(u32, TxOut)>)> where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -1907,8 +2084,6 @@ impl ChannelMonitor { watch_outputs } - /// Determines if the disconnected block contained any transactions of interest and updates - /// appropriately. pub fn block_disconnected(&mut self, header: &BlockHeader, height: u32, broadcaster: B, fee_estimator: F, logger: L) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -2298,7 +2473,7 @@ pub trait Persist: Send + Sync { fn update_persisted_channel(&self, id: OutPoint, update: &ChannelMonitorUpdate, data: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr>; } -impl chain::Listen for (RefCell>, T, F, L) +impl chain::Listen for (ChannelMonitor, T, F, L) where T::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -2306,11 +2481,11 @@ where { fn block_connected(&self, block: &Block, height: u32) { let txdata: Vec<_> = block.txdata.iter().enumerate().collect(); - self.0.borrow_mut().block_connected(&block.header, &txdata, height, &*self.1, &*self.2, &*self.3); + self.0.block_connected(&block.header, &txdata, height, &*self.1, &*self.2, &*self.3); } fn block_disconnected(&self, header: &BlockHeader, height: u32) { - self.0.borrow_mut().block_disconnected(header, height, &*self.1, &*self.2, &*self.3); + self.0.block_disconnected(header, height, &*self.1, &*self.2, &*self.3); } } @@ -2561,51 +2736,53 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes()); Ok((last_block_hash.clone(), ChannelMonitor { - latest_update_id, - commitment_transaction_number_obscure_factor, + inner: Mutex::new(ChannelMonitorImpl { + latest_update_id, + commitment_transaction_number_obscure_factor, - destination_script, - broadcasted_holder_revokable_script, - counterparty_payment_script, - shutdown_script, + destination_script, + broadcasted_holder_revokable_script, + counterparty_payment_script, + shutdown_script, - channel_keys_id, - holder_revocation_basepoint, - funding_info, - current_counterparty_commitment_txid, - prev_counterparty_commitment_txid, + channel_keys_id, + holder_revocation_basepoint, + funding_info, + current_counterparty_commitment_txid, + prev_counterparty_commitment_txid, - counterparty_tx_cache, - funding_redeemscript, - channel_value_satoshis, - their_cur_revocation_points, + counterparty_tx_cache, + funding_redeemscript, + channel_value_satoshis, + their_cur_revocation_points, - on_holder_tx_csv, + on_holder_tx_csv, - commitment_secrets, - counterparty_claimable_outpoints, - counterparty_commitment_txn_on_chain, - counterparty_hash_commitment_number, + commitment_secrets, + counterparty_claimable_outpoints, + counterparty_commitment_txn_on_chain, + counterparty_hash_commitment_number, - prev_holder_signed_commitment_tx, - current_holder_commitment_tx, - current_counterparty_commitment_number, - current_holder_commitment_number, + prev_holder_signed_commitment_tx, + current_holder_commitment_tx, + current_counterparty_commitment_number, + current_holder_commitment_number, - payment_preimages, - pending_monitor_events, - pending_events, + payment_preimages, + pending_monitor_events, + pending_events, - onchain_events_waiting_threshold_conf, - outputs_to_watch, + onchain_events_waiting_threshold_conf, + outputs_to_watch, - onchain_tx_handler, + onchain_tx_handler, - lockdown_from_offchain, - holder_tx_signed, + lockdown_from_offchain, + holder_tx_signed, - last_block_hash, - secp_ctx, + last_block_hash, + secp_ctx, + }), })) } } @@ -2683,7 +2860,7 @@ mod tests { macro_rules! test_preimages_exist { ($preimages_slice: expr, $monitor: expr) => { for preimage in $preimages_slice { - assert!($monitor.payment_preimages.contains_key(&preimage.1)); + assert!($monitor.inner.lock().unwrap().payment_preimages.contains_key(&preimage.1)); } } } @@ -2720,12 +2897,12 @@ mod tests { }; // Prune with one old state and a holder commitment tx holding a few overlaps with the // old state. - let mut monitor = ChannelMonitor::new(Secp256k1::new(), keys, - &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(), - (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), - &channel_parameters, - Script::new(), 46, 0, - HolderCommitmentTransaction::dummy()); + let monitor = ChannelMonitor::new(Secp256k1::new(), keys, + &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(), + (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), + &channel_parameters, + Script::new(), 46, 0, + HolderCommitmentTransaction::dummy()); monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..10])).unwrap(); let dummy_txid = dummy_tx.txid(); @@ -2741,14 +2918,14 @@ mod tests { let mut secret = [0; 32]; secret[0..32].clone_from_slice(&hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); monitor.provide_secret(281474976710655, secret.clone()).unwrap(); - assert_eq!(monitor.payment_preimages.len(), 15); + assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 15); test_preimages_exist!(&preimages[0..10], monitor); test_preimages_exist!(&preimages[15..20], monitor); // Now provide a further secret, pruning preimages 15-17 secret[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); monitor.provide_secret(281474976710654, secret.clone()).unwrap(); - assert_eq!(monitor.payment_preimages.len(), 13); + assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 13); test_preimages_exist!(&preimages[0..10], monitor); test_preimages_exist!(&preimages[17..20], monitor); @@ -2757,7 +2934,7 @@ mod tests { monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..5])).unwrap(); secret[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); monitor.provide_secret(281474976710653, secret.clone()).unwrap(); - assert_eq!(monitor.payment_preimages.len(), 12); + assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 12); test_preimages_exist!(&preimages[0..10], monitor); test_preimages_exist!(&preimages[18..20], monitor); @@ -2765,7 +2942,7 @@ mod tests { monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..3])).unwrap(); secret[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); monitor.provide_secret(281474976710652, secret.clone()).unwrap(); - assert_eq!(monitor.payment_preimages.len(), 5); + assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 5); test_preimages_exist!(&preimages[0..5], monitor); } diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs index 8fc773f68ae..d764bc78215 100644 --- a/lightning/src/ln/chanmon_update_fail_tests.rs +++ b/lightning/src/ln/chanmon_update_fail_tests.rs @@ -102,7 +102,7 @@ fn test_monitor_and_persister_update_fail() { let logger = test_utils::TestLogger::with_id(format!("node {}", 0)); let persister = test_utils::TestPersister::new(); let chain_mon = { - let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); + let monitors = nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap(); let monitor = monitors.get(&outpoint).unwrap(); let mut w = test_utils::TestVecWriter(Vec::new()); monitor.write(&mut w).unwrap(); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index d9c7fc5ad27..2bbe367de75 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -1570,13 +1570,13 @@ impl Channel { let funding_redeemscript = self.get_funding_redeemscript(); let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()); - let mut channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(), - &self.shutdown_pubkey, self.get_holder_selected_contest_delay(), - &self.destination_script, (funding_txo, funding_txo_script.clone()), - &self.channel_transaction_parameters, - funding_redeemscript.clone(), self.channel_value_satoshis, - obscure_factor, - holder_commitment_tx); + let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(), + &self.shutdown_pubkey, self.get_holder_selected_contest_delay(), + &self.destination_script, (funding_txo, funding_txo_script.clone()), + &self.channel_transaction_parameters, + funding_redeemscript.clone(), self.channel_value_satoshis, + obscure_factor, + holder_commitment_tx); channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_commitment_txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger); @@ -1640,13 +1640,13 @@ impl Channel { let funding_txo = self.get_funding_txo().unwrap(); let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.get_holder_pubkeys().payment_point, &self.get_counterparty_pubkeys().payment_point, self.is_outbound()); - let mut channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(), - &self.shutdown_pubkey, self.get_holder_selected_contest_delay(), - &self.destination_script, (funding_txo, funding_txo_script), - &self.channel_transaction_parameters, - funding_redeemscript.clone(), self.channel_value_satoshis, - obscure_factor, - holder_commitment_tx); + let channel_monitor = ChannelMonitor::new(self.secp_ctx.clone(), self.holder_signer.clone(), + &self.shutdown_pubkey, self.get_holder_selected_contest_delay(), + &self.destination_script, (funding_txo, funding_txo_script), + &self.channel_transaction_parameters, + funding_redeemscript.clone(), self.channel_value_satoshis, + obscure_factor, + holder_commitment_tx); channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_bitcoin_tx.txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger); diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 219417d562f..f0937817bdc 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -168,7 +168,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let feeest = test_utils::TestFeeEstimator { sat_per_kw: 253 }; let mut deserialized_monitors = Vec::new(); { - let old_monitors = self.chain_monitor.chain_monitor.monitors.lock().unwrap(); + let old_monitors = self.chain_monitor.chain_monitor.monitors.read().unwrap(); for (_, old_monitor) in old_monitors.iter() { let mut w = test_utils::TestVecWriter(Vec::new()); old_monitor.write(&mut w).unwrap(); @@ -305,9 +305,9 @@ macro_rules! get_feerate { macro_rules! get_local_commitment_txn { ($node: expr, $channel_id: expr) => { { - let mut monitors = $node.chain_monitor.chain_monitor.monitors.lock().unwrap(); + let monitors = $node.chain_monitor.chain_monitor.monitors.read().unwrap(); let mut commitment_txn = None; - for (funding_txo, monitor) in monitors.iter_mut() { + for (funding_txo, monitor) in monitors.iter() { if funding_txo.to_channel_id() == $channel_id { commitment_txn = Some(monitor.unsafe_get_latest_holder_commitment_txn(&$node.logger)); break; diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index ea33bb56144..fdf5d200675 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -3517,8 +3517,8 @@ fn test_force_close_fail_back() { // Now check that if we add the preimage to ChannelMonitor it broadcasts our HTLC-Success.. { - let mut monitors = nodes[2].chain_monitor.chain_monitor.monitors.lock().unwrap(); - monitors.get_mut(&OutPoint{ txid: Txid::from_slice(&payment_event.commitment_msg.channel_id[..]).unwrap(), index: 0 }).unwrap() + let mut monitors = nodes[2].chain_monitor.chain_monitor.monitors.read().unwrap(); + monitors.get(&OutPoint{ txid: Txid::from_slice(&payment_event.commitment_msg.channel_id[..]).unwrap(), index: 0 }).unwrap() .provide_payment_preimage(&our_payment_hash, &our_payment_preimage, &node_cfgs[2].tx_broadcaster, &node_cfgs[2].fee_estimator, &&logger); } connect_block(&nodes[2], &block, 1); @@ -4314,7 +4314,7 @@ fn test_no_txn_manager_serialize_deserialize() { let nodes_0_serialized = nodes[0].node.encode(); let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write(&mut chan_0_monitor_serialized).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap().iter().next().unwrap().1.write(&mut chan_0_monitor_serialized).unwrap(); logger = test_utils::TestLogger::new(); fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; @@ -4423,7 +4423,7 @@ fn test_manager_serialize_deserialize_events() { // Start the de/seriailization process mid-channel creation to check that the channel manager will hold onto events that are serialized let nodes_0_serialized = nodes[0].node.encode(); let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write(&mut chan_0_monitor_serialized).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap().iter().next().unwrap().1.write(&mut chan_0_monitor_serialized).unwrap(); fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; logger = test_utils::TestLogger::new(); @@ -4515,7 +4515,7 @@ fn test_simple_manager_serialize_deserialize() { let nodes_0_serialized = nodes[0].node.encode(); let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write(&mut chan_0_monitor_serialized).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap().iter().next().unwrap().1.write(&mut chan_0_monitor_serialized).unwrap(); logger = test_utils::TestLogger::new(); fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; @@ -4572,7 +4572,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { let (_, _, channel_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 3, InitFeatures::known(), InitFeatures::known()); let mut node_0_stale_monitors_serialized = Vec::new(); - for monitor in nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter() { + for monitor in nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap().iter() { let mut writer = test_utils::TestVecWriter(Vec::new()); monitor.1.write(&mut writer).unwrap(); node_0_stale_monitors_serialized.push(writer.0); @@ -4591,7 +4591,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() { // Now the ChannelMonitor (which is now out-of-sync with ChannelManager for channel w/ // nodes[3]) let mut node_0_monitors_serialized = Vec::new(); - for monitor in nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter() { + for monitor in nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap().iter() { let mut writer = test_utils::TestVecWriter(Vec::new()); monitor.1.write(&mut writer).unwrap(); node_0_monitors_serialized.push(writer.0); @@ -7479,7 +7479,7 @@ fn test_data_loss_protect() { // Cache node A state before any channel update let previous_node_state = nodes[0].node.encode(); let mut previous_chain_monitor_state = test_utils::TestVecWriter(Vec::new()); - nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write(&mut previous_chain_monitor_state).unwrap(); + nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap().iter().next().unwrap().1.write(&mut previous_chain_monitor_state).unwrap(); send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000); send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000); @@ -8226,10 +8226,10 @@ fn test_bump_txn_sanitize_tracking_maps() { connect_block(&nodes[0], &Block { header: header_130, txdata: penalty_txn }, 130); connect_blocks(&nodes[0], 5, 130, false, header_130.block_hash()); { - let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); + let monitors = nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap(); if let Some(monitor) = monitors.get(&OutPoint { txid: chan.3.txid(), index: 0 }) { - assert!(monitor.onchain_tx_handler.pending_claim_requests.is_empty()); - assert!(monitor.onchain_tx_handler.claimable_outpoints.is_empty()); + assert!(monitor.inner.lock().unwrap().onchain_tx_handler.pending_claim_requests.is_empty()); + assert!(monitor.inner.lock().unwrap().onchain_tx_handler.claimable_outpoints.is_empty()); } } } @@ -8360,7 +8360,7 @@ fn test_update_err_monitor_lockdown() { let logger = test_utils::TestLogger::with_id(format!("node {}", 0)); let persister = test_utils::TestPersister::new(); let watchtower = { - let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); + let monitors = nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap(); let monitor = monitors.get(&outpoint).unwrap(); let mut w = test_utils::TestVecWriter(Vec::new()); monitor.write(&mut w).unwrap(); @@ -8419,7 +8419,7 @@ fn test_concurrent_monitor_claim() { let logger = test_utils::TestLogger::with_id(format!("node {}", "Alice")); let persister = test_utils::TestPersister::new(); let watchtower_alice = { - let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); + let monitors = nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap(); let monitor = monitors.get(&outpoint).unwrap(); let mut w = test_utils::TestVecWriter(Vec::new()); monitor.write(&mut w).unwrap(); @@ -8445,7 +8445,7 @@ fn test_concurrent_monitor_claim() { let logger = test_utils::TestLogger::with_id(format!("node {}", "Bob")); let persister = test_utils::TestPersister::new(); let watchtower_bob = { - let monitors = nodes[0].chain_monitor.chain_monitor.monitors.lock().unwrap(); + let monitors = nodes[0].chain_monitor.chain_monitor.monitors.read().unwrap(); let monitor = monitors.get(&outpoint).unwrap(); let mut w = test_utils::TestVecWriter(Vec::new()); monitor.write(&mut w).unwrap(); diff --git a/lightning/src/util/macro_logger.rs b/lightning/src/util/macro_logger.rs index ab2b6ceea79..90a1bdb4814 100644 --- a/lightning/src/util/macro_logger.rs +++ b/lightning/src/util/macro_logger.rs @@ -72,7 +72,7 @@ impl<'a, T> std::fmt::Display for DebugFundingInfo<'a, T> { } macro_rules! log_funding_info { ($key_storage: expr) => { - ::util::macro_logger::DebugFundingInfo($key_storage.get_funding_txo()) + ::util::macro_logger::DebugFundingInfo(&$key_storage.get_funding_txo()) } } diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index c2d22a4a060..9f87795e31e 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -133,7 +133,7 @@ impl<'a> chain::Watch for TestChainMonitor<'a> { let update_res = self.chain_monitor.update_channel(funding_txo, update); // At every point where we get a monitor update, we should be able to send a useful monitor // to a watchtower and disk... - let monitors = self.chain_monitor.monitors.lock().unwrap(); + let monitors = self.chain_monitor.monitors.read().unwrap(); let monitor = monitors.get(&funding_txo).unwrap(); w.0.clear(); monitor.write(&mut w).unwrap();