@@ -109,10 +109,11 @@ use core::{
109
109
/// [module-level documentation]: crate::tx_graph
110
110
#[ derive( Clone , Debug , PartialEq ) ]
111
111
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 > ) > ,
114
114
spends : BTreeMap < OutPoint , HashSet < Txid > > ,
115
115
anchors : BTreeSet < ( A , Txid ) > ,
116
+ last_seen : HashMap < Txid , u64 > ,
116
117
117
118
// This atrocity exists so that `TxGraph::outspends()` can return a reference.
118
119
// FIXME: This can be removed once `HashSet::new` is a const fn.
@@ -125,6 +126,7 @@ impl<A> Default for TxGraph<A> {
125
126
txs : Default :: default ( ) ,
126
127
spends : Default :: default ( ) ,
127
128
anchors : Default :: default ( ) ,
129
+ last_seen : Default :: default ( ) ,
128
130
empty_outspends : Default :: default ( ) ,
129
131
}
130
132
}
@@ -210,7 +212,7 @@ impl<A> TxGraph<A> {
210
212
///
211
213
/// This includes txouts of both full transactions as well as floating transactions.
212
214
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 {
214
216
TxNodeInternal :: Whole ( tx) => tx
215
217
. as_ref ( )
216
218
. output
@@ -232,7 +234,7 @@ impl<A> TxGraph<A> {
232
234
pub fn floating_txouts ( & self ) -> impl Iterator < Item = ( OutPoint , & TxOut ) > {
233
235
self . txs
234
236
. iter ( )
235
- . filter_map ( |( txid, ( tx_node, _, _ ) ) | match tx_node {
237
+ . filter_map ( |( txid, ( tx_node, _) ) | match tx_node {
236
238
TxNodeInternal :: Whole ( _) => None ,
237
239
TxNodeInternal :: Partial ( txouts) => Some (
238
240
txouts
@@ -247,12 +249,12 @@ impl<A> TxGraph<A> {
247
249
pub fn full_txs ( & self ) -> impl Iterator < Item = TxNode < ' _ , Arc < Transaction > , A > > {
248
250
self . txs
249
251
. iter ( )
250
- . filter_map ( |( & txid, ( tx, anchors, last_seen ) ) | match tx {
252
+ . filter_map ( |( & txid, ( tx, anchors) ) | match tx {
251
253
TxNodeInternal :: Whole ( tx) => Some ( TxNode {
252
254
txid,
253
255
tx : tx. clone ( ) ,
254
256
anchors,
255
- last_seen_unconfirmed : * last_seen,
257
+ last_seen_unconfirmed : self . last_seen . get ( & txid ) . copied ( ) ,
256
258
} ) ,
257
259
TxNodeInternal :: Partial ( _) => None ,
258
260
} )
@@ -283,11 +285,11 @@ impl<A> TxGraph<A> {
283
285
/// Get a transaction node by txid. This only returns `Some` for full transactions.
284
286
pub fn get_tx_node ( & self , txid : Txid ) -> Option < TxNode < ' _ , Arc < Transaction > , A > > {
285
287
match & self . txs . get ( & txid) ? {
286
- ( TxNodeInternal :: Whole ( tx) , anchors, last_seen ) => Some ( TxNode {
288
+ ( TxNodeInternal :: Whole ( tx) , anchors) => Some ( TxNode {
287
289
txid,
288
290
tx : tx. clone ( ) ,
289
291
anchors,
290
- last_seen_unconfirmed : * last_seen,
292
+ last_seen_unconfirmed : self . last_seen . get ( & txid ) . copied ( ) ,
291
293
} ) ,
292
294
_ => None ,
293
295
}
@@ -517,7 +519,6 @@ impl<A: Clone + Ord> TxGraph<A> {
517
519
(
518
520
TxNodeInternal :: Partial ( [ ( outpoint. vout , txout) ] . into ( ) ) ,
519
521
BTreeSet :: new ( ) ,
520
- None ,
521
522
) ,
522
523
) ;
523
524
self . apply_update ( update)
@@ -531,7 +532,7 @@ impl<A: Clone + Ord> TxGraph<A> {
531
532
let mut update = Self :: default ( ) ;
532
533
update. txs . insert (
533
534
tx. compute_txid ( ) ,
534
- ( TxNodeInternal :: Whole ( tx) , BTreeSet :: new ( ) , None ) ,
535
+ ( TxNodeInternal :: Whole ( tx) , BTreeSet :: new ( ) ) ,
535
536
) ;
536
537
self . apply_update ( update)
537
538
}
@@ -572,8 +573,7 @@ impl<A: Clone + Ord> TxGraph<A> {
572
573
/// [`update_last_seen_unconfirmed`]: Self::update_last_seen_unconfirmed
573
574
pub fn insert_seen_at ( & mut self , txid : Txid , seen_at : u64 ) -> ChangeSet < A > {
574
575
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) ;
577
577
self . apply_update ( update)
578
578
}
579
579
@@ -620,7 +620,7 @@ impl<A: Clone + Ord> TxGraph<A> {
620
620
. txs
621
621
. iter ( )
622
622
. filter_map (
623
- |( & txid, ( _, anchors, _ ) ) | {
623
+ |( & txid, ( _, anchors) ) | {
624
624
if anchors. is_empty ( ) {
625
625
Some ( txid)
626
626
} else {
@@ -669,21 +669,19 @@ impl<A: Clone + Ord> TxGraph<A> {
669
669
} ) ;
670
670
671
671
match self . txs . get_mut ( & txid) {
672
- Some ( ( tx_node @ TxNodeInternal :: Partial ( _) , _, _ ) ) => {
672
+ Some ( ( tx_node @ TxNodeInternal :: Partial ( _) , _) ) => {
673
673
* tx_node = TxNodeInternal :: Whole ( wrapped_tx. clone ( ) ) ;
674
674
}
675
- Some ( ( TxNodeInternal :: Whole ( tx) , _, _ ) ) => {
675
+ Some ( ( TxNodeInternal :: Whole ( tx) , _) ) => {
676
676
debug_assert_eq ! (
677
677
tx. as_ref( ) . compute_txid( ) ,
678
678
txid,
679
679
"tx should produce txid that is same as key"
680
680
) ;
681
681
}
682
682
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 ( ) ) ) ;
687
685
}
688
686
}
689
687
}
@@ -692,25 +690,24 @@ impl<A: Clone + Ord> TxGraph<A> {
692
690
let tx_entry = self . txs . entry ( outpoint. txid ) . or_default ( ) ;
693
691
694
692
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) , _) => {
698
695
txouts. insert ( outpoint. vout , txout) ;
699
696
}
700
697
}
701
698
}
702
699
703
700
for ( anchor, txid) in changeset. anchors {
704
701
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 ( ) ;
706
703
anchors. insert ( anchor) ;
707
704
}
708
705
}
709
706
710
707
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;
714
711
}
715
712
}
716
713
}
@@ -722,30 +719,24 @@ impl<A: Clone + Ord> TxGraph<A> {
722
719
pub ( crate ) fn determine_changeset ( & self , update : TxGraph < A > ) -> ChangeSet < A > {
723
720
let mut changeset = ChangeSet :: < A > :: default ( ) ;
724
721
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) {
727
724
( None , TxNodeInternal :: Whole ( update_tx) ) => {
728
725
changeset. txs . insert ( update_tx. clone ( ) ) ;
729
- None
730
726
}
731
727
( None , TxNodeInternal :: Partial ( update_txos) ) => {
732
728
changeset. txouts . extend (
733
729
update_txos
734
730
. iter ( )
735
731
. map ( |( & vout, txo) | ( OutPoint :: new ( txid, vout) , txo. clone ( ) ) ) ,
736
732
) ;
737
- None
738
733
}
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) ) => {
744
736
changeset. txs . insert ( update_tx. clone ( ) ) ;
745
- * last_seen
746
737
}
747
738
(
748
- Some ( ( TxNodeInternal :: Partial ( txos) , _, last_seen ) ) ,
739
+ Some ( ( TxNodeInternal :: Partial ( txos) , _) ) ,
749
740
TxNodeInternal :: Partial ( update_txos) ,
750
741
) => {
751
742
changeset. txouts . extend (
@@ -754,15 +745,14 @@ impl<A: Clone + Ord> TxGraph<A> {
754
745
. filter ( |( vout, _) | !txos. contains_key ( * vout) )
755
746
. map ( |( & vout, txo) | ( OutPoint :: new ( txid, vout) , txo. clone ( ) ) ) ,
756
747
) ;
757
- * last_seen
758
748
}
759
- } ;
749
+ }
750
+ }
760
751
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) ;
766
756
}
767
757
}
768
758
@@ -802,7 +792,7 @@ impl<A: Anchor> TxGraph<A> {
802
792
chain_tip : BlockId ,
803
793
txid : Txid ,
804
794
) -> 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) {
806
796
Some ( v) => v,
807
797
None => return Ok ( None ) ,
808
798
} ;
@@ -816,7 +806,7 @@ impl<A: Anchor> TxGraph<A> {
816
806
817
807
// If no anchors are in best chain and we don't have a last_seen, we can return
818
808
// 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 ) {
820
810
Some ( t) => * t,
821
811
None => return Ok ( None ) ,
822
812
} ;
0 commit comments