Skip to content

Commit 3babbcb

Browse files
committed
Remove confusing MAX_BLOCK_BASE_SIZE.
Some people keep thinking that MAX_BLOCK_BASE_SIZE is a separate size limit from the weight limit when it fact it is superfluous, and used in early tests before the witness data has been validated or just to compute worst case sizes. The size checks that use it would not behave any differently consensus wise if they were eliminated completely. Its correct value is not independently settable but is a function of the weight limit and weight formula. This patch just eliminates it and uses the scale factor as required to compute the worse case constants. It also moves the weight factor out of primitives into consensus, which is a more logical place for it.
1 parent e4fcbf7 commit 3babbcb

17 files changed

+43
-45
lines changed

src/bitcoin-tx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
239239
uint256 txid(uint256S(strTxid));
240240

241241
static const unsigned int minTxOutSz = 9;
242-
static const unsigned int maxVout = MAX_BLOCK_BASE_SIZE / minTxOutSz;
242+
static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
243243

244244
// extract and validate vout
245245
std::string strVout = vStrInputParts[1];

src/blockencodings.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
#include <unordered_map>
1717

18-
#define MIN_TRANSACTION_BASE_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS))
19-
2018
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID) :
2119
nonce(GetRand(std::numeric_limits<uint64_t>::max())),
2220
shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) {
@@ -50,7 +48,7 @@ uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const uint256& txhash) const {
5048
ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock, const std::vector<std::pair<uint256, CTransactionRef>>& extra_txn) {
5149
if (cmpctblock.header.IsNull() || (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty()))
5250
return READ_STATUS_INVALID;
53-
if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_BASE_SIZE / MIN_TRANSACTION_BASE_SIZE)
51+
if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_WEIGHT / MIN_SERIALIZEABLE_TRANSACTION_WEIGHT)
5452
return READ_STATUS_INVALID;
5553

5654
assert(header.IsNull() && txn_available.empty());

src/coins.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
245245
return true;
246246
}
247247

248-
static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_BASE_SIZE / ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION); // TODO: merge with similar definition in undo.h.
248+
static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION);
249+
static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT;
249250

250251
const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid)
251252
{

src/consensus/consensus.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,23 @@
66
#ifndef BITCOIN_CONSENSUS_CONSENSUS_H
77
#define BITCOIN_CONSENSUS_CONSENSUS_H
88

9+
#include <stdlib.h>
910
#include <stdint.h>
1011

1112
/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */
1213
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000;
1314
/** The maximum allowed weight for a block, see BIP 141 (network rule) */
1415
static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
15-
/**
16-
* The maximum allowed size for a block excluding witness data, in bytes (network rule).
17-
* This parameter is largely superfluous because it is directly implied by the above block
18-
* weight limit, even when BIP 141 is not active. It continues to exist for use in
19-
* various early tests that run before the witness data has been checked.
20-
* All tests related to it could be removed without breaking consensus compatibility.
21-
*/
22-
static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000;
2316
/** The maximum allowed number of signature check operations in a block (network rule) */
2417
static const int64_t MAX_BLOCK_SIGOPS_COST = 80000;
2518
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
2619
static const int COINBASE_MATURITY = 100;
2720

21+
static const int WITNESS_SCALE_FACTOR = 4;
22+
23+
static const size_t MIN_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 60; // 60 is the lower bound for the size of a valid serialized CTransaction
24+
static const size_t MIN_SERIALIZEABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 10; // 10 is the lower bound for the size of a serialized CTransaction
25+
2826
/** Flags for nSequence and nLockTime locks */
2927
enum {
3028
/* Interpret sequence numbers as relative lock-time constraints. */

src/consensus/tx_verify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
164164
if (tx.vout.empty())
165165
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
166166
// Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
167-
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE)
167+
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
168168
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
169169

170170
// Check for negative or overflow output values

src/consensus/validation.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
#define BITCOIN_CONSENSUS_VALIDATION_H
88

99
#include <string>
10+
#include "version.h"
11+
#include "consensus/consensus.h"
12+
#include "primitives/transaction.h"
13+
#include "primitives/block.h"
1014

1115
/** "reject" message codes */
1216
static const unsigned char REJECT_MALFORMED = 0x01;
@@ -85,4 +89,18 @@ class CValidationState {
8589
std::string GetDebugMessage() const { return strDebugMessage; }
8690
};
8791

92+
static inline int64_t GetTransactionWeight(const CTransaction& tx)
93+
{
94+
return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
95+
}
96+
97+
static inline int64_t GetBlockWeight(const CBlock& block)
98+
{
99+
// This implements the weight = (stripped_size * 4) + witness_size formula,
100+
// using only serialization with and without witness data. As witness_size
101+
// is equal to total_size - stripped_size, this formula is identical to:
102+
// weight = (stripped_size * 3) + total_size.
103+
return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
104+
}
105+
88106
#endif // BITCOIN_CONSENSUS_VALIDATION_H

src/core_write.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
#include "core_io.h"
66

77
#include "base58.h"
8-
#include "primitives/transaction.h"
8+
#include "consensus/consensus.h"
9+
#include "consensus/validation.h"
910
#include "script/script.h"
1011
#include "script/standard.h"
1112
#include "serialize.h"
@@ -15,7 +16,6 @@
1516
#include "utilmoneystr.h"
1617
#include "utilstrencodings.h"
1718

18-
1919
std::string FormatScript(const CScript& script)
2020
{
2121
std::string ret;

src/merkleblock.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch, std::ve
153153
if (nTransactions == 0)
154154
return uint256();
155155
// check for excessively high numbers of transactions
156-
if (nTransactions > MAX_BLOCK_BASE_SIZE / 60) // 60 is the lower bound for the size of a serialized CTransaction
156+
if (nTransactions > MAX_BLOCK_WEIGHT / MIN_TRANSACTION_WEIGHT)
157157
return uint256();
158158
// there can never be more hashes provided than one for every txid
159159
if (vHash.size() > nTransactions)

src/policy/policy.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "policy/policy.h"
99

10+
#include "consensus/validation.h"
1011
#include "validation.h"
1112
#include "coins.h"
1213
#include "tinyformat.h"

src/primitives/block.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,3 @@ std::string CBlock::ToString() const
3131
}
3232
return s.str();
3333
}
34-
35-
int64_t GetBlockWeight(const CBlock& block)
36-
{
37-
// This implements the weight = (stripped_size * 4) + witness_size formula,
38-
// using only serialization with and without witness data. As witness_size
39-
// is equal to total_size - stripped_size, this formula is identical to:
40-
// weight = (stripped_size * 3) + total_size.
41-
return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
42-
}

0 commit comments

Comments
 (0)