99//! separate method, [`Emitter::mempool`] can be used to emit the whole mempool.
1010#![ warn( missing_docs) ]
1111
12+ #[ allow( unused_imports) ]
13+ #[ macro_use]
14+ extern crate alloc;
15+
16+ use alloc:: sync:: Arc ;
17+ use bdk_core:: collections:: { HashMap , HashSet } ;
1218use bdk_core:: { BlockId , CheckPoint } ;
1319use bitcoin:: { Block , BlockHash , Transaction , Txid } ;
1420use bitcoincore_rpc:: { bitcoincore_rpc_json, RpcApi } ;
15- use std:: {
16- collections:: { HashMap , HashSet } ,
17- ops:: Deref ,
18- sync:: Arc ,
19- } ;
21+ use core:: ops:: Deref ;
2022
2123pub mod bip158;
2224
@@ -53,11 +55,11 @@ pub struct Emitter<C> {
5355 mempool_snapshot : HashMap < Txid , Arc < Transaction > > ,
5456}
5557
56- /// Indicates that there are no initially expected mempool transactions.
58+ /// Indicates that there are no initially- expected mempool transactions.
5759///
58- /// Pass this to the `expected_mempool_txids ` field of [`Emitter::new`] when the wallet is known
60+ /// Use this as the `expected_mempool_txs ` field of [`Emitter::new`] when the wallet is known
5961/// to start empty (i.e. with no unconfirmed transactions).
60- pub const NO_EXPECTED_MEMPOOL_TXIDS : core:: iter:: Empty < Arc < Transaction > > = core:: iter:: empty ( ) ;
62+ pub const NO_EXPECTED_MEMPOOL_TXS : core:: iter:: Empty < Arc < Transaction > > = core:: iter:: empty ( ) ;
6163
6264impl < C > Emitter < C >
6365where
7476 ///
7577 /// `expected_mempool_txs` is the initial set of unconfirmed transactions provided by the
7678 /// wallet. This allows the [`Emitter`] to inform the wallet about relevant mempool evictions.
77- /// If it is known that the wallet is empty, [`NO_EXPECTED_MEMPOOL_TXIDS `] can be used.
79+ /// If it is known that the wallet is empty, [`NO_EXPECTED_MEMPOOL_TXS `] can be used.
7880 pub fn new (
7981 client : C ,
8082 last_cp : CheckPoint ,
@@ -99,21 +101,26 @@ where
99101 /// Emit mempool transactions and any evicted [`Txid`]s.
100102 ///
101103 /// This method returns a [`MempoolEvent`] containing the full transactions (with their
102- /// first-seen unix timestamps) that were emitted, and [`MempoolEvent::evicted_txids `] which are
104+ /// first-seen unix timestamps) that were emitted, and [`MempoolEvent::evicted `] which are
103105 /// any [`Txid`]s which were previously seen in the mempool and are now missing. Evicted txids
104106 /// are only reported once the emitter’s checkpoint matches the RPC’s best block in both height
105107 /// and hash. Until `next_block()` advances the checkpoint to tip, `mempool()` will always
106- /// return an empty `evicted_txids` set.
108+ /// return an empty `evicted` set.
109+ #[ cfg( feature = "std" ) ]
110+ pub fn mempool ( & mut self ) -> Result < MempoolEvent , bitcoincore_rpc:: Error > {
111+ let sync_time = std:: time:: UNIX_EPOCH
112+ . elapsed ( )
113+ . expect ( "must get current time" )
114+ . as_secs ( ) ;
115+ self . mempool_at ( sync_time)
116+ }
117+
118+ /// Emit mempool transactions and any evicted [`Txid`]s at the given `sync_time`.
107119 ///
108- /// This method emits each transaction only once, unless we cannot guarantee the transaction's
109- /// ancestors are already emitted.
120+ /// `sync_time` is in unix seconds.
110121 ///
111- /// To understand why, consider a receiver which filters transactions based on whether it
112- /// alters the UTXO set of tracked script pubkeys. If an emitted mempool transaction spends a
113- /// tracked UTXO which is confirmed at height `h`, but the receiver has only seen up to block
114- /// of height `h-1`, we want to re-emit this transaction until the receiver has seen the block
115- /// at height `h`.
116- pub fn mempool ( & mut self ) -> Result < MempoolEvent , bitcoincore_rpc:: Error > {
122+ /// This is the no-std version of [`mempool`](Self::mempool).
123+ pub fn mempool_at ( & mut self , sync_time : u64 ) -> Result < MempoolEvent , bitcoincore_rpc:: Error > {
117124 let client = & * self . client ;
118125
119126 let mut rpc_tip_height;
@@ -125,8 +132,8 @@ where
125132 loop {
126133 rpc_tip_height = client. get_block_count ( ) ?;
127134 rpc_tip_hash = client. get_block_hash ( rpc_tip_height) ?;
128- rpc_mempool = client. get_raw_mempool_verbose ( ) ?;
129- rpc_mempool_txids = rpc_mempool. keys ( ) . copied ( ) . collect :: < HashSet < Txid > > ( ) ;
135+ rpc_mempool = client. get_raw_mempool ( ) ?;
136+ rpc_mempool_txids = rpc_mempool. iter ( ) . copied ( ) . collect :: < HashSet < Txid > > ( ) ;
130137 let is_still_at_tip = rpc_tip_hash == client. get_block_hash ( rpc_tip_height) ?
131138 && rpc_tip_height == client. get_block_count ( ) ?;
132139 if is_still_at_tip {
@@ -135,13 +142,11 @@ where
135142 }
136143
137144 let mut mempool_event = MempoolEvent :: default ( ) ;
138- let update_time = & mut 0_u64 ;
139145
140146 mempool_event. update = rpc_mempool
141147 . into_iter ( )
142148 . filter_map ( {
143- |( txid, tx_entry) | -> Option < Result < _ , bitcoincore_rpc:: Error > > {
144- * update_time = u64:: max ( * update_time, tx_entry. time ) ;
149+ |txid| -> Option < Result < _ , bitcoincore_rpc:: Error > > {
145150 let tx = match self . mempool_snapshot . get ( & txid) {
146151 Some ( tx) => tx. clone ( ) ,
147152 None => match client. get_raw_transaction ( & txid, None ) {
@@ -154,7 +159,7 @@ where
154159 Err ( err) => return Some ( Err ( err) ) ,
155160 } ,
156161 } ;
157- Some ( Ok ( ( tx, tx_entry . time ) ) )
162+ Some ( Ok ( ( tx, sync_time ) ) )
158163 }
159164 } )
160165 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
@@ -171,7 +176,7 @@ where
171176 . mempool_snapshot
172177 . keys ( )
173178 . filter ( |& txid| !rpc_mempool_txids. contains ( txid) )
174- . map ( |& txid| ( txid, * update_time ) )
179+ . map ( |& txid| ( txid, sync_time ) )
175180 . collect ( ) ;
176181 self . mempool_snapshot = mempool_event
177182 . update
@@ -396,7 +401,7 @@ impl BitcoindRpcErrorExt for bitcoincore_rpc::Error {
396401
397402#[ cfg( test) ]
398403mod test {
399- use crate :: { bitcoincore_rpc:: RpcApi , Emitter , NO_EXPECTED_MEMPOOL_TXIDS } ;
404+ use crate :: { bitcoincore_rpc:: RpcApi , Emitter , NO_EXPECTED_MEMPOOL_TXS } ;
400405 use bdk_chain:: local_chain:: LocalChain ;
401406 use bdk_testenv:: { anyhow, TestEnv } ;
402407 use bitcoin:: { hashes:: Hash , Address , Amount , ScriptBuf , Txid , WScriptHash } ;
@@ -411,7 +416,7 @@ mod test {
411416 env. rpc_client ( ) ,
412417 chain_tip. clone ( ) ,
413418 1 ,
414- NO_EXPECTED_MEMPOOL_TXIDS ,
419+ NO_EXPECTED_MEMPOOL_TXS ,
415420 ) ;
416421
417422 env. mine_blocks ( 100 , None ) ?;
0 commit comments