2021-08-05 10:03:29 +02:00
// Copyright (c) 2011-2021 The Bitcoin Core developers
2014-12-13 12:09:33 +08:00
// Distributed under the MIT software license, see the accompanying
2014-03-18 10:11:00 +01:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2013-04-13 00:13:08 -05:00
2017-11-10 13:57:53 +13:00
# include <chainparams.h>
# include <coins.h>
# include <consensus/consensus.h>
# include <consensus/merkle.h>
# include <consensus/tx_verify.h>
2021-11-15 13:42:00 +01:00
# include <node/miner.h>
2017-11-10 13:57:53 +13:00
# include <policy/policy.h>
# include <script/standard.h>
2022-03-01 16:14:12 -05:00
# include <timedata.h>
2017-11-10 13:57:53 +13:00
# include <txmempool.h>
# include <uint256.h>
2018-10-22 15:51:11 -07:00
# include <util/strencodings.h>
2019-04-19 13:19:20 -04:00
# include <util/system.h>
2019-06-24 17:22:28 +02:00
# include <util/time.h>
2019-04-19 13:19:20 -04:00
# include <validation.h>
2021-08-05 10:03:29 +02:00
# include <versionbits.h>
2017-11-10 13:57:53 +13:00
2019-11-05 15:18:59 -05:00
# include <test/util/setup_common.h>
2015-03-03 07:49:12 -08:00
2016-06-18 19:38:28 +02:00
# include <memory>
2013-04-13 00:13:08 -05:00
# include <boost/test/unit_test.hpp>
2021-11-12 10:06:00 -05:00
using node : : BlockAssembler ;
using node : : CBlockTemplate ;
2019-11-08 11:07:36 -05:00
namespace miner_tests {
struct MinerTestingSetup : public TestingSetup {
void TestPackageSelection ( const CChainParams & chainparams , const CScript & scriptPubKey , const std : : vector < CTransactionRef > & txFirst ) EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main , m_node . mempool - > cs ) ;
2022-03-11 16:02:23 +00:00
void TestBasicMining ( const CChainParams & chainparams , const CScript & scriptPubKey , const std : : vector < CTransactionRef > & txFirst , int baseheight ) EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main , m_node . mempool - > cs ) ;
2022-03-11 15:41:51 +00:00
void TestPrioritisedMining ( const CChainParams & chainparams , const CScript & scriptPubKey , const std : : vector < CTransactionRef > & txFirst ) EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main , m_node . mempool - > cs ) ;
2022-01-11 17:02:23 +01:00
bool TestSequenceLocks ( const CTransaction & tx ) EXCLUSIVE_LOCKS_REQUIRED ( : : cs_main , m_node . mempool - > cs )
2019-11-08 11:07:36 -05:00
{
2021-05-27 08:39:59 +01:00
CCoinsViewMemPool view_mempool ( & m_node . chainman - > ActiveChainstate ( ) . CoinsTip ( ) , * m_node . mempool ) ;
2022-01-11 15:53:50 +01:00
return CheckSequenceLocksAtTip ( m_node . chainman - > ActiveChain ( ) . Tip ( ) , view_mempool , tx ) ;
2019-11-08 11:07:36 -05:00
}
2019-12-17 07:11:44 +07:00
BlockAssembler AssemblerForTest ( const CChainParams & params ) ;
2019-11-08 11:07:36 -05:00
} ;
} // namespace miner_tests
BOOST_FIXTURE_TEST_SUITE ( miner_tests , MinerTestingSetup )
2011-09-27 20:16:07 +02:00
2017-01-19 21:02:54 -05:00
static CFeeRate blockMinFeeRate = CFeeRate ( DEFAULT_BLOCK_MIN_TX_FEE ) ;
2019-12-17 07:11:44 +07:00
BlockAssembler MinerTestingSetup : : AssemblerForTest ( const CChainParams & params )
{
2017-02-26 16:13:51 -08:00
BlockAssembler : : Options options ;
options . nBlockMaxWeight = MAX_BLOCK_WEIGHT ;
options . blockMinFeeRate = blockMinFeeRate ;
2022-05-25 22:06:23 -04:00
return BlockAssembler { m_node . chainman - > ActiveChainstate ( ) , m_node . mempool . get ( ) , options } ;
2017-02-26 16:13:51 -08:00
}
2019-07-03 20:46:43 +07:00
constexpr static struct {
2012-05-22 21:55:15 +00:00
unsigned char extranonce ;
unsigned int nonce ;
2021-06-18 10:25:16 +02:00
} BLOCKINFO [ ] { { 8 , 582909131 } , { 0 , 971462344 } , { 2 , 1169481553 } , { 6 , 66147495 } , { 7 , 427785981 } , { 8 , 80538907 } ,
{ 8 , 207348013 } , { 2 , 1951240923 } , { 4 , 215054351 } , { 1 , 491520534 } , { 8 , 1282281282 } , { 4 , 639565734 } ,
{ 3 , 248274685 } , { 8 , 1160085976 } , { 6 , 396349768 } , { 5 , 393780549 } , { 5 , 1096899528 } , { 4 , 965381630 } ,
{ 0 , 728758712 } , { 5 , 318638310 } , { 3 , 164591898 } , { 2 , 274234550 } , { 2 , 254411237 } , { 7 , 561761812 } ,
{ 2 , 268342573 } , { 0 , 402816691 } , { 1 , 221006382 } , { 6 , 538872455 } , { 7 , 393315655 } , { 4 , 814555937 } ,
{ 7 , 504879194 } , { 6 , 467769648 } , { 3 , 925972193 } , { 2 , 200581872 } , { 3 , 168915404 } , { 8 , 430446262 } ,
{ 5 , 773507406 } , { 3 , 1195366164 } , { 0 , 433361157 } , { 3 , 297051771 } , { 0 , 558856551 } , { 2 , 501614039 } ,
{ 3 , 528488272 } , { 2 , 473587734 } , { 8 , 230125274 } , { 2 , 494084400 } , { 4 , 357314010 } , { 8 , 60361686 } ,
{ 7 , 640624687 } , { 3 , 480441695 } , { 8 , 1424447925 } , { 4 , 752745419 } , { 1 , 288532283 } , { 6 , 669170574 } ,
{ 5 , 1900907591 } , { 3 , 555326037 } , { 3 , 1121014051 } , { 0 , 545835650 } , { 8 , 189196651 } , { 5 , 252371575 } ,
{ 0 , 199163095 } , { 6 , 558895874 } , { 6 , 1656839784 } , { 6 , 815175452 } , { 6 , 718677851 } , { 5 , 544000334 } ,
{ 0 , 340113484 } , { 6 , 850744437 } , { 4 , 496721063 } , { 8 , 524715182 } , { 6 , 574361898 } , { 6 , 1642305743 } ,
{ 6 , 355110149 } , { 5 , 1647379658 } , { 8 , 1103005356 } , { 7 , 556460625 } , { 3 , 1139533992 } , { 5 , 304736030 } ,
{ 2 , 361539446 } , { 2 , 143720360 } , { 6 , 201939025 } , { 7 , 423141476 } , { 4 , 574633709 } , { 3 , 1412254823 } ,
{ 4 , 873254135 } , { 0 , 341817335 } , { 6 , 53501687 } , { 3 , 179755410 } , { 5 , 172209688 } , { 8 , 516810279 } ,
{ 4 , 1228391489 } , { 8 , 325372589 } , { 6 , 550367589 } , { 0 , 876291812 } , { 7 , 412454120 } , { 7 , 717202854 } ,
{ 2 , 222677843 } , { 6 , 251778867 } , { 7 , 842004420 } , { 7 , 194762829 } , { 4 , 96668841 } , { 1 , 925485796 } ,
{ 0 , 792342903 } , { 6 , 678455063 } , { 6 , 773251385 } , { 5 , 186617471 } , { 6 , 883189502 } , { 7 , 396077336 } ,
{ 8 , 254702874 } , { 0 , 455592851 } } ;
2012-05-22 21:55:15 +00:00
2020-10-14 17:03:18 -04:00
static CBlockIndex CreateBlockIndex ( int nHeight , CBlockIndex * active_chain_tip ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main )
2015-12-07 15:44:16 -05:00
{
CBlockIndex index ;
index . nHeight = nHeight ;
2020-10-14 17:03:18 -04:00
index . pprev = active_chain_tip ;
2015-12-07 15:44:16 -05:00
return index ;
}
2016-02-20 20:58:23 -05:00
// Test suite for ancestor feerate transaction selection.
// Implemented as an additional function, rather than a separate test case,
// to allow reusing the blockchain created in CreateNewBlock_validity.
2019-11-08 11:07:36 -05:00
void MinerTestingSetup : : TestPackageSelection ( const CChainParams & chainparams , const CScript & scriptPubKey , const std : : vector < CTransactionRef > & txFirst )
2016-02-20 20:58:23 -05:00
{
// Test the ancestor feerate transaction selection.
TestMemPoolEntryHelper entry ;
// Test that a medium fee transaction will be selected after a higher fee
// rate package with a low fee rate parent.
CMutableTransaction tx ;
tx . vin . resize ( 1 ) ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 0 ] . prevout . n = 0 ;
tx . vout . resize ( 1 ) ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 ;
// This tx has a low fee: 1000 satoshis
uint256 hashParentTx = tx . GetHash ( ) ; // save this txid for later use
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( 1000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2016-02-20 20:58:23 -05:00
// This tx has a medium fee: 10000 satoshis
tx . vin [ 0 ] . prevout . hash = txFirst [ 1 ] - > GetHash ( ) ;
tx . vout [ 0 ] . nValue = 5000000000LL - 10000 ;
uint256 hashMediumFeeTx = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( 10000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2016-02-20 20:58:23 -05:00
// This tx has a high fee, but depends on the first transaction
tx . vin [ 0 ] . prevout . hash = hashParentTx ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 - 50000 ; // 50k satoshi fee
uint256 hashHighFeeTx = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( 50000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
2016-02-20 20:58:23 -05:00
2021-03-16 19:32:10 -04:00
std : : unique_ptr < CBlockTemplate > pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2021-02-18 20:34:10 +01:00
BOOST_REQUIRE_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 4U ) ;
2016-11-10 17:26:00 -08:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ 1 ] - > GetHash ( ) = = hashParentTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 2 ] - > GetHash ( ) = = hashHighFeeTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 3 ] - > GetHash ( ) = = hashMediumFeeTx ) ;
2016-02-20 20:58:23 -05:00
2017-01-19 21:02:54 -05:00
// Test that a package below the block min tx fee doesn't get included
2016-02-20 20:58:23 -05:00
tx . vin [ 0 ] . prevout . hash = hashHighFeeTx ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 - 50000 ; // 0 fee
uint256 hashFreeTx = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( 0 ) . FromTx ( tx ) ) ;
2018-06-22 18:27:18 +00:00
size_t freeTxSize = : : GetSerializeSize ( tx , PROTOCOL_VERSION ) ;
2016-02-20 20:58:23 -05:00
// Calculate a fee on child transaction that will put the package just
2017-01-19 21:02:54 -05:00
// below the block min tx fee (assuming 1 child tx of the same size).
CAmount feeToUse = blockMinFeeRate . GetFee ( 2 * freeTxSize ) - 1 ;
2016-02-20 20:58:23 -05:00
tx . vin [ 0 ] . prevout . hash = hashFreeTx ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 - 50000 - feeToUse ;
uint256 hashLowFeeTx = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( feeToUse ) . FromTx ( tx ) ) ;
2021-03-16 19:32:10 -04:00
pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2016-02-20 20:58:23 -05:00
// Verify that the free tx and the low fee tx didn't get selected
for ( size_t i = 0 ; i < pblocktemplate - > block . vtx . size ( ) ; + + i ) {
2016-11-10 17:26:00 -08:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashFreeTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashLowFeeTx ) ;
2016-02-20 20:58:23 -05:00
}
// Test that packages above the min relay fee do get included, even if one
// of the transactions is below the min relay fee
// Remove the low fee transaction and replace with a higher fee transaction
2019-11-08 11:10:13 -05:00
m_node . mempool - > removeRecursive ( CTransaction ( tx ) , MemPoolRemovalReason : : REPLACED ) ;
2016-02-20 20:58:23 -05:00
tx . vout [ 0 ] . nValue - = 2 ; // Now we should be just over the min relay fee
hashLowFeeTx = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( feeToUse + 2 ) . FromTx ( tx ) ) ;
2021-03-16 19:32:10 -04:00
pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2021-02-18 20:34:10 +01:00
BOOST_REQUIRE_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 6U ) ;
2016-11-10 17:26:00 -08:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ 4 ] - > GetHash ( ) = = hashFreeTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 5 ] - > GetHash ( ) = = hashLowFeeTx ) ;
2016-02-20 20:58:23 -05:00
// Test that transaction selection properly updates ancestor fee
// calculations as ancestor transactions get included in a block.
// Add a 0-fee transaction that has 2 outputs.
tx . vin [ 0 ] . prevout . hash = txFirst [ 2 ] - > GetHash ( ) ;
tx . vout . resize ( 2 ) ;
tx . vout [ 0 ] . nValue = 5000000000LL - 100000000 ;
tx . vout [ 1 ] . nValue = 100000000 ; // 1BTC output
uint256 hashFreeTx2 = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( 0 ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2016-02-20 20:58:23 -05:00
// This tx can't be mined by itself
tx . vin [ 0 ] . prevout . hash = hashFreeTx2 ;
tx . vout . resize ( 1 ) ;
2017-01-19 21:02:54 -05:00
feeToUse = blockMinFeeRate . GetFee ( freeTxSize ) ;
2016-02-20 20:58:23 -05:00
tx . vout [ 0 ] . nValue = 5000000000LL - 100000000 - feeToUse ;
uint256 hashLowFeeTx2 = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( feeToUse ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
2021-03-16 19:32:10 -04:00
pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2016-02-20 20:58:23 -05:00
// Verify that this tx isn't selected.
for ( size_t i = 0 ; i < pblocktemplate - > block . vtx . size ( ) ; + + i ) {
2016-11-10 17:26:00 -08:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashFreeTx2 ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashLowFeeTx2 ) ;
2016-02-20 20:58:23 -05:00
}
// This tx will be mineable, and should cause hashLowFeeTx2 to be selected
// as well.
tx . vin [ 0 ] . prevout . n = 1 ;
tx . vout [ 0 ] . nValue = 100000000 - 10000 ; // 10k satoshi fee
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( 10000 ) . FromTx ( tx ) ) ;
2021-03-16 19:32:10 -04:00
pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2021-02-18 20:34:10 +01:00
BOOST_REQUIRE_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 9U ) ;
2016-11-10 17:26:00 -08:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ 8 ] - > GetHash ( ) = = hashLowFeeTx2 ) ;
2016-02-20 20:58:23 -05:00
}
2022-03-11 16:02:23 +00:00
void MinerTestingSetup : : TestBasicMining ( const CChainParams & chainparams , const CScript & scriptPubKey , const std : : vector < CTransactionRef > & txFirst , int baseheight )
2012-05-22 21:55:15 +00:00
{
uint256 hash ;
2022-03-11 16:02:23 +00:00
CMutableTransaction tx ;
2015-11-14 17:04:15 -05:00
TestMemPoolEntryHelper entry ;
entry . nFee = 11 ;
entry . nHeight = 11 ;
2012-05-22 21:55:15 +00:00
// Just to make sure we can still make simple blocks
2022-03-11 16:02:23 +00:00
auto pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
BOOST_CHECK ( pblocktemplate ) ;
2012-05-22 21:55:15 +00:00
2016-04-04 11:17:23 -04:00
const CAmount BLOCKSUBSIDY = 50 * COIN ;
const CAmount LOWFEE = CENT ;
const CAmount HIGHFEE = COIN ;
const CAmount HIGHERFEE = 4 * COIN ;
2012-05-22 21:55:15 +00:00
// block sigops > limit: 1000 CHECKMULTISIG + 1
tx . vin . resize ( 1 ) ;
// NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_0 < < OP_0 < < OP_0 < < OP_NOP < < OP_CHECKMULTISIG < < OP_1 ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 0 ] . prevout . n = 0 ;
tx . vout . resize ( 1 ) ;
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY ;
2012-05-22 21:55:15 +00:00
for ( unsigned int i = 0 ; i < 1001 ; + + i )
{
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue - = LOWFEE ;
2012-05-22 21:55:15 +00:00
hash = tx . GetHash ( ) ;
2017-06-08 12:06:09 +02:00
bool spendsCoinbase = i = = 0 ; // only first tx spends coinbase
2015-11-03 10:35:39 -05:00
// If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . FromTx ( tx ) ) ;
2015-11-03 10:35:39 -05:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2017-11-09 12:02:46 +01:00
2021-03-16 19:32:10 -04:00
BOOST_CHECK_EXCEPTION ( AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error , HasReason ( " bad-blk-sigops " ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2015-11-03 10:35:39 -05:00
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY ;
2015-11-03 10:35:39 -05:00
for ( unsigned int i = 0 ; i < 1001 ; + + i )
{
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue - = LOWFEE ;
2015-11-03 10:35:39 -05:00
hash = tx . GetHash ( ) ;
2017-06-08 12:06:09 +02:00
bool spendsCoinbase = i = = 0 ; // only first tx spends coinbase
2015-11-03 10:35:39 -05:00
// If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . SigOpsCost ( 80 ) . FromTx ( tx ) ) ;
2012-05-22 21:55:15 +00:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2021-03-16 19:32:10 -04:00
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2012-05-22 21:55:15 +00:00
// block size > limit
tx . vin [ 0 ] . scriptSig = CScript ( ) ;
// 18 * (520char + DROP) + OP_1 = 9433 bytes
std : : vector < unsigned char > vchData ( 520 ) ;
for ( unsigned int i = 0 ; i < 18 ; + + i )
tx . vin [ 0 ] . scriptSig < < vchData < < OP_DROP ;
tx . vin [ 0 ] . scriptSig < < OP_1 ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY ;
2012-05-22 21:55:15 +00:00
for ( unsigned int i = 0 ; i < 128 ; + + i )
{
2016-04-06 08:29:19 -04:00
tx . vout [ 0 ] . nValue - = LOWFEE ;
2012-05-22 21:55:15 +00:00
hash = tx . GetHash ( ) ;
2017-06-08 12:06:09 +02:00
bool spendsCoinbase = i = = 0 ; // only first tx spends coinbase
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . FromTx ( tx ) ) ;
2012-05-22 21:55:15 +00:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2021-03-16 19:32:10 -04:00
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2012-05-22 21:55:15 +00:00
2019-11-08 11:10:13 -05:00
// orphan in *m_node.mempool, template creation fails
2012-05-22 21:55:15 +00:00
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
2021-03-16 19:32:10 -04:00
BOOST_CHECK_EXCEPTION ( AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error , HasReason ( " bad-txns-inputs-missingorspent " ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2012-05-22 21:55:15 +00:00
2017-01-19 22:46:50 -05:00
// child with higher feerate than parent
2012-05-22 21:55:15 +00:00
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 1 ] - > GetHash ( ) ;
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - HIGHFEE ;
2012-05-22 21:55:15 +00:00
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2012-05-22 21:55:15 +00:00
tx . vin [ 0 ] . prevout . hash = hash ;
tx . vin . resize ( 2 ) ;
tx . vin [ 1 ] . scriptSig = CScript ( ) < < OP_1 ;
tx . vin [ 1 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 1 ] . prevout . n = 0 ;
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue = tx . vout [ 0 ] . nValue + BLOCKSUBSIDY - HIGHERFEE ; //First txn output + fresh coinbase - new txn fee
2012-05-22 21:55:15 +00:00
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( HIGHERFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2021-03-16 19:32:10 -04:00
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2012-05-22 21:55:15 +00:00
2019-11-08 11:10:13 -05:00
// coinbase in *m_node.mempool, template creation fails
2012-05-22 21:55:15 +00:00
tx . vin . resize ( 1 ) ;
tx . vin [ 0 ] . prevout . SetNull ( ) ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_0 < < OP_1 ;
tx . vout [ 0 ] . nValue = 0 ;
hash = tx . GetHash ( ) ;
2015-11-03 10:35:39 -05:00
// give it a fee so it'll get mined
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
2017-11-09 12:02:46 +01:00
// Should throw bad-cb-multiple
2021-03-16 19:32:10 -04:00
BOOST_CHECK_EXCEPTION ( AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error , HasReason ( " bad-cb-multiple " ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2012-05-22 21:55:15 +00:00
2019-11-08 11:10:13 -05:00
// double spend txn pair in *m_node.mempool, template creation fails
2012-05-22 21:55:15 +00:00
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - HIGHFEE ;
2012-05-22 21:55:15 +00:00
tx . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_1 ;
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2012-05-22 21:55:15 +00:00
tx . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_2 ;
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2021-03-16 19:32:10 -04:00
BOOST_CHECK_EXCEPTION ( AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error , HasReason ( " bad-txns-inputs-missingorspent " ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2012-05-22 21:55:15 +00:00
// subsidy changing
2020-09-09 16:15:15 -04:00
int nHeight = m_node . chainman - > ActiveChain ( ) . Height ( ) ;
2016-02-15 05:13:27 +01:00
// Create an actual 209999-long block chain (without valid blocks).
2020-09-09 16:15:15 -04:00
while ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight < 209999 ) {
CBlockIndex * prev = m_node . chainman - > ActiveChain ( ) . Tip ( ) ;
2016-02-15 05:13:27 +01:00
CBlockIndex * next = new CBlockIndex ( ) ;
2017-06-07 12:03:17 -07:00
next - > phashBlock = new uint256 ( InsecureRand256 ( ) ) ;
2020-09-09 16:15:15 -04:00
m_node . chainman - > ActiveChainstate ( ) . CoinsTip ( ) . SetBestBlock ( next - > GetBlockHash ( ) ) ;
2016-02-15 05:13:27 +01:00
next - > pprev = prev ;
next - > nHeight = prev - > nHeight + 1 ;
next - > BuildSkip ( ) ;
2022-04-29 09:41:09 +02:00
m_node . chainman - > ActiveChain ( ) . SetTip ( * next ) ;
2016-02-15 05:13:27 +01:00
}
2021-03-16 19:32:10 -04:00
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2016-02-15 05:13:27 +01:00
// Extend to a 210000-long block chain.
2020-09-09 16:15:15 -04:00
while ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight < 210000 ) {
CBlockIndex * prev = m_node . chainman - > ActiveChain ( ) . Tip ( ) ;
2016-02-15 05:13:27 +01:00
CBlockIndex * next = new CBlockIndex ( ) ;
2017-06-07 12:03:17 -07:00
next - > phashBlock = new uint256 ( InsecureRand256 ( ) ) ;
2020-09-09 16:15:15 -04:00
m_node . chainman - > ActiveChainstate ( ) . CoinsTip ( ) . SetBestBlock ( next - > GetBlockHash ( ) ) ;
2016-02-15 05:13:27 +01:00
next - > pprev = prev ;
next - > nHeight = prev - > nHeight + 1 ;
next - > BuildSkip ( ) ;
2022-04-29 09:41:09 +02:00
m_node . chainman - > ActiveChain ( ) . SetTip ( * next ) ;
2016-02-15 05:13:27 +01:00
}
2021-03-16 19:32:10 -04:00
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2017-10-13 11:35:18 -04:00
2019-11-08 11:10:13 -05:00
// invalid p2sh txn in *m_node.mempool, template creation fails
2017-10-13 11:35:18 -04:00
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 0 ] . prevout . n = 0 ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - LOWFEE ;
2022-03-11 16:02:23 +00:00
CScript script = CScript ( ) < < OP_0 ;
2019-02-19 17:00:45 -05:00
tx . vout [ 0 ] . scriptPubKey = GetScriptForDestination ( ScriptHash ( script ) ) ;
2017-10-13 11:35:18 -04:00
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2017-10-13 11:35:18 -04:00
tx . vin [ 0 ] . prevout . hash = hash ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < std : : vector < unsigned char > ( script . begin ( ) , script . end ( ) ) ;
tx . vout [ 0 ] . nValue - = LOWFEE ;
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
2017-11-09 12:02:46 +01:00
// Should throw block-validation-failed
2021-03-16 19:32:10 -04:00
BOOST_CHECK_EXCEPTION ( AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error , HasReason ( " block-validation-failed " ) ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2017-10-13 11:35:18 -04:00
2016-02-15 05:13:27 +01:00
// Delete the dummy blocks again.
2020-09-09 16:15:15 -04:00
while ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight > nHeight ) {
CBlockIndex * del = m_node . chainman - > ActiveChain ( ) . Tip ( ) ;
2022-04-29 09:41:09 +02:00
m_node . chainman - > ActiveChain ( ) . SetTip ( * Assert ( del - > pprev ) ) ;
2020-09-09 16:15:15 -04:00
m_node . chainman - > ActiveChainstate ( ) . CoinsTip ( ) . SetBestBlock ( del - > pprev - > GetBlockHash ( ) ) ;
2016-02-15 05:13:27 +01:00
delete del - > phashBlock ;
delete del ;
}
2013-09-19 00:01:36 +02:00
2014-01-26 21:50:15 -05:00
// non-final txs in mempool
2022-03-14 18:20:03 +01:00
SetMockTime ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetMedianTimePast ( ) + 1 ) ;
const int flags { LOCKTIME_VERIFY_SEQUENCE } ;
2015-12-07 15:44:16 -05:00
// height map
std : : vector < int > prevheights ;
2014-01-26 21:50:15 -05:00
2015-12-07 15:44:16 -05:00
// relative height locked
tx . nVersion = 2 ;
tx . vin . resize ( 1 ) ;
prevheights . resize ( 1 ) ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ; // only 1 transaction
tx . vin [ 0 ] . prevout . n = 0 ;
2014-01-26 21:50:15 -05:00
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
2020-09-09 16:15:15 -04:00
tx . vin [ 0 ] . nSequence = m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight + 1 ; // txFirst[0] is the 2nd block
2015-12-07 15:44:16 -05:00
prevheights [ 0 ] = baseheight + 1 ;
tx . vout . resize ( 1 ) ;
2016-04-04 11:17:23 -04:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - HIGHFEE ;
2014-01-26 21:50:15 -05:00
tx . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_1 ;
2015-12-07 15:44:16 -05:00
tx . nLockTime = 0 ;
2014-01-26 21:50:15 -05:00
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2022-07-22 14:28:18 +02:00
BOOST_CHECK ( CheckFinalTxAtTip ( * Assert ( m_node . chainman - > ActiveChain ( ) . Tip ( ) ) , CTransaction { tx } ) ) ; // Locktime passes
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( ! TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks fail
2020-10-14 17:03:18 -04:00
{
CBlockIndex * active_chain_tip = m_node . chainman - > ActiveChain ( ) . Tip ( ) ;
BOOST_CHECK ( SequenceLocks ( CTransaction ( tx ) , flags , prevheights , CreateBlockIndex ( active_chain_tip - > nHeight + 2 , active_chain_tip ) ) ) ; // Sequence locks pass on 2nd block
}
2015-12-07 15:44:16 -05:00
// relative time locked
tx . vin [ 0 ] . prevout . hash = txFirst [ 1 ] - > GetHash ( ) ;
2020-09-09 16:15:15 -04:00
tx . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG | ( ( ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetMedianTimePast ( ) + 1 - m_node . chainman - > ActiveChain ( ) [ 1 ] - > GetMedianTimePast ( ) ) > > CTxIn : : SEQUENCE_LOCKTIME_GRANULARITY ) + 1 ) ; // txFirst[1] is the 3rd block
2015-12-07 15:44:16 -05:00
prevheights [ 0 ] = baseheight + 2 ;
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
2022-07-22 14:28:18 +02:00
BOOST_CHECK ( CheckFinalTxAtTip ( * Assert ( m_node . chainman - > ActiveChain ( ) . Tip ( ) ) , CTransaction { tx } ) ) ; // Locktime passes
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( ! TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks fail
2015-12-07 15:44:16 -05:00
2019-10-21 13:17:22 -04:00
const int SEQUENCE_LOCK_TIME = 512 ; // Sequence locks pass 512 seconds later
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; + + i )
m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetAncestor ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight - i ) - > nTime + = SEQUENCE_LOCK_TIME ; // Trick the MedianTimePast
2020-10-14 17:03:18 -04:00
{
CBlockIndex * active_chain_tip = m_node . chainman - > ActiveChain ( ) . Tip ( ) ;
2019-10-21 13:17:22 -04:00
BOOST_CHECK ( SequenceLocks ( CTransaction ( tx ) , flags , prevheights , CreateBlockIndex ( active_chain_tip - > nHeight + 1 , active_chain_tip ) ) ) ;
2020-10-14 17:03:18 -04:00
}
2019-10-21 13:17:22 -04:00
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; + + i ) {
CBlockIndex * ancestor { Assert ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetAncestor ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight - i ) ) } ;
ancestor - > nTime - = SEQUENCE_LOCK_TIME ; // undo tricked MTP
}
2015-12-07 15:44:16 -05:00
// absolute height locked
tx . vin [ 0 ] . prevout . hash = txFirst [ 2 ] - > GetHash ( ) ;
2022-01-10 14:48:13 +01:00
tx . vin [ 0 ] . nSequence = CTxIn : : MAX_SEQUENCE_NONFINAL ;
2015-12-07 15:44:16 -05:00
prevheights [ 0 ] = baseheight + 3 ;
2020-09-09 16:15:15 -04:00
tx . nLockTime = m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight + 1 ;
2015-12-07 15:44:16 -05:00
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
2022-07-22 14:28:18 +02:00
BOOST_CHECK ( ! CheckFinalTxAtTip ( * Assert ( m_node . chainman - > ActiveChain ( ) . Tip ( ) ) , CTransaction { tx } ) ) ; // Locktime fails
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks pass
2020-09-09 16:15:15 -04:00
BOOST_CHECK ( IsFinalTx ( CTransaction ( tx ) , m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight + 2 , m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetMedianTimePast ( ) ) ) ; // Locktime passes on 2nd block
2015-12-07 15:44:16 -05:00
// absolute time locked
tx . vin [ 0 ] . prevout . hash = txFirst [ 3 ] - > GetHash ( ) ;
2020-09-09 16:15:15 -04:00
tx . nLockTime = m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetMedianTimePast ( ) ;
2015-12-07 15:44:16 -05:00
prevheights . resize ( 1 ) ;
prevheights [ 0 ] = baseheight + 4 ;
hash = tx . GetHash ( ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > addUnchecked ( entry . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
2022-07-22 14:28:18 +02:00
BOOST_CHECK ( ! CheckFinalTxAtTip ( * Assert ( m_node . chainman - > ActiveChain ( ) . Tip ( ) ) , CTransaction { tx } ) ) ; // Locktime fails
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks pass
2020-09-09 16:15:15 -04:00
BOOST_CHECK ( IsFinalTx ( CTransaction ( tx ) , m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight + 2 , m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetMedianTimePast ( ) + 1 ) ) ; // Locktime passes 1 second later
2015-12-07 15:44:16 -05:00
// mempool-dependent transactions (not added)
tx . vin [ 0 ] . prevout . hash = hash ;
2020-09-09 16:15:15 -04:00
prevheights [ 0 ] = m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight + 1 ;
2015-12-07 15:44:16 -05:00
tx . nLockTime = 0 ;
tx . vin [ 0 ] . nSequence = 0 ;
2022-07-22 14:28:18 +02:00
BOOST_CHECK ( CheckFinalTxAtTip ( * Assert ( m_node . chainman - > ActiveChain ( ) . Tip ( ) ) , CTransaction { tx } ) ) ; // Locktime passes
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks pass
2015-12-07 15:44:16 -05:00
tx . vin [ 0 ] . nSequence = 1 ;
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( ! TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks fail
2015-12-07 15:44:16 -05:00
tx . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG ;
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks pass
2015-12-07 15:44:16 -05:00
tx . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG | 1 ;
2022-01-11 17:02:23 +01:00
BOOST_CHECK ( ! TestSequenceLocks ( CTransaction { tx } ) ) ; // Sequence locks fail
2014-01-26 21:50:15 -05:00
2021-03-16 19:32:10 -04:00
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2014-01-26 21:50:15 -05:00
2015-12-07 15:44:16 -05:00
// None of the of the absolute height/time locked tx should have made
// it into the template because we still check IsFinalTx in CreateNewBlock,
// but relative locked txs will if inconsistently added to mempool.
// For now these will still generate a valid template until BIP68 soft fork
2018-04-09 16:50:19 +09:00
BOOST_CHECK_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 3U ) ;
2019-10-21 13:17:22 -04:00
// However if we advance height by 1 and time by SEQUENCE_LOCK_TIME, all of them should be mined
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; + + i ) {
CBlockIndex * ancestor { Assert ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetAncestor ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight - i ) ) } ;
ancestor - > nTime + = SEQUENCE_LOCK_TIME ; // Trick the MedianTimePast
}
2020-09-09 16:15:15 -04:00
m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight + + ;
SetMockTime ( m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetMedianTimePast ( ) + 1 ) ;
2014-01-26 21:50:15 -05:00
2021-03-16 19:32:10 -04:00
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2018-04-09 16:50:19 +09:00
BOOST_CHECK_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 5U ) ;
2022-03-11 16:02:23 +00:00
}
2022-03-11 15:41:51 +00:00
void MinerTestingSetup : : TestPrioritisedMining ( const CChainParams & chainparams , const CScript & scriptPubKey , const std : : vector < CTransactionRef > & txFirst )
{
TestMemPoolEntryHelper entry ;
// Test that a tx below min fee but prioritised is included
CMutableTransaction tx ;
tx . vin . resize ( 1 ) ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 0 ] . prevout . n = 0 ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
tx . vout . resize ( 1 ) ;
tx . vout [ 0 ] . nValue = 5000000000LL ; // 0 fee
uint256 hashFreePrioritisedTx = tx . GetHash ( ) ;
m_node . mempool - > addUnchecked ( entry . Fee ( 0 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
m_node . mempool - > PrioritiseTransaction ( hashFreePrioritisedTx , 5 * COIN ) ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 1 ] - > GetHash ( ) ;
tx . vin [ 0 ] . prevout . n = 0 ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 ;
// This tx has a low fee: 1000 satoshis
uint256 hashParentTx = tx . GetHash ( ) ; // save this txid for later use
m_node . mempool - > addUnchecked ( entry . Fee ( 1000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
// This tx has a medium fee: 10000 satoshis
tx . vin [ 0 ] . prevout . hash = txFirst [ 2 ] - > GetHash ( ) ;
tx . vout [ 0 ] . nValue = 5000000000LL - 10000 ;
uint256 hashMediumFeeTx = tx . GetHash ( ) ;
m_node . mempool - > addUnchecked ( entry . Fee ( 10000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
m_node . mempool - > PrioritiseTransaction ( hashMediumFeeTx , - 5 * COIN ) ;
// This tx also has a low fee, but is prioritised
tx . vin [ 0 ] . prevout . hash = hashParentTx ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 - 1000 ; // 1000 satoshi fee
uint256 hashPrioritsedChild = tx . GetHash ( ) ;
m_node . mempool - > addUnchecked ( entry . Fee ( 1000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
m_node . mempool - > PrioritiseTransaction ( hashPrioritsedChild , 2 * COIN ) ;
// Test that transaction selection properly updates ancestor fee calculations as prioritised
// parents get included in a block. Create a transaction with two prioritised ancestors, each
// included by itself: FreeParent <- FreeChild <- FreeGrandchild.
// When FreeParent is added, a modified entry will be created for FreeChild + FreeGrandchild
// FreeParent's prioritisation should not be included in that entry.
// When FreeChild is included, FreeChild's prioritisation should also not be included.
tx . vin [ 0 ] . prevout . hash = txFirst [ 3 ] - > GetHash ( ) ;
tx . vout [ 0 ] . nValue = 5000000000LL ; // 0 fee
uint256 hashFreeParent = tx . GetHash ( ) ;
m_node . mempool - > addUnchecked ( entry . Fee ( 0 ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
m_node . mempool - > PrioritiseTransaction ( hashFreeParent , 10 * COIN ) ;
tx . vin [ 0 ] . prevout . hash = hashFreeParent ;
tx . vout [ 0 ] . nValue = 5000000000LL ; // 0 fee
uint256 hashFreeChild = tx . GetHash ( ) ;
m_node . mempool - > addUnchecked ( entry . Fee ( 0 ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
m_node . mempool - > PrioritiseTransaction ( hashFreeChild , 1 * COIN ) ;
tx . vin [ 0 ] . prevout . hash = hashFreeChild ;
tx . vout [ 0 ] . nValue = 5000000000LL ; // 0 fee
uint256 hashFreeGrandchild = tx . GetHash ( ) ;
m_node . mempool - > addUnchecked ( entry . Fee ( 0 ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
auto pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
BOOST_REQUIRE_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 6U ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 1 ] - > GetHash ( ) = = hashFreeParent ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 2 ] - > GetHash ( ) = = hashFreePrioritisedTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 3 ] - > GetHash ( ) = = hashParentTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 4 ] - > GetHash ( ) = = hashPrioritsedChild ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 5 ] - > GetHash ( ) = = hashFreeChild ) ;
for ( size_t i = 0 ; i < pblocktemplate - > block . vtx . size ( ) ; + + i ) {
// The FreeParent and FreeChild's prioritisations should not impact the child.
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashFreeGrandchild ) ;
// De-prioritised transaction should not be included.
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashMediumFeeTx ) ;
}
}
2022-03-11 16:02:23 +00:00
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE ( CreateNewBlock_validity )
{
// Note that by default, these tests run with size accounting enabled.
const auto chainParams = CreateChainParams ( * m_node . args , CBaseChainParams : : MAIN ) ;
const CChainParams & chainparams = * chainParams ;
CScript scriptPubKey = CScript ( ) < < ParseHex ( " 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f " ) < < OP_CHECKSIG ;
std : : unique_ptr < CBlockTemplate > pblocktemplate ;
fCheckpointsEnabled = false ;
// Simple block creation, nothing special yet:
BOOST_CHECK ( pblocktemplate = AssemblerForTest ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
// We can't make transactions until we have inputs
// Therefore, load 110 blocks :)
static_assert ( std : : size ( BLOCKINFO ) = = 110 , " Should have 110 blocks to import " ) ;
int baseheight = 0 ;
std : : vector < CTransactionRef > txFirst ;
for ( const auto & bi : BLOCKINFO ) {
CBlock * pblock = & pblocktemplate - > block ; // pointer for convenience
{
LOCK ( cs_main ) ;
pblock - > nVersion = VERSIONBITS_TOP_BITS ;
pblock - > nTime = m_node . chainman - > ActiveChain ( ) . Tip ( ) - > GetMedianTimePast ( ) + 1 ;
CMutableTransaction txCoinbase ( * pblock - > vtx [ 0 ] ) ;
txCoinbase . nVersion = 1 ;
txCoinbase . vin [ 0 ] . scriptSig = CScript { } < < ( m_node . chainman - > ActiveChain ( ) . Height ( ) + 1 ) < < bi . extranonce ;
txCoinbase . vout . resize ( 1 ) ; // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
txCoinbase . vout [ 0 ] . scriptPubKey = CScript ( ) ;
pblock - > vtx [ 0 ] = MakeTransactionRef ( std : : move ( txCoinbase ) ) ;
if ( txFirst . size ( ) = = 0 )
baseheight = m_node . chainman - > ActiveChain ( ) . Height ( ) ;
if ( txFirst . size ( ) < 4 )
txFirst . push_back ( pblock - > vtx [ 0 ] ) ;
pblock - > hashMerkleRoot = BlockMerkleRoot ( * pblock ) ;
pblock - > nNonce = bi . nonce ;
}
std : : shared_ptr < const CBlock > shared_pblock = std : : make_shared < const CBlock > ( * pblock ) ;
2022-01-18 21:49:30 +10:00
BOOST_CHECK ( Assert ( m_node . chainman ) - > ProcessNewBlock ( shared_pblock , true , nullptr ) ) ;
2022-03-11 16:02:23 +00:00
pblock - > hashPrevBlock = pblock - > GetHash ( ) ;
}
LOCK ( cs_main ) ;
LOCK ( m_node . mempool - > cs ) ;
TestBasicMining ( chainparams , scriptPubKey , txFirst , baseheight ) ;
2014-01-26 21:50:15 -05:00
2020-09-09 16:15:15 -04:00
m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight - - ;
2014-01-26 21:50:15 -05:00
SetMockTime ( 0 ) ;
2019-11-08 11:10:13 -05:00
m_node . mempool - > clear ( ) ;
2014-01-26 21:50:15 -05:00
2016-02-20 20:58:23 -05:00
TestPackageSelection ( chainparams , scriptPubKey , txFirst ) ;
2022-03-11 15:41:51 +00:00
m_node . chainman - > ActiveChain ( ) . Tip ( ) - > nHeight - - ;
SetMockTime ( 0 ) ;
m_node . mempool - > clear ( ) ;
TestPrioritisedMining ( chainparams , scriptPubKey , txFirst ) ;
2015-04-22 23:22:36 -04:00
fCheckpointsEnabled = true ;
2012-05-22 21:55:15 +00:00
}
2011-09-27 20:16:07 +02:00
BOOST_AUTO_TEST_SUITE_END ( )