From b10217590b82574d4e0f949774da50ecf630d12b Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Fri, 15 Apr 2022 09:03:00 -0500 Subject: [PATCH 1/3] Allow &dyn BlockSource in lightning-block-sync Update lightning-block-sync's init and poll modules to support &dyn BlockSource such that the BlockSource can be determined at runtime. --- lightning-block-sync/src/init.rs | 14 ++++++++------ lightning-block-sync/src/poll.rs | 6 +++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lightning-block-sync/src/init.rs b/lightning-block-sync/src/init.rs index 6611d185da3..c1f53b70171 100644 --- a/lightning-block-sync/src/init.rs +++ b/lightning-block-sync/src/init.rs @@ -10,14 +10,16 @@ use bitcoin::network::constants::Network; use lightning::chain; +use std::ops::Deref; + /// Returns a validated block header of the source's best chain tip. /// /// Upon success, the returned header can be used to initialize [`SpvClient`]. Useful during a fresh /// start when there are no chain listeners to sync yet. /// /// [`SpvClient`]: crate::SpvClient -pub async fn validate_best_block_header(block_source: &B) -> -BlockSourceResult { +pub async fn validate_best_block_header(block_source: B) -> +BlockSourceResult where B::Target: BlockSource { let (best_block_hash, best_block_height) = block_source.get_best_block().await?; block_source .get_header(&best_block_hash, best_block_height).await? @@ -121,13 +123,13 @@ BlockSourceResult { /// [`SpvClient`]: crate::SpvClient /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager /// [`ChannelMonitor`]: lightning::chain::channelmonitor::ChannelMonitor -pub async fn synchronize_listeners<'a, B: BlockSource, C: Cache, L: chain::Listen + ?Sized>( - block_source: &B, +pub async fn synchronize_listeners<'a, B: Deref + Sized + Send + Sync, C: Cache, L: chain::Listen + ?Sized>( + block_source: B, network: Network, header_cache: &mut C, mut chain_listeners: Vec<(BlockHash, &'a L)>, -) -> BlockSourceResult { - let best_header = validate_best_block_header(block_source).await?; +) -> BlockSourceResult where B::Target: BlockSource { + let best_header = validate_best_block_header(&*block_source).await?; // Fetch the header for the block hash paired with each listener. let mut chain_listeners_with_old_headers = Vec::new(); diff --git a/lightning-block-sync/src/poll.rs b/lightning-block-sync/src/poll.rs index b32d2239f69..6e30d2e86d2 100644 --- a/lightning-block-sync/src/poll.rs +++ b/lightning-block-sync/src/poll.rs @@ -170,12 +170,12 @@ mod sealed { /// /// Other `Poll` implementations should be built using `ChainPoller` as it provides the simplest way /// of validating chain data and checking consistency. -pub struct ChainPoller + Sized, T: BlockSource> { +pub struct ChainPoller + Sized + Send + Sync, T: BlockSource + ?Sized> { block_source: B, network: Network, } -impl + Sized, T: BlockSource> ChainPoller { +impl + Sized + Send + Sync, T: BlockSource + ?Sized> ChainPoller { /// Creates a new poller for the given block source. /// /// If the `network` parameter is mainnet, then the difficulty between blocks is checked for @@ -185,7 +185,7 @@ impl + Sized, T: BlockSource> ChainPoller { } } -impl + Sized + Send + Sync, T: BlockSource> Poll for ChainPoller { +impl + Sized + Send + Sync, T: BlockSource + ?Sized> Poll for ChainPoller { fn poll_chain_tip<'a>(&'a self, best_known_chain_tip: ValidatedBlockHeader) -> AsyncBlockSourceResult<'a, ChainTip> { From 8967d20b299db92991ffa03fc7cc3df361b6619c Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Fri, 15 Apr 2022 10:32:51 -0500 Subject: [PATCH 2/3] Remove mut in lightning-block-sync tests --- lightning-block-sync/src/init.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lightning-block-sync/src/init.rs b/lightning-block-sync/src/init.rs index c1f53b70171..5ba6ba39a8f 100644 --- a/lightning-block-sync/src/init.rs +++ b/lightning-block-sync/src/init.rs @@ -238,7 +238,7 @@ mod tests { #[tokio::test] async fn sync_from_same_chain() { - let mut chain = Blockchain::default().with_height(4); + let chain = Blockchain::default().with_height(4); let listener_1 = MockChainListener::new() .expect_block_connected(*chain.at_height(2)) @@ -256,7 +256,7 @@ mod tests { (chain.at_height(3).block_hash, &listener_3 as &dyn chain::Listen), ]; let mut cache = chain.header_cache(0..=4); - match synchronize_listeners(&mut chain, Network::Bitcoin, &mut cache, listeners).await { + match synchronize_listeners(&chain, Network::Bitcoin, &mut cache, listeners).await { Ok(header) => assert_eq!(header, chain.tip()), Err(e) => panic!("Unexpected error: {:?}", e), } @@ -264,7 +264,7 @@ mod tests { #[tokio::test] async fn sync_from_different_chains() { - let mut main_chain = Blockchain::default().with_height(4); + let main_chain = Blockchain::default().with_height(4); let fork_chain_1 = main_chain.fork_at_height(1); let fork_chain_2 = main_chain.fork_at_height(2); let fork_chain_3 = main_chain.fork_at_height(3); @@ -293,7 +293,7 @@ mod tests { let mut cache = fork_chain_1.header_cache(2..=4); cache.extend(fork_chain_2.header_cache(3..=4)); cache.extend(fork_chain_3.header_cache(4..=4)); - match synchronize_listeners(&mut main_chain, Network::Bitcoin, &mut cache, listeners).await { + match synchronize_listeners(&main_chain, Network::Bitcoin, &mut cache, listeners).await { Ok(header) => assert_eq!(header, main_chain.tip()), Err(e) => panic!("Unexpected error: {:?}", e), } @@ -301,7 +301,7 @@ mod tests { #[tokio::test] async fn sync_from_overlapping_chains() { - let mut main_chain = Blockchain::default().with_height(4); + let main_chain = Blockchain::default().with_height(4); let fork_chain_1 = main_chain.fork_at_height(1); let fork_chain_2 = fork_chain_1.fork_at_height(2); let fork_chain_3 = fork_chain_2.fork_at_height(3); @@ -336,7 +336,7 @@ mod tests { let mut cache = fork_chain_1.header_cache(2..=4); cache.extend(fork_chain_2.header_cache(3..=4)); cache.extend(fork_chain_3.header_cache(4..=4)); - match synchronize_listeners(&mut main_chain, Network::Bitcoin, &mut cache, listeners).await { + match synchronize_listeners(&main_chain, Network::Bitcoin, &mut cache, listeners).await { Ok(header) => assert_eq!(header, main_chain.tip()), Err(e) => panic!("Unexpected error: {:?}", e), } @@ -344,7 +344,7 @@ mod tests { #[tokio::test] async fn cache_connected_and_keep_disconnected_blocks() { - let mut main_chain = Blockchain::default().with_height(2); + let main_chain = Blockchain::default().with_height(2); let fork_chain = main_chain.fork_at_height(1); let new_tip = main_chain.tip(); let old_tip = fork_chain.tip(); @@ -355,7 +355,7 @@ mod tests { let listeners = vec![(old_tip.block_hash, &listener as &dyn chain::Listen)]; let mut cache = fork_chain.header_cache(2..=2); - match synchronize_listeners(&mut main_chain, Network::Bitcoin, &mut cache, listeners).await { + match synchronize_listeners(&main_chain, Network::Bitcoin, &mut cache, listeners).await { Ok(_) => { assert!(cache.contains_key(&new_tip.block_hash)); assert!(cache.contains_key(&old_tip.block_hash)); From b902cc7c49f7495c56c057e8e02f8faa2091c540 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Fri, 15 Apr 2022 11:34:51 -0500 Subject: [PATCH 3/3] Remove unnecessary lifetime bound --- lightning-block-sync/src/init.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning-block-sync/src/init.rs b/lightning-block-sync/src/init.rs index 5ba6ba39a8f..f5d839d21ca 100644 --- a/lightning-block-sync/src/init.rs +++ b/lightning-block-sync/src/init.rs @@ -123,11 +123,11 @@ BlockSourceResult where B::Target: BlockSource { /// [`SpvClient`]: crate::SpvClient /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager /// [`ChannelMonitor`]: lightning::chain::channelmonitor::ChannelMonitor -pub async fn synchronize_listeners<'a, B: Deref + Sized + Send + Sync, C: Cache, L: chain::Listen + ?Sized>( +pub async fn synchronize_listeners( block_source: B, network: Network, header_cache: &mut C, - mut chain_listeners: Vec<(BlockHash, &'a L)>, + mut chain_listeners: Vec<(BlockHash, &L)>, ) -> BlockSourceResult where B::Target: BlockSource { let best_header = validate_best_block_header(&*block_source).await?;