@@ -16,10 +16,11 @@ extern crate alloc;
1616
1717use alloc:: sync:: Arc ;
1818use bdk_core:: collections:: { HashMap , HashSet } ;
19- use bdk_core:: { BlockId , CheckPoint } ;
19+ use bdk_core:: { BlockId , CheckPoint , FromBlockHeader , ToBlockHash } ;
2020use bitcoin:: { Block , BlockHash , Transaction , Txid } ;
2121use bitcoincore_rpc:: { bitcoincore_rpc_json, RpcApi } ;
2222use core:: ops:: Deref ;
23+ use std:: fmt:: Debug ;
2324
2425pub mod bip158;
2526
@@ -30,13 +31,13 @@ pub use bitcoincore_rpc;
3031/// Refer to [module-level documentation] for more.
3132///
3233/// [module-level documentation]: crate
33- pub struct Emitter < C > {
34+ pub struct Emitter < C , D = BlockHash > {
3435 client : C ,
3536 start_height : u32 ,
3637
3738 /// The checkpoint of the last-emitted block that is in the best chain. If it is later found
3839 /// that the block is no longer in the best chain, it will be popped off from here.
39- last_cp : CheckPoint < BlockHash > ,
40+ last_cp : CheckPoint < D > ,
4041
4142 /// The block result returned from rpc of the last-emitted block. As this result contains the
4243 /// next block's block hash (which we use to fetch the next block), we set this to `None`
@@ -62,10 +63,11 @@ pub struct Emitter<C> {
6263/// to start empty (i.e. with no unconfirmed transactions).
6364pub const NO_EXPECTED_MEMPOOL_TXS : core:: iter:: Empty < Arc < Transaction > > = core:: iter:: empty ( ) ;
6465
65- impl < C > Emitter < C >
66+ impl < C , D > Emitter < C , D >
6667where
6768 C : Deref ,
6869 C :: Target : RpcApi ,
70+ D : ToBlockHash + Clone + Debug ,
6971{
7072 /// Construct a new [`Emitter`].
7173 ///
8082 /// If it is known that the wallet is empty, [`NO_EXPECTED_MEMPOOL_TXS`] can be used.
8183 pub fn new (
8284 client : C ,
83- last_cp : CheckPoint < BlockHash > ,
85+ last_cp : CheckPoint < D > ,
8486 start_height : u32 ,
8587 expected_mempool_txs : impl IntoIterator < Item = impl Into < Arc < Transaction > > > ,
8688 ) -> Self {
@@ -198,9 +200,18 @@ where
198200 Ok ( mempool_event)
199201 }
200202
201- /// Emit the next block height and block (if any).
202- pub fn next_block ( & mut self ) -> Result < Option < BlockEvent < Block > > , bitcoincore_rpc:: Error > {
203- if let Some ( ( checkpoint, block) ) = poll ( self , move |hash, client| client. get_block ( hash) ) ? {
203+ /// Emit the next block, using `to_data` to construct checkpoint data from the block.
204+ ///
205+ /// This is the alternative to [`next_block`](Self::next_block) when [`FromBlockHeader`] isn't
206+ /// implemented for `D`.
207+ pub fn next_block_with < F > (
208+ & mut self ,
209+ to_data : F ,
210+ ) -> Result < Option < BlockEvent < Block , D > > , bitcoincore_rpc:: Error >
211+ where
212+ F : Fn ( & Block ) -> D ,
213+ {
214+ if let Some ( ( checkpoint, block) ) = poll ( self , to_data) ? {
204215 // Stop tracking unconfirmed transactions that have been confirmed in this block.
205216 for tx in & block. txdata {
206217 self . mempool_snapshot . remove ( & tx. compute_txid ( ) ) ;
@@ -209,6 +220,14 @@ where
209220 }
210221 Ok ( None )
211222 }
223+
224+ /// Emit the next block height and block (if any).
225+ pub fn next_block ( & mut self ) -> Result < Option < BlockEvent < Block , D > > , bitcoincore_rpc:: Error >
226+ where
227+ D : FromBlockHeader ,
228+ {
229+ self . next_block_with ( |block| D :: from_blockheader ( block. header ) )
230+ }
212231}
213232
214233/// A new emission from mempool.
@@ -223,7 +242,7 @@ pub struct MempoolEvent {
223242
224243/// A newly emitted block from [`Emitter`].
225244#[ derive( Debug ) ]
226- pub struct BlockEvent < B > {
245+ pub struct BlockEvent < B = Block , D = BlockHash > {
227246 /// The block.
228247 pub block : B ,
229248
@@ -235,7 +254,7 @@ pub struct BlockEvent<B> {
235254 ///
236255 /// This is important as BDK structures require block-to-apply to be connected with another
237256 /// block in the original chain.
238- pub checkpoint : CheckPoint < BlockHash > ,
257+ pub checkpoint : CheckPoint < D > ,
239258}
240259
241260impl < B > BlockEvent < B > {
@@ -264,17 +283,17 @@ impl<B> BlockEvent<B> {
264283 }
265284}
266285
267- enum PollResponse {
286+ enum PollResponse < D = BlockHash > {
268287 Block ( bitcoincore_rpc_json:: GetBlockResult ) ,
269288 NoMoreBlocks ,
270289 /// Fetched block is not in the best chain.
271290 BlockNotInBestChain ,
272- AgreementFound ( bitcoincore_rpc_json:: GetBlockResult , CheckPoint < BlockHash > ) ,
291+ AgreementFound ( bitcoincore_rpc_json:: GetBlockResult , CheckPoint < D > ) ,
273292 /// Force the genesis checkpoint down the receiver's throat.
274293 AgreementPointNotFound ( BlockHash ) ,
275294}
276295
277- fn poll_once < C > ( emitter : & Emitter < C > ) -> Result < PollResponse , bitcoincore_rpc:: Error >
296+ fn poll_once < C , D > ( emitter : & Emitter < C , D > ) -> Result < PollResponse < D > , bitcoincore_rpc:: Error >
278297where
279298 C : Deref ,
280299 C :: Target : RpcApi ,
@@ -328,30 +347,32 @@ where
328347 Ok ( PollResponse :: AgreementPointNotFound ( genesis_hash) )
329348}
330349
331- fn poll < C , V , F > (
332- emitter : & mut Emitter < C > ,
333- get_item : F ,
334- ) -> Result < Option < ( CheckPoint < BlockHash > , V ) > , bitcoincore_rpc:: Error >
350+ fn poll < C , D , F > (
351+ emitter : & mut Emitter < C , D > ,
352+ to_cp_data : F ,
353+ ) -> Result < Option < ( CheckPoint < D > , Block ) > , bitcoincore_rpc:: Error >
335354where
336355 C : Deref ,
337356 C :: Target : RpcApi ,
338- F : Fn ( & BlockHash , & C :: Target ) -> Result < V , bitcoincore_rpc:: Error > ,
357+ D : ToBlockHash + Clone + Debug ,
358+ F : Fn ( & Block ) -> D ,
339359{
360+ let client = & emitter. client ;
340361 loop {
341362 match poll_once ( emitter) ? {
342363 PollResponse :: Block ( res) => {
343364 let height = res. height as u32 ;
344- let hash = res. hash ;
345- let item = get_item ( & hash , & emitter . client ) ? ;
365+ let block = client . get_block ( & res. hash ) ? ;
366+ let cp_data = to_cp_data ( & block ) ;
346367
347368 let new_cp = emitter
348369 . last_cp
349370 . clone ( )
350- . push ( height, hash )
371+ . push ( height, cp_data )
351372 . expect ( "must push" ) ;
352373 emitter. last_cp = new_cp. clone ( ) ;
353374 emitter. last_block = Some ( res) ;
354- return Ok ( Some ( ( new_cp, item ) ) ) ;
375+ return Ok ( Some ( ( new_cp, block ) ) ) ;
355376 }
356377 PollResponse :: NoMoreBlocks => {
357378 emitter. last_block = None ;
@@ -368,7 +389,9 @@ where
368389 continue ;
369390 }
370391 PollResponse :: AgreementPointNotFound ( genesis_hash) => {
371- emitter. last_cp = CheckPoint :: new ( 0 , genesis_hash) ;
392+ let block = client. get_block ( & genesis_hash) ?;
393+ let cp_data = to_cp_data ( & block) ;
394+ emitter. last_cp = CheckPoint :: new ( 0 , cp_data) ;
372395 emitter. last_block = None ;
373396 continue ;
374397 }
0 commit comments