diff --git a/src/miner.h b/src/miner.h --- a/src/miner.h +++ b/src/miner.h @@ -213,10 +213,10 @@ }; /** Modify the extranonce in a block */ -void IncrementExtraNonce(CBlock *pblock, const CBlockIndex *pindexPrev, +void IncrementExtraNonce(const Config &config, CBlock *pblock, + const CBlockIndex *pindexPrev, unsigned int &nExtraNonce); int64_t UpdateTime(CBlockHeader *pblock, const Consensus::Params &consensusParams, const CBlockIndex *pindexPrev); - #endif // BITCOIN_MINER_H diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -33,6 +33,8 @@ #include #include +static const int MAX_COINBASE_SCRIPTSIG_SIZE = 100; + ////////////////////////////////////////////////////////////////////////////// // // BitcoinMiner @@ -142,6 +144,14 @@ blockFinished = false; } +static const std::vector +getExcessiveBlockSizeSig(const Config &config) { + std::string cbmsg = "/EB" + getSubVersionEB(config.GetMaxBlockSize()) + "/"; + const char *cbcstr = cbmsg.c_str(); + std::vector vec(cbcstr, cbcstr + cbmsg.size()); + return vec; +} + std::unique_ptr BlockAssembler::CreateNewBlock(const CScript &scriptPubKeyIn) { int64_t nTimeStart = GetTimeMicros(); @@ -199,7 +209,7 @@ coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; - pblock->vtx[0] = MakeTransactionRef(coinbaseTx); + pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx)); pblocktemplate->vTxFees[0] = -nFees; uint64_t nSerializeSize = @@ -658,7 +668,8 @@ } } -void IncrementExtraNonce(CBlock *pblock, const CBlockIndex *pindexPrev, +void IncrementExtraNonce(const Config &config, CBlock *pblock, + const CBlockIndex *pindexPrev, unsigned int &nExtraNonce) { // Update nExtraNonce static uint256 hashPrevBlock; @@ -671,8 +682,10 @@ unsigned int nHeight = pindexPrev->nHeight + 1; CMutableTransaction txCoinbase(*pblock->vtx[0]); txCoinbase.vin[0].scriptSig = - (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; - assert(txCoinbase.vin[0].scriptSig.size() <= 100); + (CScript() << nHeight << CScriptNum(nExtraNonce) + << getExcessiveBlockSizeSig(config)) + + COINBASE_FLAGS; + assert(txCoinbase.vin[0].scriptSig.size() <= MAX_COINBASE_SCRIPTSIG_SIZE); pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -130,7 +130,7 @@ CBlock *pblock = &pblocktemplate->block; { LOCK(cs_main); - IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); + IncrementExtraNonce(config, pblock, chainActive.Tip(), nExtraNonce); } while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -202,6 +202,42 @@ BOOST_CHECK(pblocktemplate->block.vtx[8]->GetId() == hashLowFeeTx2); } +void TestCoinbaseMessageEB(uint64_t eb, std::string cbmsg) { + + GlobalConfig config; + config.SetMaxBlockSize(eb); + const CChainParams &chainparams = config.GetChainParams(); + + CScript scriptPubKey = + CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909" + "a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112" + "de5c384df7ba0b8d578a4c702b6bf11d5f") + << OP_CHECKSIG; + + std::unique_ptr pblocktemplate = + BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); + + CBlock *pblock = &pblocktemplate->block; + + // IncrementExtraNonce creates a valid coinbase and merkleRoot + unsigned int extraNonce = 0; + IncrementExtraNonce(config, pblock, chainActive.Tip(), extraNonce); + unsigned int nHeight = chainActive.Tip()->nHeight + 1; + std::vector vec(cbmsg.begin(), cbmsg.end()); + BOOST_CHECK(pblock->vtx[0]->vin[0].scriptSig == + ((CScript() << nHeight << CScriptNum(extraNonce) << vec) + + COINBASE_FLAGS)); +} + +// Coinbase scriptSig has to contains the correct EB value +// converted to MB, rounded down to the first decimal +BOOST_AUTO_TEST_CASE(CheckCoinbase_EB) { + TestCoinbaseMessageEB(1000001, "/EB1.0/"); + TestCoinbaseMessageEB(2000000, "/EB2.0/"); + TestCoinbaseMessageEB(8000000, "/EB8.0/"); + TestCoinbaseMessageEB(8320000, "/EB8.3/"); +} + // 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. diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -117,8 +117,9 @@ CBlock TestChain100Setup::CreateAndProcessBlock( const std::vector &txns, const CScript &scriptPubKey) { const CChainParams &chainparams = Params(); + const Config &config = GetConfig(); std::unique_ptr pblocktemplate = - BlockAssembler(GetConfig(), chainparams).CreateNewBlock(scriptPubKey); + BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); CBlock &block = pblocktemplate->block; // Replace mempool-selected txns with just coinbase plus passed-in txns: @@ -128,7 +129,7 @@ } // IncrementExtraNonce creates a valid coinbase and merkleRoot unsigned int extraNonce = 0; - IncrementExtraNonce(&block, chainActive.Tip(), extraNonce); + IncrementExtraNonce(config, &block, chainActive.Tip(), extraNonce); while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus()))