|
|
@ -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
|
|
|
|