@@ -512,28 +512,66 @@ impl<A: Clone + Ord> TxGraph<A> {
512
512
///
513
513
/// [`apply_changeset`]: Self::apply_changeset
514
514
pub fn insert_txout ( & mut self , outpoint : OutPoint , txout : TxOut ) -> ChangeSet < A > {
515
- let mut update = Self :: default ( ) ;
516
- update. txs . insert (
517
- outpoint. txid ,
518
- (
519
- TxNodeInternal :: Partial ( [ ( outpoint. vout , txout) ] . into ( ) ) ,
520
- BTreeSet :: new ( ) ,
521
- ) ,
522
- ) ;
523
- self . apply_update ( update)
515
+ let mut changeset = ChangeSet :: < A > :: default ( ) ;
516
+ let ( tx_node, _) = self . txs . entry ( outpoint. txid ) . or_default ( ) ;
517
+ match tx_node {
518
+ TxNodeInternal :: Whole ( _) => {
519
+ // ignore this txout we have the full one already.
520
+ // NOTE: You might think putting a debug_assert! here to check the output being
521
+ // replaced was actually correct is a good idea but the tests have already been
522
+ // written assuming this never panics.
523
+ }
524
+ TxNodeInternal :: Partial ( partial_tx) => {
525
+ match partial_tx. insert ( outpoint. vout , txout. clone ( ) ) {
526
+ Some ( old_txout) => {
527
+ debug_assert_eq ! (
528
+ txout, old_txout,
529
+ "txout of the same outpoint should never change"
530
+ ) ;
531
+ }
532
+ None => {
533
+ changeset. txouts . insert ( outpoint, txout) ;
534
+ }
535
+ }
536
+ }
537
+ }
538
+ changeset
524
539
}
525
540
526
541
/// Inserts the given transaction into [`TxGraph`].
527
542
///
528
543
/// The [`ChangeSet`] returned will be empty if `tx` already exists.
529
544
pub fn insert_tx < T : Into < Arc < Transaction > > > ( & mut self , tx : T ) -> ChangeSet < A > {
530
- let tx = tx. into ( ) ;
531
- let mut update = Self :: default ( ) ;
532
- update. txs . insert (
533
- tx. compute_txid ( ) ,
534
- ( TxNodeInternal :: Whole ( tx) , BTreeSet :: new ( ) ) ,
535
- ) ;
536
- self . apply_update ( update)
545
+ let tx: Arc < Transaction > = tx. into ( ) ;
546
+ let txid = tx. compute_txid ( ) ;
547
+ let mut changeset = ChangeSet :: < A > :: default ( ) ;
548
+
549
+ let ( tx_node, _) = self . txs . entry ( txid) . or_default ( ) ;
550
+ match tx_node {
551
+ TxNodeInternal :: Whole ( existing_tx) => {
552
+ debug_assert_eq ! (
553
+ existing_tx. as_ref( ) ,
554
+ tx. as_ref( ) ,
555
+ "tx of same txid should never change"
556
+ ) ;
557
+ }
558
+ partial_tx => {
559
+ for txin in & tx. input {
560
+ // this means the tx is coinbase so there is no previous output
561
+ if txin. previous_output . is_null ( ) {
562
+ continue ;
563
+ }
564
+ self . spends
565
+ . entry ( txin. previous_output )
566
+ . or_default ( )
567
+ . insert ( txid) ;
568
+ }
569
+ * partial_tx = TxNodeInternal :: Whole ( tx. clone ( ) ) ;
570
+ changeset. txs . insert ( tx) ;
571
+ }
572
+ }
573
+
574
+ changeset
537
575
}
538
576
539
577
/// Batch insert unconfirmed transactions.
@@ -558,9 +596,17 @@ impl<A: Clone + Ord> TxGraph<A> {
558
596
/// The [`ChangeSet`] returned will be empty if graph already knows that `txid` exists in
559
597
/// `anchor`.
560
598
pub fn insert_anchor ( & mut self , txid : Txid , anchor : A ) -> ChangeSet < A > {
561
- let mut update = Self :: default ( ) ;
562
- update. anchors . insert ( ( anchor, txid) ) ;
563
- self . apply_update ( update)
599
+ let mut changeset = ChangeSet :: < A > :: default ( ) ;
600
+ if self . anchors . insert ( ( anchor. clone ( ) , txid) ) {
601
+ let ( _tx_node, anchors) = self . txs . entry ( txid) . or_default ( ) ;
602
+ let _inserted = anchors. insert ( anchor. clone ( ) ) ;
603
+ debug_assert ! (
604
+ _inserted,
605
+ "anchors in `.anchors` and `.txs` should be consistent"
606
+ ) ;
607
+ changeset. anchors . insert ( ( anchor, txid) ) ;
608
+ }
609
+ changeset
564
610
}
565
611
566
612
/// Inserts the given `seen_at` for `txid` into [`TxGraph`].
@@ -571,9 +617,13 @@ impl<A: Clone + Ord> TxGraph<A> {
571
617
///
572
618
/// [`update_last_seen_unconfirmed`]: Self::update_last_seen_unconfirmed
573
619
pub fn insert_seen_at ( & mut self , txid : Txid , seen_at : u64 ) -> ChangeSet < A > {
574
- let mut update = Self :: default ( ) ;
575
- update. last_seen . insert ( txid, seen_at) ;
576
- self . apply_update ( update)
620
+ let mut changeset = ChangeSet :: < A > :: default ( ) ;
621
+ let last_seen = self . last_seen . entry ( txid) . or_default ( ) ;
622
+ if seen_at > * last_seen {
623
+ * last_seen = seen_at;
624
+ changeset. last_seen . insert ( txid, seen_at) ;
625
+ }
626
+ changeset
577
627
}
578
628
579
629
/// Update the last seen time for all unconfirmed transactions.
@@ -641,124 +691,50 @@ impl<A: Clone + Ord> TxGraph<A> {
641
691
/// The returned [`ChangeSet`] is the set difference between `update` and `self` (transactions that
642
692
/// exist in `update` but not in `self`).
643
693
pub fn apply_update ( & mut self , update : TxGraph < A > ) -> ChangeSet < A > {
644
- let changeset = self . determine_changeset ( update) ;
645
- self . apply_changeset ( changeset. clone ( ) ) ;
694
+ let mut changeset = ChangeSet :: < A > :: default ( ) ;
695
+ for tx_node in update. full_txs ( ) {
696
+ changeset. merge ( self . insert_tx ( tx_node. tx ) ) ;
697
+ }
698
+ for ( outpoint, txout) in update. floating_txouts ( ) {
699
+ changeset. merge ( self . insert_txout ( outpoint, txout. clone ( ) ) ) ;
700
+ }
701
+ for ( anchor, txid) in & update. anchors {
702
+ changeset. merge ( self . insert_anchor ( * txid, anchor. clone ( ) ) ) ;
703
+ }
704
+ for ( & txid, & last_seen) in & update. last_seen {
705
+ changeset. merge ( self . insert_seen_at ( txid, last_seen) ) ;
706
+ }
646
707
changeset
647
708
}
648
709
649
710
/// Determines the [`ChangeSet`] between `self` and an empty [`TxGraph`].
650
711
pub fn initial_changeset ( & self ) -> ChangeSet < A > {
651
- Self :: default ( ) . determine_changeset ( self . clone ( ) )
712
+ ChangeSet {
713
+ txs : self . full_txs ( ) . map ( |tx_node| tx_node. tx ) . collect ( ) ,
714
+ txouts : self
715
+ . floating_txouts ( )
716
+ . map ( |( op, txout) | ( op, txout. clone ( ) ) )
717
+ . collect ( ) ,
718
+ anchors : self . anchors . clone ( ) ,
719
+ last_seen : self . last_seen . iter ( ) . map ( |( & k, & v) | ( k, v) ) . collect ( ) ,
720
+ }
652
721
}
653
722
654
723
/// Applies [`ChangeSet`] to [`TxGraph`].
655
724
pub fn apply_changeset ( & mut self , changeset : ChangeSet < A > ) {
656
- for wrapped_tx in changeset. txs {
657
- let tx = wrapped_tx. as_ref ( ) ;
658
- let txid = tx. compute_txid ( ) ;
659
-
660
- tx. input
661
- . iter ( )
662
- . map ( |txin| txin. previous_output )
663
- // coinbase spends are not to be counted
664
- . filter ( |outpoint| !outpoint. is_null ( ) )
665
- // record spend as this tx has spent this outpoint
666
- . for_each ( |outpoint| {
667
- self . spends . entry ( outpoint) . or_default ( ) . insert ( txid) ;
668
- } ) ;
669
-
670
- match self . txs . get_mut ( & txid) {
671
- Some ( ( tx_node @ TxNodeInternal :: Partial ( _) , _) ) => {
672
- * tx_node = TxNodeInternal :: Whole ( wrapped_tx. clone ( ) ) ;
673
- }
674
- Some ( ( TxNodeInternal :: Whole ( tx) , _) ) => {
675
- debug_assert_eq ! (
676
- tx. as_ref( ) . compute_txid( ) ,
677
- txid,
678
- "tx should produce txid that is same as key"
679
- ) ;
680
- }
681
- None => {
682
- self . txs
683
- . insert ( txid, ( TxNodeInternal :: Whole ( wrapped_tx) , BTreeSet :: new ( ) ) ) ;
684
- }
685
- }
725
+ for tx in changeset. txs {
726
+ let _ = self . insert_tx ( tx) ;
686
727
}
687
-
688
728
for ( outpoint, txout) in changeset. txouts {
689
- let tx_entry = self . txs . entry ( outpoint. txid ) . or_default ( ) ;
690
-
691
- match tx_entry {
692
- ( TxNodeInternal :: Whole ( _) , _) => { /* do nothing since we already have full tx */ }
693
- ( TxNodeInternal :: Partial ( txouts) , _) => {
694
- txouts. insert ( outpoint. vout , txout) ;
695
- }
696
- }
729
+ let _ = self . insert_txout ( outpoint, txout) ;
697
730
}
698
-
699
731
for ( anchor, txid) in changeset. anchors {
700
- if self . anchors . insert ( ( anchor. clone ( ) , txid) ) {
701
- let ( _, anchors) = self . txs . entry ( txid) . or_default ( ) ;
702
- anchors. insert ( anchor) ;
703
- }
732
+ let _ = self . insert_anchor ( txid, anchor) ;
704
733
}
705
-
706
- for ( txid, new_last_seen) in changeset. last_seen {
707
- let last_seen = self . last_seen . entry ( txid) . or_default ( ) ;
708
- if new_last_seen > * last_seen {
709
- * last_seen = new_last_seen;
710
- }
734
+ for ( txid, seen_at) in changeset. last_seen {
735
+ let _ = self . insert_seen_at ( txid, seen_at) ;
711
736
}
712
737
}
713
-
714
- /// Previews the resultant [`ChangeSet`] when [`Self`] is updated against the `update` graph.
715
- ///
716
- /// The [`ChangeSet`] would be the set difference between `update` and `self` (transactions that
717
- /// exist in `update` but not in `self`).
718
- pub ( crate ) fn determine_changeset ( & self , update : TxGraph < A > ) -> ChangeSet < A > {
719
- let mut changeset = ChangeSet :: < A > :: default ( ) ;
720
-
721
- for ( & txid, ( update_tx_node, _) ) in & update. txs {
722
- match ( self . txs . get ( & txid) , update_tx_node) {
723
- ( None , TxNodeInternal :: Whole ( update_tx) ) => {
724
- changeset. txs . insert ( update_tx. clone ( ) ) ;
725
- }
726
- ( None , TxNodeInternal :: Partial ( update_txos) ) => {
727
- changeset. txouts . extend (
728
- update_txos
729
- . iter ( )
730
- . map ( |( & vout, txo) | ( OutPoint :: new ( txid, vout) , txo. clone ( ) ) ) ,
731
- ) ;
732
- }
733
- ( Some ( ( TxNodeInternal :: Whole ( _) , _) ) , _) => { }
734
- ( Some ( ( TxNodeInternal :: Partial ( _) , _) ) , TxNodeInternal :: Whole ( update_tx) ) => {
735
- changeset. txs . insert ( update_tx. clone ( ) ) ;
736
- }
737
- (
738
- Some ( ( TxNodeInternal :: Partial ( txos) , _) ) ,
739
- TxNodeInternal :: Partial ( update_txos) ,
740
- ) => {
741
- changeset. txouts . extend (
742
- update_txos
743
- . iter ( )
744
- . filter ( |( vout, _) | !txos. contains_key ( * vout) )
745
- . map ( |( & vout, txo) | ( OutPoint :: new ( txid, vout) , txo. clone ( ) ) ) ,
746
- ) ;
747
- }
748
- }
749
- }
750
-
751
- for ( txid, update_last_seen) in update. last_seen {
752
- let prev_last_seen = self . last_seen . get ( & txid) . copied ( ) ;
753
- if Some ( update_last_seen) > prev_last_seen {
754
- changeset. last_seen . insert ( txid, update_last_seen) ;
755
- }
756
- }
757
-
758
- changeset. anchors = update. anchors . difference ( & self . anchors ) . cloned ( ) . collect ( ) ;
759
-
760
- changeset
761
- }
762
738
}
763
739
764
740
impl < A : Anchor > TxGraph < A > {
0 commit comments