diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 5a099cf53c57b..750437fe21b10 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -7,7 +7,10 @@ #define BITCOIN_CONSENSUS_CONSENSUS_H /** The maximum allowed size for a serialized block, in bytes (network rule) */ -static const unsigned int MAX_BLOCK_SIZE = 1000000; +static const unsigned int MAX_BLOCK_COST = 4000000; + +/** The maximum allowed size for a serialized block, in bytes (network rule) */ +static const unsigned int MAX_BLOCK_SIZE = MAX_BLOCK_COST/4; /** The maximum allowed number of signature check operations in a block (network rule) */ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ diff --git a/src/main.cpp b/src/main.cpp index 97388e1796348..02a6359809307 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3223,7 +3223,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn // Note: we aren't checking virtual size for blocks that aren't // witness enabled, but that's okay because CheckBlock still // checks the block size without any witnesses. - if (GetVirtualBlockSize(block) > MAX_BLOCK_SIZE) { + if (GetBlockCost(block) > MAX_BLOCK_COST) { return state.DoS(100, error("ContextualCheckBlock(): witness size limits failed"), REJECT_INVALID, "bad-blk-wit-length"); } return true; diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index ab1333351ce1f..fed8379ed1352 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -32,12 +32,13 @@ std::string CBlock::ToString() const return s.str(); } -size_t GetVirtualBlockSize(const CBlock& block) -{ - // The intended approximate formula is: vsize = base_size + witness_size / 4. - // We can only serialize base or base+witness, so the formula - // becomes: vsize = base_size + (total_size - base_size) / 4 or - // vsize = (total_size + 3 * base_size) / 4, which we round up to - // vsize = (total_size + 3 * base_size + 3) / 4. - return (::GetSerializeSize(block, SER_NETWORK, 0) * 3 + ::GetSerializeSize(block, SER_NETWORK, SERIALIZE_TRANSACTION_WITNESS) + 3) / 4; +size_t GetBlockCost(const CBlock& block) +{ + // coreSize is the size of block without witness data + size_t coreSize = ::GetSerializeSize(block, SER_NETWORK, 0); + size_t totalSize = ::GetSerializeSize(block, SER_NETWORK, SERIALIZE_TRANSACTION_WITNESS); + // size_t witSize = totalSize - coreSize; + // return witSize + 4 * coreSize; + // Since totalSize == witSize + coreSize, we can avoid a substraction + return totalSize + 3 * coreSize; } diff --git a/src/primitives/block.h b/src/primitives/block.h index 44ae695c5509d..076e49c6f9b4d 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -156,6 +156,6 @@ struct CBlockLocator }; /** Compute the consensus-critical virtual block size. */ -size_t GetVirtualBlockSize(const CBlock& tx); +size_t GetBlockCost(const CBlock& block); #endif // BITCOIN_PRIMITIVES_BLOCK_H diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 3e0d21b183432..a8c5c1906b2be 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -97,7 +97,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("confirmations", confirmations)); result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); result.push_back(Pair("wsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_WITNESS))); - result.push_back(Pair("vsize", (int)::GetVirtualBlockSize(block))); + result.push_back(Pair("bcost", (int)::GetBlockCost(block))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));