Skip to content

Commit

Permalink
Limit blocks by BDB locks required.
Browse files Browse the repository at this point in the history
This is a temporary measure to make the rebased client "compatible" with
the old BDB-based one.

Based on
bitcoin/bitcoin@8c222dc.
  • Loading branch information
domob1812 committed Dec 9, 2014
1 parent fd8d484 commit cdf312f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 3 deletions.
3 changes: 2 additions & 1 deletion TODO
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
* soft fork in namecoind:
+ prevent "name_new stealing" in memory pool
+ enforce nametx-version also for name *outputs*
- limit DB locks / unique tx
- disallow greedy names
- enforce nametx-version also for name *outputs*
- disallow auxpow parent blocks with auxpow
- update fee logic?

Expand Down
43 changes: 43 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2485,6 +2485,43 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
return true;
}

/* Temporary check that blocks are compatible with BDB's 10,000 lock limit.
This is based on Bitcoin's commit 8c222dca4f961ad13ec64d690134a40d09b20813.
Each "object" touched in the DB may cause two locks (one read and one
write lock). Objects are transaction IDs and names. Thus, count the
total number of transaction IDs (tx themselves plus all distinct inputs).
In addition, each Namecoin transaction could touch at most one name,
so add them as well. */
bool CheckDbLockLimit(const CBlock& block, const CTransaction* extraTx)
{
std::vector<CTransaction> vtx = block.vtx;
if (extraTx)
vtx.push_back(*extraTx);

set<uint256> setTxIds;
unsigned nNames = 0;
BOOST_FOREACH(const CTransaction& tx, vtx)
{
setTxIds.insert(tx.GetHash());
if (tx.IsNamecoin())
++nNames;

BOOST_FOREACH(const CTxIn& txIn, tx.vin)
setTxIds.insert(txIn.prevout.hash);
}

const unsigned nTotalIds = setTxIds.size() + nNames;

if (nTotalIds > 4500)
return error("%s : %u locks estimated, that is too much for BDB",
__func__, nTotalIds);

if (fDebug)
LogPrintf ("%s : need %u locks\n", __func__, nTotalIds);

return true;
}

bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW)
{
// Check proof of work matches claimed amount
Expand Down Expand Up @@ -2534,6 +2571,12 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
return state.DoS(100, error("CheckBlock() : size limits failed"),
REJECT_INVALID, "bad-blk-length");

// Enforce the temporary DB lock limit.
// TODO: Remove with a hardfork in the future.
if (!CheckDbLockLimit(block))
return state.DoS(100, error("%s : DB lock limit failed", __func__),
REJECT_INVALID, "bad-db-locks");

// First transaction must be coinbase, the rest must not be
if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
return state.DoS(100, error("CheckBlock() : first tx is not coinbase"),
Expand Down
3 changes: 3 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
/** Apply the effects of this block (with given index) on the UTXO set represented by coins */
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, std::set<valtype>& expiredNames, bool fJustCheck = false);

// TODO: Remove when this check is no longer necessary.
bool CheckDbLockLimit(const CBlock& block, const CTransaction* extraTx = NULL);

/** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
Expand Down
4 changes: 4 additions & 0 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
if (nBlockSize + nTxSize >= nBlockMaxSize)
continue;

// Check the DB lock limit won't be exceeded.
if (!CheckDbLockLimit(*pblock, &tx))
continue;

// Legacy limits on sigOps:
unsigned int nTxSigOps = GetLegacySigOpCount(tx);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
Expand Down
4 changes: 2 additions & 2 deletions src/rpcmining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,10 @@ Value getblocktemplate(const Array& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");

if (vNodes.empty())
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!");
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Namecoin is not connected!");

if (IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Namecoin is downloading blocks...");

static unsigned int nTransactionsUpdatedLast;

Expand Down

0 comments on commit cdf312f

Please sign in to comment.