Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,4 @@ tests: test_bip32 bitflash-node
./test_bip32
./bitflash-node -selftest=wallet-keypool
./bitflash-node -selftest=wallet-hd
./bitflash-node -selftest=consensus-limits
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@ bool CBlock::CheckBlock() const
// that can be verified before saving an orphan block.

// Size limits
if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
if (!CheckSizeLimits())
return error("CheckBlock() : size limits failed");

// Check timestamp
Expand Down
11 changes: 11 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ static const unsigned int MAX_ORPHAN_BLOCKS = 200;
// so a block within the size limit could still hold millions of them and take
// the network minutes of CPU to reject. Same value Bitcoin settled on.
static const unsigned int MAX_BLOCK_SIGOPS = 20000;
// Consensus block-size ceiling. MAX_SIZE is the serializer's generic safety
// limit (32 MB), not a block rule. Bitcoin 0.1.0 predated the later 1 MB block
// cap, so this tree inherited no real block-size consensus limit.
static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const int64 COIN = 100000000;
// Total Bitflash emission: identical to Bitcoin (21 million).
// MAX_MONEY guards against the value overflow bug (CVE-2010-5139), which in
Expand Down Expand Up @@ -1053,6 +1057,13 @@ class CBlock
return RandomXPoWHash((const void*)BEGIN(nVersion), END(nNonce) - BEGIN(nVersion));
}

bool CheckSizeLimits() const
{
return (!vtx.empty() &&
vtx.size() <= MAX_BLOCK_SIZE &&
::GetSerializeSize(*this, SER_DISK) <= MAX_BLOCK_SIZE);
}


uint256 BuildMerkleTree() const
{
Expand Down
1 change: 1 addition & 0 deletions src/makefile.mingw
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,4 @@ tests: test_bip32.exe bitflash.exe
./test_bip32.exe
./bitflash.exe -selftest=wallet-keypool
./bitflash.exe -selftest=wallet-hd
./bitflash.exe -selftest=consensus-limits
62 changes: 61 additions & 1 deletion src/selftest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,64 @@ static int RunWalletHDSelfTest()
return nFail == 0 ? 0 : 1;
}

static CBlock MakeSizedConsensusBlock(size_t nScriptBytes)
{
CTransaction tx;
tx.vin.push_back(CTxIn(COutPoint(), CScript() << 1 << 1));
tx.vout.push_back(CTxOut(0, CScript()));
tx.vout[0].scriptPubKey.insert(tx.vout[0].scriptPubKey.end(), nScriptBytes, 0);

CBlock block;
block.vtx.push_back(tx);
block.hashMerkleRoot = block.BuildMerkleTree();
block.nVersion = 1;
block.nTime = GetAdjustedTime();
block.nBits = bnProofOfWorkLimit.GetCompact();
block.nNonce = 0;
return block;
}

static int RunConsensusLimitsSelfTest()
{
fflush(stdout);
printf("consensus-limits self-test\n");

int nFail = 0;
try
{
nFail += Check(MAX_BLOCK_SIZE == 1000000,
"the consensus block-size cap is 1 MB") ? 0 : 1;
nFail += Check(MAX_BLOCK_SIZE < MAX_SIZE,
"the block cap is tighter than the serializer cap") ? 0 : 1;

CBlock small = MakeSizedConsensusBlock(100);
nFail += Check(small.CheckSizeLimits(),
"a small block is within the consensus size limit") ? 0 : 1;

CBlock oversized = MakeSizedConsensusBlock(MAX_BLOCK_SIZE);
unsigned int nSerialized = ::GetSerializeSize(oversized, SER_DISK);
nFail += Check(nSerialized > MAX_BLOCK_SIZE && nSerialized <= MAX_SIZE,
"the test block sits between 1 MB and the old 32 MB cap") ? 0 : 1;
nFail += Check(!oversized.CheckSizeLimits(),
"a block above 1 MB is outside the consensus size limit") ? 0 : 1;
}
catch (const std::exception& e)
{
printf(" FAIL exception: %s\n", e.what());
nFail++;
}
catch (...)
{
printf(" FAIL unknown exception\n");
nFail++;
}

printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
nFail, nFail == 1 ? "" : "s");
fflush(stdout);
return nFail == 0 ? 0 : 1;
}

int RunSelfTest(const std::string& name)
{
AttachTerminal();
Expand All @@ -478,8 +536,10 @@ int RunSelfTest(const std::string& name)
return RunWalletKeyPoolSelfTest();
if (name == "wallet-hd")
return RunWalletHDSelfTest();
if (name == "consensus-limits")
return RunConsensusLimitsSelfTest();

printf("Unknown self-test '%s'\n", name.c_str());
printf("Known self-tests: wallet-keypool, wallet-hd\n");
printf("Known self-tests: wallet-keypool, wallet-hd, consensus-limits\n");
return 1;
}