Merge #5699: Split logic to undo txin's off DisconnectBlock.
eb1c2cd
Split logic to undo txin's off DisconnectBlock. (Daniel Kraft)
This commit is contained in:
commit
183ca292bd
62
src/main.cpp
62
src/main.cpp
@ -1588,6 +1588,39 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
|
||||
|
||||
} // anon namespace
|
||||
|
||||
/**
|
||||
* Apply the undo operation of a CTxInUndo to the given chain state.
|
||||
* @param undo The undo object.
|
||||
* @param view The coins view to which to apply the changes.
|
||||
* @param out The out point that corresponds to the tx input.
|
||||
* @return True on success.
|
||||
*/
|
||||
static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint& out)
|
||||
{
|
||||
bool fClean = true;
|
||||
|
||||
CCoinsModifier coins = view.ModifyCoins(out.hash);
|
||||
if (undo.nHeight != 0) {
|
||||
// undo data contains height: this is the last output of the prevout tx being spent
|
||||
if (!coins->IsPruned())
|
||||
fClean = fClean && error("%s: undo data overwriting existing transaction", __func__);
|
||||
coins->Clear();
|
||||
coins->fCoinBase = undo.fCoinBase;
|
||||
coins->nHeight = undo.nHeight;
|
||||
coins->nVersion = undo.nVersion;
|
||||
} else {
|
||||
if (coins->IsPruned())
|
||||
fClean = fClean && error("%s: undo data adding output to missing transaction", __func__);
|
||||
}
|
||||
if (coins->IsAvailable(out.n))
|
||||
fClean = fClean && error("%s: undo data overwriting existing output", __func__);
|
||||
if (coins->vout.size() < out.n+1)
|
||||
coins->vout.resize(out.n+1);
|
||||
coins->vout[out.n] = undo.txout;
|
||||
|
||||
return fClean;
|
||||
}
|
||||
|
||||
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
|
||||
{
|
||||
assert(pindex->GetBlockHash() == view.GetBestBlock());
|
||||
@ -1613,11 +1646,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||
uint256 hash = tx.GetHash();
|
||||
|
||||
// Check that all outputs are available and match the outputs in the block itself
|
||||
// exactly. Note that transactions with only provably unspendable outputs won't
|
||||
// have outputs available even in the block itself, so we handle that case
|
||||
// specially with outsEmpty.
|
||||
// exactly.
|
||||
{
|
||||
CCoins outsEmpty;
|
||||
CCoinsModifier outs = view.ModifyCoins(hash);
|
||||
outs->ClearUnspendable();
|
||||
|
||||
@ -1642,24 +1672,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||
for (unsigned int j = tx.vin.size(); j-- > 0;) {
|
||||
const COutPoint &out = tx.vin[j].prevout;
|
||||
const CTxInUndo &undo = txundo.vprevout[j];
|
||||
CCoinsModifier coins = view.ModifyCoins(out.hash);
|
||||
if (undo.nHeight != 0) {
|
||||
// undo data contains height: this is the last output of the prevout tx being spent
|
||||
if (!coins->IsPruned())
|
||||
fClean = fClean && error("DisconnectBlock(): undo data overwriting existing transaction");
|
||||
coins->Clear();
|
||||
coins->fCoinBase = undo.fCoinBase;
|
||||
coins->nHeight = undo.nHeight;
|
||||
coins->nVersion = undo.nVersion;
|
||||
} else {
|
||||
if (coins->IsPruned())
|
||||
fClean = fClean && error("DisconnectBlock(): undo data adding output to missing transaction");
|
||||
}
|
||||
if (coins->IsAvailable(out.n))
|
||||
fClean = fClean && error("DisconnectBlock(): undo data overwriting existing output");
|
||||
if (coins->vout.size() < out.n+1)
|
||||
coins->vout.resize(out.n+1);
|
||||
coins->vout[out.n] = undo.txout;
|
||||
if (!ApplyTxInUndo(undo, view, out))
|
||||
fClean = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1670,9 +1684,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||
if (pfClean) {
|
||||
*pfClean = fClean;
|
||||
return true;
|
||||
} else {
|
||||
return fClean;
|
||||
}
|
||||
|
||||
return fClean;
|
||||
}
|
||||
|
||||
void static FlushBlockFile(bool fFinalize = false)
|
||||
|
Loading…
Reference in New Issue
Block a user