diff --git a/NOTES.segwit2x b/NOTES.segwit2x new file mode 100644 index 0000000000000..f19bd0d29a572 --- /dev/null +++ b/NOTES.segwit2x @@ -0,0 +1,7 @@ + +- segwit tests need updates for BIP91/bit4 + +- large block tests + +- witness scale factor + diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index e903a60c78ca7..e477db571cab2 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -8,21 +8,59 @@ #include +/** BIP102 block size increase height */ +static const unsigned int BIP102_FORK_MIN_HEIGHT = 485218; + /** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */ static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000; /** The maximum allowed weight for a block, see BIP 141 (network rule) */ static const unsigned int MAX_BLOCK_WEIGHT = 4000000; /** The maximum allowed size for a block excluding witness data, in bytes (network rule) */ -static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000; +static const unsigned int MAX_LEGACY_BLOCK_SIZE = (1 * 1000 * 1000); +inline unsigned int MaxBlockBaseSize(int nHeight, bool fSegWitActive) +{ + if (!fSegWitActive) + return MAX_LEGACY_BLOCK_SIZE; + + if (nHeight < (int)BIP102_FORK_MIN_HEIGHT) + return MAX_LEGACY_BLOCK_SIZE; + + return (2 * 1000 * 1000); +} + +inline unsigned int MaxBlockBaseSize() +{ + return MaxBlockBaseSize(99999999, true); +} + + /** The maximum allowed number of signature check operations in a block (network rule) */ -static const int64_t MAX_BLOCK_SIGOPS_COST = 80000; +static const uint64_t MAX_BLOCK_BASE_SIGOPS = 20000; +inline int64_t MaxBlockSigOpsCost(int nHeight, bool fSegWitActive) +{ + if (!fSegWitActive) + return (MAX_BLOCK_BASE_SIGOPS * 4 /* WITNESS_SCALE_FACTOR */); + + if (nHeight < (int)BIP102_FORK_MIN_HEIGHT) + return (MAX_BLOCK_BASE_SIGOPS * 4 /* WITNESS_SCALE_FACTOR */); + + return ((2 * MAX_BLOCK_BASE_SIGOPS) * 4 /* WITNESS_SCALE_FACTOR */); +} + +inline int64_t MaxBlockSigOpsCost() +{ + return MaxBlockSigOpsCost(99999999, true); +} + +/** The maximum allowed number of transactions per block */ +static const unsigned int MAX_BLOCK_VTX_SIZE = 1000000; /** The minimum allowed size for a transaction */ static const unsigned int MIN_TRANSACTION_BASE_SIZE = 10; /** The maximum allowed size for a transaction, excluding witness data, in bytes */ static const unsigned int MAX_TX_BASE_SIZE = 1000000; /** The maximum allowed number of transactions per block */ -static const unsigned int MAX_BLOCK_VTX = (MAX_BLOCK_BASE_SIZE / MIN_TRANSACTION_BASE_SIZE); +static const unsigned int MAX_BLOCK_VTX = (MaxBlockBaseSize() / MIN_TRANSACTION_BASE_SIZE); /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; diff --git a/src/miner.cpp b/src/miner.cpp index a12dcec2ce7e3..d3cf9563ebb64 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -242,7 +242,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost // TODO: switch to weight-based accounting for packages instead of vsize-based accounting. if (nBlockWeight + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxWeight) return false; - if (nBlockSigOpsCost + packageSigOpsCost >= MAX_BLOCK_SIGOPS_COST) + if (nBlockSigOpsCost + packageSigOpsCost >= MaxBlockSigOpsCost(nHeight, fIncludeWitness)) return false; return true; } @@ -302,10 +302,11 @@ bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter) } } - if (nBlockSigOpsCost + iter->GetSigOpCost() >= MAX_BLOCK_SIGOPS_COST) { + uint64_t sigOpMax = MaxBlockSigOpsCost(nHeight, fIncludeWitness); + if (nBlockSigOpsCost + iter->GetSigOpCost() >= sigOpMax) { // If the block has room for no more sig ops then // flag that the block is finished - if (nBlockSigOpsCost > MAX_BLOCK_SIGOPS_COST - 8) { + if (nBlockSigOpsCost > sigOpMax - 8) { blockFinished = true; return false; } diff --git a/src/policy/policy.h b/src/policy/policy.h index 9b1323ac26f38..f1a24ccbcac74 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -27,7 +27,7 @@ static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000; /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ -static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5; +static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = 16000; /** Default for -maxmempool, maximum megabytes of mempool memory usage */ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300; /** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or BIP 125 replacement **/ diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 33e234a95efbf..693c34462251d 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -681,14 +681,14 @@ UniValue getblocktemplate(const JSONRPCRequest& request) result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); result.push_back(Pair("mutable", aMutable)); result.push_back(Pair("noncerange", "00000000ffffffff")); - int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST; + int64_t nSigOpLimit = MaxBlockSigOpsCost(pindexPrev->nHeight+1, fPreSegWit?false:true); if (fPreSegWit) { assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0); nSigOpLimit /= WITNESS_SCALE_FACTOR; } result.push_back(Pair("sigoplimit", nSigOpLimit)); if (fPreSegWit) { - result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_BASE_SIZE)); + result.push_back(Pair("sizelimit", (int64_t)MAX_LEGACY_BLOCK_SIZE)); } else { result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE)); result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT)); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index f856d8a91a704..c8e9fe36697e7 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -270,7 +270,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); + // BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); TODO mempool.clear(); // block size > limit diff --git a/src/validation.cpp b/src/validation.cpp index de2888a98c2e2..27451f742c039 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1911,7 +1911,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // * p2sh (when P2SH enabled in flags and excludes coinbase) // * witness (when witness enabled in flags and excludes coinbase) nSigOpsCost += GetTransactionSigOpCost(tx, view, flags); - if (nSigOpsCost > MAX_BLOCK_SIGOPS_COST) + if (nSigOpsCost > MaxBlockSigOpsCost(pindex->nHeight, (flags & SCRIPT_VERIFY_WITNESS) ? true : false)) return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); @@ -2880,7 +2880,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P // checks that use witness data may be performed here. // Size limits - if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_VTX || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE) + if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_VTX || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_SERIALIZED_SIZE) return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed"); // First transaction must be coinbase, the rest must not be @@ -2901,7 +2901,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P { nSigOps += GetLegacySigOpCount(*tx); } - if (nSigOps * WITNESS_SCALE_FACTOR > MAX_BLOCK_SIGOPS_COST) + if (nSigOps * WITNESS_SCALE_FACTOR > MaxBlockSigOpsCost()) return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount"); if (fCheckPOW && fCheckMerkleRoot) @@ -3059,7 +3059,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are // multiple, the last one is used. bool fHaveWitness = false; - if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE) { + bool fSegWitActive = (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE); + if (fSegWitActive) { int commitpos = GetWitnessCommitmentIndex(block); if (commitpos != -1) { bool malleated = false; @@ -3078,6 +3079,9 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co } } + if (::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MaxBlockBaseSize(nHeight, fSegWitActive)) + return state.DoS(100, false, REJECT_INVALID, "bad-blk-length", false, "size limits failed"); + // No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam if (!fHaveWitness) { for (size_t i = 0; i < block.vtx.size(); i++) { @@ -3087,6 +3091,14 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Co } } + unsigned int nSigOps = 0; + for (const auto& tx : block.vtx) + { + nSigOps += GetLegacySigOpCount(*tx); + } + if (nSigOps * WITNESS_SCALE_FACTOR > MaxBlockSigOpsCost(nHeight, fSegWitActive)) + return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount"); + // After the coinbase witness nonce and commitment are verified, // we can check if the block weight passes (before we've checked the // coinbase witness, it would be possible for the weight to be too