9
9
//! separate method, [`Emitter::mempool`] can be used to emit the whole mempool.
10
10
#![ warn( missing_docs) ]
11
11
12
+ #[ allow( unused_imports) ]
13
+ #[ macro_use]
14
+ extern crate alloc;
15
+
16
+ use alloc:: sync:: Arc ;
17
+ use bdk_core:: collections:: { HashMap , HashSet } ;
12
18
use bdk_core:: { BlockId , CheckPoint } ;
13
19
use bitcoin:: { Block , BlockHash , Transaction , Txid } ;
14
20
use 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 ;
20
22
21
23
pub mod bip158;
22
24
@@ -53,11 +55,11 @@ pub struct Emitter<C> {
53
55
mempool_snapshot : HashMap < Txid , Arc < Transaction > > ,
54
56
}
55
57
56
- /// Indicates that there are no initially expected mempool transactions.
58
+ /// Indicates that there are no initially- expected mempool transactions.
57
59
///
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
59
61
/// 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 ( ) ;
61
63
62
64
impl < C > Emitter < C >
63
65
where
74
76
///
75
77
/// `expected_mempool_txs` is the initial set of unconfirmed transactions provided by the
76
78
/// 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.
78
80
pub fn new (
79
81
client : C ,
80
82
last_cp : CheckPoint ,
@@ -99,21 +101,26 @@ where
99
101
/// Emit mempool transactions and any evicted [`Txid`]s.
100
102
///
101
103
/// 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
103
105
/// any [`Txid`]s which were previously seen in the mempool and are now missing. Evicted txids
104
106
/// are only reported once the emitter’s checkpoint matches the RPC’s best block in both height
105
107
/// 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`.
107
119
///
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.
110
121
///
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 > {
117
124
let client = & * self . client ;
118
125
119
126
let mut rpc_tip_height;
@@ -125,8 +132,8 @@ where
125
132
loop {
126
133
rpc_tip_height = client. get_block_count ( ) ?;
127
134
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 > > ( ) ;
130
137
let is_still_at_tip = rpc_tip_hash == client. get_block_hash ( rpc_tip_height) ?
131
138
&& rpc_tip_height == client. get_block_count ( ) ?;
132
139
if is_still_at_tip {
@@ -135,13 +142,11 @@ where
135
142
}
136
143
137
144
let mut mempool_event = MempoolEvent :: default ( ) ;
138
- let update_time = & mut 0_u64 ;
139
145
140
146
mempool_event. update = rpc_mempool
141
147
. into_iter ( )
142
148
. 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 > > {
145
150
let tx = match self . mempool_snapshot . get ( & txid) {
146
151
Some ( tx) => tx. clone ( ) ,
147
152
None => match client. get_raw_transaction ( & txid, None ) {
@@ -154,7 +159,7 @@ where
154
159
Err ( err) => return Some ( Err ( err) ) ,
155
160
} ,
156
161
} ;
157
- Some ( Ok ( ( tx, tx_entry . time ) ) )
162
+ Some ( Ok ( ( tx, sync_time ) ) )
158
163
}
159
164
} )
160
165
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
@@ -171,7 +176,7 @@ where
171
176
. mempool_snapshot
172
177
. keys ( )
173
178
. filter ( |& txid| !rpc_mempool_txids. contains ( txid) )
174
- . map ( |& txid| ( txid, * update_time ) )
179
+ . map ( |& txid| ( txid, sync_time ) )
175
180
. collect ( ) ;
176
181
self . mempool_snapshot = mempool_event
177
182
. update
@@ -396,7 +401,7 @@ impl BitcoindRpcErrorExt for bitcoincore_rpc::Error {
396
401
397
402
#[ cfg( test) ]
398
403
mod test {
399
- use crate :: { bitcoincore_rpc:: RpcApi , Emitter , NO_EXPECTED_MEMPOOL_TXIDS } ;
404
+ use crate :: { bitcoincore_rpc:: RpcApi , Emitter , NO_EXPECTED_MEMPOOL_TXS } ;
400
405
use bdk_chain:: local_chain:: LocalChain ;
401
406
use bdk_testenv:: { anyhow, TestEnv } ;
402
407
use bitcoin:: { hashes:: Hash , Address , Amount , ScriptBuf , Txid , WScriptHash } ;
@@ -411,7 +416,7 @@ mod test {
411
416
env. rpc_client ( ) ,
412
417
chain_tip. clone ( ) ,
413
418
1 ,
414
- NO_EXPECTED_MEMPOOL_TXIDS ,
419
+ NO_EXPECTED_MEMPOOL_TXS ,
415
420
) ;
416
421
417
422
env. mine_blocks ( 100 , None ) ?;
0 commit comments