@@ -57,12 +57,12 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
5757 std::list<CTransaction> removed;
5858
5959 // Nothing in pool, remove should do nothing:
60- testPool.remove (txParent, removed, true );
60+ testPool.removeRecursive (txParent, removed);
6161 BOOST_CHECK_EQUAL (removed.size (), 0 );
6262
6363 // Just the parent:
6464 testPool.addUnchecked (txParent.GetHash (), entry.FromTx (txParent));
65- testPool.remove (txParent, removed, true );
65+ testPool.removeRecursive (txParent, removed);
6666 BOOST_CHECK_EQUAL (removed.size (), 1 );
6767 removed.clear ();
6868
@@ -74,16 +74,16 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
7474 testPool.addUnchecked (txGrandChild[i].GetHash (), entry.FromTx (txGrandChild[i]));
7575 }
7676 // Remove Child[0], GrandChild[0] should be removed:
77- testPool.remove (txChild[0 ], removed, true );
77+ testPool.removeRecursive (txChild[0 ], removed);
7878 BOOST_CHECK_EQUAL (removed.size (), 2 );
7979 removed.clear ();
8080 // ... make sure grandchild and child are gone:
81- testPool.remove (txGrandChild[0 ], removed, true );
81+ testPool.removeRecursive (txGrandChild[0 ], removed);
8282 BOOST_CHECK_EQUAL (removed.size (), 0 );
83- testPool.remove (txChild[0 ], removed, true );
83+ testPool.removeRecursive (txChild[0 ], removed);
8484 BOOST_CHECK_EQUAL (removed.size (), 0 );
8585 // Remove parent, all children/grandchildren should go:
86- testPool.remove (txParent, removed, true );
86+ testPool.removeRecursive (txParent, removed);
8787 BOOST_CHECK_EQUAL (removed.size (), 5 );
8888 BOOST_CHECK_EQUAL (testPool.size (), 0 );
8989 removed.clear ();
@@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
9696 }
9797 // Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
9898 // put into the mempool (maybe because it is non-standard):
99- testPool.remove (txParent, removed, true );
99+ testPool.removeRecursive (txParent, removed);
100100 BOOST_CHECK_EQUAL (removed.size (), 6 );
101101 BOOST_CHECK_EQUAL (testPool.size (), 0 );
102102 removed.clear ();
@@ -281,11 +281,11 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
281281
282282 // Now try removing tx10 and verify the sort order returns to normal
283283 std::list<CTransaction> removed;
284- pool.remove (pool.mapTx .find (tx10.GetHash ())->GetTx (), removed, true );
284+ pool.removeRecursive (pool.mapTx .find (tx10.GetHash ())->GetTx (), removed);
285285 CheckSort<descendant_score>(pool, snapshotOrder);
286286
287- pool.remove (pool.mapTx .find (tx9.GetHash ())->GetTx (), removed, true );
288- pool.remove (pool.mapTx .find (tx8.GetHash ())->GetTx (), removed, true );
287+ pool.removeRecursive (pool.mapTx .find (tx9.GetHash ())->GetTx (), removed);
288+ pool.removeRecursive (pool.mapTx .find (tx8.GetHash ())->GetTx (), removed);
289289 /* Now check the sort on the mining score index.
290290 * Final order should be:
291291 *
@@ -317,6 +317,110 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
317317 CheckSort<mining_score>(pool, sortedOrder);
318318}
319319
320+ BOOST_AUTO_TEST_CASE (MempoolAncestorIndexingTest)
321+ {
322+ CTxMemPool pool (CFeeRate (0 ));
323+ TestMemPoolEntryHelper entry;
324+ entry.hadNoDependencies = true ;
325+
326+ /* 3rd highest fee */
327+ CMutableTransaction tx1 = CMutableTransaction ();
328+ tx1.vout .resize (1 );
329+ tx1.vout [0 ].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
330+ tx1.vout [0 ].nValue = 10 * COIN;
331+ pool.addUnchecked (tx1.GetHash (), entry.Fee (10000LL ).Priority (10.0 ).FromTx (tx1));
332+
333+ /* highest fee */
334+ CMutableTransaction tx2 = CMutableTransaction ();
335+ tx2.vout .resize (1 );
336+ tx2.vout [0 ].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
337+ tx2.vout [0 ].nValue = 2 * COIN;
338+ pool.addUnchecked (tx2.GetHash (), entry.Fee (20000LL ).Priority (9.0 ).FromTx (tx2));
339+ uint64_t tx2Size = ::GetSerializeSize (tx2, SER_NETWORK, PROTOCOL_VERSION);
340+
341+ /* lowest fee */
342+ CMutableTransaction tx3 = CMutableTransaction ();
343+ tx3.vout .resize (1 );
344+ tx3.vout [0 ].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
345+ tx3.vout [0 ].nValue = 5 * COIN;
346+ pool.addUnchecked (tx3.GetHash (), entry.Fee (0LL ).Priority (100.0 ).FromTx (tx3));
347+
348+ /* 2nd highest fee */
349+ CMutableTransaction tx4 = CMutableTransaction ();
350+ tx4.vout .resize (1 );
351+ tx4.vout [0 ].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
352+ tx4.vout [0 ].nValue = 6 * COIN;
353+ pool.addUnchecked (tx4.GetHash (), entry.Fee (15000LL ).Priority (1.0 ).FromTx (tx4));
354+
355+ /* equal fee rate to tx1, but newer */
356+ CMutableTransaction tx5 = CMutableTransaction ();
357+ tx5.vout .resize (1 );
358+ tx5.vout [0 ].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
359+ tx5.vout [0 ].nValue = 11 * COIN;
360+ pool.addUnchecked (tx5.GetHash (), entry.Fee (10000LL ).FromTx (tx5));
361+ BOOST_CHECK_EQUAL (pool.size (), 5 );
362+
363+ std::vector<std::string> sortedOrder;
364+ sortedOrder.resize (5 );
365+ sortedOrder[0 ] = tx2.GetHash ().ToString (); // 20000
366+ sortedOrder[1 ] = tx4.GetHash ().ToString (); // 15000
367+ // tx1 and tx5 are both 10000
368+ // Ties are broken by hash, not timestamp, so determine which
369+ // hash comes first.
370+ if (tx1.GetHash () < tx5.GetHash ()) {
371+ sortedOrder[2 ] = tx1.GetHash ().ToString ();
372+ sortedOrder[3 ] = tx5.GetHash ().ToString ();
373+ } else {
374+ sortedOrder[2 ] = tx5.GetHash ().ToString ();
375+ sortedOrder[3 ] = tx1.GetHash ().ToString ();
376+ }
377+ sortedOrder[4 ] = tx3.GetHash ().ToString (); // 0
378+
379+ CheckSort<ancestor_score>(pool, sortedOrder);
380+
381+ /* low fee parent with high fee child */
382+ /* tx6 (0) -> tx7 (high) */
383+ CMutableTransaction tx6 = CMutableTransaction ();
384+ tx6.vout .resize (1 );
385+ tx6.vout [0 ].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
386+ tx6.vout [0 ].nValue = 20 * COIN;
387+ uint64_t tx6Size = ::GetSerializeSize (tx6, SER_NETWORK, PROTOCOL_VERSION);
388+
389+ pool.addUnchecked (tx6.GetHash (), entry.Fee (0LL ).FromTx (tx6));
390+ BOOST_CHECK_EQUAL (pool.size (), 6 );
391+ sortedOrder.push_back (tx6.GetHash ().ToString ());
392+ CheckSort<ancestor_score>(pool, sortedOrder);
393+
394+ CMutableTransaction tx7 = CMutableTransaction ();
395+ tx7.vin .resize (1 );
396+ tx7.vin [0 ].prevout = COutPoint (tx6.GetHash (), 0 );
397+ tx7.vin [0 ].scriptSig = CScript () << OP_11;
398+ tx7.vout .resize (1 );
399+ tx7.vout [0 ].scriptPubKey = CScript () << OP_11 << OP_EQUAL;
400+ tx7.vout [0 ].nValue = 10 * COIN;
401+ uint64_t tx7Size = ::GetSerializeSize (tx7, SER_NETWORK, PROTOCOL_VERSION);
402+
403+ /* set the fee to just below tx2's feerate when including ancestor */
404+ CAmount fee = (20000 /tx2Size)*(tx7Size + tx6Size) - 1 ;
405+
406+ // CTxMemPoolEntry entry7(tx7, fee, 2, 10.0, 1, true);
407+ pool.addUnchecked (tx7.GetHash (), entry.Fee (fee).FromTx (tx7));
408+ BOOST_CHECK_EQUAL (pool.size (), 7 );
409+ sortedOrder.insert (sortedOrder.begin ()+1 , tx7.GetHash ().ToString ());
410+ CheckSort<ancestor_score>(pool, sortedOrder);
411+
412+ /* after tx6 is mined, tx7 should move up in the sort */
413+ std::vector<CTransaction> vtx;
414+ vtx.push_back (tx6);
415+ std::list<CTransaction> dummy;
416+ pool.removeForBlock (vtx, 1 , dummy, false );
417+
418+ sortedOrder.erase (sortedOrder.begin ()+1 );
419+ sortedOrder.pop_back ();
420+ sortedOrder.insert (sortedOrder.begin (), tx7.GetHash ().ToString ());
421+ CheckSort<ancestor_score>(pool, sortedOrder);
422+ }
423+
320424
321425BOOST_AUTO_TEST_CASE (MempoolSizeLimitTest)
322426{
0 commit comments