2015-12-13 14:51:43 +01:00
// Copyright (c) 2011-2015 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"
2017-08-09 02:19:06 +02:00
# include "validation.h"
2016-03-03 22:24:32 +01:00
# include "masternode-payments.h"
2013-04-13 07:13:08 +02:00
# include "miner.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
2016-03-03 20:20:32 +01:00
# include "test/test_dash.h"
2011-09-27 20:16:07 +02:00
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
2012-05-22 23:55:15 +02:00
static
struct {
unsigned char extranonce ;
unsigned int nonce ;
} blockinfo [ ] = {
2016-01-27 13:23:36 +01:00
{ 0 , 0x009c5477 } , { 0 , 0x00a94582 } , { 0 , 0x00af3d7f } , { 0 , 0x00d0b721 } ,
{ 0 , 0x00d53e10 } , { 0 , 0x00f52f0f } , { 0 , 0x00fb5876 } , { 0 , 0x0117fb12 } ,
{ 0 , 0x011f930b } , { 0 , 0x013365d2 } , { 0 , 0x0151737e } , { 0 , 0x0152cdd0 } ,
{ 0 , 0x01758d20 } , { 0 , 0x0178d509 } , { 0 , 0x0192103c } , { 0 , 0x01a3f1b8 } ,
{ 0 , 0x01abc9c7 } , { 0 , 0x01d2f50c } , { 0 , 0x01eebad1 } , { 0 , 0x01ef3419 } ,
{ 0 , 0x01f3f154 } , { 0 , 0x01fa6245 } , { 0 , 0x0224e780 } , { 0 , 0x02281625 } ,
{ 0 , 0x023a4d10 } , { 0 , 0x0251d3cf } , { 0 , 0x02555277 } , { 0 , 0x02648a41 } ,
{ 0 , 0x0280795e } , { 0 , 0x02a3a585 } , { 0 , 0x02ade34a } , { 0 , 0x02b02b02 } ,
{ 0 , 0x02c9dc32 } , { 0 , 0x02da9867 } , { 0 , 0x02e4126e } , { 0 , 0x02e738c7 } ,
{ 0 , 0x02f5c6a9 } , { 0 , 0x0307bb0f } , { 0 , 0x0328ea58 } , { 0 , 0x034fe819 } ,
{ 0 , 0x036c6fcb } , { 0 , 0x039b8e11 } , { 0 , 0x039fec90 } , { 0 , 0x03a268ff } ,
{ 0 , 0x03d37583 } , { 0 , 0x03d6a9a7 } , { 0 , 0x03e7a013 } , { 0 , 0x03f01ebe } ,
{ 0 , 0x0437104d } , { 0 , 0x043d0af7 } , { 0 , 0x043d824d } , { 0 , 0x043f50fc } ,
{ 0 , 0x044def8c } , { 0 , 0x0452309a } , { 0 , 0x04538bd3 } , { 0 , 0x0459286b } ,
{ 0 , 0x045bc734 } , { 0 , 0x045c878a } , { 0 , 0x0485d3ba } , { 0 , 0x048a64e5 } ,
{ 0 , 0x048d6ae1 } , { 0 , 0x048dcfec } , { 0 , 0x049d2c79 } , { 0 , 0x04ade791 } ,
{ 0 , 0x04b75856 } , { 0 , 0x04c1f89e } , { 0 , 0x04c2f731 } , { 0 , 0x04ca0376 } ,
{ 0 , 0x04ca102a } , { 0 , 0x04cbdfe5 } , { 0 , 0x04cbe35a } , { 0 , 0x04ccfa95 } ,
{ 0 , 0x04dcd6e4 } , { 0 , 0x05066d8b } , { 0 , 0x05150274 } , { 0 , 0x051dcfa0 } ,
{ 0 , 0x052a4c40 } , { 0 , 0x05310c4e } , { 0 , 0x05452f69 } , { 0 , 0x05517592 } ,
{ 0 , 0x05543eb8 } , { 0 , 0x05549dc7 } , { 0 , 0x05732695 } , { 0 , 0x057b00d3 } ,
{ 0 , 0x0584760d } , { 0 , 0x059ca419 } , { 0 , 0x05b23b58 } , { 0 , 0x05c69745 } ,
{ 0 , 0x05e31a12 } , { 0 , 0x05e932d5 } , { 0 , 0x05ef8400 } , { 0 , 0x05f0bdf6 } ,
{ 0 , 0x05f93997 } , { 0 , 0x05ff2978 } , { 0 , 0x06030233 } , { 0 , 0x0627d615 } ,
{ 0 , 0x0644a441 } , { 0 , 0x06518661 } , { 0 , 0x06805ef2 } , { 0 , 0x068c43dd } ,
{ 0 , 0x069cca16 } , { 0 , 0x06acbf10 } , { 0 , 0x06c2d607 } , { 0 , 0x06d9ea08 } ,
{ 0 , 0x0700d639 } , { 0 , 0x07083d86 } , { 0 , 0x071cc39d } , { 0 , 0x072c3cb8 } ,
{ 0 , 0x07665a0f } , { 0 , 0x07741214 } ,
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 ) ;
}
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 )
{
2015-04-20 00:17:11 +02:00
const CChainParams & chainparams = Params ( CBaseChainParams : : MAIN ) ;
2013-12-09 09:22:15 +01:00
CScript scriptPubKey = CScript ( ) < < ParseHex ( " 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f " ) < < OP_CHECKSIG ;
2012-12-19 21:21:21 +01:00
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
2017-08-25 14:57:05 +02:00
// force UpdatedBlockTip to initialize nCachedBlockHeight
2017-09-19 16:51:38 +02:00
mnpayments . UpdatedBlockTip ( chainActive . Tip ( ) , * connman ) ;
2016-03-03 22:24:32 +01:00
2012-05-22 23:55:15 +02:00
// Simple block creation, nothing special yet:
2015-04-17 14:19:52 +02:00
BOOST_CHECK ( pblocktemplate = CreateNewBlock ( chainparams , 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 ;
2012-05-22 23:55:15 +02:00
std : : vector < CTransaction * > txFirst ;
for ( unsigned int i = 0 ; i < sizeof ( blockinfo ) / sizeof ( * blockinfo ) ; + + i )
{
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 ;
2013-10-10 23:07:44 +02:00
pblock - > nTime = chainActive . Tip ( ) - > GetMedianTimePast ( ) + 1 ;
2014-06-07 13:53:27 +02: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 ( ) ) ;
txCoinbase . vout [ 0 ] . scriptPubKey = CScript ( ) ;
pblock - > vtx [ 0 ] = CTransaction ( txCoinbase ) ;
2015-12-07 21:44:16 +01:00
if ( txFirst . size ( ) = = 0 )
baseheight = chainActive . Height ( ) ;
if ( txFirst . size ( ) < 4 )
2012-05-22 23:55:15 +02:00
txFirst . push_back ( new CTransaction ( 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 ;
2017-08-02 20:35:04 +02:00
BOOST_CHECK ( ProcessNewBlock ( chainparams , pblock , true , NULL , NULL ) ) ;
2012-05-22 23:55:15 +02:00
pblock - > hashPrevBlock = pblock - > GetHash ( ) ;
}
2012-12-19 21:21:21 +01:00
delete pblocktemplate ;
2012-05-22 23:55:15 +02:00
// Just to make sure we can still make simple blocks
2015-04-17 14:19:52 +02:00
BOOST_CHECK ( pblocktemplate = CreateNewBlock ( chainparams , scriptPubKey ) ) ;
2013-09-19 00:01:36 +02:00
delete pblocktemplate ;
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-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 50000000000LL ;
2012-05-22 23:55:15 +02:00
for ( unsigned int i = 0 ; i < 1001 ; + + i )
{
tx . vout [ 0 ] . nValue - = 1000000 ;
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
mempool . addUnchecked ( hash , entry . Fee ( 1000000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2015-11-03 16:35:39 +01:00
BOOST_CHECK_THROW ( CreateNewBlock ( chainparams , scriptPubKey ) , std : : runtime_error ) ;
mempool . clear ( ) ;
tx . vin [ 0 ] . prevout . hash = txFirst [ 0 ] - > GetHash ( ) ;
2016-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 50000000000LL ;
2015-11-03 16:35:39 +01:00
for ( unsigned int i = 0 ; i < 1001 ; + + i )
{
tx . vout [ 0 ] . nValue - = 1000000 ;
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
mempool . addUnchecked ( hash , entry . Fee ( 1000000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . SigOps ( 20 ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2015-04-17 14:19:52 +02:00
BOOST_CHECK ( pblocktemplate = CreateNewBlock ( chainparams , scriptPubKey ) ) ;
2012-12-19 21:21:21 +01:00
delete pblocktemplate ;
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-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 50000000000LL ;
2012-05-22 23:55:15 +02:00
for ( unsigned int i = 0 ; i < 128 ; + + i )
{
tx . vout [ 0 ] . nValue - = 10000000 ;
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
mempool . addUnchecked ( hash , entry . Fee ( 1000000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( spendsCoinbase ) . FromTx ( tx ) ) ;
2012-05-22 23:55:15 +02:00
tx . vin [ 0 ] . prevout . hash = hash ;
}
2015-04-17 14:19:52 +02:00
BOOST_CHECK ( pblocktemplate = CreateNewBlock ( chainparams , scriptPubKey ) ) ;
2012-12-19 21:21:21 +01:00
delete pblocktemplate ;
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 ( ) ;
2015-11-03 16:35:39 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 1000000 ) . Time ( GetTime ( ) ) . FromTx ( tx ) ) ;
BOOST_CHECK_THROW ( CreateNewBlock ( chainparams , 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-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 49000000000LL ;
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2016-03-03 20:20:32 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 1000000000LL ) . 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-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 59000000000LL ;
2012-05-22 23:55:15 +02:00
hash = tx . GetHash ( ) ;
2016-03-03 20:20:32 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 4000000000LL ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2015-04-17 14:19:52 +02:00
BOOST_CHECK ( pblocktemplate = CreateNewBlock ( chainparams , scriptPubKey ) ) ;
2012-12-19 21:21:21 +01:00
delete pblocktemplate ;
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
mempool . addUnchecked ( hash , entry . Fee ( 100000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
BOOST_CHECK_THROW ( CreateNewBlock ( chainparams , 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-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 49000000000LL ;
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-03-03 20:20:32 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 100000000L ) . 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 ( ) ) ;
2012-05-22 23:55:15 +02:00
tx . vout [ 0 ] . nValue - = 1000000 ;
hash = tx . GetHash ( ) ;
2015-11-03 16:35:39 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 1000000 ) . Time ( GetTime ( ) ) . SpendsCoinbase ( false ) . FromTx ( tx ) ) ;
BOOST_CHECK_THROW ( CreateNewBlock ( chainparams , 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-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 49000000000LL ;
2012-05-22 23:55:15 +02:00
tx . vout [ 0 ] . scriptPubKey = CScript ( ) < < OP_1 ;
hash = tx . GetHash ( ) ;
2016-03-03 20:20:32 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 1000000000L ) . 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-03-03 20:20:32 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 1000000000L ) . Time ( GetTime ( ) ) . SpendsCoinbase ( true ) . FromTx ( tx ) ) ;
2015-11-03 16:35:39 +01:00
BOOST_CHECK_THROW ( CreateNewBlock ( chainparams , scriptPubKey ) , std : : runtime_error ) ;
2012-05-22 23:55:15 +02:00
mempool . clear ( ) ;
// subsidy changing
2016-03-03 20:20:32 +01:00
// int nHeight = chainActive.Height();
2016-07-04 07:42:50 +02: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);
// }
2016-03-03 20:20:32 +01:00
// BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey));
// delete pblocktemplate;
2016-07-04 07:42:50 +02: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);
// }
2016-03-03 20:20:32 +01:00
// BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey));
// delete pblocktemplate;
2016-07-04 07:42:50 +02: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
SetMockTime ( chainActive . Tip ( ) - > GetMedianTimePast ( ) + 1 ) ;
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-03-03 20:20:32 +01:00
tx . vout [ 0 ] . nValue = 49000000000LL ;
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-03-03 20:20:32 +01:00
mempool . addUnchecked ( hash , entry . Fee ( 1000000000L ) . 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 ( ) ;
2017-09-21 15:58:23 +02:00
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
2015-12-07 21:44:16 +01:00
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 + + )
2017-09-21 15:58:23 +02:00
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
2015-12-07 21:44:16 +01:00
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; i + + )
2017-09-21 15:58:23 +02:00
chainActive . Tip ( ) - > GetAncestor ( chainActive . Tip ( ) - > nHeight - i ) - > nTime - = 512 ; //undo tricked MTP
2015-12-07 21:44:16 +01:00
// 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-04-17 14:19:52 +02:00
BOOST_CHECK ( pblocktemplate = CreateNewBlock ( chainparams , 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 ) ;
2014-01-27 03:50:15 +01:00
delete pblocktemplate ;
2017-09-21 15:58:23 +02:00
// However if we advance height by 1 and time by 512, all of them should be mined
2015-12-07 21:44:16 +01:00
for ( int i = 0 ; i < CBlockIndex : : nMedianTimeSpan ; i + + )
2017-09-21 15:58:23 +02:00
chainActive . Tip ( ) - > GetAncestor ( chainActive . Tip ( ) - > nHeight - i ) - > nTime + = 512 ; //Trick the MedianTimePast
2014-01-27 03:50:15 +01:00
chainActive . Tip ( ) - > nHeight + + ;
2015-12-07 21:44:16 +01:00
SetMockTime ( chainActive . Tip ( ) - > GetMedianTimePast ( ) + 1 ) ;
2014-01-27 03:50:15 +01:00
2015-04-17 14:19:52 +02:00
BOOST_CHECK ( pblocktemplate = CreateNewBlock ( chainparams , 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
delete pblocktemplate ;
chainActive . Tip ( ) - > nHeight - - ;
SetMockTime ( 0 ) ;
2014-09-04 21:23:42 +02:00
mempool . clear ( ) ;
2014-01-27 03:50:15 +01:00
2013-09-19 00:01:36 +02:00
BOOST_FOREACH ( CTransaction * tx , txFirst )
delete tx ;
2014-01-27 03:50:15 +01:00
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 ( )