Skip to content

Commit f77e1d3

Browse files
committed
test: Add MempoolAncestryTests
1 parent a08d76b commit f77e1d3

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

src/test/mempool_tests.cpp

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,4 +571,182 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
571571
SetMockTime(0);
572572
}
573573

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+
574752
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)