diff --git a/src/chainparams.cpp b/src/chainparams.cpp --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -152,6 +152,9 @@ // November 13, 2017 hard fork consensus.daaHeight = 504031; + // May 15, 2018 hard fork + consensus.monolithActivationTime = 1526400000; + /** * The message start string is designed to be unlikely to occur in * normal data. The characters are rarely used upper ASCII, not valid as @@ -325,6 +328,9 @@ // November 13, 2017 hard fork consensus.daaHeight = 1188697; + // May 15, 2018 hard fork + consensus.monolithActivationTime = 1526400000; + diskMagic[0] = 0x0b; diskMagic[1] = 0x11; diskMagic[2] = 0x09; @@ -449,6 +455,9 @@ // November 13, 2017 hard fork is always on on regtest. consensus.daaHeight = 0; + // May 15, 2018 hard fork. + consensus.monolithActivationTime = 1526400000; + diskMagic[0] = 0xfa; diskMagic[1] = 0xbf; diskMagic[2] = 0xb5; diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -15,7 +15,7 @@ /** The maximum allowed size for a block, before the UAHF */ static const uint64_t LEGACY_MAX_BLOCK_SIZE = ONE_MEGABYTE; /** Default setting for maximum allowed size for a block, in bytes */ -static const uint64_t DEFAULT_MAX_BLOCK_SIZE = 8 * ONE_MEGABYTE; +static const uint64_t DEFAULT_MAX_BLOCK_SIZE = 32 * ONE_MEGABYTE; /** The maximum allowed number of signature check operations per MB in a block * (network rule) */ static const int64_t MAX_BLOCK_SIGOPS_PER_MB = 20000; diff --git a/src/consensus/params.h b/src/consensus/params.h --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -52,6 +52,8 @@ int uahfHeight; /** Block height at which the new DAA becomes active */ int daaHeight; + /** Unix time used for MTP activation of May 15 2018, hardfork */ + int monolithActivationTime; /** Block height at which OP_RETURN replay protection stops */ int antiReplayOpReturnSunsetHeight; /** Committed OP_RETURN value for replay protection */ diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -87,6 +87,13 @@ std::max(uint64_t(1000), std::min(config.GetMaxBlockSize() - 1000, nMaxGeneratedBlockSize)); + // If May 15, 2018 HF is not activated yet, we also want to limit the max + // generated block size to 8MB - 1000 + if (!IsMonolithEnabled(config, pindexPrev)) { + nMaxGeneratedBlockSize = + std::min(8 * ONE_MEGABYTE - 1000, nMaxGeneratedBlockSize); + } + return nMaxGeneratedBlockSize; } 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 @@ -31,7 +31,7 @@ static struct { uint8_t extranonce; - unsigned int nonce; + uint32_t nonce; } blockinfo[] = { {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5}, {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84}, @@ -723,19 +723,37 @@ CheckBlockMaxSize(chainparams, ONE_MEGABYTE - 999, ONE_MEGABYTE - 999); CheckBlockMaxSize(chainparams, ONE_MEGABYTE, ONE_MEGABYTE - 999); - // Test around higher limit such as 8MB + // The maximum block size to be generated before the May 15, 2018 HF static const auto EIGHT_MEGABYTES = 8 * ONE_MEGABYTE; - config.SetMaxBlockSize(EIGHT_MEGABYTES); + static const auto LEGACY_CAP = EIGHT_MEGABYTES - 1000; + + // Test around historical 8MB cap. + config.SetMaxBlockSize(EIGHT_MEGABYTES + 1); CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 1001, EIGHT_MEGABYTES - 1001); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 1000, - EIGHT_MEGABYTES - 1000); - CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 999, - EIGHT_MEGABYTES - 1000); + CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 1000, LEGACY_CAP); + CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES - 999, LEGACY_CAP); CheckBlockMaxSize(chainparams, EIGHT_MEGABYTES, EIGHT_MEGABYTES - 1000); // Test around default cap config.SetMaxBlockSize(DEFAULT_MAX_BLOCK_SIZE); + + // We are stuck at the legacy cap before activation. + CheckBlockMaxSize(chainparams, DEFAULT_MAX_BLOCK_SIZE, LEGACY_CAP); + + // Activate May 15, 2018 HF the dirty way + const int64_t monolithTime = + config.GetChainParams().GetConsensus().monolithActivationTime; + auto pindex = chainActive.Tip(); + for (size_t i = 0; pindex && i < 5; i++) { + BOOST_CHECK(!IsMonolithEnabled(config, chainActive.Tip())); + pindex->nTime = monolithTime; + pindex = pindex->pprev; + } + + BOOST_CHECK(IsMonolithEnabled(config, chainActive.Tip())); + + // Now we can use the default max block size. CheckBlockMaxSize(chainparams, DEFAULT_MAX_BLOCK_SIZE - 1001, DEFAULT_MAX_BLOCK_SIZE - 1001); CheckBlockMaxSize(chainparams, DEFAULT_MAX_BLOCK_SIZE - 1000, diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -360,6 +360,9 @@ /** Check if DAA HF has activated. */ bool IsDAAEnabled(const Config &config, const CBlockIndex *pindexPrev); +/** Check if May 15, 2018 HF has activated. */ +bool IsMonolithEnabled(const Config &config, const CBlockIndex *pindexPrev); + /** * (try to) add transaction to memory pool * plTxnReplaced will be appended to with all transactions replaced from diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -599,6 +599,19 @@ return IsDAAEnabled(config, pindexPrev->nHeight); } +static bool IsMonolithEnabled(const Config &config, int64_t nMedianTimePast) { + return nMedianTimePast >= + config.GetChainParams().GetConsensus().monolithActivationTime; +} + +bool IsMonolithEnabled(const Config &config, const CBlockIndex *pindexPrev) { + if (pindexPrev == nullptr) { + return false; + } + + return IsMonolithEnabled(config, pindexPrev->GetMedianTimePast()); +} + /** * Make mempool consistent after a reorg, by re-adding or recursively erasing * disconnected block transactions from the mempool, and also removing any other @@ -3562,6 +3575,17 @@ nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST; } + if (!IsMonolithEnabled(config, pindexPrev)) { + // When the May 15, 2018 HF is not enabled, block cannot be bigger + // than 8MB . + const uint64_t currentBlockSize = + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); + if (currentBlockSize > 8 * ONE_MEGABYTE) { + return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", + false, "size limits failed"); + } + } + const int64_t nMedianTimePast = pindexPrev == nullptr ? 0 : pindexPrev->GetMedianTimePast(); diff --git a/test/functional/abc-p2p-compactblocks.py b/test/functional/abc-p2p-compactblocks.py --- a/test/functional/abc-p2p-compactblocks.py +++ b/test/functional/abc-p2p-compactblocks.py @@ -21,6 +21,9 @@ MAX_BLOCK_SIGOPS_PER_MB, MAX_TX_SIGOPS_COUNT) from collections import deque +# far into the future +MONOLITH_START_TIME = 2000000000 + class PreviousSpendableOutput(): @@ -95,6 +98,7 @@ NetworkThread().start() # Set the blocksize to 2MB as initial condition self.nodes[0].setexcessiveblock(self.excessive_block_size) + self.nodes[0].setmocktime(MONOLITH_START_TIME) self.test.run() def add_transactions_to_block(self, block, tx_list): @@ -268,6 +272,19 @@ block(5000 + i) test.blocks_and_transactions.append([self.tip, True]) save_spendable_output() + + # Fork block + bfork = block(5555) + bfork.nTime = MONOLITH_START_TIME + update_block(5555, []) + test.blocks_and_transactions.append([self.tip, True]) + + # Get to one block of the May 15, 2018 HF activation + for i in range(5): + block(5100 + i) + test.blocks_and_transactions.append([self.tip, True]) + + # Send it all to the node at once. yield test # collect spendable outputs now to avoid cluttering the code later on diff --git a/test/functional/abc-p2p-fullblocktest.py b/test/functional/abc-p2p-fullblocktest.py --- a/test/functional/abc-p2p-fullblocktest.py +++ b/test/functional/abc-p2p-fullblocktest.py @@ -22,6 +22,9 @@ MAX_BLOCK_SIGOPS_PER_MB, MAX_TX_SIGOPS_COUNT) from collections import deque +# far into the future +MONOLITH_START_TIME = 2000000000 + class PreviousSpendableOutput(): @@ -59,6 +62,7 @@ NetworkThread().start() # Set the blocksize to 2MB as initial condition self.nodes[0].setexcessiveblock(self.excessive_block_size) + self.nodes[0].setmocktime(MONOLITH_START_TIME) self.test.run() def add_transactions_to_block(self, block, tx_list): @@ -241,11 +245,34 @@ out.append(get_spendable_output()) # Let's build some blocks and test them. - for i in range(16): + for i in range(15): n = i + 1 - block(n, spend=out[i], block_size=n * ONE_MEGABYTE) + block(n, spend=out[i], block_size=n * ONE_MEGABYTE // 2) yield accepted() + # Fork block + bfork = block(5555, out[15], block_size=8 * ONE_MEGABYTE) + bfork.nTime = MONOLITH_START_TIME + update_block(5555, []) + yield accepted() + + # Get to one block of the May 15, 2018 HF activation + for i in range(4): + block(5100 + i) + test.blocks_and_transactions.append([self.tip, True]) + yield test + + # Before we acivate the May 15, 2018 HF, 8MB is the limit. + block(4444, spend=out[16], block_size=8 * ONE_MEGABYTE + 1) + yield rejected(RejectResult(16, b'bad-blk-length')) + + # Rewind bad block. + tip(5103) + + # Actiavte the May 15, 2018 HF + block(5104) + yield accepted() + # block of maximal size block(17, spend=out[16], block_size=self.excessive_block_size) yield accepted()