Skip to content

Commit af75817

Browse files
committed
ref(tx_graph): Change last_seen to HashMap<Txid, u64>
1 parent 6204d2c commit af75817

File tree

1 file changed

+36
-46
lines changed

1 file changed

+36
-46
lines changed

crates/chain/src/tx_graph.rs

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ use core::{
109109
/// [module-level documentation]: crate::tx_graph
110110
#[derive(Clone, Debug, PartialEq)]
111111
pub struct TxGraph<A = ()> {
112-
// all transactions that the graph is aware of in format: `(tx_node, tx_anchors, tx_last_seen)`
113-
txs: HashMap<Txid, (TxNodeInternal, BTreeSet<A>, Option<u64>)>,
112+
// all transactions that the graph is aware of in format: `(tx_node, tx_anchors)`
113+
txs: HashMap<Txid, (TxNodeInternal, BTreeSet<A>)>,
114114
spends: BTreeMap<OutPoint, HashSet<Txid>>,
115115
anchors: BTreeSet<(A, Txid)>,
116+
last_seen: HashMap<Txid, u64>,
116117

117118
// This atrocity exists so that `TxGraph::outspends()` can return a reference.
118119
// FIXME: This can be removed once `HashSet::new` is a const fn.
@@ -125,6 +126,7 @@ impl<A> Default for TxGraph<A> {
125126
txs: Default::default(),
126127
spends: Default::default(),
127128
anchors: Default::default(),
129+
last_seen: Default::default(),
128130
empty_outspends: Default::default(),
129131
}
130132
}
@@ -210,7 +212,7 @@ impl<A> TxGraph<A> {
210212
///
211213
/// This includes txouts of both full transactions as well as floating transactions.
212214
pub fn all_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
213-
self.txs.iter().flat_map(|(txid, (tx, _, _))| match tx {
215+
self.txs.iter().flat_map(|(txid, (tx, _))| match tx {
214216
TxNodeInternal::Whole(tx) => tx
215217
.as_ref()
216218
.output
@@ -232,7 +234,7 @@ impl<A> TxGraph<A> {
232234
pub fn floating_txouts(&self) -> impl Iterator<Item = (OutPoint, &TxOut)> {
233235
self.txs
234236
.iter()
235-
.filter_map(|(txid, (tx_node, _, _))| match tx_node {
237+
.filter_map(|(txid, (tx_node, _))| match tx_node {
236238
TxNodeInternal::Whole(_) => None,
237239
TxNodeInternal::Partial(txouts) => Some(
238240
txouts
@@ -247,12 +249,12 @@ impl<A> TxGraph<A> {
247249
pub fn full_txs(&self) -> impl Iterator<Item = TxNode<'_, Arc<Transaction>, A>> {
248250
self.txs
249251
.iter()
250-
.filter_map(|(&txid, (tx, anchors, last_seen))| match tx {
252+
.filter_map(|(&txid, (tx, anchors))| match tx {
251253
TxNodeInternal::Whole(tx) => Some(TxNode {
252254
txid,
253255
tx: tx.clone(),
254256
anchors,
255-
last_seen_unconfirmed: *last_seen,
257+
last_seen_unconfirmed: self.last_seen.get(&txid).copied(),
256258
}),
257259
TxNodeInternal::Partial(_) => None,
258260
})
@@ -283,11 +285,11 @@ impl<A> TxGraph<A> {
283285
/// Get a transaction node by txid. This only returns `Some` for full transactions.
284286
pub fn get_tx_node(&self, txid: Txid) -> Option<TxNode<'_, Arc<Transaction>, A>> {
285287
match &self.txs.get(&txid)? {
286-
(TxNodeInternal::Whole(tx), anchors, last_seen) => Some(TxNode {
288+
(TxNodeInternal::Whole(tx), anchors) => Some(TxNode {
287289
txid,
288290
tx: tx.clone(),
289291
anchors,
290-
last_seen_unconfirmed: *last_seen,
292+
last_seen_unconfirmed: self.last_seen.get(&txid).copied(),
291293
}),
292294
_ => None,
293295
}
@@ -517,7 +519,6 @@ impl<A: Clone + Ord> TxGraph<A> {
517519
(
518520
TxNodeInternal::Partial([(outpoint.vout, txout)].into()),
519521
BTreeSet::new(),
520-
None,
521522
),
522523
);
523524
self.apply_update(update)
@@ -531,7 +532,7 @@ impl<A: Clone + Ord> TxGraph<A> {
531532
let mut update = Self::default();
532533
update.txs.insert(
533534
tx.compute_txid(),
534-
(TxNodeInternal::Whole(tx), BTreeSet::new(), None),
535+
(TxNodeInternal::Whole(tx), BTreeSet::new()),
535536
);
536537
self.apply_update(update)
537538
}
@@ -572,8 +573,7 @@ impl<A: Clone + Ord> TxGraph<A> {
572573
/// [`update_last_seen_unconfirmed`]: Self::update_last_seen_unconfirmed
573574
pub fn insert_seen_at(&mut self, txid: Txid, seen_at: u64) -> ChangeSet<A> {
574575
let mut update = Self::default();
575-
let (_, _, update_last_seen) = update.txs.entry(txid).or_default();
576-
*update_last_seen = Some(seen_at);
576+
update.last_seen.insert(txid, seen_at);
577577
self.apply_update(update)
578578
}
579579

@@ -620,7 +620,7 @@ impl<A: Clone + Ord> TxGraph<A> {
620620
.txs
621621
.iter()
622622
.filter_map(
623-
|(&txid, (_, anchors, _))| {
623+
|(&txid, (_, anchors))| {
624624
if anchors.is_empty() {
625625
Some(txid)
626626
} else {
@@ -669,21 +669,19 @@ impl<A: Clone + Ord> TxGraph<A> {
669669
});
670670

671671
match self.txs.get_mut(&txid) {
672-
Some((tx_node @ TxNodeInternal::Partial(_), _, _)) => {
672+
Some((tx_node @ TxNodeInternal::Partial(_), _)) => {
673673
*tx_node = TxNodeInternal::Whole(wrapped_tx.clone());
674674
}
675-
Some((TxNodeInternal::Whole(tx), _, _)) => {
675+
Some((TxNodeInternal::Whole(tx), _)) => {
676676
debug_assert_eq!(
677677
tx.as_ref().compute_txid(),
678678
txid,
679679
"tx should produce txid that is same as key"
680680
);
681681
}
682682
None => {
683-
self.txs.insert(
684-
txid,
685-
(TxNodeInternal::Whole(wrapped_tx), BTreeSet::new(), None),
686-
);
683+
self.txs
684+
.insert(txid, (TxNodeInternal::Whole(wrapped_tx), BTreeSet::new()));
687685
}
688686
}
689687
}
@@ -692,25 +690,24 @@ impl<A: Clone + Ord> TxGraph<A> {
692690
let tx_entry = self.txs.entry(outpoint.txid).or_default();
693691

694692
match tx_entry {
695-
(TxNodeInternal::Whole(_), _, _) => { /* do nothing since we already have full tx */
696-
}
697-
(TxNodeInternal::Partial(txouts), _, _) => {
693+
(TxNodeInternal::Whole(_), _) => { /* do nothing since we already have full tx */ }
694+
(TxNodeInternal::Partial(txouts), _) => {
698695
txouts.insert(outpoint.vout, txout);
699696
}
700697
}
701698
}
702699

703700
for (anchor, txid) in changeset.anchors {
704701
if self.anchors.insert((anchor.clone(), txid)) {
705-
let (_, anchors, _) = self.txs.entry(txid).or_default();
702+
let (_, anchors) = self.txs.entry(txid).or_default();
706703
anchors.insert(anchor);
707704
}
708705
}
709706

710707
for (txid, new_last_seen) in changeset.last_seen {
711-
let (_, _, last_seen) = self.txs.entry(txid).or_default();
712-
if Some(new_last_seen) > *last_seen {
713-
*last_seen = Some(new_last_seen);
708+
let last_seen = self.last_seen.entry(txid).or_default();
709+
if new_last_seen > *last_seen {
710+
*last_seen = new_last_seen;
714711
}
715712
}
716713
}
@@ -722,30 +719,24 @@ impl<A: Clone + Ord> TxGraph<A> {
722719
pub(crate) fn determine_changeset(&self, update: TxGraph<A>) -> ChangeSet<A> {
723720
let mut changeset = ChangeSet::<A>::default();
724721

725-
for (&txid, (update_tx_node, _, update_last_seen)) in &update.txs {
726-
let prev_last_seen = match (self.txs.get(&txid), update_tx_node) {
722+
for (&txid, (update_tx_node, _)) in &update.txs {
723+
match (self.txs.get(&txid), update_tx_node) {
727724
(None, TxNodeInternal::Whole(update_tx)) => {
728725
changeset.txs.insert(update_tx.clone());
729-
None
730726
}
731727
(None, TxNodeInternal::Partial(update_txos)) => {
732728
changeset.txouts.extend(
733729
update_txos
734730
.iter()
735731
.map(|(&vout, txo)| (OutPoint::new(txid, vout), txo.clone())),
736732
);
737-
None
738733
}
739-
(Some((TxNodeInternal::Whole(_), _, last_seen)), _) => *last_seen,
740-
(
741-
Some((TxNodeInternal::Partial(_), _, last_seen)),
742-
TxNodeInternal::Whole(update_tx),
743-
) => {
734+
(Some((TxNodeInternal::Whole(_), _)), _) => {}
735+
(Some((TxNodeInternal::Partial(_), _)), TxNodeInternal::Whole(update_tx)) => {
744736
changeset.txs.insert(update_tx.clone());
745-
*last_seen
746737
}
747738
(
748-
Some((TxNodeInternal::Partial(txos), _, last_seen)),
739+
Some((TxNodeInternal::Partial(txos), _)),
749740
TxNodeInternal::Partial(update_txos),
750741
) => {
751742
changeset.txouts.extend(
@@ -754,15 +745,14 @@ impl<A: Clone + Ord> TxGraph<A> {
754745
.filter(|(vout, _)| !txos.contains_key(*vout))
755746
.map(|(&vout, txo)| (OutPoint::new(txid, vout), txo.clone())),
756747
);
757-
*last_seen
758748
}
759-
};
749+
}
750+
}
760751

761-
if *update_last_seen > prev_last_seen {
762-
changeset.last_seen.insert(
763-
txid,
764-
update_last_seen.expect("checked is greater, so we must have a last_seen"),
765-
);
752+
for (txid, update_last_seen) in update.last_seen {
753+
let prev_last_seen = self.last_seen.get(&txid).copied();
754+
if Some(update_last_seen) > prev_last_seen {
755+
changeset.last_seen.insert(txid, update_last_seen);
766756
}
767757
}
768758

@@ -802,7 +792,7 @@ impl<A: Anchor> TxGraph<A> {
802792
chain_tip: BlockId,
803793
txid: Txid,
804794
) -> Result<Option<ChainPosition<&A>>, C::Error> {
805-
let (tx_node, anchors, last_seen) = match self.txs.get(&txid) {
795+
let (tx_node, anchors) = match self.txs.get(&txid) {
806796
Some(v) => v,
807797
None => return Ok(None),
808798
};
@@ -816,7 +806,7 @@ impl<A: Anchor> TxGraph<A> {
816806

817807
// If no anchors are in best chain and we don't have a last_seen, we can return
818808
// early because by definition the tx doesn't have a chain position.
819-
let last_seen = match last_seen {
809+
let last_seen = match self.last_seen.get(&txid) {
820810
Some(t) => *t,
821811
None => return Ok(None),
822812
};

0 commit comments

Comments
 (0)