Skip to content

Commit 20aa121

Browse files
authored
Merge pull request #4 from btc1/2017_max_tx_size
[consensus] Hard limit on transaction size / decouple from block size limit
2 parents 1ab2dda + 5b9520e commit 20aa121

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

src/consensus/consensus.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
1616
static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000;
1717
/** The maximum allowed number of signature check operations in a block (network rule) */
1818
static const int64_t MAX_BLOCK_SIGOPS_COST = 80000;
19+
20+
/** The maximum allowed size for a transaction, excluding witness data, in bytes */
21+
static const unsigned int MAX_TX_BASE_SIZE = 1000000;
22+
1923
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
2024
static const int COINBASE_MATURITY = 100;
2125

src/test/transaction_tests.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,45 @@ BOOST_AUTO_TEST_CASE(test_witness)
667667
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
668668
}
669669

670+
BOOST_AUTO_TEST_CASE(test_tx_sizelimits)
671+
{
672+
CBasicKeyStore keystore;
673+
CCoinsView coinsDummy;
674+
CCoinsViewCache coins(&coinsDummy);
675+
std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
676+
677+
CMutableTransaction tx;
678+
tx.nVersion = 1;
679+
tx.vin.resize(1);
680+
tx.vin[0].prevout.hash = dummyTransactions[0].GetHash();
681+
tx.vin[0].prevout.n = 0;
682+
tx.vout.resize(1);
683+
tx.vout[0].nValue = 1;
684+
tx.vout[0].scriptPubKey = CScript();
685+
686+
size_t sersizeTx = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
687+
688+
BOOST_CHECK(sersizeTx <= MAX_TX_BASE_SIZE);
689+
690+
CValidationState state;
691+
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple transaction should be valid.");
692+
693+
const size_t nTestOutputs = 125000;
694+
tx.vout.resize(nTestOutputs);
695+
696+
for (size_t i = 0; i < nTestOutputs; i++) {
697+
tx.vout[i].nValue = 1;
698+
tx.vout[i].scriptPubKey = CScript();
699+
}
700+
701+
sersizeTx = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
702+
703+
BOOST_CHECK(sersizeTx > MAX_TX_BASE_SIZE);
704+
705+
BOOST_CHECK_MESSAGE(!CheckTransaction(tx, state) || !state.IsValid(), "Large transaction should be invalid.");
706+
707+
}
708+
670709
BOOST_AUTO_TEST_CASE(test_IsStandard)
671710
{
672711
LOCK(cs_main);

src/validation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
497497
if (tx.vout.empty())
498498
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
499499
// Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
500-
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE)
500+
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_TX_BASE_SIZE)
501501
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
502502

503503
// Check for negative or overflow output values

0 commit comments

Comments
 (0)