11//! Helper types for spk-based blockchain clients.
22
3+ use crate :: {
4+ collections:: { BTreeMap , HashMap } ,
5+ local_chain:: CheckPoint ,
6+ ConfirmationTimeHeightAnchor , TxGraph ,
7+ } ;
8+ use alloc:: { boxed:: Box , sync:: Arc , vec:: Vec } ;
9+ use bitcoin:: { OutPoint , Script , ScriptBuf , Transaction , Txid } ;
310use core:: { fmt:: Debug , marker:: PhantomData , ops:: RangeBounds } ;
411
5- use alloc :: { boxed :: Box , collections :: BTreeMap , vec :: Vec } ;
6- use bitcoin :: { OutPoint , Script , ScriptBuf , Txid } ;
7-
8- use crate :: { local_chain :: CheckPoint , ConfirmationTimeHeightAnchor , TxGraph } ;
12+ /// A cache of [`Arc`]-wrapped full transactions, identified by their [`Txid`]s.
13+ ///
14+ /// This is used by the chain-source to avoid re-fetching full transactions.
15+ pub type TxCache = HashMap < Txid , Arc < Transaction > > ;
916
1017/// Data required to perform a spk-based blockchain client sync.
1118///
@@ -17,6 +24,8 @@ pub struct SyncRequest {
1724 ///
1825 /// [`LocalChain::tip`]: crate::local_chain::LocalChain::tip
1926 pub chain_tip : CheckPoint ,
27+ /// Cache of full transactions, so the chain-source can avoid re-fetching.
28+ pub tx_cache : TxCache ,
2029 /// Transactions that spend from or to these indexed script pubkeys.
2130 pub spks : Box < dyn ExactSizeIterator < Item = ScriptBuf > + Send > ,
2231 /// Transactions with these txids.
@@ -30,12 +39,37 @@ impl SyncRequest {
3039 pub fn from_chain_tip ( cp : CheckPoint ) -> Self {
3140 Self {
3241 chain_tip : cp,
42+ tx_cache : TxCache :: new ( ) ,
3343 spks : Box :: new ( core:: iter:: empty ( ) ) ,
3444 txids : Box :: new ( core:: iter:: empty ( ) ) ,
3545 outpoints : Box :: new ( core:: iter:: empty ( ) ) ,
3646 }
3747 }
3848
49+ /// Add to the [`Transaction`] cache that allows the chain source to avoid re-fetching full
50+ /// transactions.
51+ ///
52+ /// This consumes the [`SyncRequest`] and returns the updated one.
53+ #[ must_use]
54+ pub fn cache_txs < T > ( mut self , full_txs : impl IntoIterator < Item = ( Txid , T ) > ) -> Self
55+ where
56+ T : Into < Arc < Transaction > > ,
57+ {
58+ self . tx_cache = full_txs
59+ . into_iter ( )
60+ . map ( |( txid, tx) | ( txid, tx. into ( ) ) )
61+ . collect ( ) ;
62+ self
63+ }
64+
65+ /// Add all transactions from [`TxGraph`] into the [`Transaction`] cache.
66+ ///
67+ /// This consumes the [`SyncRequest`] and returns the updated one.
68+ #[ must_use]
69+ pub fn cache_graph_txs < A > ( self , graph : & TxGraph < A > ) -> Self {
70+ self . cache_txs ( graph. full_txs ( ) . map ( |tx_node| ( tx_node. txid , tx_node. tx ) ) )
71+ }
72+
3973 /// Set the [`Script`]s that will be synced against.
4074 ///
4175 /// This consumes the [`SyncRequest`] and returns the updated one.
@@ -194,6 +228,8 @@ pub struct FullScanRequest<K> {
194228 ///
195229 /// [`LocalChain::tip`]: crate::local_chain::LocalChain::tip
196230 pub chain_tip : CheckPoint ,
231+ /// Cache of full transactions, so the chain-source can avoid re-fetching.
232+ pub tx_cache : TxCache ,
197233 /// Iterators of script pubkeys indexed by the keychain index.
198234 pub spks_by_keychain : BTreeMap < K , Box < dyn Iterator < Item = ( u32 , ScriptBuf ) > + Send > > ,
199235}
@@ -204,10 +240,35 @@ impl<K: Ord + Clone> FullScanRequest<K> {
204240 pub fn from_chain_tip ( chain_tip : CheckPoint ) -> Self {
205241 Self {
206242 chain_tip,
243+ tx_cache : TxCache :: new ( ) ,
207244 spks_by_keychain : BTreeMap :: new ( ) ,
208245 }
209246 }
210247
248+ /// Add to the [`Transaction`] cache that allows the chain source to avoid re-fetching full
249+ /// transactions.
250+ ///
251+ /// This consumes the [`SyncRequest`] and returns the updated one.
252+ #[ must_use]
253+ pub fn cache_txs < T > ( mut self , full_txs : impl IntoIterator < Item = ( Txid , T ) > ) -> Self
254+ where
255+ T : Into < Arc < Transaction > > ,
256+ {
257+ self . tx_cache = full_txs
258+ . into_iter ( )
259+ . map ( |( txid, tx) | ( txid, tx. into ( ) ) )
260+ . collect ( ) ;
261+ self
262+ }
263+
264+ /// Add all transactions from [`TxGraph`] into the [`Transaction`] cache.
265+ ///
266+ /// This consumes the [`SyncRequest`] and returns the updated one.
267+ #[ must_use]
268+ pub fn cache_graph_txs < A > ( self , graph : & TxGraph < A > ) -> Self {
269+ self . cache_txs ( graph. full_txs ( ) . map ( |tx_node| ( tx_node. txid , tx_node. tx ) ) )
270+ }
271+
211272 /// Construct a new [`FullScanRequest`] from a given `chain_tip` and `index`.
212273 ///
213274 /// Unbounded script pubkey iterators for each keychain (`K`) are extracted using
0 commit comments