Skip to content

Commit 74e8d8d

Browse files
committed
Parameterize MicroSPVClient by ChainListener
1 parent 7546fd6 commit 74e8d8d

File tree

1 file changed

+23
-24
lines changed
  • lightning-block-sync/src

1 file changed

+23
-24
lines changed

lightning-block-sync/src/lib.rs

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -427,14 +427,14 @@ pub(crate) type HeaderCache = std::collections::HashMap<BlockHash, ValidatedBloc
427427
/// This prevents one block source from being able to orphan us on a fork of its own creation by
428428
/// not responding to requests for old headers on that fork. However, if one block source is
429429
/// unreachable this may result in our memory usage growing in accordance with the chain.
430-
pub struct MicroSPVClient<P: Poll> {
430+
pub struct MicroSPVClient<P: Poll, CL: ChainListener> {
431431
chain_tip: ValidatedBlockHeader,
432432
chain_poller: P,
433433
chain_notifier: ChainNotifier,
434+
chain_listener: CL,
434435
}
435436

436-
impl<P: Poll> MicroSPVClient<P> {
437-
437+
impl<P: Poll, CL: ChainListener> MicroSPVClient<P, CL> {
438438
/// Creates a new `MicroSPVClient` with a chain poller for polling one or more block sources and
439439
/// a chain listener for receiving updates of the new chain tip.
440440
///
@@ -447,24 +447,22 @@ impl<P: Poll> MicroSPVClient<P> {
447447
/// useful when you have a block source which is more censorship-resistant than others but
448448
/// which only provides headers. In this case, we can use such source(s) to learn of a censorship
449449
/// attack without giving up privacy by querying a privacy-losing block sources.
450-
pub fn init(chain_tip: ValidatedBlockHeader, chain_poller: P) -> Self {
450+
pub fn init(chain_tip: ValidatedBlockHeader, chain_poller: P, chain_listener: CL) -> Self {
451451
let header_cache = HeaderCache::new();
452452
let chain_notifier = ChainNotifier { header_cache };
453-
Self { chain_tip, chain_poller, chain_notifier }
453+
Self { chain_tip, chain_poller, chain_notifier, chain_listener }
454454
}
455455

456456
/// Check each source for a new best tip and update the chain listener accordingly.
457457
/// Returns true if some blocks were [dis]connected, false otherwise.
458-
pub async fn poll_best_tip<CL: ChainListener>(&mut self, chain_listener: &mut CL) ->
459-
BlockSourceResult<(ChainTip, bool)>
460-
{
458+
pub async fn poll_best_tip(&mut self) -> BlockSourceResult<(ChainTip, bool)> {
461459
let chain_tip = self.chain_poller.poll_chain_tip(self.chain_tip).await?;
462460
let blocks_connected = match chain_tip {
463461
ChainTip::Common => false,
464462
ChainTip::Better(chain_tip) => {
465463
debug_assert_ne!(chain_tip.block_hash, self.chain_tip.block_hash);
466464
debug_assert!(chain_tip.chainwork > self.chain_tip.chainwork);
467-
self.update_chain_tip(chain_tip, chain_listener).await
465+
self.update_chain_tip(chain_tip).await
468466
},
469467
ChainTip::Worse(chain_tip) => {
470468
debug_assert_ne!(chain_tip.block_hash, self.chain_tip.block_hash);
@@ -477,8 +475,8 @@ impl<P: Poll> MicroSPVClient<P> {
477475

478476
/// Updates the chain tip, syncing the chain listener with any connected or disconnected
479477
/// blocks. Returns whether there were any such blocks.
480-
async fn update_chain_tip<CL: ChainListener>(&mut self, best_chain_tip: ValidatedBlockHeader, chain_listener: &mut CL) -> bool {
481-
match self.chain_notifier.sync_listener(best_chain_tip, &self.chain_tip, &mut self.chain_poller, chain_listener).await {
478+
async fn update_chain_tip(&mut self, best_chain_tip: ValidatedBlockHeader) -> bool {
479+
match self.chain_notifier.sync_listener(best_chain_tip, &self.chain_tip, &mut self.chain_poller, &mut self.chain_listener).await {
482480
Ok(_) => {
483481
self.chain_tip = best_chain_tip;
484482
true
@@ -643,13 +641,13 @@ mod tests {
643641
use bitcoin::blockdata::block::{Block, BlockHeader};
644642
use bitcoin::util::uint::Uint256;
645643
use std::collections::HashMap;
646-
use std::sync::Mutex;
644+
use std::sync::{Arc, Mutex};
647645

648646
struct TestChainListener {
649647
blocks_connected: Mutex<Vec<(BlockHash, u32)>>,
650648
blocks_disconnected: Mutex<Vec<(BlockHash, u32)>>,
651649
}
652-
impl ChainListener for TestChainListener {
650+
impl ChainListener for Arc<TestChainListener> {
653651
fn block_connected(&mut self, block: &Block, height: u32) {
654652
self.blocks_connected.lock().unwrap().push((block.header.block_hash(), height));
655653
}
@@ -882,9 +880,9 @@ mod tests {
882880
};
883881

884882
// Stand up a client at block_1a with all four sources:
885-
let mut chain_listener = TestChainListener {
883+
let chain_listener = Arc::new(TestChainListener {
886884
blocks_connected: Mutex::new(Vec::new()), blocks_disconnected: Mutex::new(Vec::new())
887-
};
885+
});
888886
let mut source_one = &chain_one;
889887
let mut source_two = &chain_two;
890888
let mut source_three = &header_chain;
@@ -894,10 +892,11 @@ mod tests {
894892
poller::ChainMultiplexer::new(
895893
vec![&mut source_one as &mut dyn BlockSource, &mut source_two as &mut dyn BlockSource, &mut source_three as &mut dyn BlockSource],
896894
vec![&mut source_four as &mut dyn BlockSource],
897-
Network::Bitcoin));
895+
Network::Bitcoin),
896+
Arc::clone(&chain_listener));
898897

899898
// Test that we will reorg onto 2b because chain_one knows about 1b + 2b
900-
match client.poll_best_tip(&mut chain_listener).await {
899+
match client.poll_best_tip().await {
901900
Ok((ChainTip::Better(chain_tip), blocks_connected)) => {
902901
assert_eq!(chain_tip.block_hash, block_2b_hash);
903902
assert!(blocks_connected);
@@ -919,7 +918,7 @@ mod tests {
919918
chain_listener.blocks_disconnected.lock().unwrap().clear();
920919

921920
// First test that nothing happens if nothing changes:
922-
match client.poll_best_tip(&mut chain_listener).await {
921+
match client.poll_best_tip().await {
923922
Ok((ChainTip::Common, blocks_connected)) => {
924923
assert!(!blocks_connected);
925924
},
@@ -933,7 +932,7 @@ mod tests {
933932
chain_two.blocks.lock().unwrap().insert(block_3a_hash, block_3a.clone());
934933
*chain_two.best_block.lock().unwrap() = (block_3a_hash, Some(3));
935934

936-
match client.poll_best_tip(&mut chain_listener).await {
935+
match client.poll_best_tip().await {
937936
Ok((ChainTip::Better(chain_tip), blocks_connected)) => {
938937
assert_eq!(chain_tip.block_hash, block_3a_hash);
939938
assert!(blocks_connected);
@@ -957,7 +956,7 @@ mod tests {
957956
// the block header cache.
958957
*chain_one.best_block.lock().unwrap() = (block_3a_hash, Some(3));
959958
*header_chain.best_block.lock().unwrap() = (block_3a_hash, Some(3));
960-
match client.poll_best_tip(&mut chain_listener).await {
959+
match client.poll_best_tip().await {
961960
Ok((ChainTip::Common, blocks_connected)) => {
962961
assert!(!blocks_connected);
963962
},
@@ -976,7 +975,7 @@ mod tests {
976975
*header_chain.best_block.lock().unwrap() = (block_4a_hash, Some(4));
977976
*backup_chain.disallowed.lock().unwrap() = false;
978977

979-
match client.poll_best_tip(&mut chain_listener).await {
978+
match client.poll_best_tip().await {
980979
Ok((ChainTip::Better(chain_tip), blocks_connected)) => {
981980
assert_eq!(chain_tip.block_hash, block_4a_hash);
982981
assert!(!blocks_connected);
@@ -991,7 +990,7 @@ mod tests {
991990
backup_chain.blocks.lock().unwrap().insert(block_4a_hash, block_4a);
992991
*backup_chain.best_block.lock().unwrap() = (block_4a_hash, Some(4));
993992

994-
match client.poll_best_tip(&mut chain_listener).await {
993+
match client.poll_best_tip().await {
995994
Ok((ChainTip::Better(chain_tip), blocks_connected)) => {
996995
assert_eq!(chain_tip.block_hash, block_4a_hash);
997996
assert!(blocks_connected);
@@ -1019,7 +1018,7 @@ mod tests {
10191018
// We'll check the backup chain last, so don't give it 4a, as otherwise we'll connect it:
10201019
*backup_chain.best_block.lock().unwrap() = (block_3a_hash, Some(3));
10211020

1022-
match client.poll_best_tip(&mut chain_listener).await {
1021+
match client.poll_best_tip().await {
10231022
Ok((ChainTip::Better(chain_tip), blocks_disconnected)) => {
10241023
assert_eq!(chain_tip.block_hash, block_5c_hash);
10251024
assert!(blocks_disconnected);
@@ -1034,7 +1033,7 @@ mod tests {
10341033
// Now reset the headers chain to 4a and test that we end up back there.
10351034
*backup_chain.best_block.lock().unwrap() = (block_4a_hash, Some(4));
10361035
*header_chain.best_block.lock().unwrap() = (block_4a_hash, Some(4));
1037-
match client.poll_best_tip(&mut chain_listener).await {
1036+
match client.poll_best_tip().await {
10381037
Ok((ChainTip::Better(chain_tip), blocks_connected)) => {
10391038
assert_eq!(chain_tip.block_hash, block_4a_hash);
10401039
assert!(blocks_connected);

0 commit comments

Comments
 (0)