2016-12-31 19:01:21 +01:00
// Copyright (c) 2011-2016 The Bitcoin Core developers
2014-12-13 05:09:33 +01: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 07:13:08 +02:00
2015-07-05 14:17:46 +02:00
# include "chainparams.h"
# include "coins.h"
2015-11-03 18:14:09 +01:00
# include "consensus/consensus.h"
2015-11-17 17:35:44 +01:00
# include "consensus/merkle.h"
2015-01-24 15:57:12 +01:00
# include "consensus/validation.h"
2016-12-02 01:06:41 +01:00
# include "validation.h"
2013-04-13 07:13:08 +02:00
# include "miner.h"
2017-01-20 03:02:54 +01:00
# include "policy/policy.h"
2014-10-28 22:47:18 +01:00
# include "pubkey.h"
2015-07-05 14:17:46 +02:00
# include "script/standard.h"
# include "txmempool.h"
2011-10-12 01:50:06 +02:00
# include "uint256.h"
2012-04-17 20:37:47 +02:00
# include "util.h"
2015-07-05 14:17:46 +02:00
# include "utilstrencodings.h"
2011-09-27 20:16:07 +02:00
2015-03-03 16:49:12 +01:00
# include "test/test_bitcoin.h"
2016-06-18 19:38:28 +02:00
# include <memory>
2013-04-13 07:13:08 +02:00
# include <boost/test/unit_test.hpp>
2015-03-03 16:49:12 +01:00
BOOST_FIXTURE_TEST_SUITE ( miner_tests , TestingSetup )
2011-09-27 20:16:07 +02:00
2017-01-20 03:02:54 +01:00
static CFeeRate blockMinFeeRate = CFeeRate ( DEFAULT_BLOCK_MIN_TX_FEE ) ;
2012-05-22 23:55:15 +02:00
static
struct {
unsigned char extranonce ;
unsigned int nonce ;
} blockinfo [ ] = {
2017-04-18 17:52:01 +02:00
{ 4 , 0x127fad2d } , { 2 , 0x335d1b8f } , { 1 , 0x33d47094 } , { 2 , 0x0b09ec28 } ,
{ 1 , 0x06cf723b } , { 2 , 0x039202bc } , { 1 , 0x0a2c9d46 } , { 2 , 0x6225cb92 } ,
{ 2 , 0x6ea1513e } , { 1 , 0x4401bef3 } , { 1 , 0x04d3a1d2 } , { 2 , 0x1c512825 } ,
{ 2 , 0x54a03b14 } , { 1 , 0x6048e27d } , { 1 , 0x1b926afc } , { 2 , 0x68c4afbd } ,
{ 2 , 0x4439c313 } , { 1 , 0x1263fceb } , { 2 , 0x834dee3e } , { 2 , 0xf21ed9dc } ,
{ 1 , 0xdcdac434 } , { 2 , 0x4c1945be } , { 1 , 0x6d42a594 } , { 3 , 0x20927a30 } ,
{ 3 , 0xfd60f461 } , { 2 , 0xd9ad2207 } , { 2 , 0xe7f69d1a } , { 1 , 0x7fa9b932 } ,
{ 2 , 0xb0511080 } , { 1 , 0xe7d24cd5 } , { 2 , 0x3c57e668 } , { 2 , 0x83bfdc2e } ,
{ 2 , 0x6eeb4e10 } , { 2 , 0x9cacbcfd } , { 2 , 0xb27ea98e } , { 2 , 0x6d57c5a7 } ,
{ 1 , 0x6deb4fa8 } , { 2 , 0xabf625c6 } , { 2 , 0x27e7c569 } , { 1 , 0x89c6e991 } ,
{ 2 , 0xc359bc28 } , { 1 , 0x6f25768d } , { 2 , 0x654a4c31 } , { 1 , 0x5cd03bab } ,
{ 1 , 0xda405f69 } , { 3 , 0xfea453e5 } , { 2 , 0x137d2c3a } , { 5 , 0xdee2f36e } ,
{ 1 , 0xeccbcf26 } , { 5 , 0x9237dbaa } , { 1 , 0xb7b9350b } , { 1 , 0xcd0c7eb2 } ,
{ 1 , 0xf5ea5a32 } , { 2 , 0x3486a7f3 } , { 1 , 0xd0a0f2be } , { 1 , 0xe1238144 } ,
{ 1 , 0x28b98a9b } , { 1 , 0xe79d02aa } , { 5 , 0xf4555d56 } , { 5 , 0x74da0bb7 } ,
{ 1 , 0x18728b91 } , { 1 , 0x07ed3a93 } , { 6 , 0xd7a5e106 } , { 2 , 0xba50b06c } ,
{ 2 , 0x952c830d } , { 1 , 0xfbd1bb18 } , { 1 , 0x36126967 } , { 1 , 0xcce357d0 } ,
{ 2 , 0xff1ec2d6 } , { 2 , 0xbed5dfc9 } , { 1 , 0x0d21fdd7 } , { 1 , 0xd744edea } ,
{ 1 , 0xe09fc8f2 } , { 5 , 0x2ad325c5 } , { 5 , 0x466b6549 } , { 1 , 0x10705d49 } ,
{ 1 , 0xf88478ce } , { 2 , 0xbfda6c4a } , { 2 , 0x731fe414 } , { 1 , 0x6f1b362e } ,
{ 2 , 0x6be709cf } , { 1 , 0x60553200 } , { 2 , 0xf6a992f0 } , { 2 , 0x1521f7f5 } ,
{ 1 , 0x8b440273 } , { 1 , 0xe9ade0c8 } , { 1 , 0x4d414618 } , { 5 , 0x7b48070d } ,
{ 1 , 0x1202ebae } , { 1 , 0xd23fe97e } , { 1 , 0x8d1d6505 } , { 1 , 0xfafbaae3 } ,
{ 1 , 0xf200353e } , { 1 , 0xe77bd65e } , { 1 , 0x9fa32102 } , { 2 , 0x68dfa747 } ,
{ 0 , 0x7c74d78e } , { 1 , 0x9b79cc6b } , { 2 , 0xad957cc2 } , { 2 , 0x91acb818 }
2012-05-22 23:55:15 +02:00
} ;
2015-12-07 21:44:16 +01:00
CBlockIndex CreateBlockIndex ( int nHeight )
{
CBlockIndex index ;
index . nHeight = nHeight ;
index . pprev = chainActive . Tip ( ) ;
return index ;
}
bool TestSequenceLocks ( const CTransaction & tx , int flags )
{
LOCK ( mempool . cs ) ;
return CheckSequenceLocks ( tx , flags ) ;
}
2016-02-21 02:58:23 +01: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.
// Note that this test assumes blockprioritysize is 0.
2016-11-11 02:34:17 +01:00
void TestPackageSelection ( const CChainParams & chainparams , CScript scriptPubKey , std : : vector < CTransactionRef > & txFirst )
2016-02-21 02:58:23 +01: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
mempool . addUnchecked ( hashParentTx , entry . Fee ( 1000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
// 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 ( ) ;
mempool . addUnchecked ( hashMediumFeeTx , entry . Fee ( 10000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
// 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 ( ) ;
mempool . addUnchecked ( hashHighFeeTx , entry . Fee ( 50000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
2016-06-18 19:38:28 +02:00
std : : unique_ptr < CBlockTemplate > pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2016-11-11 02:26:00 +01: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-21 02:58:23 +01:00
2017-01-20 03:02:54 +01:00
// Test that a package below the block min tx fee doesn't get included
2016-02-21 02:58:23 +01:00
tx . vin [ 0 ] . prevout . hash = hashHighFeeTx ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 - 50000 ; // 0 fee
uint256 hashFreeTx = tx . GetHash ( ) ;
mempool . addUnchecked ( hashFreeTx , entry . Fee ( 0 ) . FromTx ( tx ) ) ;
size_t freeTxSize = : : GetSerializeSize ( tx , SER_NETWORK , PROTOCOL_VERSION ) ;
// Calculate a fee on child transaction that will put the package just
2017-01-20 03:02:54 +01:00
// below the block min tx fee (assuming 1 child tx of the same size).
CAmount feeToUse = blockMinFeeRate . GetFee ( 2 * freeTxSize ) - 1 ;
2016-02-21 02:58:23 +01:00
tx . vin [ 0 ] . prevout . hash = hashFreeTx ;
tx . vout [ 0 ] . nValue = 5000000000LL - 1000 - 50000 - feeToUse ;
uint256 hashLowFeeTx = tx . GetHash ( ) ;
mempool . addUnchecked ( hashLowFeeTx , entry . Fee ( feeToUse ) . FromTx ( tx ) ) ;
pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
// 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-11 02:26:00 +01:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashFreeTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashLowFeeTx ) ;
2016-02-21 02:58:23 +01: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
2016-08-15 13:10:57 +02:00
mempool . removeRecursive ( tx ) ;
2016-02-21 02:58:23 +01:00
tx . vout [ 0 ] . nValue - = 2 ; // Now we should be just over the min relay fee
hashLowFeeTx = tx . GetHash ( ) ;
mempool . addUnchecked ( hashLowFeeTx , entry . Fee ( feeToUse + 2 ) . FromTx ( tx ) ) ;
pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2016-11-11 02:26:00 +01:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ 4 ] - > GetHash ( ) = = hashFreeTx ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ 5 ] - > GetHash ( ) = = hashLowFeeTx ) ;
2016-02-21 02:58:23 +01: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 ( ) ;
mempool . addUnchecked ( hashFreeTx2 , entry . Fee ( 0 ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
// This tx can't be mined by itself
tx . vin [ 0 ] . prevout . hash = hashFreeTx2 ;
tx . vout . resize ( 1 ) ;
2017-01-20 03:02:54 +01:00
feeToUse = blockMinFeeRate . GetFee ( freeTxSize ) ;
2016-02-21 02:58:23 +01:00
tx . vout [ 0 ] . nValue = 5000000000LL - 100000000 - feeToUse ;
uint256 hashLowFeeTx2 = tx . GetHash ( ) ;
mempool . addUnchecked ( hashLowFeeTx2 , entry . Fee ( feeToUse ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
// Verify that this tx isn't selected.
for ( size_t i = 0 ; i < pblocktemplate - > block . vtx . size ( ) ; + + i ) {
2016-11-11 02:26:00 +01:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashFreeTx2 ) ;
BOOST_CHECK ( pblocktemplate - > block . vtx [ i ] - > GetHash ( ) ! = hashLowFeeTx2 ) ;
2016-02-21 02:58:23 +01: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
mempool . addUnchecked ( tx . GetHash ( ) , entry . Fee ( 10000 ) . FromTx ( tx ) ) ;
pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ;
2016-11-11 02:26:00 +01:00
BOOST_CHECK ( pblocktemplate - > block . vtx [ 8 ] - > GetHash ( ) = = hashLowFeeTx2 ) ;
2016-02-21 02:58:23 +01:00
}
2012-05-22 23:55:15 +02:00
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE ( CreateNewBlock_validity )
{
2016-07-28 20:27:19 +02:00
// Note that by default, these tests run with size accounting enabled.
2015-04-20 00:17:11 +02:00
const CChainParams & chainparams = Params ( CBaseChainParams : : MAIN ) ;
2017-04-18 17:52:01 +02:00
// changed this to dogecoin genesis pubkey script
CScript scriptPubKey = CScript ( ) < < ParseHex ( " 040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9 " ) < < OP_CHECKSIG ;
2016-06-18 19:38:28 +02:00
std : : unique_ptr < CBlockTemplate > pblocktemplate ;
2014-06-07 13:53:27 +02:00
CMutableTransaction tx , tx2 ;
2012-05-22 23:55:15 +02:00
CScript script ;
uint256 hash ;
2015-11-14 23:04:15 +01:00
TestMemPoolEntryHelper entry ;
entry . nFee = 11 ;
entry . dPriority = 111.0 ;
entry . nHeight = 11 ;
2012-05-22 23:55:15 +02:00
2013-12-02 04:11:21 +01:00
LOCK ( cs_main ) ;
2015-04-23 05:22:36 +02:00
fCheckpointsEnabled = false ;
2013-12-02 04:11:21 +01:00
2012-05-22 23:55:15 +02:00
// Simple block creation, nothing special yet:
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2012-05-22 23:55:15 +02:00
// We can't make transactions until we have inputs
// Therefore, load 100 blocks :)
2015-12-07 21:44:16 +01:00
int baseheight = 0 ;
2016-11-11 02:34:17 +01:00
std : : vector < CTransactionRef > txFirst ;
2012-05-22 23:55:15 +02:00
for ( unsigned int i = 0 ; i < sizeof ( blockinfo ) / sizeof ( * blockinfo ) ; + + i )
{
2017-04-18 17:52:01 +02:00
2012-12-19 21:21:21 +01:00
CBlock * pblock = & pblocktemplate - > block ; // pointer for convenience
2012-08-20 16:36:43 +02:00
pblock - > nVersion = 1 ;
2017-04-18 17:52:01 +02:00
pblock - > nTime = chainActive . Tip ( ) - > GetBlockTime ( ) + 60 ;
2016-11-11 02:26:00 +01:00
CMutableTransaction txCoinbase ( * pblock - > vtx [ 0 ] ) ;
2015-06-03 01:25:34 +02:00
txCoinbase . nVersion = 1 ;
2014-06-07 13:53:27 +02:00
txCoinbase . vin [ 0 ] . scriptSig = CScript ( ) ;
txCoinbase . vin [ 0 ] . scriptSig . push_back ( blockinfo [ i ] . extranonce ) ;
txCoinbase . vin [ 0 ] . scriptSig . push_back ( chainActive . Height ( ) ) ;
2016-11-18 21:15:01 +01:00
txCoinbase . vout . resize ( 1 ) ; // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
2014-06-07 13:53:27 +02:00
txCoinbase . vout [ 0 ] . scriptPubKey = CScript ( ) ;
2016-11-11 02:34:17 +01:00
pblock - > vtx [ 0 ] = MakeTransactionRef ( std : : move ( txCoinbase ) ) ;
2015-12-07 21:44:16 +01:00
if ( txFirst . size ( ) = = 0 )
baseheight = chainActive . Height ( ) ;
if ( txFirst . size ( ) < 4 )
2016-11-11 02:26:00 +01:00
txFirst . push_back ( pblock - > vtx [ 0 ] ) ;
2015-11-17 17:35:44 +01:00
pblock - > hashMerkleRoot = BlockMerkleRoot ( * pblock ) ;
2012-05-22 23:55:15 +02:00
pblock - > nNonce = blockinfo [ i ] . nonce ;
2016-12-04 09:17:30 +01:00
std : : shared_ptr < const CBlock > shared_pblock = std : : make_shared < const CBlock > ( * pblock ) ;
2016-12-04 09:23:17 +01:00
BOOST_CHECK ( ProcessNewBlock ( chainparams , shared_pblock , true , NULL ) ) ;
2012-05-22 23:55:15 +02:00
pblock - > hashPrevBlock = pblock - > GetHash ( ) ;
}
// Just to make sure we can still make simple blocks
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2012-05-22 23:55:15 +02:00
2016-04-04 17:17:23 +02:00
const CAmount BLOCKSUBSIDY = 50 * COIN ;
const CAmount LOWFEE = CENT ;
const CAmount HIGHFEE = COIN ;
const CAmount HIGHERFEE = 4 * COIN ;
2012-05-22 23:55:15 +02: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 17:17:23 +02:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY ;
2012-05-22 23:55:15 +02:00
for ( unsigned int i = 0 ; i < 1001 ; + + i )
{
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue - = LOWFEE ;
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2015-10-29 19:06:13 +01:00
bool spendsCoinbase = ( i = = 0 ) ? true : false ; // only first tx spends coinbase
2015-11-03 16:35:39 +01:00
// If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . FromTx ( tx ) ) ;
2015-11-03 16:35:39 +01:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2015-12-15 21:26:44 +01:00
BOOST_CHECK_THROW ( BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error ) ;
2015-11-03 16:35:39 +01:00
mempool . clear ( ) ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY ;
2015-11-03 16:35:39 +01:00
for ( unsigned int i = 0 ; i < 1001 ; + + i )
{
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue - = LOWFEE ;
2015-11-03 16:35:39 +01:00
hash = tx . GetHash ( ) ;
bool spendsCoinbase = ( i = = 0 ) ? true : false ; // only first tx spends coinbase
// If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
2016-01-03 18:54:50 +01:00
mempool . addUnchecked ( hash , entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . SigOpsCost ( 80 ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
// 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 17:17:23 +02:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY ;
2012-05-22 23:55:15 +02:00
for ( unsigned int i = 0 ; i < 128 ; + + i )
{
2016-04-06 14:29:19 +02:00
tx . vout [ 0 ] . nValue - = LOWFEE ;
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2015-10-29 19:06:13 +01:00
bool spendsCoinbase = ( i = = 0 ) ? true : false ; // only first tx spends coinbase
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
2015-11-03 16:35:39 +01:00
// orphan in mempool, template creation fails
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
2015-12-15 21:26:44 +01:00
BOOST_CHECK_THROW ( BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
// child with higher priority than parent
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 1 ] - > GetHash ( ) ;
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - HIGHFEE ;
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02: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 17:17:23 +02:00
tx . vout [ 0 ] . nValue = tx . vout [ 0 ] . nValue + BLOCKSUBSIDY - HIGHERFEE ; //First txn output + fresh coinbase - new txn fee
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( HIGHERFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
2015-11-03 16:35:39 +01:00
// coinbase in mempool, template creation fails
2012-05-22 23:55:15 +02: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 16:35:39 +01:00
// give it a fee so it'll get mined
2016-04-06 14:29:19 +02:00
mempool . addUnchecked ( hash , entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
2015-12-15 21:26:44 +01:00
BOOST_CHECK_THROW ( BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
2015-11-03 16:35:39 +01:00
// invalid (pre-p2sh) txn in mempool, template creation fails
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 0 ] . prevout . n = 0 ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - LOWFEE ;
2012-05-22 23:55:15 +02:00
script = CScript ( ) < < OP_0 ;
2014-09-25 04:24:46 +02:00
tx . vout [ 0 ] . scriptPubKey = GetScriptForDestination ( CScriptID ( script ) ) ;
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = hash ;
2015-10-29 07:11:24 +01:00
tx . vin [ 0 ] . scriptSig = CScript ( ) < < std : : vector < unsigned char > ( script . begin ( ) , script . end ( ) ) ;
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue - = LOWFEE ;
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( LOWFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
2015-12-15 21:26:44 +01:00
BOOST_CHECK_THROW ( BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
2015-11-03 16:35:39 +01:00
// double spend txn pair in mempool, template creation fails
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - HIGHFEE ;
2012-05-22 23:55:15 +02:00
tx . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_1 ;
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02:00
tx . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_2 ;
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2015-12-15 21:26:44 +01:00
BOOST_CHECK_THROW ( BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) , std : : runtime_error ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
// subsidy changing
2013-10-10 23:07:44 +02:00
int nHeight = chainActive . Height ( ) ;
2016-02-15 05:13:27 +01:00
// Create an actual 209999-long block chain (without valid blocks).
while ( chainActive . Tip ( ) - > nHeight < 209999 ) {
CBlockIndex * prev = chainActive . Tip ( ) ;
CBlockIndex * next = new CBlockIndex ( ) ;
next - > phashBlock = new uint256 ( GetRandHash ( ) ) ;
pcoinsTip - > SetBestBlock ( next - > GetBlockHash ( ) ) ;
next - > pprev = prev ;
next - > nHeight = prev - > nHeight + 1 ;
next - > BuildSkip ( ) ;
chainActive . SetTip ( next ) ;
}
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2016-02-15 05:13:27 +01:00
// Extend to a 210000-long block chain.
while ( chainActive . Tip ( ) - > nHeight < 210000 ) {
CBlockIndex * prev = chainActive . Tip ( ) ;
CBlockIndex * next = new CBlockIndex ( ) ;
next - > phashBlock = new uint256 ( GetRandHash ( ) ) ;
pcoinsTip - > SetBestBlock ( next - > GetBlockHash ( ) ) ;
next - > pprev = prev ;
next - > nHeight = prev - > nHeight + 1 ;
next - > BuildSkip ( ) ;
chainActive . SetTip ( next ) ;
}
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2016-02-15 05:13:27 +01:00
// Delete the dummy blocks again.
while ( chainActive . Tip ( ) - > nHeight > nHeight ) {
CBlockIndex * del = chainActive . Tip ( ) ;
chainActive . SetTip ( del - > pprev ) ;
pcoinsTip - > SetBestBlock ( del - > pprev - > GetBlockHash ( ) ) ;
delete del - > phashBlock ;
delete del ;
}
2013-09-19 00:01:36 +02:00
2014-01-27 03:50:15 +01:00
// non-final txs in mempool
2017-04-18 17:52:01 +02:00
// changed to 60 second block interval for consistency
SetMockTime ( chainActive . Tip ( ) - > GetBlockTime ( ) + 60 ) ;
2015-12-07 21:44:16 +01:00
int flags = LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST ;
// height map
std : : vector < int > prevheights ;
2014-01-27 03:50:15 +01:00
2015-12-07 21:44:16 +01: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-27 03:50:15 +01:00
tx . vin [ 0 ] . scriptSig = CScript ( ) < < OP_1 ;
2015-12-07 21:44:16 +01:00
tx . vin [ 0 ] . nSequence = chainActive . Tip ( ) - > nHeight + 1 ; // txFirst[0] is the 2nd block
prevheights [ 0 ] = baseheight + 1 ;
tx . vout . resize ( 1 ) ;
2016-04-04 17:17:23 +02:00
tx . vout [ 0 ] . nValue = BLOCKSUBSIDY - HIGHFEE ;
2014-01-27 03:50:15 +01:00
tx . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_1 ;
2015-12-07 21:44:16 +01:00
tx . nLockTime = 0 ;
2014-01-27 03:50:15 +01:00
hash = tx . GetHash ( ) ;
2016-04-04 17:17:23 +02:00
mempool . addUnchecked ( hash , entry . Fee ( HIGHFEE ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2015-12-07 21:44:16 +01:00
BOOST_CHECK ( CheckFinalTx ( tx , flags ) ) ; // Locktime passes
BOOST_CHECK ( ! TestSequenceLocks ( tx , flags ) ) ; // Sequence locks fail
BOOST_CHECK ( SequenceLocks ( tx , flags , & prevheights , CreateBlockIndex ( chainActive . Tip ( ) - > nHeight + 2 ) ) ) ; // Sequence locks pass on 2nd block
// relative time locked
tx . vin [ 0 ] . prevout . hash = txFirst [ 1 ] - > GetHash ( ) ;
tx . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG | ( ( ( chainActive . Tip ( ) - > GetMedianTimePast ( ) + 1 - chainActive [ 1 ] - > GetMedianTimePast ( ) ) > > CTxIn : : SEQUENCE_LOCKTIME_GRANULARITY ) + 1 ) ; // txFirst[1] is the 3rd block
prevheights [ 0 ] = baseheight + 2 ;
hash = tx . GetHash ( ) ;
mempool . addUnchecked ( hash , entry . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
BOOST_CHECK ( CheckFinalTx ( tx , flags ) ) ; // Locktime passes
BOOST_CHECK ( ! TestSequenceLocks ( tx , flags ) ) ; // Sequence locks fail
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; i + + )
chainActive . Tip ( ) - > GetAncestor ( chainActive . Tip ( ) - > nHeight - i ) - > nTime + = 512 ; //Trick the MedianTimePast
BOOST_CHECK ( SequenceLocks ( tx , flags , & prevheights , CreateBlockIndex ( chainActive . Tip ( ) - > nHeight + 1 ) ) ) ; // Sequence locks pass 512 seconds later
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; i + + )
chainActive . Tip ( ) - > GetAncestor ( chainActive . Tip ( ) - > nHeight - i ) - > nTime - = 512 ; //undo tricked MTP
// absolute height locked
tx . vin [ 0 ] . prevout . hash = txFirst [ 2 ] - > GetHash ( ) ;
tx . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_FINAL - 1 ;
prevheights [ 0 ] = baseheight + 3 ;
tx . nLockTime = chainActive . Tip ( ) - > nHeight + 1 ;
hash = tx . GetHash ( ) ;
mempool . addUnchecked ( hash , entry . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
BOOST_CHECK ( ! CheckFinalTx ( tx , flags ) ) ; // Locktime fails
BOOST_CHECK ( TestSequenceLocks ( tx , flags ) ) ; // Sequence locks pass
BOOST_CHECK ( IsFinalTx ( tx , chainActive . Tip ( ) - > nHeight + 2 , chainActive . Tip ( ) - > GetMedianTimePast ( ) ) ) ; // Locktime passes on 2nd block
// absolute time locked
tx . vin [ 0 ] . prevout . hash = txFirst [ 3 ] - > GetHash ( ) ;
tx . nLockTime = chainActive . Tip ( ) - > GetMedianTimePast ( ) ;
prevheights . resize ( 1 ) ;
prevheights [ 0 ] = baseheight + 4 ;
hash = tx . GetHash ( ) ;
mempool . addUnchecked ( hash , entry . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
BOOST_CHECK ( ! CheckFinalTx ( tx , flags ) ) ; // Locktime fails
BOOST_CHECK ( TestSequenceLocks ( tx , flags ) ) ; // Sequence locks pass
BOOST_CHECK ( IsFinalTx ( tx , chainActive . Tip ( ) - > nHeight + 2 , chainActive . Tip ( ) - > GetMedianTimePast ( ) + 1 ) ) ; // Locktime passes 1 second later
// mempool-dependent transactions (not added)
tx . vin [ 0 ] . prevout . hash = hash ;
prevheights [ 0 ] = chainActive . Tip ( ) - > nHeight + 1 ;
tx . nLockTime = 0 ;
tx . vin [ 0 ] . nSequence = 0 ;
BOOST_CHECK ( CheckFinalTx ( tx , flags ) ) ; // Locktime passes
BOOST_CHECK ( TestSequenceLocks ( tx , flags ) ) ; // Sequence locks pass
tx . vin [ 0 ] . nSequence = 1 ;
BOOST_CHECK ( ! TestSequenceLocks ( tx , flags ) ) ; // Sequence locks fail
tx . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG ;
BOOST_CHECK ( TestSequenceLocks ( tx , flags ) ) ; // Sequence locks pass
tx . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_LOCKTIME_TYPE_FLAG | 1 ;
BOOST_CHECK ( ! TestSequenceLocks ( tx , flags ) ) ; // Sequence locks fail
2014-01-27 03:50:15 +01:00
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2014-01-27 03:50:15 +01:00
2015-12-07 21:44:16 +01: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
BOOST_CHECK_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 3 ) ;
// However if we advance height by 1 and time by 512, all of them should be mined
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; i + + )
chainActive . Tip ( ) - > GetAncestor ( chainActive . Tip ( ) - > nHeight - i ) - > nTime + = 512 ; //Trick the MedianTimePast
2014-01-27 03:50:15 +01:00
chainActive . Tip ( ) - > nHeight + + ;
2017-04-18 17:52:01 +02:00
// changed to 60 second block interval for consistency
SetMockTime ( chainActive . Tip ( ) - > GetBlockTime ( ) + 60 ) ;
2014-01-27 03:50:15 +01:00
2015-12-15 21:26:44 +01:00
BOOST_CHECK ( pblocktemplate = BlockAssembler ( chainparams ) . CreateNewBlock ( scriptPubKey ) ) ;
2015-12-07 21:44:16 +01:00
BOOST_CHECK_EQUAL ( pblocktemplate - > block . vtx . size ( ) , 5 ) ;
2014-01-27 03:50:15 +01:00
chainActive . Tip ( ) - > nHeight - - ;
SetMockTime ( 0 ) ;
2014-09-04 21:23:42 +02:00
mempool . clear ( ) ;
2014-01-27 03:50:15 +01:00
2016-02-21 02:58:23 +01:00
TestPackageSelection ( chainparams , scriptPubKey , txFirst ) ;
2015-04-23 05:22:36 +02:00
fCheckpointsEnabled = true ;
2012-05-22 23:55:15 +02:00
}
2011-09-27 20:16:07 +02:00
BOOST_AUTO_TEST_SUITE_END ( )