Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 1,449 Lines • ▼ Show 20 Lines | static void InvalidBlockFound(CBlockIndex *pindex, | ||||
if (!state.CorruptionPossible()) { | if (!state.CorruptionPossible()) { | ||||
pindex->nStatus = pindex->nStatus.withFailed(); | pindex->nStatus = pindex->nStatus.withFailed(); | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
setBlockIndexCandidates.erase(pindex); | setBlockIndexCandidates.erase(pindex); | ||||
InvalidChainFound(pindex); | InvalidChainFound(pindex); | ||||
} | } | ||||
} | } | ||||
void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, | void SpendCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, | ||||
int nHeight) { | int nHeight) { | ||||
// Mark inputs spent. | // Mark inputs spent. | ||||
if (!tx.IsCoinBase()) { | if (tx.IsCoinBase()) { | ||||
return; | |||||
} | |||||
txundo.vprevout.reserve(tx.vin.size()); | txundo.vprevout.reserve(tx.vin.size()); | ||||
for (const CTxIn &txin : tx.vin) { | for (const CTxIn &txin : tx.vin) { | ||||
txundo.vprevout.emplace_back(); | txundo.vprevout.emplace_back(); | ||||
bool is_spent = | bool is_spent = view.SpendCoin(txin.prevout, &txundo.vprevout.back()); | ||||
view.SpendCoin(txin.prevout, &txundo.vprevout.back()); | |||||
assert(is_spent); | assert(is_spent); | ||||
} | } | ||||
} | } | ||||
// Add outputs. | void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, CTxUndo &txundo, | ||||
int nHeight) { | |||||
SpendCoins(view, tx, txundo, nHeight); | |||||
AddCoins(view, tx, nHeight); | AddCoins(view, tx, nHeight); | ||||
} | } | ||||
void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, int nHeight) { | void UpdateCoins(CCoinsViewCache &view, const CTransaction &tx, int nHeight) { | ||||
CTxUndo txundo; | // Mark inputs spent. | ||||
UpdateCoins(view, tx, txundo, nHeight); | if (!tx.IsCoinBase()) { | ||||
for (const CTxIn &txin : tx.vin) { | |||||
bool is_spent = view.SpendCoin(txin.prevout); | |||||
assert(is_spent); | |||||
} | |||||
} | |||||
jasonbcox: This block is not consistent with the other UpdateCoins() function. Shouldn't this be… | |||||
deadalnixAuthorUnsubmitted Not Done Inline ActionsWhy isn't it consistent ? It does the same, without updating the undo datastructure. deadalnix: Why isn't it consistent ? It does the same, without updating the undo datastructure. | |||||
// Add outputs. | |||||
AddCoins(view, tx, nHeight); | |||||
} | } | ||||
bool CScriptCheck::operator()() { | bool CScriptCheck::operator()() { | ||||
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; | const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; | ||||
return VerifyScript(scriptSig, scriptPubKey, nFlags, | return VerifyScript(scriptSig, scriptPubKey, nFlags, | ||||
CachingTransactionSignatureChecker(ptxTo, nIn, amount, | CachingTransactionSignatureChecker(ptxTo, nIn, amount, | ||||
cacheStore, txdata), | cacheStore, txdata), | ||||
&error); | &error); | ||||
▲ Show 20 Lines • Show All 756 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < block.vtx.size(); i++) { | ||||
control.Add(vChecks); | control.Add(vChecks); | ||||
} | } | ||||
CTxUndo undoDummy; | CTxUndo undoDummy; | ||||
if (i > 0) { | if (i > 0) { | ||||
blockundo.vtxundo.push_back(CTxUndo()); | blockundo.vtxundo.push_back(CTxUndo()); | ||||
} | } | ||||
UpdateCoins(view, tx, i == 0 ? undoDummy : blockundo.vtxundo.back(), | SpendCoins(view, tx, i == 0 ? undoDummy : blockundo.vtxundo.back(), | ||||
pindex->nHeight); | pindex->nHeight); | ||||
AddCoins(view, tx, pindex->nHeight); | |||||
jasonbcoxUnsubmitted Not Done Inline ActionsWhy split this apart? Do you plan on removing UpdateCoin() all together? jasonbcox: Why split this apart? Do you plan on removing UpdateCoin() all together? | |||||
deadalnixAuthorUnsubmitted Not Done Inline ActionsThe goal of this refactoring is to get to a position where we add the output in one pass and then mark the coin spent in a second pass. Separating adding and spending is the first step toward this. RollforwardBlock already does it in two passes, but ConnectBlock require some more refactoring and some activation mechanism before it can do it. deadalnix: The goal of this refactoring is to get to a position where we add the output in one pass and… | |||||
vPos.push_back(std::make_pair(tx.GetId(), pos)); | vPos.push_back(std::make_pair(tx.GetId(), pos)); | ||||
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); | pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); | ||||
} | } | ||||
int64_t nTime3 = GetTimeMicros(); | int64_t nTime3 = GetTimeMicros(); | ||||
nTimeConnect += nTime3 - nTime2; | nTimeConnect += nTime3 - nTime2; | ||||
LogPrint(BCLog::BENCH, | LogPrint(BCLog::BENCH, | ||||
▲ Show 20 Lines • Show All 2,389 Lines • ▼ Show 20 Lines | static bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &view, | ||||
// TODO: merge with ConnectBlock | // TODO: merge with ConnectBlock | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pindex, config)) { | if (!ReadBlockFromDisk(block, pindex, config)) { | ||||
return error("ReplayBlock(): ReadBlockFromDisk failed at %d, hash=%s", | return error("ReplayBlock(): ReadBlockFromDisk failed at %d, hash=%s", | ||||
pindex->nHeight, pindex->GetBlockHash().ToString()); | pindex->nHeight, pindex->GetBlockHash().ToString()); | ||||
} | } | ||||
for (const CTransactionRef &tx : block.vtx) { | for (const CTransactionRef &tx : block.vtx) { | ||||
if (!tx->IsCoinBase()) { | // Pass check = true as every addition may be an overwrite. | ||||
for (const CTxIn &txin : tx->vin) { | AddCoins(view, *tx, pindex->nHeight, true); | ||||
view.SpendCoin(txin.prevout); | |||||
} | } | ||||
for (const CTransactionRef &tx : block.vtx) { | |||||
if (tx->IsCoinBase()) { | |||||
continue; | |||||
} | } | ||||
// Pass check = true as every addition may be an overwrite. | for (const CTxIn &txin : tx->vin) { | ||||
AddCoins(view, *tx, pindex->nHeight, true); | view.SpendCoin(txin.prevout); | ||||
} | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool ReplayBlocks(const Config &config, CCoinsView *view) { | bool ReplayBlocks(const Config &config, CCoinsView *view) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
▲ Show 20 Lines • Show All 860 Lines • Show Last 20 Lines |
This block is not consistent with the other UpdateCoins() function. Shouldn't this be encapsulated in another SpendCoins() function, but without the CTxUndo param? As a side effect, the tx.IsCoinBase() check can be separated rather than wrapping the rest of the logic.