Browse Source

Merge #5699: Split logic to undo txin's off DisconnectBlock.

eb1c2cd Split logic to undo txin's off DisconnectBlock. (Daniel Kraft)
0.13
Wladimir J. van der Laan 10 years ago
parent
commit
183ca292bd
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 62
      src/main.cpp

62
src/main.cpp

@ -1588,6 +1588,39 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
} // anon namespace } // 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) bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
{ {
assert(pindex->GetBlockHash() == view.GetBestBlock()); assert(pindex->GetBlockHash() == view.GetBestBlock());
@ -1613,11 +1646,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
uint256 hash = tx.GetHash(); uint256 hash = tx.GetHash();
// Check that all outputs are available and match the outputs in the block itself // 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 // exactly.
// have outputs available even in the block itself, so we handle that case
// specially with outsEmpty.
{ {
CCoins outsEmpty;
CCoinsModifier outs = view.ModifyCoins(hash); CCoinsModifier outs = view.ModifyCoins(hash);
outs->ClearUnspendable(); outs->ClearUnspendable();
@ -1642,24 +1672,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
for (unsigned int j = tx.vin.size(); j-- > 0;) { for (unsigned int j = tx.vin.size(); j-- > 0;) {
const COutPoint &out = tx.vin[j].prevout; const COutPoint &out = tx.vin[j].prevout;
const CTxInUndo &undo = txundo.vprevout[j]; const CTxInUndo &undo = txundo.vprevout[j];
CCoinsModifier coins = view.ModifyCoins(out.hash); if (!ApplyTxInUndo(undo, view, out))
if (undo.nHeight != 0) { fClean = false;
// 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;
} }
} }
} }
@ -1670,9 +1684,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (pfClean) { if (pfClean) {
*pfClean = fClean; *pfClean = fClean;
return true; return true;
} else {
return fClean;
} }
return fClean;
} }
void static FlushBlockFile(bool fFinalize = false) void static FlushBlockFile(bool fFinalize = false)

Loading…
Cancel
Save