diff --git a/qa/rpc-tests/abc-rpc.py b/qa/rpc-tests/abc-rpc.py --- a/qa/rpc-tests/abc-rpc.py +++ b/qa/rpc-tests/abc-rpc.py @@ -60,8 +60,7 @@ try: self.nodes[0].setexcessiveblock(LEGACY_MAX_BLOCK_SIZE) except JSONRPCException as e: - assert("Invalid parameter, excessiveblock must be larger than %d" % LEGACY_MAX_BLOCK_SIZE - in e.error['message']) + assert("Excessive block size must be > 1,000,000 bytes (1MB)" in e.error['message']) else: raise AssertionError("Must not accept excessiveblock values <= %d bytes" % LEGACY_MAX_BLOCK_SIZE) getsize = self.nodes[0].getexcessiveblock() diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -117,8 +117,11 @@ netbase.h \ netmessagemaker.h \ noui.h \ + policy/bip101policy.h \ + policy/blocksizepolicy.h \ policy/fees.h \ policy/policy.h \ + policy/staticblocksize.h \ pow.h \ protocol.h \ random.h \ @@ -198,7 +201,9 @@ net_processing.cpp \ noui.cpp \ policy/fees.cpp \ + policy/bip101policy.cpp \ policy/policy.cpp \ + policy/staticblocksize.cpp \ pow.cpp \ rest.cpp \ rpc/abc.cpp \ diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -54,7 +54,7 @@ (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty())) return READ_STATUS_INVALID; if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > - config->GetMaxBlockSize() / MIN_TRANSACTION_SIZE) + config->GetBlockSizeDoSLimit() / MIN_TRANSACTION_SIZE) return READ_STATUS_INVALID; assert(header.IsNull() && txn_available.empty()); diff --git a/src/config.h b/src/config.h --- a/src/config.h +++ b/src/config.h @@ -7,26 +7,37 @@ #include +#include "policy/blocksizepolicy.h" #include +#include class CChainParams; -class Config : public boost::noncopyable { +class Config : public BlockSizePolicy, public boost::noncopyable { public: - virtual bool SetMaxBlockSize(uint64_t maxBlockSize) = 0; - virtual uint64_t GetMaxBlockSize() const = 0; + virtual void SetBlockSizePolicy(std::unique_ptr) = 0; virtual bool SetUAHFStartTime(int64_t uahfStartTime) = 0; virtual int64_t GetUAHFStartTime() const = 0; virtual const CChainParams &GetChainParams() const = 0; + virtual ~Config() = 0; }; +inline Config::~Config() {} class GlobalConfig final : public Config { public: - bool SetMaxBlockSize(uint64_t maxBlockSize); - uint64_t GetMaxBlockSize() const; + GlobalConfig(); + void SetBlockSizePolicy(std::unique_ptr) override; bool SetUAHFStartTime(int64_t uahfStartTime); int64_t GetUAHFStartTime() const; const CChainParams &GetChainParams() const; + + // BlockSizePolicy interface + uint64_t GetMaxBlockSize(uint64_t nBlockTimestamp) const override; + uint64_t GuessWithinBlockSize() const override; + uint64_t GetBlockSizeDoSLimit() const override; + +private: + std::unique_ptr blockSizePolicy; }; // Temporary woraround. diff --git a/src/config.cpp b/src/config.cpp --- a/src/config.cpp +++ b/src/config.cpp @@ -6,20 +6,14 @@ #include "chainparams.h" #include "consensus/consensus.h" #include "globals.h" +#include "policy/blocksizepolicy.h" +#include "policy/staticblocksize.h" -bool GlobalConfig::SetMaxBlockSize(uint64_t maxBlockSize) { - // Do not allow maxBlockSize to be set below historic 1MB limit - // It cannot be equal either because of the "must be big" UAHF rule. - if (maxBlockSize <= LEGACY_MAX_BLOCK_SIZE) { - return false; - } +GlobalConfig::GlobalConfig() + : blockSizePolicy(new StaticBlockSize(DEFAULT_MAX_BLOCK_SIZE)) {} - nMaxBlockSize = maxBlockSize; - return true; -} - -uint64_t GlobalConfig::GetMaxBlockSize() const { - return nMaxBlockSize; +void GlobalConfig::SetBlockSizePolicy(std::unique_ptr p) { + blockSizePolicy = std::move(p); } bool GlobalConfig::SetUAHFStartTime(int64_t uahfStartTime) { @@ -31,6 +25,20 @@ return nUAHFStartTime; } +uint64_t GlobalConfig::GetMaxBlockSize(uint64_t nBlockTimestamp) const { + assert(blockSizePolicy); + return blockSizePolicy->GetMaxBlockSize(nBlockTimestamp); +} + +uint64_t GlobalConfig::GuessWithinBlockSize() const { + assert(blockSizePolicy); + return blockSizePolicy->GuessWithinBlockSize(); +} +uint64_t GlobalConfig::GetBlockSizeDoSLimit() const { + assert(blockSizePolicy); + return blockSizePolicy->GetBlockSizeDoSLimit(); +} + const CChainParams &GlobalConfig::GetChainParams() const { return Params(); } diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -24,7 +24,9 @@ #include "net.h" #include "net_processing.h" #include "netbase.h" +#include "policy/bip101policy.h" #include "policy/policy.h" +#include "policy/staticblocksize.h" #include "rpc/register.h" #include "rpc/server.h" #include "scheduler.h" @@ -1392,11 +1394,21 @@ nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS; // Configure excessive block size. - const uint64_t nProposedExcessiveBlockSize = - GetArg("-excessiveblocksize", DEFAULT_MAX_BLOCK_SIZE); - if (!config.SetMaxBlockSize(nProposedExcessiveBlockSize)) { - return InitError( - _("Excessive block size must be > 1,000,000 bytes (1MB)")); + try { + const uint64_t nProposedExcessiveBlockSize = + GetArg("-excessiveblocksize", DEFAULT_MAX_BLOCK_SIZE); + config.SetBlockSizePolicy(std::unique_ptr( + new StaticBlockSize(nProposedExcessiveBlockSize))); + } catch (const std::invalid_argument &err) { + return InitError(err.what()); + } + + if (GetBoolArg("-bip101", false)) { + config.SetBlockSizePolicy(std::unique_ptr( + new BIP101Policy(config.GetUAHFStartTime()))); + if (GetBoolArg("-excessiveblocksize", false)) + return InitError( + "Not possible to combine -bip101 and -exessiveblocksize"); } // Check blockmaxsize does not exceed maximum accepted block size. @@ -1407,11 +1419,11 @@ const bool maxGeneratedBlockSizeTooSmall = nProposedMaxGeneratedBlockSize <= LEGACY_MAX_BLOCK_SIZE; const bool maxGeneratedBlockSizeTooBig = - nProposedMaxGeneratedBlockSize > config.GetMaxBlockSize(); + nProposedMaxGeneratedBlockSize > config.GuessWithinBlockSize(); if (maxGeneratedBlockSizeTooSmall || maxGeneratedBlockSizeTooBig) { auto msg = _("Max generated block size (blockmaxsize) cannot be lower than " - "1MB or exceed the excessive block size (excessiveblocksize)"); + "1MB or exceed the size in the configured block size policy"); if (maxGeneratedBlockSizeTooBig || !IsArgSet("-allowsmallgeneratedblocksize")) { return InitError(msg); diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -89,9 +89,13 @@ } // Limit size to between 1K and MaxBlockSize-1K for sanity: - nMaxGeneratedBlockSize = - std::max(uint64_t(1000), std::min(config.GetMaxBlockSize() - 1000, - nMaxGeneratedBlockSize)); + + // TODO: Use time for *this* block, not previous block. + uint64_t timestamp = pindexPrev ? pindexPrev->nTime : 0; + + nMaxGeneratedBlockSize = std::max( + uint64_t(1000), std::min(config.GetMaxBlockSize(timestamp) - 1000, + nMaxGeneratedBlockSize)); // If UAHF is not activated yet, we also want to limit the max generated // block size to LEGACY_MAX_BLOCK_SIZE - 1000 @@ -146,7 +150,9 @@ static const std::vector getExcessiveBlockSizeSig(const Config &config) { - std::string cbmsg = "/EB" + getSubVersionEB(config.GetMaxBlockSize()) + "/"; + // TODO: If block is available, use GetMaxBlockSize for exact EB. + std::string cbmsg = + "/EB" + getSubVersionEB(config.GuessWithinBlockSize()) + "/"; const char *cbcstr = cbmsg.c_str(); std::vector vec(cbcstr, cbcstr + cbmsg.size()); return vec; diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -323,8 +323,9 @@ /// debug print LogPrint("net", "trying connection %s lastseen=%.1fhrs\n", pszDest ? pszDest : addrConnect.ToString(), - pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime) / - 3600.0); + pszDest + ? 0.0 + : (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0); // Connect SOCKET hSocket; @@ -2806,7 +2807,7 @@ std::string userAgent(const Config &config) { // format excessive blocksize value - std::string eb = getSubVersionEB(config.GetMaxBlockSize()); + std::string eb = getSubVersionEB(config.GuessWithinBlockSize()); std::vector uacomments; uacomments.push_back("EB" + eb); diff --git a/src/policy/bip101policy.h b/src/policy/bip101policy.h new file mode 100644 --- /dev/null +++ b/src/policy/bip101policy.h @@ -0,0 +1,31 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2017 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_BIP101POLICY_H +#define BITCOIN_BIP101POLICY_H +#include "policy/blocksizepolicy.h" + +class BIP101Policy : public BlockSizePolicy { +public: + BIP101Policy(uint64_t nUAHFStartTime) + : nSizeForkActivationTime(nUAHFStartTime), + nEarliestSizeForkTime(nUAHFStartTime), + nSizeDoubleEpoch(60 * 60 * 24 * 365 * 2), // two years + nMaxSizeBase(8 * 1000 * 1000), // 8MB + nMaxSizeDoublings(10) {} + + uint64_t GetMaxBlockSize(uint64_t nBlockTimestamp) const override; + uint64_t GuessWithinBlockSize() const override; + uint64_t GetBlockSizeDoSLimit() const override; + +private: + uint64_t nSizeForkActivationTime; + uint64_t nEarliestSizeForkTime; + uint32_t nSizeDoubleEpoch; + uint64_t nMaxSizeBase; + uint8_t nMaxSizeDoublings; +}; + +#endif diff --git a/src/policy/bip101policy.cpp b/src/policy/bip101policy.cpp new file mode 100644 --- /dev/null +++ b/src/policy/bip101policy.cpp @@ -0,0 +1,38 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2017 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "policy/bip101policy.h" +#include "consensus/consensus.h" +#include "timedata.h" + +static const uint64_t TWO_HOURS = 2 * 60 * 60; + +uint64_t BIP101Policy::GetMaxBlockSize(uint64_t nBlockTimestamp) const { + + if (nBlockTimestamp < nSizeForkActivationTime) return LEGACY_MAX_BLOCK_SIZE; + + if (nBlockTimestamp >= + nEarliestSizeForkTime + nSizeDoubleEpoch * nMaxSizeDoublings) + return nMaxSizeBase << nMaxSizeDoublings; + + // Piecewise-linear-between-doublings growth. Calculated based on a fixed + // timestamp and not the activation time so the maximum size is + // predictable, and so the activation time can be completely removed in + // a future version of this code after the fork is complete. + uint64_t timeDelta = nBlockTimestamp - nEarliestSizeForkTime; + uint64_t doublings = timeDelta / nSizeDoubleEpoch; + uint64_t remain = timeDelta % nSizeDoubleEpoch; + uint64_t interpolate = + (nMaxSizeBase << doublings) * remain / nSizeDoubleEpoch; + uint64_t nMaxSize = (nMaxSizeBase << doublings) + interpolate; + return nMaxSize; +} + +uint64_t BIP101Policy::GuessWithinBlockSize() const { + return GetMaxBlockSize(GetAdjustedTime() - TWO_HOURS); +} +uint64_t BIP101Policy::GetBlockSizeDoSLimit() const { + return GetMaxBlockSize(GetAdjustedTime() + TWO_HOURS); +} diff --git a/src/policy/blocksizepolicy.h b/src/policy/blocksizepolicy.h new file mode 100644 --- /dev/null +++ b/src/policy/blocksizepolicy.h @@ -0,0 +1,27 @@ +// Copyright (c) 2017 Bitcoin Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_BLOCKSIZEPOLICY_H +#define BITCOIN_BLOCKSIZEPOLICY_H + +#include + +class BlockSizePolicy { +public: + // Hard limit for maximum block size. + virtual uint64_t GetMaxBlockSize(uint64_t nBlockTimestamp) const = 0; + + // Without knowing exact details about the block, <= this is our best + // guess at how big block we'll accept. + virtual uint64_t GuessWithinBlockSize() const = 0; + + // Without knowing exact details about the block, > this is our best + // guess at when a block exceeds our limits. + virtual uint64_t GetBlockSizeDoSLimit() const = 0; + + virtual ~BlockSizePolicy() = 0; +}; + +inline BlockSizePolicy::~BlockSizePolicy() {} + +#endif diff --git a/src/policy/staticblocksize.h b/src/policy/staticblocksize.h new file mode 100644 --- /dev/null +++ b/src/policy/staticblocksize.h @@ -0,0 +1,23 @@ +// Copyright (c) 2017 The Bitcoin Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef BITCOIN_STATICBLOCKSIZE_H +#define BITCOIN_STATICBLOCKSIZE_H +#include "policy/blocksizepolicy.h" + +class StaticBlockSize : public BlockSizePolicy { +public: + StaticBlockSize(uint64_t maxBlockSize); + ~StaticBlockSize(); + + uint64_t GetMaxBlockSize(uint64_t nBlockTimestamp) const override { + return nMaxBlockSize; + } + uint64_t GuessWithinBlockSize() const override { return nMaxBlockSize; } + uint64_t GetBlockSizeDoSLimit() const override { return nMaxBlockSize; } + +private: + uint64_t nMaxBlockSize; +}; + +#endif diff --git a/src/policy/staticblocksize.cpp b/src/policy/staticblocksize.cpp new file mode 100644 --- /dev/null +++ b/src/policy/staticblocksize.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2017 The Bitcoin Developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "policy/staticblocksize.h" +#include "consensus/consensus.h" +#include + +StaticBlockSize::~StaticBlockSize() {} + +StaticBlockSize::StaticBlockSize(uint64_t maxBlockSize) + : nMaxBlockSize(maxBlockSize) { + if (nMaxBlockSize <= LEGACY_MAX_BLOCK_SIZE) { + throw std::invalid_argument( + "Excessive block size must be > 1,000,000 bytes (1MB)"); + } +} diff --git a/src/rpc/abc.cpp b/src/rpc/abc.cpp --- a/src/rpc/abc.cpp +++ b/src/rpc/abc.cpp @@ -4,6 +4,7 @@ #include "config.h" #include "consensus/consensus.h" +#include "policy/staticblocksize.h" #include "rpc/server.h" #include "utilstrencodings.h" #include "validation.h" @@ -26,7 +27,7 @@ } UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("excessiveBlockSize", config.GetMaxBlockSize())); + ret.push_back(Pair("excessiveBlockSize", config.GuessWithinBlockSize())); return ret; } @@ -54,22 +55,15 @@ ebs = boost::lexical_cast(temp); } - // Do not allow maxBlockSize to be set below historic 1MB limit - if (ebs <= LEGACY_MAX_BLOCK_SIZE) - throw JSONRPCError( - RPC_INVALID_PARAMETER, - std::string( - "Invalid parameter, excessiveblock must be larger than ") + - std::to_string(LEGACY_MAX_BLOCK_SIZE)); - - // Set the new max block size. - if (!config.SetMaxBlockSize(ebs)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Unexpected error"); + try { + config.SetBlockSizePolicy( + std::unique_ptr(new StaticBlockSize(ebs))); + } catch (const std::invalid_argument &e) { + throw JSONRPCError(RPC_INVALID_PARAMETER, e.what()); } - // settingsToUserAgentString(); std::ostringstream ret; - ret << "Excessive Block set to " << ebs << " bytes."; + ret << "Excessive Block set to static value " << ebs << " bytes."; return UniValue(ret.str()); } diff --git a/src/test/blockcheck_tests.cpp b/src/test/blockcheck_tests.cpp --- a/src/test/blockcheck_tests.cpp +++ b/src/test/blockcheck_tests.cpp @@ -6,6 +6,7 @@ #include "config.h" #include "consensus/consensus.h" #include "consensus/validation.h" +#include "policy/staticblocksize.h" #include "validation.h" #include "test/test_bitcoin.h" @@ -43,7 +44,8 @@ // Set max blocksize to default in case other tests left it dirty GlobalConfig config; - config.SetMaxBlockSize(DEFAULT_MAX_BLOCK_SIZE); + config.SetBlockSizePolicy(std::unique_ptr( + new StaticBlockSize(DEFAULT_MAX_BLOCK_SIZE))); CBlock block; RunCheckOnBlock(config, block, "bad-cb-missing"); diff --git a/src/test/config_tests.cpp b/src/test/config_tests.cpp --- a/src/test/config_tests.cpp +++ b/src/test/config_tests.cpp @@ -2,45 +2,59 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "config.h" #include "chainparams.h" +#include "config.h" #include "consensus/consensus.h" +#include "policy/staticblocksize.h" #include "test/test_bitcoin.h" #include BOOST_FIXTURE_TEST_SUITE(config_tests, BasicTestingSetup) -BOOST_AUTO_TEST_CASE(max_block_size) { +namespace { +std::unique_ptr staticSize(uint64_t size) { + return std::unique_ptr(new StaticBlockSize(size)); +} +} + +BOOST_AUTO_TEST_CASE(static_block_size) { GlobalConfig config; // Too small. - BOOST_CHECK(!config.SetMaxBlockSize(0)); - BOOST_CHECK(!config.SetMaxBlockSize(12345)); - BOOST_CHECK(!config.SetMaxBlockSize(LEGACY_MAX_BLOCK_SIZE - 1)); - BOOST_CHECK(!config.SetMaxBlockSize(LEGACY_MAX_BLOCK_SIZE)); + BOOST_CHECK_THROW(config.SetBlockSizePolicy(staticSize(0)), + std::invalid_argument); + BOOST_CHECK_THROW(config.SetBlockSizePolicy(staticSize(12345)), + std::invalid_argument); + BOOST_CHECK_THROW( + config.SetBlockSizePolicy(staticSize(LEGACY_MAX_BLOCK_SIZE - 1)), + std::invalid_argument); + BOOST_CHECK_THROW( + config.SetBlockSizePolicy(staticSize(LEGACY_MAX_BLOCK_SIZE)), + std::invalid_argument); // LEGACY_MAX_BLOCK_SIZE + 1 - BOOST_CHECK(config.SetMaxBlockSize(LEGACY_MAX_BLOCK_SIZE + 1)); - BOOST_CHECK_EQUAL(config.GetMaxBlockSize(), LEGACY_MAX_BLOCK_SIZE + 1); + config.SetBlockSizePolicy(staticSize(LEGACY_MAX_BLOCK_SIZE + 1)); + BOOST_CHECK_EQUAL(config.GetMaxBlockSize(0), LEGACY_MAX_BLOCK_SIZE + 1); // 2MB - BOOST_CHECK(config.SetMaxBlockSize(2 * ONE_MEGABYTE)); - BOOST_CHECK_EQUAL(config.GetMaxBlockSize(), 2 * ONE_MEGABYTE); + config.SetBlockSizePolicy(staticSize(2 * ONE_MEGABYTE)); + BOOST_CHECK_EQUAL(config.GetMaxBlockSize(0), 2 * ONE_MEGABYTE); // 8MB - BOOST_CHECK(config.SetMaxBlockSize(8 * ONE_MEGABYTE)); - BOOST_CHECK_EQUAL(config.GetMaxBlockSize(), 8 * ONE_MEGABYTE); + config.SetBlockSizePolicy(staticSize(8 * ONE_MEGABYTE)); + BOOST_CHECK_EQUAL(config.GetMaxBlockSize(0), 8 * ONE_MEGABYTE); // Invalid size keep config. - BOOST_CHECK(!config.SetMaxBlockSize(54321)); - BOOST_CHECK_EQUAL(config.GetMaxBlockSize(), 8 * ONE_MEGABYTE); + BOOST_CHECK_THROW(config.SetBlockSizePolicy(staticSize(54321)), + std::invalid_argument); + BOOST_CHECK_EQUAL(config.GetMaxBlockSize(0), 8 * ONE_MEGABYTE); // Setting it back down - BOOST_CHECK(config.SetMaxBlockSize(7 * ONE_MEGABYTE)); - BOOST_CHECK_EQUAL(config.GetMaxBlockSize(), 7 * ONE_MEGABYTE); - BOOST_CHECK(config.SetMaxBlockSize(ONE_MEGABYTE + 1)); - BOOST_CHECK_EQUAL(config.GetMaxBlockSize(), ONE_MEGABYTE + 1); + config.SetBlockSizePolicy(staticSize(7 * ONE_MEGABYTE)); + BOOST_CHECK_EQUAL(config.GetMaxBlockSize(0), 7 * ONE_MEGABYTE); + config.SetBlockSizePolicy(staticSize(ONE_MEGABYTE + 1)); + BOOST_CHECK_EQUAL(config.GetMaxBlockSize(0), ONE_MEGABYTE + 1); } BOOST_AUTO_TEST_CASE(chain_params) { 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 @@ -2,14 +2,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "miner.h" #include "chainparams.h" #include "coins.h" #include "config.h" #include "consensus/consensus.h" #include "consensus/merkle.h" #include "consensus/validation.h" +#include "miner.h" #include "policy/policy.h" +#include "policy/staticblocksize.h" #include "pubkey.h" #include "script/standard.h" #include "txmempool.h" @@ -205,7 +206,8 @@ void TestCoinbaseMessageEB(uint64_t eb, std::string cbmsg) { GlobalConfig config; - config.SetMaxBlockSize(eb); + config.SetBlockSizePolicy( + std::unique_ptr(new StaticBlockSize(eb))); const CChainParams &chainparams = config.GetChainParams(); CScript scriptPubKey = @@ -707,10 +709,8 @@ fCheckpointsEnabled = true; } -void CheckBlockMaxSize(const CChainParams &chainparams, uint64_t size, - uint64_t expected) { - GlobalConfig config; - +void CheckBlockMaxSize(const CChainParams &chainparams, const Config &config, + uint64_t size, uint64_t expected) { ForceSetArg("-blockmaxsize", std::to_string(size)); BlockAssembler ba(config, chainparams); @@ -731,24 +731,35 @@ BOOST_CHECK(!IsUAHFenabledForCurrentBlock(config)); // Test around the historical 1MB cap - config.SetMaxBlockSize(ONE_MEGABYTE); - CheckBlockMaxSize(chainparams, 0, 1000); - CheckBlockMaxSize(chainparams, 1000, 1000); - CheckBlockMaxSize(chainparams, 1001, 1001); - CheckBlockMaxSize(chainparams, 12345, 12345); - - CheckBlockMaxSize(chainparams, ONE_MEGABYTE - 1001, ONE_MEGABYTE - 1001); - CheckBlockMaxSize(chainparams, ONE_MEGABYTE - 1000, ONE_MEGABYTE - 1000); - CheckBlockMaxSize(chainparams, ONE_MEGABYTE - 999, LEGACY_CAP); - CheckBlockMaxSize(chainparams, ONE_MEGABYTE, LEGACY_CAP); + class HistoricalSize : public BlockSizePolicy { + uint64_t GetMaxBlockSize(uint64_t) const override { + return ONE_MEGABYTE; + } + uint64_t GuessWithinBlockSize() const { return ONE_MEGABYTE; } + uint64_t GetBlockSizeDoSLimit() const { return ONE_MEGABYTE; } + }; + config.SetBlockSizePolicy( + std::unique_ptr(new HistoricalSize())); + CheckBlockMaxSize(chainparams, config, 0, 1000); + CheckBlockMaxSize(chainparams, config, 1000, 1000); + CheckBlockMaxSize(chainparams, config, 1001, 1001); + CheckBlockMaxSize(chainparams, config, 12345, 12345); + + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE - 1001, + ONE_MEGABYTE - 1001); + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE - 1000, + ONE_MEGABYTE - 1000); + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE - 999, LEGACY_CAP); + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE, LEGACY_CAP); // Test around higher limit, the block size should still cap at LEGACY_CAP. static const auto EIGHT_MEGABYTES = 8 * ONE_MEGABYTE; - config.SetMaxBlockSize(EIGHT_MEGABYTES); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 1001, LEGACY_CAP); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 1000, LEGACY_CAP); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 999, LEGACY_CAP); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES, LEGACY_CAP); + config.SetBlockSizePolicy( + std::unique_ptr(new StaticBlockSize(EIGHT_MEGABYTES))); + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES - 1001, LEGACY_CAP); + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES - 1000, LEGACY_CAP); + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES - 999, LEGACY_CAP); + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES, LEGACY_CAP); // Before the UAHF, the default generated block size is the LEGACY_CAP. { @@ -768,36 +779,45 @@ BOOST_CHECK(IsUAHFenabledForCurrentBlock(config)); // Test around historical 1MB (plus one byte because that's mandatory) - config.SetMaxBlockSize(ONE_MEGABYTE + 1); - CheckBlockMaxSize(chainparams, 0, 1000); - CheckBlockMaxSize(chainparams, 1000, 1000); - CheckBlockMaxSize(chainparams, 1001, 1001); - CheckBlockMaxSize(chainparams, 12345, 12345); - - CheckBlockMaxSize(chainparams, ONE_MEGABYTE - 1001, ONE_MEGABYTE - 1001); - CheckBlockMaxSize(chainparams, ONE_MEGABYTE - 1000, ONE_MEGABYTE - 1000); - CheckBlockMaxSize(chainparams, ONE_MEGABYTE - 999, ONE_MEGABYTE - 999); - CheckBlockMaxSize(chainparams, ONE_MEGABYTE, ONE_MEGABYTE - 999); + config.SetBlockSizePolicy(std::unique_ptr( + new StaticBlockSize(ONE_MEGABYTE + 1))); + + CheckBlockMaxSize(chainparams, config, 0, 1000); + CheckBlockMaxSize(chainparams, config, 1000, 1000); + CheckBlockMaxSize(chainparams, config, 1001, 1001); + CheckBlockMaxSize(chainparams, config, 12345, 12345); + + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE - 1001, + ONE_MEGABYTE - 1001); + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE - 1000, + ONE_MEGABYTE - 1000); + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE - 999, + ONE_MEGABYTE - 999); + CheckBlockMaxSize(chainparams, config, ONE_MEGABYTE, ONE_MEGABYTE - 999); // Test around higher limit such as 8MB - config.SetMaxBlockSize(EIGHT_MEGABYTES); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 1001, + config.SetBlockSizePolicy( + std::unique_ptr(new StaticBlockSize(EIGHT_MEGABYTES))); + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES - 1001, EIGHT_MEGABYTES - 1001); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 1000, + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES - 1000, EIGHT_MEGABYTES - 1000); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 999, + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES - 999, + EIGHT_MEGABYTES - 1000); + CheckBlockMaxSize(chainparams, config, EIGHT_MEGABYTES, EIGHT_MEGABYTES - 1000); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES, EIGHT_MEGABYTES - 1000); // Test around default cap - config.SetMaxBlockSize(DEFAULT_MAX_BLOCK_SIZE); - CheckBlockMaxSize(chainparams, DEFAULT_MAX_BLOCK_SIZE - 1001, + config.SetBlockSizePolicy(std::unique_ptr( + new StaticBlockSize(DEFAULT_MAX_BLOCK_SIZE))); + + CheckBlockMaxSize(chainparams, config, DEFAULT_MAX_BLOCK_SIZE - 1001, DEFAULT_MAX_BLOCK_SIZE - 1001); - CheckBlockMaxSize(chainparams, DEFAULT_MAX_BLOCK_SIZE - 1000, + CheckBlockMaxSize(chainparams, config, DEFAULT_MAX_BLOCK_SIZE - 1000, DEFAULT_MAX_BLOCK_SIZE - 1000); - CheckBlockMaxSize(chainparams, DEFAULT_MAX_BLOCK_SIZE - 999, + CheckBlockMaxSize(chainparams, config, DEFAULT_MAX_BLOCK_SIZE - 999, DEFAULT_MAX_BLOCK_SIZE - 1000); - CheckBlockMaxSize(chainparams, DEFAULT_MAX_BLOCK_SIZE, + CheckBlockMaxSize(chainparams, config, DEFAULT_MAX_BLOCK_SIZE, DEFAULT_MAX_BLOCK_SIZE - 1000); // If the parameter is not specified, we use diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -1,16 +1,18 @@ // Copyright (c) 2012-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "net.h" #include "addrman.h" #include "chainparams.h" #include "config.h" #include "hash.h" +#include "net.h" #include "netbase.h" +#include "policy/staticblocksize.h" #include "serialize.h" #include "streams.h" #include "test/test_bitcoin.h" +#include #include #include @@ -182,7 +184,8 @@ BOOST_AUTO_TEST_CASE(test_userAgentLength) { GlobalConfig config; - config.SetMaxBlockSize(8000000); + config.SetBlockSizePolicy( + std::unique_ptr(new StaticBlockSize(8000000))); std::string long_uacomment = "very very very very very very very very very " "very very very very very very very very very " "very very very very very very very very very " diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3179,7 +3179,7 @@ } // Size limits. - auto nMaxBlockSize = config.GetMaxBlockSize(); + auto nMaxBlockSize = config.GetMaxBlockSize(block.GetBlockTime()); // Bail early if there is no way this block is of reasonable size. if ((block.vtx.size() * MIN_TRANSACTION_SIZE) > nMaxBlockSize) {