But what about mut? 2021-02-791-mut
authorMatt Corallo <git@bluematt.me>
Wed, 24 Feb 2021 20:38:32 +0000 (15:38 -0500)
committerMatt Corallo <git@bluematt.me>
Wed, 24 Feb 2021 20:38:32 +0000 (15:38 -0500)
lightning-block-sync/src/init.rs
lightning-block-sync/src/lib.rs
lightning-block-sync/src/test_utils.rs
lightning/src/chain/chainmonitor.rs
lightning/src/chain/channelmonitor.rs
lightning/src/chain/mod.rs
lightning/src/ln/channelmanager.rs

index abefd1bcddf4891b4ebd1a9648fbaf168e7deb72..50f39e8a2abc27443ea35e6691171933d41417b0 100644 (file)
@@ -80,15 +80,17 @@ use lightning::chain;
 ///    };
 ///
 ///    let mut cache = UnboundedCache::new();
-///    let mut monitor_listener = (RefCell::new(monitor), &*tx_broadcaster, &*fee_estimator, &*logger);
+///            let mut monitor_listener = channelmonitor::MonitorTraits {
+///                    monitor: &mut monitor, broadcaster: &*tx_broadcaster, fee_estimator: &*fee_estimator, logger: &*logger
+///            };
+///            let mut manager_ref = &manager;
 ///    let listeners = vec![
 ///            (monitor_block_hash, &mut monitor_listener as &mut dyn chain::Listen),
-///            (manager_block_hash, &mut manager as &mut dyn chain::Listen),
+///            (manager_block_hash, &mut manager_ref as &mut dyn chain::Listen),
 ///    ];
 ///    let chain_tip =
 ///            init::sync_listeners(block_source, Network::Bitcoin, &mut cache, listeners).await.unwrap();
 ///
-///    let monitor = monitor_listener.0.into_inner();
 ///    chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
 ///
 ///    let chain_poller = poll::ChainPoller::new(block_source, Network::Bitcoin);
