|
|
@ -1556,6 +1556,43 @@ void static FlushBlockFile(bool fFinalize = false) |
|
|
|
|
|
|
|
|
|
|
|
static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); |
|
|
|
static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Write undo information to disk
|
|
|
|
|
|
|
|
if (pindex->GetUndoPos().IsNull()) { |
|
|
|
|
|
|
|
CDiskBlockPos _pos; |
|
|
|
|
|
|
|
if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) |
|
|
|
|
|
|
|
return error("ConnectBlock(): FindUndoPos failed"); |
|
|
|
|
|
|
|
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) |
|
|
|
|
|
|
|
return AbortNode(state, "Failed to write undo data"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// update nUndoPos in block index
|
|
|
|
|
|
|
|
pindex->nUndoPos = _pos.nPos; |
|
|
|
|
|
|
|
pindex->nStatus |= BLOCK_HAVE_UNDO; |
|
|
|
|
|
|
|
setDirtyBlockIndex.insert(pindex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool WriteTxIndexDataForBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); |
|
|
|
|
|
|
|
std::vector<std::pair<uint256, CDiskTxPos> > vPos; |
|
|
|
|
|
|
|
vPos.reserve(block.vtx.size()); |
|
|
|
|
|
|
|
for (const CTransactionRef& tx : block.vtx) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vPos.push_back(std::make_pair(tx->GetHash(), pos)); |
|
|
|
|
|
|
|
pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fTxIndex) |
|
|
|
|
|
|
|
if (!pblocktree->WriteTxIndex(vPos)) |
|
|
|
|
|
|
|
return AbortNode(state, "Failed to write transaction index"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static CCheckQueue<CScriptCheck> scriptcheckqueue(128); |
|
|
|
static CCheckQueue<CScriptCheck> scriptcheckqueue(128); |
|
|
|
|
|
|
|
|
|
|
|
void ThreadScriptCheck() { |
|
|
|
void ThreadScriptCheck() { |
|
|
@ -1783,9 +1820,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd |
|
|
|
CAmount nFees = 0; |
|
|
|
CAmount nFees = 0; |
|
|
|
int nInputs = 0; |
|
|
|
int nInputs = 0; |
|
|
|
int64_t nSigOpsCost = 0; |
|
|
|
int64_t nSigOpsCost = 0; |
|
|
|
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); |
|
|
|
|
|
|
|
std::vector<std::pair<uint256, CDiskTxPos> > vPos; |
|
|
|
|
|
|
|
vPos.reserve(block.vtx.size()); |
|
|
|
|
|
|
|
blockundo.vtxundo.reserve(block.vtx.size() - 1); |
|
|
|
blockundo.vtxundo.reserve(block.vtx.size() - 1); |
|
|
|
std::vector<PrecomputedTransactionData> txdata; |
|
|
|
std::vector<PrecomputedTransactionData> txdata; |
|
|
|
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
|
|
|
|
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
|
|
|
@ -1846,9 +1880,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd |
|
|
|
blockundo.vtxundo.push_back(CTxUndo()); |
|
|
|
blockundo.vtxundo.push_back(CTxUndo()); |
|
|
|
} |
|
|
|
} |
|
|
|
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); |
|
|
|
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight); |
|
|
|
|
|
|
|
|
|
|
|
vPos.push_back(std::make_pair(tx.GetHash(), pos)); |
|
|
|
|
|
|
|
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2; |
|
|
|
int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2; |
|
|
|
LogPrint(BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (unsigned)block.vtx.size(), MILLI * (nTime3 - nTime2), MILLI * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * MICRO, nTimeConnect * MILLI / nBlocksTotal); |
|
|
|
LogPrint(BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (unsigned)block.vtx.size(), MILLI * (nTime3 - nTime2), MILLI * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * MICRO, nTimeConnect * MILLI / nBlocksTotal); |
|
|
@ -1868,28 +1899,16 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd |
|
|
|
if (fJustCheck) |
|
|
|
if (fJustCheck) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
// Write undo information to disk
|
|
|
|
if (!WriteUndoDataForBlock(blockundo, state, pindex, chainparams)) |
|
|
|
if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) |
|
|
|
return false; |
|
|
|
{ |
|
|
|
|
|
|
|
if (pindex->GetUndoPos().IsNull()) { |
|
|
|
|
|
|
|
CDiskBlockPos _pos; |
|
|
|
|
|
|
|
if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) |
|
|
|
|
|
|
|
return error("ConnectBlock(): FindUndoPos failed"); |
|
|
|
|
|
|
|
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) |
|
|
|
|
|
|
|
return AbortNode(state, "Failed to write undo data"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// update nUndoPos in block index
|
|
|
|
|
|
|
|
pindex->nUndoPos = _pos.nPos; |
|
|
|
|
|
|
|
pindex->nStatus |= BLOCK_HAVE_UNDO; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!pindex->IsValid(BLOCK_VALID_SCRIPTS)) { |
|
|
|
pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); |
|
|
|
pindex->RaiseValidity(BLOCK_VALID_SCRIPTS); |
|
|
|
setDirtyBlockIndex.insert(pindex); |
|
|
|
setDirtyBlockIndex.insert(pindex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fTxIndex) |
|
|
|
if (!WriteTxIndexDataForBlock(block, state, pindex)) |
|
|
|
if (!pblocktree->WriteTxIndex(vPos)) |
|
|
|
return false; |
|
|
|
return AbortNode(state, "Failed to write transaction index"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(pindex->phashBlock); |
|
|
|
assert(pindex->phashBlock); |
|
|
|
// add this block to the view's block chain
|
|
|
|
// add this block to the view's block chain
|
|
|
|