Skip to content

Commit 53d726e

Browse files
committed
Implementing base+wit/4 block size limit rule
1 parent 587dbee commit 53d726e

File tree

9 files changed

+28
-7
lines changed

9 files changed

+28
-7
lines changed

src/main.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& in
745745

746746

747747

748+
748749
bool CheckTransaction(const CTransaction& tx, CValidationState &state)
749750
{
750751
// Basic checks that don't depend on any context
@@ -753,7 +754,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
753754
if (tx.vout.empty())
754755
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
755756
// Size limits
756-
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
757+
if (GetVirtualTransactionSize(tx) > MAX_BLOCK_SIZE)
757758
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
758759

759760
// Check for negative or overflow output values
@@ -2977,7 +2978,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
29772978
// because we receive the wrong transactions for it.
29782979

29792980
// Size limits
2980-
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
2981+
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || GetVirtualBlockSize(block) > MAX_BLOCK_SIZE)
29812982
return state.DoS(100, error("CheckBlock(): size limits failed"),
29822983
REJECT_INVALID, "bad-blk-length");
29832984

src/primitives/block.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,12 @@ std::string CBlock::ToString() const
3131
}
3232
return s.str();
3333
}
34+
35+
size_t GetVirtualBlockSize(const CBlock& block)
36+
{
37+
// The formula is: vsize = base_size + witness_size / 4.
38+
// We can only serialize base or totalbase+witness, however, so the formula
39+
// becomes: vsize = base_size + (total_size - base_size) / 4 or
40+
// vsize = (total_size + 3 * base_size) / 4.
41+
return (::GetSerializeSize(block, SER_NETWORK, 0) * 3 + ::GetSerializeSize(block, SER_NETWORK, SERIALIZE_TRANSACTION_WITNESS) + 3) / 4;
42+
}

src/primitives/block.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,7 @@ struct CBlockLocator
155155
}
156156
};
157157

158+
/** Compute the consensus-critical virtual block size. */
159+
size_t GetVirtualBlockSize(const CBlock& tx);
160+
158161
#endif // BITCOIN_PRIMITIVES_BLOCK_H

src/primitives/transaction.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,8 @@ std::string CTransaction::ToString() const
148148
str += " " + vout[i].ToString() + "\n";
149149
return str;
150150
}
151+
152+
size_t GetVirtualTransactionSize(const CTransaction& tx)
153+
{
154+
return (::GetSerializeSize(tx, SER_NETWORK, 0) * 3 + ::GetSerializeSize(tx, SER_NETWORK, SERIALIZE_TRANSACTION_WITNESS) + 3) / 4;
155+
}

src/primitives/transaction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,7 @@ struct CMutableTransaction
408408
uint256 GetHash() const;
409409
};
410410

411+
/** Compute the consensus-critical virtual transaction size. */
412+
size_t GetVirtualTransactionSize(const CTransaction& tx);
413+
411414
#endif // BITCOIN_PRIMITIVES_TRANSACTION_H

src/test/mempool_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,12 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
363363
BOOST_CHECK(pool.exists(tx2.GetHash()));
364364
BOOST_CHECK(pool.exists(tx3.GetHash()));
365365

366-
pool.TrimToSize(::GetSerializeSize(CTransaction(tx1), SER_NETWORK, PROTOCOL_VERSION)); // mempool is limited to tx1's size in memory usage, so nothing fits
366+
pool.TrimToSize(GetVirtualTransactionSize(tx1)); // mempool is limited to tx1's size in memory usage, so nothing fits
367367
BOOST_CHECK(!pool.exists(tx1.GetHash()));
368368
BOOST_CHECK(!pool.exists(tx2.GetHash()));
369369
BOOST_CHECK(!pool.exists(tx3.GetHash()));
370370

371-
CFeeRate maxFeeRateRemoved(25000, ::GetSerializeSize(CTransaction(tx3), SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(CTransaction(tx2), SER_NETWORK, PROTOCOL_VERSION));
371+
CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(tx3) + GetVirtualTransactionSize(tx2));
372372
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
373373

374374
CMutableTransaction tx4 = CMutableTransaction();

src/test/policyestimator_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
5050
tx.vin[0].scriptSig = garbage;
5151
tx.vout.resize(1);
5252
tx.vout[0].nValue=0LL;
53-
CFeeRate baseRate(basefee, ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
53+
CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx));
5454

5555
// Create a fake block
5656
std::vector<CTransaction> block;

src/txmempool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
2727
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
2828
spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps)
2929
{
30-
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
30+
nTxSize = GetVirtualTransactionSize(tx);
3131
nModSize = tx.CalculateModifiedSize(nTxSize);
3232
nUsageSize = RecursiveDynamicUsage(tx);
3333

src/wallet/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2173,7 +2173,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
21732173
nIn++;
21742174
}
21752175

2176-
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
2176+
unsigned int nBytes = GetVirtualTransactionSize(txNew);
21772177

21782178
// Remove scriptSigs if we used dummy signatures for fee calculation
21792179
if (!sign) {

0 commit comments

Comments
 (0)