@@ -72,32 +72,34 @@ impl<A: Anchor, I: Indexer> IndexedTxGraph<A, I>
7272where
7373 I :: ChangeSet : Default + Append ,
7474{
75+ fn index_tx_graph_changeset (
76+ & mut self ,
77+ tx_graph_changeset : & tx_graph:: ChangeSet < A > ,
78+ ) -> I :: ChangeSet {
79+ let mut changeset = I :: ChangeSet :: default ( ) ;
80+ for added_tx in & tx_graph_changeset. txs {
81+ changeset. append ( self . index . index_tx ( added_tx) ) ;
82+ }
83+ for ( & added_outpoint, added_txout) in & tx_graph_changeset. txouts {
84+ changeset. append ( self . index . index_txout ( added_outpoint, added_txout) ) ;
85+ }
86+ changeset
87+ }
88+
7589 /// Apply an `update` directly.
7690 ///
7791 /// `update` is a [`TxGraph<A>`] and the resultant changes is returned as [`ChangeSet`].
7892 pub fn apply_update ( & mut self , update : TxGraph < A > ) -> ChangeSet < A , I :: ChangeSet > {
7993 let graph = self . graph . apply_update ( update) ;
80-
81- let mut indexer = I :: ChangeSet :: default ( ) ;
82- for added_tx in & graph. txs {
83- indexer. append ( self . index . index_tx ( added_tx) ) ;
84- }
85- for ( & added_outpoint, added_txout) in & graph. txouts {
86- indexer. append ( self . index . index_txout ( added_outpoint, added_txout) ) ;
87- }
88-
94+ let indexer = self . index_tx_graph_changeset ( & graph) ;
8995 ChangeSet { graph, indexer }
9096 }
9197
9298 /// Insert a floating `txout` of given `outpoint`.
93- pub fn insert_txout (
94- & mut self ,
95- outpoint : OutPoint ,
96- txout : & TxOut ,
97- ) -> ChangeSet < A , I :: ChangeSet > {
98- let mut update = TxGraph :: < A > :: default ( ) ;
99- let _ = update. insert_txout ( outpoint, txout. clone ( ) ) ;
100- self . apply_update ( update)
99+ pub fn insert_txout ( & mut self , outpoint : OutPoint , txout : TxOut ) -> ChangeSet < A , I :: ChangeSet > {
100+ let graph = self . graph . insert_txout ( outpoint, txout) ;
101+ let indexer = self . index_tx_graph_changeset ( & graph) ;
102+ ChangeSet { graph, indexer }
101103 }
102104
103105 /// Insert and index a transaction into the graph.
@@ -112,18 +114,19 @@ where
112114 ) -> ChangeSet < A , I :: ChangeSet > {
113115 let txid = tx. txid ( ) ;
114116
115- let mut update = TxGraph :: < A > :: default ( ) ;
117+ let mut graph = tx_graph :: ChangeSet :: default ( ) ;
116118 if self . graph . get_tx ( txid) . is_none ( ) {
117- let _ = update . insert_tx ( tx. clone ( ) ) ;
119+ graph . append ( self . graph . insert_tx ( tx. clone ( ) ) ) ;
118120 }
119121 for anchor in anchors. into_iter ( ) {
120- let _ = update . insert_anchor ( txid, anchor) ;
122+ graph . append ( self . graph . insert_anchor ( txid, anchor) ) ;
121123 }
122124 if let Some ( seen_at) = seen_at {
123- let _ = update . insert_seen_at ( txid, seen_at) ;
125+ graph . append ( self . graph . insert_seen_at ( txid, seen_at) ) ;
124126 }
125127
126- self . apply_update ( update)
128+ let indexer = self . index_tx_graph_changeset ( & graph) ;
129+ ChangeSet { graph, indexer }
127130 }
128131
129132 /// Batch insert transactions, filtering out those that are irrelevant.
@@ -132,85 +135,85 @@ where
132135 /// transactions in `txs` will be ignored. `txs` do not need to be in topological order.
133136 pub fn batch_insert_relevant < ' t > (
134137 & mut self ,
135- txs : impl IntoIterator < Item = InsertTxItem < ' t , impl IntoIterator < Item = A > > > ,
138+ txs : impl IntoIterator < Item = ( & ' t Transaction , impl IntoIterator < Item = A > ) > ,
136139 ) -> ChangeSet < A , I :: ChangeSet > {
137140 // The algorithm below allows for non-topologically ordered transactions by using two loops.
138141 // This is achieved by:
139142 // 1. insert all txs into the index. If they are irrelevant then that's fine it will just
140143 // not store anything about them.
141144 // 2. decide whether to insert them into the graph depending on whether `is_tx_relevant`
142145 // returns true or not. (in a second loop).
143- let mut changeset = ChangeSet :: < A , I :: ChangeSet > :: default ( ) ;
146+ let txs = txs . into_iter ( ) . collect :: < Vec < _ > > ( ) ;
144147
145- let txs = txs
146- . into_iter ( )
147- . inspect ( | ( tx , _ , _ ) | changeset . indexer . append ( self . index . index_tx ( tx) ) )
148- . collect :: < Vec < _ > > ( ) ;
148+ let mut indexer = I :: ChangeSet :: default ( ) ;
149+ for ( tx , _ ) in & txs {
150+ indexer. append ( self . index . index_tx ( tx) ) ;
151+ }
149152
150- for ( tx, anchors, seen_at) in txs {
153+ let mut graph = tx_graph:: ChangeSet :: default ( ) ;
154+ for ( tx, anchors) in txs {
151155 if self . index . is_tx_relevant ( tx) {
152- changeset. append ( self . insert_tx ( tx, anchors, seen_at) ) ;
156+ let txid = tx. txid ( ) ;
157+ graph. append ( self . graph . insert_tx ( tx. clone ( ) ) ) ;
158+ for anchor in anchors {
159+ graph. append ( self . graph . insert_anchor ( txid, anchor) ) ;
160+ }
153161 }
154162 }
155163
156- changeset
157- }
158-
159- /// Batch insert transactions.
160- ///
161- /// All transactions in `txs` will be inserted. To filter out irrelevant transactions, use
162- /// [`batch_insert_relevant`] instead.
163- ///
164- /// [`batch_insert_relevant`]: IndexedTxGraph::batch_insert_relevant
165- pub fn batch_insert < ' t > (
166- & mut self ,
167- txs : impl IntoIterator < Item = InsertTxItem < ' t , impl IntoIterator < Item = A > > > ,
168- ) -> ChangeSet < A , I :: ChangeSet > {
169- let mut changeset = ChangeSet :: < A , I :: ChangeSet > :: default ( ) ;
170- for ( tx, anchors, seen_at) in txs {
171- changeset. indexer . append ( self . index . index_tx ( tx) ) ;
172- changeset. append ( self . insert_tx ( tx, anchors, seen_at) ) ;
173- }
174- changeset
164+ ChangeSet { graph, indexer }
175165 }
176166
177167 /// Batch insert unconfirmed transactions, filtering out those that are irrelevant.
178168 ///
179169 /// Relevancy is determined by the internal [`Indexer::is_tx_relevant`] implementation of `I`.
180170 /// Irrelevant tansactions in `txs` will be ignored.
181171 ///
182- /// Items of `txs` are tuples containing the transaction and an optional *last seen* timestamp.
183- /// The *last seen* communicates when the transaction is last seen in the mempool which is used
184- /// for conflict-resolution in [`TxGraph`] (refer to [`TxGraph::insert_seen_at`] for details).
172+ /// Items of `txs` are tuples containing the transaction and a *last seen* timestamp. The
173+ /// *last seen* communicates when the transaction is last seen in the mempool which is used for
174+ /// conflict-resolution in [`TxGraph`] (refer to [`TxGraph::insert_seen_at`] for details).
185175 pub fn batch_insert_relevant_unconfirmed < ' t > (
186176 & mut self ,
187- unconfirmed_txs : impl IntoIterator < Item = ( & ' t Transaction , Option < u64 > ) > ,
177+ unconfirmed_txs : impl IntoIterator < Item = ( & ' t Transaction , u64 ) > ,
188178 ) -> ChangeSet < A , I :: ChangeSet > {
189- self . batch_insert_relevant (
190- unconfirmed_txs
191- . into_iter ( )
192- . map ( |( tx, last_seen) | ( tx, core:: iter:: empty ( ) , last_seen) ) ,
193- )
179+ // The algorithm below allows for non-topologically ordered transactions by using two loops.
180+ // This is achieved by:
181+ // 1. insert all txs into the index. If they are irrelevant then that's fine it will just
182+ // not store anything about them.
183+ // 2. decide whether to insert them into the graph depending on whether `is_tx_relevant`
184+ // returns true or not. (in a second loop).
185+ let txs = unconfirmed_txs. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
186+
187+ let mut indexer = I :: ChangeSet :: default ( ) ;
188+ for ( tx, _) in & txs {
189+ indexer. append ( self . index . index_tx ( tx) ) ;
190+ }
191+
192+ let graph = self . graph . batch_insert_unconfirmed (
193+ txs. into_iter ( )
194+ . filter ( |( tx, _) | self . index . is_tx_relevant ( tx) )
195+ . map ( |( tx, seen_at) | ( tx. clone ( ) , seen_at) ) ,
196+ ) ;
197+
198+ ChangeSet { graph, indexer }
194199 }
195200
196201 /// Batch insert unconfirmed transactions.
197202 ///
198- /// Items of `txs` are tuples containing the transaction and an optional *last seen* timestamp.
199- /// The *last seen* communicates when the transaction is last seen in the mempool which is used
200- /// for conflict-resolution in [`TxGraph`] (refer to [`TxGraph::insert_seen_at`] for details).
203+ /// Items of `txs` are tuples containing the transaction and a *last seen* timestamp. The
204+ /// *last seen* communicates when the transaction is last seen in the mempool which is used for
205+ /// conflict-resolution in [`TxGraph`] (refer to [`TxGraph::insert_seen_at`] for details).
201206 ///
202207 /// To filter out irrelevant transactions, use [`batch_insert_relevant_unconfirmed`] instead.
203208 ///
204209 /// [`batch_insert_relevant_unconfirmed`]: IndexedTxGraph::batch_insert_relevant_unconfirmed
205- pub fn batch_insert_unconfirmed < ' t > (
210+ pub fn batch_insert_unconfirmed (
206211 & mut self ,
207- unconfirmed_txs : impl IntoIterator < Item = ( & ' t Transaction , Option < u64 > ) > ,
212+ txs : impl IntoIterator < Item = ( Transaction , u64 ) > ,
208213 ) -> ChangeSet < A , I :: ChangeSet > {
209- self . batch_insert (
210- unconfirmed_txs
211- . into_iter ( )
212- . map ( |( tx, last_seen) | ( tx, core:: iter:: empty ( ) , last_seen) ) ,
213- )
214+ let graph = self . graph . batch_insert_unconfirmed ( txs) ;
215+ let indexer = self . index_tx_graph_changeset ( & graph) ;
216+ ChangeSet { graph, indexer }
214217 }
215218}
216219
@@ -241,7 +244,6 @@ where
241244 (
242245 tx,
243246 core:: iter:: once ( A :: from_block_position ( & block, block_id, tx_pos) ) ,
244- None ,
245247 )
246248 } ) ;
247249 self . batch_insert_relevant ( txs)
@@ -260,30 +262,17 @@ where
260262 hash : block. block_hash ( ) ,
261263 height,
262264 } ;
263- let txs = block . txdata . iter ( ) . enumerate ( ) . map ( | ( tx_pos , tx ) | {
264- (
265- tx ,
266- core :: iter :: once ( A :: from_block_position ( & block , block_id , tx_pos ) ) ,
267- None ,
268- )
269- } ) ;
270- self . batch_insert ( txs )
265+ let mut graph = tx_graph :: ChangeSet :: default ( ) ;
266+ for ( tx_pos , tx ) in block . txdata . iter ( ) . enumerate ( ) {
267+ let anchor = A :: from_block_position ( & block , block_id , tx_pos ) ;
268+ graph . append ( self . graph . insert_anchor ( tx . txid ( ) , anchor ) ) ;
269+ graph . append ( self . graph . insert_tx ( tx . clone ( ) ) ) ;
270+ }
271+ let indexer = self . index_tx_graph_changeset ( & graph ) ;
272+ ChangeSet { graph , indexer }
271273 }
272274}
273275
274- /// A tuple of a transaction, and associated metadata, that are to be inserted into [`IndexedTxGraph`].
275- ///
276- /// This tuple contains fields in the following order:
277- /// * A reference to the transaction.
278- /// * A collection of [`Anchor`]s.
279- /// * An optional last-seen timestamp.
280- ///
281- /// This is used as a input item of [`batch_insert_relevant`] and [`batch_insert`].
282- ///
283- /// [`batch_insert_relevant`]: IndexedTxGraph::batch_insert_relevant
284- /// [`batch_insert`]: IndexedTxGraph::batch_insert
285- pub type InsertTxItem < ' t , A > = ( & ' t Transaction , A , Option < u64 > ) ;
286-
287276/// A structure that represents changes to an [`IndexedTxGraph`].
288277#[ derive( Clone , Debug , PartialEq ) ]
289278#[ cfg_attr(
0 commit comments