11//! Helper types for spk-based blockchain clients.
22
3+ use crate :: {
4+ collections:: BTreeMap , local_chain:: CheckPoint , ConfirmationTimeHeightAnchor , TxGraph ,
5+ } ;
6+ use alloc:: { boxed:: Box , sync:: Arc , vec:: Vec } ;
7+ use bitcoin:: { OutPoint , Script , ScriptBuf , Transaction , Txid } ;
38use core:: { fmt:: Debug , marker:: PhantomData , ops:: RangeBounds } ;
9+ use std:: collections:: HashMap ;
410
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 } ;
11+ /// A cache of [`Arc`]-wrapped full transactions, identified by their [`Txid`]s.
12+ ///
13+ /// This is used by the chain-source to avoid re-fetching full transactions.
14+ pub type TxCache = HashMap < Txid , Arc < Transaction > > ;
915
1016/// Data required to perform a spk-based blockchain client sync.
1117///
@@ -17,6 +23,8 @@ pub struct SyncRequest {
1723 ///
1824 /// [`LocalChain::tip`]: crate::local_chain::LocalChain::tip
1925 pub chain_tip : CheckPoint ,
26+ /// Cache of full transactions, so the chain-source can avoid re-fetching.
27+ pub tx_cache : TxCache ,
2028 /// Transactions that spend from or to these indexed script pubkeys.
2129 pub spks : Box < dyn ExactSizeIterator < Item = ScriptBuf > + Send > ,
2230 /// Transactions with these txids.
@@ -30,12 +38,37 @@ impl SyncRequest {
3038 pub fn from_chain_tip ( cp : CheckPoint ) -> Self {
3139 Self {
3240 chain_tip : cp,
41+ tx_cache : TxCache :: new ( ) ,
3342 spks : Box :: new ( core:: iter:: empty ( ) ) ,
3443 txids : Box :: new ( core:: iter:: empty ( ) ) ,
3544 outpoints : Box :: new ( core:: iter:: empty ( ) ) ,
3645 }
3746 }
3847
48+ /// Add to the [`Transaction`] cache that allows the chain source to avoid re-fetching full
49+ /// transactions.
50+ ///
51+ /// This consumes the [`SyncRequest`] and returns the updated one.
52+ #[ must_use]
53+ pub fn cache_txs < T > ( mut self , full_txs : impl IntoIterator < Item = ( Txid , T ) > ) -> Self
54+ where
55+ T : Into < Arc < Transaction > > ,
56+ {
57+ self . tx_cache = full_txs
58+ . into_iter ( )
59+ . map ( |( txid, tx) | ( txid, tx. into ( ) ) )
60+ . collect ( ) ;
61+ self
62+ }
63+
64+ /// Add all transactions from [`TxGraph`] into the [`Transaction`] cache.
65+ ///
66+ /// This consumes the [`SyncRequest`] and returns the updated one.
67+ #[ must_use]
68+ pub fn cache_graph_txs < A > ( self , graph : & TxGraph < A > ) -> Self {
69+ self . cache_txs ( graph. full_txs ( ) . map ( |tx_node| ( tx_node. txid , tx_node. tx ) ) )
70+ }
71+
3972 /// Set the [`Script`]s that will be synced against.
4073 ///
4174 /// This consumes the [`SyncRequest`] and returns the updated one.
@@ -194,6 +227,8 @@ pub struct FullScanRequest<K> {
194227 ///
195228 /// [`LocalChain::tip`]: crate::local_chain::LocalChain::tip
196229 pub chain_tip : CheckPoint ,
230+ /// Cache of full transactions, so the chain-source can avoid re-fetching.
231+ pub tx_cache : TxCache ,
197232 /// Iterators of script pubkeys indexed by the keychain index.
198233 pub spks_by_keychain : BTreeMap < K , Box < dyn Iterator < Item = ( u32 , ScriptBuf ) > + Send > > ,
199234}
@@ -204,10 +239,35 @@ impl<K: Ord + Clone> FullScanRequest<K> {
204239 pub fn from_chain_tip ( chain_tip : CheckPoint ) -> Self {
205240 Self {
206241 chain_tip,
242+ tx_cache : TxCache :: new ( ) ,
207243 spks_by_keychain : BTreeMap :: new ( ) ,
208244 }
209245 }
210246
247+ /// Add to the [`Transaction`] cache that allows the chain source to avoid re-fetching full
248+ /// transactions.
249+ ///
250+ /// This consumes the [`SyncRequest`] and returns the updated one.
251+ #[ must_use]
252+ pub fn cache_txs < T > ( mut self , full_txs : impl IntoIterator < Item = ( Txid , T ) > ) -> Self
253+ where
254+ T : Into < Arc < Transaction > > ,
255+ {
256+ self . tx_cache = full_txs
257+ . into_iter ( )
258+ . map ( |( txid, tx) | ( txid, tx. into ( ) ) )
259+ . collect ( ) ;
260+ self
261+ }
262+
263+ /// Add all transactions from [`TxGraph`] into the [`Transaction`] cache.
264+ ///
265+ /// This consumes the [`SyncRequest`] and returns the updated one.
266+ #[ must_use]
267+ pub fn cache_graph_txs < A > ( self , graph : & TxGraph < A > ) -> Self {
268+ self . cache_txs ( graph. full_txs ( ) . map ( |tx_node| ( tx_node. txid , tx_node. tx ) ) )
269+ }
270+
211271 /// Construct a new [`FullScanRequest`] from a given `chain_tip` and `index`.
212272 ///
213273 /// Unbounded script pubkey iterators for each keychain (`K`) are extracted using
0 commit comments