44//! [`Emitter`] is the main structure which sources blockchain data from [`bitcoincore_rpc::Client`].
55//!
66//! To only get block updates (exclude mempool transactions), the caller can use
7- //! [`Emitter::next_block`] or/and [`Emitter::next_header`] until it returns `Ok(None)` (which means
8- //! the chain tip is reached). A separate method, [`Emitter::mempool`] can be used to emit the whole
9- //! mempool.
7+ //! [`Emitter::next_block`] until it returns `Ok(None)` (which means the chain tip is reached). A
8+ //! separate method, [`Emitter::mempool`] can be used to emit the whole mempool.
109#![ warn( missing_docs) ]
1110
1211use bdk_core:: { BlockId , CheckPoint } ;
1312use bitcoin:: { Block , BlockHash , Transaction , Txid } ;
14- use bitcoincore_rpc:: bitcoincore_rpc_json;
15- use std:: collections:: HashSet ;
13+ use bitcoincore_rpc:: { bitcoincore_rpc_json, RpcApi } ;
14+ use std:: { collections:: HashSet , ops :: Deref } ;
1615
1716pub mod bip158;
1817
@@ -23,8 +22,8 @@ pub use bitcoincore_rpc;
2322/// Refer to [module-level documentation] for more.
2423///
2524/// [module-level documentation]: crate
26- pub struct Emitter < ' c , C > {
27- client : & ' c C ,
25+ pub struct Emitter < C > {
26+ client : C ,
2827 start_height : u32 ,
2928
3029 /// The checkpoint of the last-emitted block that is in the best chain. If it is later found
@@ -56,7 +55,17 @@ pub struct Emitter<'c, C> {
5655 expected_mempool_txids : HashSet < Txid > ,
5756}
5857
59- impl < ' c , C : bitcoincore_rpc:: RpcApi > Emitter < ' c , C > {
58+ /// Indicates that there are no initially expected mempool transactions.
59+ ///
60+ /// Pass this to the `expected_mempool_txids` field of [`Emitter::new`] when the wallet is known
61+ /// to start empty (i.e. with no unconfirmed transactions).
62+ pub const NO_EXPECTED_MEMPOOL_TXIDS : core:: iter:: Empty < Txid > = core:: iter:: empty ( ) ;
63+
64+ impl < C > Emitter < C >
65+ where
66+ C : Deref ,
67+ C :: Target : RpcApi ,
68+ {
6069 /// Construct a new [`Emitter`].
6170 ///
6271 /// `last_cp` informs the emitter of the chain we are starting off with. This way, the emitter
@@ -66,12 +75,13 @@ impl<'c, C: bitcoincore_rpc::RpcApi> Emitter<'c, C> {
6675 /// original chain).
6776 ///
6877 /// `expected_mempool_txids` is the initial set of unconfirmed txids provided by the wallet.
69- /// This allows the [`Emitter`] to inform the wallet about relevant mempool evictions.
78+ /// This allows the [`Emitter`] to inform the wallet about relevant mempool evictions. If it is
79+ /// known that the wallet is empty, [`NO_EXPECTED_MEMPOOL_TXIDS`] can be used.
7080 pub fn new (
71- client : & ' c C ,
81+ client : C ,
7282 last_cp : CheckPoint ,
7383 start_height : u32 ,
74- expected_mempool_txids : HashSet < Txid > ,
84+ expected_mempool_txids : impl IntoIterator < Item = impl Into < Txid > > ,
7585 ) -> Self {
7686 Self {
7787 client,
@@ -80,7 +90,7 @@ impl<'c, C: bitcoincore_rpc::RpcApi> Emitter<'c, C> {
8090 last_block : None ,
8191 last_mempool_time : 0 ,
8292 last_mempool_tip : None ,
83- expected_mempool_txids,
93+ expected_mempool_txids : expected_mempool_txids . into_iter ( ) . map ( Into :: into ) . collect ( ) ,
8494 }
8595 }
8696
@@ -102,7 +112,7 @@ impl<'c, C: bitcoincore_rpc::RpcApi> Emitter<'c, C> {
102112 /// of height `h-1`, we want to re-emit this transaction until the receiver has seen the block
103113 /// at height `h`.
104114 pub fn mempool ( & mut self ) -> Result < MempoolEvent , bitcoincore_rpc:: Error > {
105- let client = self . client ;
115+ let client = & * self . client ;
106116
107117 // This is the emitted tip height during the last mempool emission.
108118 let prev_mempool_tip = self
@@ -204,7 +214,7 @@ impl<'c, C: bitcoincore_rpc::RpcApi> Emitter<'c, C> {
204214
205215 /// Emit the next block height and block (if any).
206216 pub fn next_block ( & mut self ) -> Result < Option < BlockEvent < Block > > , bitcoincore_rpc:: Error > {
207- if let Some ( ( checkpoint, block) ) = poll ( self , |hash| self . client . get_block ( hash) ) ? {
217+ if let Some ( ( checkpoint, block) ) = poll ( self , move |hash, client| client. get_block ( hash) ) ? {
208218 // Stop tracking unconfirmed transactions that have been confirmed in this block.
209219 for tx in & block. txdata {
210220 self . expected_mempool_txids . remove ( & tx. compute_txid ( ) ) ;
@@ -247,7 +257,7 @@ impl MempoolEvent {
247257/// A newly emitted block from [`Emitter`].
248258#[ derive( Debug ) ]
249259pub struct BlockEvent < B > {
250- /// Either a full [`Block`] or [`Header`] of the new block.
260+ /// The block.
251261 pub block : B ,
252262
253263 /// The checkpoint of the new block.
@@ -299,9 +309,10 @@ enum PollResponse {
299309
300310fn poll_once < C > ( emitter : & Emitter < C > ) -> Result < PollResponse , bitcoincore_rpc:: Error >
301311where
302- C : bitcoincore_rpc:: RpcApi ,
312+ C : Deref ,
313+ C :: Target : RpcApi ,
303314{
304- let client = emitter. client ;
315+ let client = & * emitter. client ;
305316
306317 if let Some ( last_res) = & emitter. last_block {
307318 let next_hash = if last_res. height < emitter. start_height as _ {
@@ -355,15 +366,16 @@ fn poll<C, V, F>(
355366 get_item : F ,
356367) -> Result < Option < ( CheckPoint , V ) > , bitcoincore_rpc:: Error >
357368where
358- C : bitcoincore_rpc:: RpcApi ,
359- F : Fn ( & BlockHash ) -> Result < V , bitcoincore_rpc:: Error > ,
369+ C : Deref ,
370+ C :: Target : RpcApi ,
371+ F : Fn ( & BlockHash , & C :: Target ) -> Result < V , bitcoincore_rpc:: Error > ,
360372{
361373 loop {
362374 match poll_once ( emitter) ? {
363375 PollResponse :: Block ( res) => {
364376 let height = res. height as u32 ;
365377 let hash = res. hash ;
366- let item = get_item ( & hash) ?;
378+ let item = get_item ( & hash, & emitter . client ) ?;
367379
368380 let new_cp = emitter
369381 . last_cp
@@ -432,19 +444,23 @@ impl BitcoindRpcErrorExt for bitcoincore_rpc::Error {
432444
433445#[ cfg( test) ]
434446mod test {
435- use crate :: { bitcoincore_rpc:: RpcApi , Emitter } ;
436- use bdk_bitcoind_rpc:: bitcoincore_rpc:: bitcoin:: Txid ;
447+ use crate :: { bitcoincore_rpc:: RpcApi , Emitter , NO_EXPECTED_MEMPOOL_TXIDS } ;
437448 use bdk_chain:: local_chain:: LocalChain ;
438449 use bdk_testenv:: { anyhow, TestEnv } ;
439- use bitcoin:: { hashes:: Hash , Address , Amount , ScriptBuf , WScriptHash } ;
450+ use bitcoin:: { hashes:: Hash , Address , Amount , ScriptBuf , Txid , WScriptHash } ;
440451 use std:: collections:: HashSet ;
441452
442453 #[ test]
443454 fn test_expected_mempool_txids_accumulate_and_remove ( ) -> anyhow:: Result < ( ) > {
444455 let env = TestEnv :: new ( ) ?;
445456 let chain = LocalChain :: from_genesis_hash ( env. rpc_client ( ) . get_block_hash ( 0 ) ?) . 0 ;
446457 let chain_tip = chain. tip ( ) ;
447- let mut emitter = Emitter :: new ( env. rpc_client ( ) , chain_tip. clone ( ) , 1 , HashSet :: new ( ) ) ;
458+ let mut emitter = Emitter :: new (
459+ env. rpc_client ( ) ,
460+ chain_tip. clone ( ) ,
461+ 1 ,
462+ NO_EXPECTED_MEMPOOL_TXIDS ,
463+ ) ;
448464
449465 env. mine_blocks ( 100 , None ) ?;
450466 while emitter. next_block ( ) ?. is_some ( ) { }
0 commit comments