@@ -132,7 +134,7 @@ pub async fn sync_listeners<B: BlockSource, C: Cache>(
                // Disconnect any stale blocks, but keep them in the cache for the next iteration.
                let header_cache = &mut ReadOnlyCache(header_cache);
                let (common_ancestor, connected_blocks) = {
-                       let chain_listener = &DynamicChainListener(chain_listener);
+                       let chain_listener = DynamicChainListener(chain_listener);
                        let mut chain_notifier = ChainNotifier { header_cache, chain_listener };
                        let difference =
                                chain_notifier.find_difference(new_header, &old_header, &mut chain_poller).await?;
@@ -150,7 +152,7 @@ pub async fn sync_listeners<B: BlockSource, C: Cache>(
 
        // Connect new blocks for all listeners at once to avoid re-fetching blocks.
        if let Some(common_ancestor) = most_common_ancestor {
-               let chain_listener = &ChainListenerSet(chain_listeners_at_height);
+               let chain_listener = ChainListenerSet(chain_listeners_at_height);
                let mut chain_notifier = ChainNotifier { header_cache, chain_listener };
                chain_notifier.connect_blocks(common_ancestor, most_connected_blocks, &mut chain_poller)
                        .await.or_else(|(e, _)| Err(e))?;
@@ -183,11 +185,11 @@ impl<'a, C: Cache> Cache for ReadOnlyCache<'a, C> {
 struct DynamicChainListener<'a>(&'a mut dyn chain::Listen);
 
 impl<'a> chain::Listen for DynamicChainListener<'a> {
-       fn block_connected(&self, _block: &Block, _height: u32) {
+       fn block_connected(&mut self, _block: &Block, _height: u32) {
                unreachable!()
        }
 
-       fn block_disconnected(&self, header: &BlockHeader, height: u32) {
+       fn block_disconnected(&mut self, header: &BlockHeader, height: u32) {
                self.0.block_disconnected(header, height)
        }
 }
@@ -196,15 +198,15 @@ impl<'a> chain::Listen for DynamicChainListener<'a> {
 struct ChainListenerSet<'a>(Vec<(u32, &'a mut dyn chain::Listen)>);
 
 impl<'a> chain::Listen for ChainListenerSet<'a> {
-       fn block_connected(&self, block: &Block, height: u32) {
-               for (starting_height, chain_listener) in self.0.iter() {
+       fn block_connected(&mut self, block: &Block, height: u32) {
+               for (starting_height, chain_listener) in self.0.iter_mut() {
                        if height > *starting_height {
                                chain_listener.block_connected(block, height);
                        }
                }
        }
 
-       fn block_disconnected(&self, _header: &BlockHeader, _height: u32) {
+       fn block_disconnected(&mut self, _header: &BlockHeader, _height: u32) {
                unreachable!()
        }
 }
index f7e9db97f426f7c378b25164ecd10699ccccec52..614026856a7da322a62a96beb8c3bf90452a0da0 100644 (file)
@@ -159,8 +159,7 @@ pub struct BlockHeaderData {
 /// custom cache eviction policy. This offers flexibility to those sensitive to resource usage.
 /// Hence, there is a trade-off between a lower memory footprint and potentially increased network
 /// I/O as headers are re-fetched during fork detection.
-pub struct SpvClient<'a, P: Poll, C: Cache, L: Deref>
-where L::Target: chain::Listen {
+pub struct SpvClient<'a, P: Poll, C: Cache, L: chain::Listen> {
        chain_tip: ValidatedBlockHeader,
        chain_poller: P,
        chain_notifier: ChainNotifier<'a, C, L>,
@@ -208,7 +207,7 @@ impl Cache for UnboundedCache {
        }
 }
 
-impl<'a, P: Poll, C: Cache, L: Deref> SpvClient<'a, P, C, L> where L::Target: chain::Listen {
+impl<'a, P: Poll, C: Cache, L: chain::Listen> SpvClient<'a, P, C, L> {
        /// Creates a new SPV client using `chain_tip` as the best known chain tip.
        ///
        /// Subsequent calls to [`poll_best_tip`] will poll for the best chain tip using the given chain
@@ -272,7 +271,7 @@ impl<'a, P: Poll, C: Cache, L: Deref> SpvClient<'a, P, C, L> where L::Target: ch
 /// Notifies [listeners] of blocks that have been connected or disconnected from the chain.
 ///
 /// [listeners]: ../../lightning/chain/trait.Listen.html
-pub struct ChainNotifier<'a, C: Cache, L: Deref> where L::Target: chain::Listen {
+pub struct ChainNotifier<'a, C: Cache, L: chain::Listen> {
        /// Cache for looking up headers before fetching from a block source.
        header_cache: &'a mut C,
 
@@ -298,7 +297,7 @@ struct ChainDifference {
        connected_blocks: Vec<ValidatedBlockHeader>,
 }
 
-impl<'a, C: Cache, L: Deref> ChainNotifier<'a, C, L> where L::Target: chain::Listen {
+impl<'a, C: Cache, L: chain::Listen> ChainNotifier<'a, C, L> {
        /// Finds the first common ancestor between `new_header` and `old_header`, disconnecting blocks
        /// from `old_header` to get to that point and then connecting blocks until `new_header`.
        ///
@@ -419,8 +418,8 @@ mod spv_client_tests {
 
                let poller = poll::ChainPoller::new(&mut chain, Network::Testnet);
                let mut cache = UnboundedCache::new();
-               let mut listener = NullChainListener {};
-               let mut client = SpvClient::new(best_tip, poller, &mut cache, &mut listener);
+               let listener = NullChainListener {};
+               let mut client = SpvClient::new(best_tip, poller, &mut cache, listener);
                match client.poll_best_tip().await {
                        Err(e) => {
                                assert_eq!(e.kind(), BlockSourceErrorKind::Persistent);
@@ -438,8 +437,8 @@ mod spv_client_tests {
 
                let poller = poll::ChainPoller::new(&mut chain, Network::Testnet);
                let mut cache = UnboundedCache::new();
-               let mut listener = NullChainListener {};
-               let mut client = SpvClient::new(common_tip, poller, &mut cache, &mut listener);
+               let listener = NullChainListener {};
+               let mut client = SpvClient::new(common_tip, poller, &mut cache, listener);
                match client.poll_best_tip().await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok((chain_tip, blocks_connected)) => {
@@ -458,8 +457,8 @@ mod spv_client_tests {
 
                let poller = poll::ChainPoller::new(&mut chain, Network::Testnet);
                let mut cache = UnboundedCache::new();
-               let mut listener = NullChainListener {};
-               let mut client = SpvClient::new(old_tip, poller, &mut cache, &mut listener);
+               let listener = NullChainListener {};
+               let mut client = SpvClient::new(old_tip, poller, &mut cache, listener);
                match client.poll_best_tip().await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok((chain_tip, blocks_connected)) => {
@@ -478,8 +477,8 @@ mod spv_client_tests {
 
                let poller = poll::ChainPoller::new(&mut chain, Network::Testnet);
                let mut cache = UnboundedCache::new();
-               let mut listener = NullChainListener {};
-               let mut client = SpvClient::new(old_tip, poller, &mut cache, &mut listener);
+               let listener = NullChainListener {};
+               let mut client = SpvClient::new(old_tip, poller, &mut cache, listener);
                match client.poll_best_tip().await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok((chain_tip, blocks_connected)) => {
@@ -498,8 +497,8 @@ mod spv_client_tests {
 
                let poller = poll::ChainPoller::new(&mut chain, Network::Testnet);
                let mut cache = UnboundedCache::new();
-               let mut listener = NullChainListener {};
-               let mut client = SpvClient::new(old_tip, poller, &mut cache, &mut listener);
+               let listener = NullChainListener {};
+               let mut client = SpvClient::new(old_tip, poller, &mut cache, listener);
                match client.poll_best_tip().await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok((chain_tip, blocks_connected)) => {
@@ -519,8 +518,8 @@ mod spv_client_tests {
 
                let poller = poll::ChainPoller::new(&mut chain, Network::Testnet);
                let mut cache = UnboundedCache::new();
-               let mut listener = NullChainListener {};
-               let mut client = SpvClient::new(best_tip, poller, &mut cache, &mut listener);
+               let listener = NullChainListener {};
+               let mut client = SpvClient::new(best_tip, poller, &mut cache, listener);
                match client.poll_best_tip().await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok((chain_tip, blocks_connected)) => {
@@ -545,7 +544,7 @@ mod chain_notifier_tests {
 
                let new_tip = chain.tip();
                let old_tip = chain.at_height(1);
-               let chain_listener = &MockChainListener::new()
+               let chain_listener = MockChainListener::new()
                        .expect_block_connected(*chain.at_height(2))
                        .expect_block_connected(*new_tip);
                let mut notifier = ChainNotifier {
@@ -566,7 +565,7 @@ mod chain_notifier_tests {
 
                let new_tip = test_chain.tip();
                let old_tip = main_chain.tip();
-               let chain_listener = &MockChainListener::new();
+               let chain_listener = MockChainListener::new();
                let mut notifier = ChainNotifier {
                        header_cache: &mut main_chain.header_cache(0..=1),
                        chain_listener,
@@ -588,7 +587,7 @@ mod chain_notifier_tests {
 
                let new_tip = fork_chain.tip();
                let old_tip = main_chain.tip();
-               let chain_listener = &MockChainListener::new()
+               let chain_listener = MockChainListener::new()
                        .expect_block_disconnected(*old_tip)
                        .expect_block_connected(*new_tip);
                let mut notifier = ChainNotifier {
@@ -610,7 +609,7 @@ mod chain_notifier_tests {
 
                let new_tip = fork_chain.tip();
                let old_tip = main_chain.tip();
-               let chain_listener = &MockChainListener::new()
+               let chain_listener = MockChainListener::new()
                        .expect_block_disconnected(*old_tip)
                        .expect_block_disconnected(*main_chain.at_height(2))
                        .expect_block_connected(*new_tip);
@@ -633,7 +632,7 @@ mod chain_notifier_tests {
 
                let new_tip = fork_chain.tip();
                let old_tip = main_chain.tip();
-               let chain_listener = &MockChainListener::new()
+               let chain_listener = MockChainListener::new()
                        .expect_block_disconnected(*old_tip)
                        .expect_block_connected(*fork_chain.at_height(2))
                        .expect_block_connected(*new_tip);
@@ -654,7 +653,7 @@ mod chain_notifier_tests {
 
                let new_tip = chain.tip();
                let old_tip = chain.at_height(1);
-               let chain_listener = &MockChainListener::new();
+               let chain_listener = MockChainListener::new();
                let mut notifier = ChainNotifier {
                        header_cache: &mut chain.header_cache(0..=1),
                        chain_listener,
@@ -672,7 +671,7 @@ mod chain_notifier_tests {
 
                let new_tip = chain.tip();
                let old_tip = chain.at_height(1);
-               let chain_listener = &MockChainListener::new();
+               let chain_listener = MockChainListener::new();
                let mut notifier = ChainNotifier {
                        header_cache: &mut chain.header_cache(0..=3),
                        chain_listener,
@@ -690,7 +689,7 @@ mod chain_notifier_tests {
 
                let new_tip = chain.tip();
                let old_tip = chain.at_height(1);
-               let chain_listener = &MockChainListener::new()
+               let chain_listener = MockChainListener::new()
                        .expect_block_connected(*chain.at_height(2));
                let mut notifier = ChainNotifier {
                        header_cache: &mut chain.header_cache(0..=3),
index 8c37c94d8ec4c2146d978170fd66ccf1fae75172..093266e3e6fa5046c67cc3b4122d621db635f6d5 100644 (file)
@@ -166,8 +166,8 @@ impl BlockSource for Blockchain {
 pub struct NullChainListener;
 
 impl chain::Listen for NullChainListener {
-       fn block_connected(&self, _block: &Block, _height: u32) {}
-       fn block_disconnected(&self, _header: &BlockHeader, _height: u32) {}
+       fn block_connected(&mut self, _block: &Block, _height: u32) {}
+       fn block_disconnected(&mut self, _header: &BlockHeader, _height: u32) {}
 }
 
 pub struct MockChainListener {
@@ -195,7 +195,7 @@ impl MockChainListener {
 }
 
 impl chain::Listen for MockChainListener {
-       fn block_connected(&self, block: &Block, height: u32) {
+       fn block_connected(&mut self, block: &Block, height: u32) {
                match self.expected_blocks_connected.borrow_mut().pop_front() {
                        None => {
                                panic!("Unexpected block connected: {:?}", block.block_hash());
@@ -207,7 +207,7 @@ impl chain::Listen for MockChainListener {
                }
        }
 
-       fn block_disconnected(&self, header: &BlockHeader, height: u32) {
+       fn block_disconnected(&mut self, header: &BlockHeader, height: u32) {
                match self.expected_blocks_disconnected.borrow_mut().pop_front() {
                        None => {
                                panic!("Unexpected block disconnected: {:?}", header.block_hash());
index 4cb9128d92fdbd826bf92f2cd62c5a25cd401dff..a3d0d22b1a5530142a134046150d3bbdd3fd4fbe 100644 (file)
@@ -141,7 +141,7 @@ where C::Target: chain::Filter,
 }
 
 impl<ChannelSigner: Sign, C: Deref + Send + Sync, T: Deref + Send + Sync, F: Deref + Send + Sync, L: Deref + Send + Sync, P: Deref + Send + Sync>
-chain::Listen for ChainMonitor<ChannelSigner, C, T, F, L, P>
+chain::sealed::DerefListen for ChainMonitor<ChannelSigner, C, T, F, L, P>
 where
        ChannelSigner: Sign,
        C::Target: chain::Filter,
index 71490dd6e0e1af4de7b19b71e8699da47d5c2f46..4e2ca659f724dc74b9157005eb644b9c5696e500 100644 (file)
@@ -53,7 +53,7 @@ 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::ops::{Deref, DerefMut};
 use std::io::Error;
 
 /// An update generated by the underlying Channel itself which contains some new information the
@@ -2299,19 +2299,33 @@ pub trait Persist<ChannelSigner: Sign>: Send + Sync {
        fn update_persisted_channel(&self, id: OutPoint, update: &ChannelMonitorUpdate, data: &ChannelMonitor<ChannelSigner>) -> Result<(), ChannelMonitorUpdateErr>;
 }
 
-impl<Signer: Sign, T: Deref, F: Deref, L: Deref> chain::Listen for (RefCell<ChannelMonitor<Signer>>, T, F, L)
+
+/// does things
+pub struct MonitorTraits<CM: DerefMut<Target=ChannelMonitor<Signer>>, Signer: Sign, T: Deref, F: Deref, L: Deref> {
+       /// a
+       pub monitor: CM,
+       /// b
+       pub broadcaster: T,
+       /// c
+       pub fee_estimator: F,
+       /// d
+       pub logger: L,
+}
+
+impl<CM: DerefMut<Target=ChannelMonitor<Signer>>, Signer: Sign, T: Deref, F: Deref, L: Deref>
+chain::Listen for MonitorTraits<CM, Signer, T, F, L>
 where
        T::Target: BroadcasterInterface,
        F::Target: FeeEstimator,
        L::Target: Logger,
 {
-       fn block_connected(&self, block: &Block, height: u32) {
+       fn block_connected(&mut 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.monitor.block_connected(&block.header, &txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
        }
 
-       fn block_disconnected(&self, header: &BlockHeader, height: u32) {
-               self.0.borrow_mut().block_disconnected(header, height, &*self.1, &*self.2, &*self.3);
+       fn block_disconnected(&mut self, header: &BlockHeader, height: u32) {
+               self.monitor.block_disconnected(header, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
        }
 }
 
index c1fceec8c47171969397558db0ce62d11faf93ed..86f35ebca4860b84c81c68e1e95253f638a67e54 100644 (file)
@@ -18,6 +18,8 @@ use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitor
 use chain::keysinterface::Sign;
 use chain::transaction::OutPoint;
 
+use std::ops::Deref;
+
 pub mod chaininterface;
 pub mod chainmonitor;
 pub mod channelmonitor;
@@ -53,12 +55,44 @@ pub trait Access: Send + Sync {
 /// Useful when needing to replay chain data upon startup or as new chain events occur.
 pub trait Listen {
        /// Notifies the listener that a block was added at the given height.
-       fn block_connected(&self, block: &Block, height: u32);
+       fn block_connected(&mut self, block: &Block, height: u32);
 
        /// Notifies the listener that a block was removed at the given height.
-       fn block_disconnected(&self, header: &BlockHeader, height: u32);
+       fn block_disconnected(&mut self, header: &BlockHeader, height: u32);
+}
+
+pub(crate) mod sealed {
+       use super::*;
+       /// Rustc currently isn't smart enough to figure out that two impls are not conflicting when they
+       /// both impl for `Deref` but with a different `Target`
+       /// (https://github.com/rust-lang/rust/issues/20400). Instead, we use the workaround suggested at
+       /// https://stackoverflow.com/questions/40392524/conflicting-trait-implementations-even-though-associated-types-differ/40408431#40408431
+       pub trait DerefListen {
+               fn block_connected(&self, block: &Block, height: u32);
+               fn block_disconnected(&self, header: &BlockHeader, height: u32);
+       }
+       impl<T: Deref, U: Deref> DerefListen for (T, U) where T::Target: DerefListen, U::Target: DerefListen {
+               fn block_connected(&self, block: &Block, height: u32) {
+                       Deref::deref(&self.0).block_connected(block, height);
+                       Deref::deref(&self.1).block_connected(block, height);
+               }
+
+               fn block_disconnected(&self, header: &BlockHeader, height: u32) {
+                       Deref::deref(&self.0).block_disconnected(header, height);
+                       Deref::deref(&self.1).block_disconnected(header, height);
+               }
+       }
+}
+impl<T: Deref> Listen for T where T::Target: sealed::DerefListen {
+       fn block_connected(&mut self, block: &Block, height: u32) {
+               sealed::DerefListen::block_connected(Deref::deref(self), block, height);
+       }
+       fn block_disconnected(&mut self, header: &BlockHeader, height: u32) {
+               sealed::DerefListen::block_disconnected(Deref::deref(self), header, height);
+       }
 }
 
+
 /// The `Watch` trait defines behavior for watching on-chain activity pertaining to channels as
 /// blocks are connected and disconnected.
 ///
@@ -136,29 +170,3 @@ pub trait Filter: Send + Sync {
        /// `script_pubkey` as the spending condition.
        fn register_output(&self, outpoint: &OutPoint, script_pubkey: &Script);
 }
-
-impl<T: Listen> Listen for std::ops::Deref<Target = T> {
-       fn block_connected(&self, block: &Block, height: u32) {
-               (**self).block_connected(block, height);
-       }
-
-       fn block_disconnected(&self, header: &BlockHeader, height: u32) {
-               (**self).block_disconnected(header, height);
-       }
-}
-
-impl<T: std::ops::Deref, U: std::ops::Deref> Listen for (T, U)
-where
-       T::Target: Listen,
-       U::Target: Listen,
-{
-       fn block_connected(&self, block: &Block, height: u32) {
-               self.0.block_connected(block, height);
-               self.1.block_connected(block, height);
-       }
-
-       fn block_disconnected(&self, header: &BlockHeader, height: u32) {
-               self.0.block_disconnected(header, height);
-               self.1.block_disconnected(header, height);
-       }
-}
index 8f7fbde5f9cb131312ea2ae0d8be6df4b634474a..ec2f1e4cc24fc5036f7e42de1302c91f67e8fa1b 100644 (file)
@@ -3139,7 +3139,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> EventsProvi
        }
 }
 
-impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> chain::Listen for ChannelManager<Signer, M, T, K, F, L>
+impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> chain::sealed::DerefListen for ChannelManager<Signer, M, T, K, F, L>
 where
        M::Target: chain::Watch<Signer>,
        T::Target: BroadcasterInterface,