@@ -571,4 +571,182 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
571
571
SetMockTime (0 );
572
572
}
573
573
574
+ inline CTransactionRef make_tx (std::vector<CAmount>&& output_values, std::vector<CTransactionRef>&& inputs=std::vector<CTransactionRef>(), std::vector<uint32_t>&& input_indices=std::vector<uint32_t>())
575
+ {
576
+ CMutableTransaction tx = CMutableTransaction ();
577
+ tx.vin .resize (inputs.size ());
578
+ tx.vout .resize (output_values.size ());
579
+ for (size_t i = 0 ; i < inputs.size (); ++i) {
580
+ tx.vin [i].prevout .hash = inputs[i]->GetHash ();
581
+ tx.vin [i].prevout .n = input_indices.size () > i ? input_indices[i] : 0 ;
582
+ }
583
+ for (size_t i = 0 ; i < output_values.size (); ++i) {
584
+ tx.vout [i].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
585
+ tx.vout [i].nValue = output_values[i];
586
+ }
587
+ return MakeTransactionRef (tx);
588
+ }
589
+
590
+ #define MK_OUTPUTS (amounts... ) std::vector<CAmount>{amounts}
591
+ #define MK_INPUTS (txs... ) std::vector<CTransactionRef>{txs}
592
+ #define MK_INPUT_IDX (idxes... ) std::vector<uint32_t >{idxes}
593
+
594
+ BOOST_AUTO_TEST_CASE (MempoolAncestryTests)
595
+ {
596
+ size_t ancestors, descendants;
597
+
598
+ CTxMemPool pool;
599
+ TestMemPoolEntryHelper entry;
600
+
601
+ /* Base transaction */
602
+ //
603
+ // [tx1]
604
+ //
605
+ CTransactionRef tx1 = make_tx (MK_OUTPUTS (10 * COIN));
606
+ pool.addUnchecked (tx1->GetHash (), entry.Fee (10000LL ).FromTx (tx1));
607
+
608
+ // Ancestors / descendants should be 1 / 1 (itself / itself)
609
+ pool.GetTransactionAncestry (tx1->GetHash (), ancestors, descendants);
610
+ BOOST_CHECK_EQUAL (ancestors, 1ULL );
611
+ BOOST_CHECK_EQUAL (descendants, 1ULL );
612
+
613
+ /* Child transaction */
614
+ //
615
+ // [tx1].0 <- [tx2]
616
+ //
617
+ CTransactionRef tx2 = make_tx (MK_OUTPUTS (495 * CENT, 5 * COIN), MK_INPUTS (tx1));
618
+ pool.addUnchecked (tx2->GetHash (), entry.Fee (10000LL ).FromTx (tx2));
619
+
620
+ // Ancestors / descendants should be:
621
+ // transaction ancestors descendants
622
+ // ============ =========== ===========
623
+ // tx1 1 (tx1) 2 (tx1,2)
624
+ // tx2 2 (tx1,2) 2 (tx1,2)
625
+ pool.GetTransactionAncestry (tx1->GetHash (), ancestors, descendants);
626
+ BOOST_CHECK_EQUAL (ancestors, 1ULL );
627
+ BOOST_CHECK_EQUAL (descendants, 2ULL );
628
+ pool.GetTransactionAncestry (tx2->GetHash (), ancestors, descendants);
629
+ BOOST_CHECK_EQUAL (ancestors, 2ULL );
630
+ BOOST_CHECK_EQUAL (descendants, 2ULL );
631
+
632
+ /* Grand-child 1 */
633
+ //
634
+ // [tx1].0 <- [tx2].0 <- [tx3]
635
+ //
636
+ CTransactionRef tx3 = make_tx (MK_OUTPUTS (290 * CENT, 200 * CENT), MK_INPUTS (tx2));
637
+ pool.addUnchecked (tx3->GetHash (), entry.Fee (10000LL ).FromTx (tx3));
638
+
639
+ // Ancestors / descendants should be:
640
+ // transaction ancestors descendants
641
+ // ============ =========== ===========
642
+ // tx1 1 (tx1) 3 (tx1,2,3)
643
+ // tx2 2 (tx1,2) 3 (tx1,2,3)
644
+ // tx3 3 (tx1,2,3) 3 (tx1,2,3)
645
+ pool.GetTransactionAncestry (tx1->GetHash (), ancestors, descendants);
646
+ BOOST_CHECK_EQUAL (ancestors, 1ULL );
647
+ BOOST_CHECK_EQUAL (descendants, 3ULL );
648
+ pool.GetTransactionAncestry (tx2->GetHash (), ancestors, descendants);
649
+ BOOST_CHECK_EQUAL (ancestors, 2ULL );
650
+ BOOST_CHECK_EQUAL (descendants, 3ULL );
651
+ pool.GetTransactionAncestry (tx3->GetHash (), ancestors, descendants);
652
+ BOOST_CHECK_EQUAL (ancestors, 3ULL );
653
+ BOOST_CHECK_EQUAL (descendants, 3ULL );
654
+
655
+ /* Grand-child 2 */
656
+ //
657
+ // [tx1].0 <- [tx2].0 <- [tx3]
658
+ // |
659
+ // \---1 <- [tx4]
660
+ //
661
+ CTransactionRef tx4 = make_tx (MK_OUTPUTS (290 * CENT, 250 * CENT), MK_INPUTS (tx2), MK_INPUT_IDX (1 ));
662
+ pool.addUnchecked (tx4->GetHash (), entry.Fee (10000LL ).FromTx (tx4));
663
+
664
+ // Ancestors / descendants should be:
665
+ // transaction ancestors descendants
666
+ // ============ =========== ===========
667
+ // tx1 1 (tx1) 4 (tx1,2,3,4)
668
+ // tx2 2 (tx1,2) 4 (tx1,2,3,4)
669
+ // tx3 3 (tx1,2,3) 4 (tx1,2,3,4)
670
+ // tx4 3 (tx1,2,4) 4 (tx1,2,3,4)
671
+ pool.GetTransactionAncestry (tx1->GetHash (), ancestors, descendants);
672
+ BOOST_CHECK_EQUAL (ancestors, 1ULL );
673
+ BOOST_CHECK_EQUAL (descendants, 4ULL );
674
+ pool.GetTransactionAncestry (tx2->GetHash (), ancestors, descendants);
675
+ BOOST_CHECK_EQUAL (ancestors, 2ULL );
676
+ BOOST_CHECK_EQUAL (descendants, 4ULL );
677
+ pool.GetTransactionAncestry (tx3->GetHash (), ancestors, descendants);
678
+ BOOST_CHECK_EQUAL (ancestors, 3ULL );
679
+ BOOST_CHECK_EQUAL (descendants, 4ULL );
680
+ pool.GetTransactionAncestry (tx4->GetHash (), ancestors, descendants);
681
+ BOOST_CHECK_EQUAL (ancestors, 3ULL );
682
+ BOOST_CHECK_EQUAL (descendants, 4ULL );
683
+
684
+ /* Make an alternate branch that is longer and connect it to tx3 */
685
+ //
686
+ // [ty1].0 <- [ty2].0 <- [ty3].0 <- [ty4].0 <- [ty5].0
687
+ // |
688
+ // [tx1].0 <- [tx2].0 <- [tx3].0 <- [ty6] --->--/
689
+ // |
690
+ // \---1 <- [tx4]
691
+ //
692
+ CTransactionRef ty1, ty2, ty3, ty4, ty5;
693
+ CTransactionRef* ty[5 ] = {&ty1, &ty2, &ty3, &ty4, &ty5};
694
+ CAmount v = 5 * COIN;
695
+ for (uint64_t i = 0 ; i < 5 ; i++) {
696
+ CTransactionRef& tyi = *ty[i];
697
+ tyi = make_tx (MK_OUTPUTS (v), i > 0 ? MK_INPUTS (*ty[i-1 ]) : std::vector<CTransactionRef>());
698
+ v -= 50 * CENT;
699
+ pool.addUnchecked (tyi->GetHash (), entry.Fee (10000LL ).FromTx (tyi));
700
+ pool.GetTransactionAncestry (tyi->GetHash (), ancestors, descendants);
701
+ BOOST_CHECK_EQUAL (ancestors, i+1 );
702
+ BOOST_CHECK_EQUAL (descendants, i+1 );
703
+ }
704
+ CTransactionRef ty6 = make_tx (MK_OUTPUTS (5 * COIN), MK_INPUTS (tx3, ty5));
705
+ pool.addUnchecked (ty6->GetHash (), entry.Fee (10000LL ).FromTx (ty6));
706
+
707
+ // Ancestors / descendants should be:
708
+ // transaction ancestors descendants
709
+ // ============ =================== ===========
710
+ // tx1 1 (tx1) 5 (tx1,2,3,4, ty6)
711
+ // tx2 2 (tx1,2) 5 (tx1,2,3,4, ty6)
712
+ // tx3 3 (tx1,2,3) 5 (tx1,2,3,4, ty6)
713
+ // tx4 3 (tx1,2,4) 5 (tx1,2,3,4, ty6)
714
+ // ty1 1 (ty1) 6 (ty1,2,3,4,5,6)
715
+ // ty2 2 (ty1,2) 6 (ty1,2,3,4,5,6)
716
+ // ty3 3 (ty1,2,3) 6 (ty1,2,3,4,5,6)
717
+ // ty4 4 (y1234) 6 (ty1,2,3,4,5,6)
718
+ // ty5 5 (y12345) 6 (ty1,2,3,4,5,6)
719
+ // ty6 9 (tx123, ty123456) 6 (ty1,2,3,4,5,6)
720
+ pool.GetTransactionAncestry (tx1->GetHash (), ancestors, descendants);
721
+ BOOST_CHECK_EQUAL (ancestors, 1ULL );
722
+ BOOST_CHECK_EQUAL (descendants, 5ULL );
723
+ pool.GetTransactionAncestry (tx2->GetHash (), ancestors, descendants);
724
+ BOOST_CHECK_EQUAL (ancestors, 2ULL );
725
+ BOOST_CHECK_EQUAL (descendants, 5ULL );
726
+ pool.GetTransactionAncestry (tx3->GetHash (), ancestors, descendants);
727
+ BOOST_CHECK_EQUAL (ancestors, 3ULL );
728
+ BOOST_CHECK_EQUAL (descendants, 5ULL );
729
+ pool.GetTransactionAncestry (tx4->GetHash (), ancestors, descendants);
730
+ BOOST_CHECK_EQUAL (ancestors, 3ULL );
731
+ BOOST_CHECK_EQUAL (descendants, 5ULL );
732
+ pool.GetTransactionAncestry (ty1->GetHash (), ancestors, descendants);
733
+ BOOST_CHECK_EQUAL (ancestors, 1ULL );
734
+ BOOST_CHECK_EQUAL (descendants, 6ULL );
735
+ pool.GetTransactionAncestry (ty2->GetHash (), ancestors, descendants);
736
+ BOOST_CHECK_EQUAL (ancestors, 2ULL );
737
+ BOOST_CHECK_EQUAL (descendants, 6ULL );
738
+ pool.GetTransactionAncestry (ty3->GetHash (), ancestors, descendants);
739
+ BOOST_CHECK_EQUAL (ancestors, 3ULL );
740
+ BOOST_CHECK_EQUAL (descendants, 6ULL );
741
+ pool.GetTransactionAncestry (ty4->GetHash (), ancestors, descendants);
742
+ BOOST_CHECK_EQUAL (ancestors, 4ULL );
743
+ BOOST_CHECK_EQUAL (descendants, 6ULL );
744
+ pool.GetTransactionAncestry (ty5->GetHash (), ancestors, descendants);
745
+ BOOST_CHECK_EQUAL (ancestors, 5ULL );
746
+ BOOST_CHECK_EQUAL (descendants, 6ULL );
747
+ pool.GetTransactionAncestry (ty6->GetHash (), ancestors, descendants);
748
+ BOOST_CHECK_EQUAL (ancestors, 9ULL );
749
+ BOOST_CHECK_EQUAL (descendants, 6ULL );
750
+ }
751
+
574
752
BOOST_AUTO_TEST_SUITE_END ()
0 commit comments