2017-11-09 19:34:51 +01:00
/*
* This file is part of the Flowee project
* Copyright (C) 2011-2015 The Bitcoin Core developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2015-03-25 13:13:09 -04:00
# include "txmempool.h"
# include "util.h"
2021-01-05 22:05:25 +01:00
# include <hash.h>
2015-03-25 13:13:09 -04:00
# include "test/test_bitcoin.h"
# include <boost/test/unit_test.hpp>
# include <list>
2017-08-17 20:53:23 -06:00
2015-03-25 13:13:09 -04:00
BOOST_FIXTURE_TEST_SUITE ( mempool_tests , TestingSetup )
BOOST_AUTO_TEST_CASE ( MempoolRemoveTest )
{
// Test CTxMemPool::remove functionality
2015-11-14 17:04:15 -05:00
TestMemPoolEntryHelper entry ;
2015-03-25 13:13:09 -04:00
// Parent transaction with three children,
// and three grand-children:
CMutableTransaction txParent ;
txParent . vin . resize ( 1 ) ;
txParent . vin [ 0 ] . scriptSig = CScript ( ) < < OP_11 ;
txParent . vout . resize ( 3 ) ;
for ( int i = 0 ; i < 3 ; i + + )
{
txParent . vout [ i ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
txParent . vout [ i ] . nValue = 33000LL ;
}
CMutableTransaction txChild [ 3 ] ;
for ( int i = 0 ; i < 3 ; i + + )
{
txChild [ i ] . vin . resize ( 1 ) ;
txChild [ i ] . vin [ 0 ] . scriptSig = CScript ( ) < < OP_11 ;
txChild [ i ] . vin [ 0 ] . prevout . hash = txParent . GetHash ( ) ;
txChild [ i ] . vin [ 0 ] . prevout . n = i ;
txChild [ i ] . vout . resize ( 1 ) ;
txChild [ i ] . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
txChild [ i ] . vout [ 0 ] . nValue = 11000LL ;
}
CMutableTransaction txGrandChild [ 3 ] ;
for ( int i = 0 ; i < 3 ; i + + )
{
txGrandChild [ i ] . vin . resize ( 1 ) ;
txGrandChild [ i ] . vin [ 0 ] . scriptSig = CScript ( ) < < OP_11 ;
txGrandChild [ i ] . vin [ 0 ] . prevout . hash = txChild [ i ] . GetHash ( ) ;
txGrandChild [ i ] . vin [ 0 ] . prevout . n = 0 ;
txGrandChild [ i ] . vout . resize ( 1 ) ;
txGrandChild [ i ] . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
txGrandChild [ i ] . vout [ 0 ] . nValue = 11000LL ;
}
2019-06-28 12:38:46 +02:00
CTxMemPool testPool ;
2015-03-25 13:13:09 -04:00
std : : list < CTransaction > removed ;
// Nothing in pool, remove should do nothing:
testPool . remove ( txParent , removed , true ) ;
BOOST_CHECK_EQUAL ( removed . size ( ) , 0 ) ;
// Just the parent:
2015-11-14 17:04:15 -05:00
testPool . addUnchecked ( txParent . GetHash ( ) , entry . FromTx ( txParent ) ) ;
2015-03-25 13:13:09 -04:00
testPool . remove ( txParent , removed , true ) ;
BOOST_CHECK_EQUAL ( removed . size ( ) , 1 ) ;
removed . clear ( ) ;
// Parent, children, grandchildren:
2015-11-14 17:04:15 -05:00
testPool . addUnchecked ( txParent . GetHash ( ) , entry . FromTx ( txParent ) ) ;
2015-03-25 13:13:09 -04:00
for ( int i = 0 ; i < 3 ; i + + )
{
2015-11-14 17:04:15 -05:00
testPool . addUnchecked ( txChild [ i ] . GetHash ( ) , entry . FromTx ( txChild [ i ] ) ) ;
testPool . addUnchecked ( txGrandChild [ i ] . GetHash ( ) , entry . FromTx ( txGrandChild [ i ] ) ) ;
2015-03-25 13:13:09 -04:00
}
// Remove Child[0], GrandChild[0] should be removed:
testPool . remove ( txChild [ 0 ] , removed , true ) ;
BOOST_CHECK_EQUAL ( removed . size ( ) , 2 ) ;
removed . clear ( ) ;
// ... make sure grandchild and child are gone:
testPool . remove ( txGrandChild [ 0 ] , removed , true ) ;
BOOST_CHECK_EQUAL ( removed . size ( ) , 0 ) ;
testPool . remove ( txChild [ 0 ] , removed , true ) ;
BOOST_CHECK_EQUAL ( removed . size ( ) , 0 ) ;
// Remove parent, all children/grandchildren should go:
testPool . remove ( txParent , removed , true ) ;
BOOST_CHECK_EQUAL ( removed . size ( ) , 5 ) ;
BOOST_CHECK_EQUAL ( testPool . size ( ) , 0 ) ;
removed . clear ( ) ;
// Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
for ( int i = 0 ; i < 3 ; i + + )
{
2015-11-14 17:04:15 -05:00
testPool . addUnchecked ( txChild [ i ] . GetHash ( ) , entry . FromTx ( txChild [ i ] ) ) ;
testPool . addUnchecked ( txGrandChild [ i ] . GetHash ( ) , entry . FromTx ( txGrandChild [ i ] ) ) ;
2015-03-25 13:13:09 -04:00
}
// Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
// put into the mempool (maybe because it is non-standard):
testPool . remove ( txParent , removed , true ) ;
BOOST_CHECK_EQUAL ( removed . size ( ) , 6 ) ;
BOOST_CHECK_EQUAL ( testPool . size ( ) , 0 ) ;
removed . clear ( ) ;
}
2015-10-26 14:06:06 -04:00
template < int index >
2015-07-15 14:47:45 -04:00
void CheckSort ( CTxMemPool & pool , std : : vector < std : : string > & sortedOrder )
{
BOOST_CHECK_EQUAL ( pool . size ( ) , sortedOrder . size ( ) ) ;
2015-10-26 14:06:06 -04:00
typename CTxMemPool : : indexed_transaction_set : : nth_index < index > : : type : : iterator it = pool . mapTx . get < index > ( ) . begin ( ) ;
2015-07-15 14:47:45 -04:00
int count = 0 ;
2015-10-26 14:06:06 -04:00
for ( ; it ! = pool . mapTx . get < index > ( ) . end ( ) ; + + it , + + count ) {
2015-07-15 14:47:45 -04:00
BOOST_CHECK_EQUAL ( it - > GetTx ( ) . GetHash ( ) . ToString ( ) , sortedOrder [ count ] ) ;
}
}
2015-06-24 03:32:20 -05:00
BOOST_AUTO_TEST_CASE ( MempoolIndexingTest )
{
2019-06-28 12:38:46 +02:00
CTxMemPool pool ;
2015-11-14 17:04:15 -05:00
TestMemPoolEntryHelper entry ;
entry . hadNoDependencies = true ;
2015-06-24 03:32:20 -05:00
/* 3rd highest fee */
CMutableTransaction tx1 = CMutableTransaction ( ) ;
tx1 . vout . resize ( 1 ) ;
tx1 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx1 . vout [ 0 ] . nValue = 10 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx1 . GetHash ( ) , entry . Fee ( 10000LL ) . Priority ( 10.0 ) . FromTx ( tx1 ) ) ;
2015-06-24 03:32:20 -05:00
/* highest fee */
CMutableTransaction tx2 = CMutableTransaction ( ) ;
tx2 . vout . resize ( 1 ) ;
tx2 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx2 . vout [ 0 ] . nValue = 2 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx2 . GetHash ( ) , entry . Fee ( 20000LL ) . Priority ( 9.0 ) . FromTx ( tx2 ) ) ;
2015-06-24 03:32:20 -05:00
/* lowest fee */
CMutableTransaction tx3 = CMutableTransaction ( ) ;
tx3 . vout . resize ( 1 ) ;
tx3 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx3 . vout [ 0 ] . nValue = 5 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx3 . GetHash ( ) , entry . Fee ( 0LL ) . Priority ( 100.0 ) . FromTx ( tx3 ) ) ;
2015-06-24 03:32:20 -05:00
/* 2nd highest fee */
CMutableTransaction tx4 = CMutableTransaction ( ) ;
tx4 . vout . resize ( 1 ) ;
tx4 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx4 . vout [ 0 ] . nValue = 6 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx4 . GetHash ( ) , entry . Fee ( 15000LL ) . Priority ( 1.0 ) . FromTx ( tx4 ) ) ;
2015-06-24 03:32:20 -05:00
/* equal fee rate to tx1, but newer */
CMutableTransaction tx5 = CMutableTransaction ( ) ;
tx5 . vout . resize ( 1 ) ;
tx5 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx5 . vout [ 0 ] . nValue = 11 * COIN ;
2015-11-14 17:04:15 -05:00
entry . nTime = 1 ;
entry . dPriority = 10.0 ;
pool . addUnchecked ( tx5 . GetHash ( ) , entry . Fee ( 10000LL ) . FromTx ( tx5 ) ) ;
2015-06-24 03:32:20 -05:00
BOOST_CHECK_EQUAL ( pool . size ( ) , 5 ) ;
2015-07-15 14:47:45 -04:00
std : : vector < std : : string > sortedOrder ;
sortedOrder . resize ( 5 ) ;
2015-09-24 13:21:31 -04:00
sortedOrder [ 0 ] = tx3 . GetHash ( ) . ToString ( ) ; // 0
sortedOrder [ 1 ] = tx5 . GetHash ( ) . ToString ( ) ; // 10000
2015-07-15 14:47:45 -04:00
sortedOrder [ 2 ] = tx1 . GetHash ( ) . ToString ( ) ; // 10000
2015-09-24 13:21:31 -04:00
sortedOrder [ 3 ] = tx4 . GetHash ( ) . ToString ( ) ; // 15000
sortedOrder [ 4 ] = tx2 . GetHash ( ) . ToString ( ) ; // 20000
2015-10-26 14:06:06 -04:00
CheckSort < 1 > ( pool , sortedOrder ) ;
2015-07-15 14:47:45 -04:00
/* low fee but with high fee child */
/* tx6 -> tx7 -> tx8, tx9 -> tx10 */
CMutableTransaction tx6 = CMutableTransaction ( ) ;
tx6 . vout . resize ( 1 ) ;
tx6 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx6 . vout [ 0 ] . nValue = 20 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx6 . GetHash ( ) , entry . Fee ( 0LL ) . FromTx ( tx6 ) ) ;
2015-07-15 14:47:45 -04:00
BOOST_CHECK_EQUAL ( pool . size ( ) , 6 ) ;
// Check that at this point, tx6 is sorted low
2015-09-24 13:21:31 -04:00
sortedOrder . insert ( sortedOrder . begin ( ) , tx6 . GetHash ( ) . ToString ( ) ) ;
2015-10-26 14:06:06 -04:00
CheckSort < 1 > ( pool , sortedOrder ) ;
2015-07-15 14:47:45 -04:00
CTxMemPool : : setEntries setAncestors ;
setAncestors . insert ( pool . mapTx . find ( tx6 . GetHash ( ) ) ) ;
CMutableTransaction tx7 = CMutableTransaction ( ) ;
tx7 . vin . resize ( 1 ) ;
tx7 . vin [ 0 ] . prevout = COutPoint ( tx6 . GetHash ( ) , 0 ) ;
tx7 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_11 ;
tx7 . vout . resize ( 2 ) ;
tx7 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx7 . vout [ 0 ] . nValue = 10 * COIN ;
tx7 . vout [ 1 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx7 . vout [ 1 ] . nValue = 1 * COIN ;
CTxMemPool : : setEntries setAncestorsCalculated ;
std : : string dummy ;
2015-11-14 17:04:15 -05:00
BOOST_CHECK_EQUAL ( pool . CalculateMemPoolAncestors ( entry . Fee ( 2000000LL ) . FromTx ( tx7 ) , setAncestorsCalculated , 100 , 1000000 , 1000 , 1000000 , dummy ) , true ) ;
2015-07-15 14:47:45 -04:00
BOOST_CHECK ( setAncestorsCalculated = = setAncestors ) ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx7 . GetHash ( ) , entry . FromTx ( tx7 ) , setAncestors ) ;
2015-07-15 14:47:45 -04:00
BOOST_CHECK_EQUAL ( pool . size ( ) , 7 ) ;
// Now tx6 should be sorted higher (high fee child): tx7, tx6, tx2, ...
2015-09-24 13:21:31 -04:00
sortedOrder . erase ( sortedOrder . begin ( ) ) ;
sortedOrder . push_back ( tx6 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . push_back ( tx7 . GetHash ( ) . ToString ( ) ) ;
2015-10-26 14:06:06 -04:00
CheckSort < 1 > ( pool , sortedOrder ) ;
2015-07-15 14:47:45 -04:00
/* low fee child of tx7 */
CMutableTransaction tx8 = CMutableTransaction ( ) ;
tx8 . vin . resize ( 1 ) ;
tx8 . vin [ 0 ] . prevout = COutPoint ( tx7 . GetHash ( ) , 0 ) ;
tx8 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_11 ;
tx8 . vout . resize ( 1 ) ;
tx8 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx8 . vout [ 0 ] . nValue = 10 * COIN ;
setAncestors . insert ( pool . mapTx . find ( tx7 . GetHash ( ) ) ) ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx8 . GetHash ( ) , entry . Fee ( 0LL ) . Time ( 2 ) . FromTx ( tx8 ) , setAncestors ) ;
2015-07-15 14:47:45 -04:00
// Now tx8 should be sorted low, but tx6/tx both high
2015-09-24 13:21:31 -04:00
sortedOrder . insert ( sortedOrder . begin ( ) , tx8 . GetHash ( ) . ToString ( ) ) ;
2015-10-26 14:06:06 -04:00
CheckSort < 1 > ( pool , sortedOrder ) ;
2015-07-15 14:47:45 -04:00
/* low fee child of tx7 */
CMutableTransaction tx9 = CMutableTransaction ( ) ;
tx9 . vin . resize ( 1 ) ;
tx9 . vin [ 0 ] . prevout = COutPoint ( tx7 . GetHash ( ) , 1 ) ;
tx9 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_11 ;
tx9 . vout . resize ( 1 ) ;
tx9 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx9 . vout [ 0 ] . nValue = 1 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx9 . GetHash ( ) , entry . Fee ( 0LL ) . Time ( 3 ) . FromTx ( tx9 ) , setAncestors ) ;
2015-07-15 14:47:45 -04:00
// tx9 should be sorted low
BOOST_CHECK_EQUAL ( pool . size ( ) , 9 ) ;
2015-09-24 13:21:31 -04:00
sortedOrder . insert ( sortedOrder . begin ( ) , tx9 . GetHash ( ) . ToString ( ) ) ;
2015-10-26 14:06:06 -04:00
CheckSort < 1 > ( pool , sortedOrder ) ;
2015-07-15 14:47:45 -04:00
std : : vector < std : : string > snapshotOrder = sortedOrder ;
setAncestors . insert ( pool . mapTx . find ( tx8 . GetHash ( ) ) ) ;
setAncestors . insert ( pool . mapTx . find ( tx9 . GetHash ( ) ) ) ;
/* tx10 depends on tx8 and tx9 and has a high fee*/
CMutableTransaction tx10 = CMutableTransaction ( ) ;
tx10 . vin . resize ( 2 ) ;
tx10 . vin [ 0 ] . prevout = COutPoint ( tx8 . GetHash ( ) , 0 ) ;
tx10 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_11 ;
tx10 . vin [ 1 ] . prevout = COutPoint ( tx9 . GetHash ( ) , 0 ) ;
tx10 . vin [ 1 ] . scriptSig = CScript ( ) < < OP_11 ;
tx10 . vout . resize ( 1 ) ;
tx10 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_11 < < OP_EQUAL ;
tx10 . vout [ 0 ] . nValue = 10 * COIN ;
setAncestorsCalculated . clear ( ) ;
2015-11-14 17:04:15 -05:00
BOOST_CHECK_EQUAL ( pool . CalculateMemPoolAncestors ( entry . Fee ( 200000LL ) . Time ( 4 ) . FromTx ( tx10 ) , setAncestorsCalculated , 100 , 1000000 , 1000 , 1000000 , dummy ) , true ) ;
2015-07-15 14:47:45 -04:00
BOOST_CHECK ( setAncestorsCalculated = = setAncestors ) ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx10 . GetHash ( ) , entry . FromTx ( tx10 ) , setAncestors ) ;
2015-07-15 14:47:45 -04:00
/**
* tx8 and tx9 should both now be sorted higher
* Final order after tx10 is added:
*
* tx3 = 0 (1)
2015-09-24 13:21:31 -04:00
* tx5 = 10000 (1)
* tx1 = 10000 (1)
* tx4 = 15000 (1)
* tx2 = 20000 (1)
* tx9 = 200k (2 txs)
* tx8 = 200k (2 txs)
* tx10 = 200k (1 tx)
* tx6 = 2.2M (5 txs)
* tx7 = 2.2M (4 txs)
2015-07-15 14:47:45 -04:00
*/
2015-09-24 13:21:31 -04:00
sortedOrder . erase ( sortedOrder . begin ( ) , sortedOrder . begin ( ) + 2 ) ; // take out tx9, tx8 from the beginning
sortedOrder . insert ( sortedOrder . begin ( ) + 5 , tx9 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . insert ( sortedOrder . begin ( ) + 6 , tx8 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . insert ( sortedOrder . begin ( ) + 7 , tx10 . GetHash ( ) . ToString ( ) ) ; // tx10 is just before tx6
2015-10-26 14:06:06 -04:00
CheckSort < 1 > ( pool , sortedOrder ) ;
2015-07-15 14:47:45 -04:00
// there should be 10 transactions in the mempool
BOOST_CHECK_EQUAL ( pool . size ( ) , 10 ) ;
// Now try removing tx10 and verify the sort order returns to normal
std : : list < CTransaction > removed ;
pool . remove ( pool . mapTx . find ( tx10 . GetHash ( ) ) - > GetTx ( ) , removed , true ) ;
2015-10-26 14:06:06 -04:00
CheckSort < 1 > ( pool , snapshotOrder ) ;
pool . remove ( pool . mapTx . find ( tx9 . GetHash ( ) ) - > GetTx ( ) , removed , true ) ;
pool . remove ( pool . mapTx . find ( tx8 . GetHash ( ) ) - > GetTx ( ) , removed , true ) ;
/* Now check the sort on the mining score index.
* Final order should be:
*
* tx7 (2M)
* tx2 (20k)
* tx4 (15000)
* tx1/tx5 (10000)
* tx3/6 (0)
* (Ties resolved by hash)
*/
sortedOrder . clear ( ) ;
sortedOrder . push_back ( tx7 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . push_back ( tx2 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . push_back ( tx4 . GetHash ( ) . ToString ( ) ) ;
if ( tx1 . GetHash ( ) < tx5 . GetHash ( ) ) {
sortedOrder . push_back ( tx5 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . push_back ( tx1 . GetHash ( ) . ToString ( ) ) ;
} else {
sortedOrder . push_back ( tx1 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . push_back ( tx5 . GetHash ( ) . ToString ( ) ) ;
}
if ( tx3 . GetHash ( ) < tx6 . GetHash ( ) ) {
sortedOrder . push_back ( tx6 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . push_back ( tx3 . GetHash ( ) . ToString ( ) ) ;
} else {
sortedOrder . push_back ( tx3 . GetHash ( ) . ToString ( ) ) ;
sortedOrder . push_back ( tx6 . GetHash ( ) . ToString ( ) ) ;
}
CheckSort < 3 > ( pool , sortedOrder ) ;
2015-06-24 03:32:20 -05:00
}
2015-10-26 14:06:06 -04:00
2015-10-13 00:43:15 -07:00
BOOST_AUTO_TEST_CASE ( MempoolSizeLimitTest )
{
2019-06-28 12:38:46 +02:00
CTxMemPool pool ;
2015-11-14 17:04:15 -05:00
TestMemPoolEntryHelper entry ;
entry . dPriority = 10.0 ;
2015-10-13 00:43:15 -07:00
CMutableTransaction tx1 = CMutableTransaction ( ) ;
tx1 . vin . resize ( 1 ) ;
tx1 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
tx1 . vout . resize ( 1 ) ;
tx1 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_1 < < OP_EQUAL ;
tx1 . vout [ 0 ] . nValue = 10 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx1 . GetHash ( ) , entry . Fee ( 10000LL ) . FromTx ( tx1 , & pool ) ) ;
2015-10-13 00:43:15 -07:00
CMutableTransaction tx2 = CMutableTransaction ( ) ;
tx2 . vin . resize ( 1 ) ;
tx2 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_2 ;
tx2 . vout . resize ( 1 ) ;
tx2 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_2 < < OP_EQUAL ;
tx2 . vout [ 0 ] . nValue = 10 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx2 . GetHash ( ) , entry . Fee ( 5000LL ) . FromTx ( tx2 , & pool ) ) ;
2015-10-13 00:43:15 -07:00
pool . TrimToSize ( pool . DynamicMemoryUsage ( ) ) ; // should do nothing
BOOST_CHECK ( pool . exists ( tx1 . GetHash ( ) ) ) ;
BOOST_CHECK ( pool . exists ( tx2 . GetHash ( ) ) ) ;
pool . TrimToSize ( pool . DynamicMemoryUsage ( ) * 3 / 4 ) ; // should remove the lower-feerate transaction
BOOST_CHECK ( pool . exists ( tx1 . GetHash ( ) ) ) ;
BOOST_CHECK ( ! pool . exists ( tx2 . GetHash ( ) ) ) ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx2 . GetHash ( ) , entry . FromTx ( tx2 , & pool ) ) ;
2015-10-13 00:43:15 -07:00
CMutableTransaction tx3 = CMutableTransaction ( ) ;
tx3 . vin . resize ( 1 ) ;
tx3 . vin [ 0 ] . prevout = COutPoint ( tx2 . GetHash ( ) , 0 ) ;
tx3 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_2 ;
tx3 . vout . resize ( 1 ) ;
tx3 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_3 < < OP_EQUAL ;
tx3 . vout [ 0 ] . nValue = 10 * COIN ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx3 . GetHash ( ) , entry . Fee ( 20000LL ) . FromTx ( tx3 , & pool ) ) ;
2015-10-13 00:43:15 -07:00
pool . TrimToSize ( pool . DynamicMemoryUsage ( ) * 3 / 4 ) ; // tx3 should pay for tx2 (CPFP)
BOOST_CHECK ( ! pool . exists ( tx1 . GetHash ( ) ) ) ;
BOOST_CHECK ( pool . exists ( tx2 . GetHash ( ) ) ) ;
BOOST_CHECK ( pool . exists ( tx3 . GetHash ( ) ) ) ;
pool . TrimToSize ( : : GetSerializeSize ( CTransaction ( tx1 ) , SER_NETWORK , PROTOCOL_VERSION ) ) ; // mempool is limited to tx1's size in memory usage, so nothing fits
BOOST_CHECK ( ! pool . exists ( tx1 . GetHash ( ) ) ) ;
BOOST_CHECK ( ! pool . exists ( tx2 . GetHash ( ) ) ) ;
BOOST_CHECK ( ! pool . exists ( tx3 . GetHash ( ) ) ) ;
CMutableTransaction tx4 = CMutableTransaction ( ) ;
tx4 . vin . resize ( 2 ) ;
tx4 . vin [ 0 ] . prevout . SetNull ( ) ;
tx4 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_4 ;
tx4 . vin [ 1 ] . prevout . SetNull ( ) ;
tx4 . vin [ 1 ] . scriptSig = CScript ( ) < < OP_4 ;
tx4 . vout . resize ( 2 ) ;
tx4 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_4 < < OP_EQUAL ;
tx4 . vout [ 0 ] . nValue = 10 * COIN ;
tx4 . vout [ 1 ] . scriptPubKey = CScript ( ) < < OP_4 < < OP_EQUAL ;
tx4 . vout [ 1 ] . nValue = 10 * COIN ;
CMutableTransaction tx5 = CMutableTransaction ( ) ;
tx5 . vin . resize ( 2 ) ;
tx5 . vin [ 0 ] . prevout = COutPoint ( tx4 . GetHash ( ) , 0 ) ;
tx5 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_4 ;
tx5 . vin [ 1 ] . prevout . SetNull ( ) ;
tx5 . vin [ 1 ] . scriptSig = CScript ( ) < < OP_5 ;
tx5 . vout . resize ( 2 ) ;
tx5 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_5 < < OP_EQUAL ;
tx5 . vout [ 0 ] . nValue = 10 * COIN ;
tx5 . vout [ 1 ] . scriptPubKey = CScript ( ) < < OP_5 < < OP_EQUAL ;
tx5 . vout [ 1 ] . nValue = 10 * COIN ;
CMutableTransaction tx6 = CMutableTransaction ( ) ;
tx6 . vin . resize ( 2 ) ;
tx6 . vin [ 0 ] . prevout = COutPoint ( tx4 . GetHash ( ) , 1 ) ;
tx6 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_4 ;
tx6 . vin [ 1 ] . prevout . SetNull ( ) ;
tx6 . vin [ 1 ] . scriptSig = CScript ( ) < < OP_6 ;
tx6 . vout . resize ( 2 ) ;
tx6 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_6 < < OP_EQUAL ;
tx6 . vout [ 0 ] . nValue = 10 * COIN ;
tx6 . vout [ 1 ] . scriptPubKey = CScript ( ) < < OP_6 < < OP_EQUAL ;
tx6 . vout [ 1 ] . nValue = 10 * COIN ;
CMutableTransaction tx7 = CMutableTransaction ( ) ;
tx7 . vin . resize ( 2 ) ;
tx7 . vin [ 0 ] . prevout = COutPoint ( tx5 . GetHash ( ) , 0 ) ;
tx7 . vin [ 0 ] . scriptSig = CScript ( ) < < OP_5 ;
tx7 . vin [ 1 ] . prevout = COutPoint ( tx6 . GetHash ( ) , 0 ) ;
tx7 . vin [ 1 ] . scriptSig = CScript ( ) < < OP_6 ;
tx7 . vout . resize ( 2 ) ;
tx7 . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_7 < < OP_EQUAL ;
tx7 . vout [ 0 ] . nValue = 10 * COIN ;
2015-11-13 10:48:57 -05:00
tx7 . vout [ 1 ] . scriptPubKey = CScript ( ) < < OP_7 < < OP_EQUAL ;
tx7 . vout [ 1 ] . nValue = 10 * COIN ;
2015-10-13 00:43:15 -07:00
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx4 . GetHash ( ) , entry . Fee ( 7000LL ) . FromTx ( tx4 , & pool ) ) ;
pool . addUnchecked ( tx5 . GetHash ( ) , entry . Fee ( 1000LL ) . FromTx ( tx5 , & pool ) ) ;
pool . addUnchecked ( tx6 . GetHash ( ) , entry . Fee ( 1100LL ) . FromTx ( tx6 , & pool ) ) ;
pool . addUnchecked ( tx7 . GetHash ( ) , entry . Fee ( 9000LL ) . FromTx ( tx7 , & pool ) ) ;
2015-10-13 00:43:15 -07:00
// we only require this remove, at max, 2 txn, because its not clear what we're really optimizing for aside from that
pool . TrimToSize ( pool . DynamicMemoryUsage ( ) - 1 ) ;
BOOST_CHECK ( pool . exists ( tx4 . GetHash ( ) ) ) ;
BOOST_CHECK ( pool . exists ( tx6 . GetHash ( ) ) ) ;
BOOST_CHECK ( ! pool . exists ( tx7 . GetHash ( ) ) ) ;
if ( ! pool . exists ( tx5 . GetHash ( ) ) )
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx5 . GetHash ( ) , entry . Fee ( 1000LL ) . FromTx ( tx5 , & pool ) ) ;
pool . addUnchecked ( tx7 . GetHash ( ) , entry . Fee ( 9000LL ) . FromTx ( tx7 , & pool ) ) ;
2015-10-13 00:43:15 -07:00
pool . TrimToSize ( pool . DynamicMemoryUsage ( ) / 2 ) ; // should maximize mempool size by only removing 5/7
BOOST_CHECK ( pool . exists ( tx4 . GetHash ( ) ) ) ;
BOOST_CHECK ( ! pool . exists ( tx5 . GetHash ( ) ) ) ;
BOOST_CHECK ( pool . exists ( tx6 . GetHash ( ) ) ) ;
BOOST_CHECK ( ! pool . exists ( tx7 . GetHash ( ) ) ) ;
2015-11-14 17:04:15 -05:00
pool . addUnchecked ( tx5 . GetHash ( ) , entry . Fee ( 1000LL ) . FromTx ( tx5 , & pool ) ) ;
pool . addUnchecked ( tx7 . GetHash ( ) , entry . Fee ( 9000LL ) . FromTx ( tx7 , & pool ) ) ;
2015-10-13 00:43:15 -07:00
}
2015-03-25 13:13:09 -04:00
BOOST_AUTO_TEST_SUITE_END ( )