Skip to content

Commit 9ab4194

Browse files
committed
feat(chain) allow changing the indexer on TxGraph
1 parent 7307bb1 commit 9ab4194

File tree

1 file changed

+67
-12
lines changed

1 file changed

+67
-12
lines changed

crates/chain/src/tx_graph.rs

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ enum TxNodeInternal {
184184
Partial(BTreeMap<u32, TxOut>),
185185
}
186186

187+
impl TxNodeInternal {
188+
fn iter_txouts(
189+
txid: Txid,
190+
partial: &BTreeMap<u32, TxOut>,
191+
) -> impl Iterator<Item = (OutPoint, &TxOut)> {
192+
partial
193+
.iter()
194+
.map(move |(&vout, txout)| (OutPoint { txid, vout }, txout))
195+
}
196+
}
197+
187198
impl Default for TxNodeInternal {
188199
fn default() -> Self {
189200
Self::Partial(BTreeMap::new())
@@ -233,18 +244,17 @@ impl<A, X> TxGraph<A, X> {
233244
///
234245
/// This includes txouts of both full transactions as well as floating transactions.
235246
pub fn all_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
236-
self.txs.iter().flat_map(|(txid, tx)| match tx {
247+
self.txs.iter().flat_map(|(&txid, tx)| match tx {
237248
TxNodeInternal::Whole(tx) => tx
238249
.as_ref()
239250
.output
240251
.iter()
241252
.enumerate()
242-
.map(|(vout, txout)| (OutPoint::new(*txid, vout as _), txout))
243-
.collect::<Vec<_>>(),
244-
TxNodeInternal::Partial(txouts) => txouts
245-
.iter()
246-
.map(|(vout, txout)| (OutPoint::new(*txid, *vout as _), txout))
253+
.map(|(vout, txout)| (OutPoint::new(txid, vout as _), txout))
247254
.collect::<Vec<_>>(),
255+
TxNodeInternal::Partial(partial) => {
256+
TxNodeInternal::iter_txouts(txid, partial).collect::<Vec<_>>()
257+
}
248258
})
249259
}
250260

@@ -255,13 +265,11 @@ impl<A, X> TxGraph<A, X> {
255265
pub fn floating_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
256266
self.txs
257267
.iter()
258-
.filter_map(|(txid, tx_node)| match tx_node {
268+
.filter_map(|(&txid, tx_node)| match tx_node {
259269
TxNodeInternal::Whole(_) => None,
260-
TxNodeInternal::Partial(txouts) => Some(
261-
txouts
262-
.iter()
263-
.map(|(&vout, txout)| (OutPoint::new(*txid, vout), txout)),
264-
),
270+
TxNodeInternal::Partial(partial) => {
271+
Some(TxNodeInternal::iter_txouts(txid, partial))
272+
}
265273
})
266274
.flatten()
267275
}
@@ -806,8 +814,13 @@ impl<A: Clone + Ord, X: Indexer> TxGraph<A, X> {
806814
/// Extends this graph with another so that `self` becomes the union of the two sets of
807815
/// transactions.
808816
///
817+
/// `X` must be `()` for the `update` tx graph. If you want to update with a `TxGraph` that
818+
/// happens to have an indexer first use [`swap_indexer`] to get rid of it.
819+
///
809820
/// The returned [`ChangeSet`] is the set difference between `update` and `self` (transactions that
810821
/// exist in `update` but not in `self`).
822+
///
823+
/// [`swap_indexer`]: Self::swap_indexer
811824
pub fn apply_update(&mut self, update: TxGraph<A>) -> ChangeSet<A, X::ChangeSet> {
812825
let mut changeset = ChangeSet::default();
813826
for tx in update.full_txs() {
@@ -829,6 +842,48 @@ impl<A: Clone + Ord, X: Indexer> TxGraph<A, X> {
829842
changeset
830843
}
831844

845+
/// Changes the [`Indexer`] for a `TxGraph`. **This doesn't re-index the transactions in the
846+
/// graph** for that call [`reindex`].
847+
///
848+
/// Returns the new `TxGraph` and the old indexer.
849+
///
850+
/// [`reindex`]: Self::reindex
851+
pub fn swap_indexer<XNew>(self, indexer: XNew) -> (TxGraph<A, XNew>, X) {
852+
(
853+
TxGraph {
854+
txs: self.txs,
855+
spends: self.spends,
856+
anchors: self.anchors,
857+
rev_anchors: self.rev_anchors,
858+
last_seen: self.last_seen,
859+
empty_outspends: self.empty_outspends,
860+
empty_anchors: self.empty_anchors,
861+
indexer,
862+
},
863+
self.indexer,
864+
)
865+
}
866+
867+
/// Reindexs the transaction graph by calling the [`Indexer`] on every transaction.
868+
///
869+
/// The returned changeset will only bne non-empty in the `indexer` field.
870+
pub fn reindex(&mut self) -> ChangeSet<A, X::ChangeSet> {
871+
let mut changeset = ChangeSet::<A, X::ChangeSet>::default();
872+
for (txid, node) in &self.txs {
873+
match node {
874+
TxNodeInternal::Whole(tx) => {
875+
changeset.merge(self.indexer.index_tx(tx.as_ref()).into())
876+
}
877+
TxNodeInternal::Partial(txouts) => {
878+
for (op, txout) in TxNodeInternal::iter_txouts(*txid, txouts) {
879+
changeset.merge(self.indexer.index_txout(op, txout).into());
880+
}
881+
}
882+
};
883+
}
884+
changeset
885+
}
886+
832887
/// Determines the [`ChangeSet`] between `self` and an empty [`TxGraph`].
833888
pub fn initial_changeset(&self) -> ChangeSet<A, X::ChangeSet> {
834889
ChangeSet {

0 commit comments

Comments
 (0)