aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/undo.h3
-rw-r--r--src/validation.cpp17
2 files changed, 11 insertions, 9 deletions
diff --git a/src/undo.h b/src/undo.h
index d21b82e2ec..37a1c89f45 100644
--- a/src/undo.h
+++ b/src/undo.h
@@ -12,8 +12,7 @@
/** Undo information for a CTxIn
*
- * Contains the prevout's CTxOut being spent, and if this was the
- * last output of the affected transaction, its metadata as well
+ * Contains the prevout's CTxOut being spent, and its metadata as well
* (coinbase or not, height). Earlier versions also stored the transaction
* version.
*/
diff --git a/src/validation.cpp b/src/validation.cpp
index be0c9b564e..fccef17196 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1082,11 +1082,9 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund
// mark an outpoint spent, and construct undo information
txundo.vprevout.push_back(CTxInUndo(coins->vout[nPos]));
coins->Spend(nPos);
- if (coins->vout.size() == 0) {
- CTxInUndo& undo = txundo.vprevout.back();
- undo.nHeight = coins->nHeight;
- undo.fCoinBase = coins->fCoinBase;
- }
+ CTxInUndo& undo = txundo.vprevout.back();
+ undo.nHeight = coins->nHeight;
+ undo.fCoinBase = coins->fCoinBase;
}
}
// add outputs
@@ -1266,11 +1264,16 @@ int ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint&
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 = false; // overwriting existing transaction
+ if (!coins->IsPruned()) {
+ if (coins->fCoinBase != undo.fCoinBase || (uint32_t)coins->nHeight != undo.nHeight) fClean = false; // metadata mismatch
+ }
+ // restore height/coinbase tx metadata from undo data
coins->fCoinBase = undo.fCoinBase;
coins->nHeight = undo.nHeight;
} else {
+ // Undo data does not contain height/coinbase. This should never happen
+ // for newly created undo entries. Previously, this data was only saved
+ // for the last spend of a transaction's outputs, so check IsPruned().
if (coins->IsPruned()) fClean = false; // adding output to missing transaction
}
if (coins->IsAvailable(out.n)) fClean = false; // overwriting existing output