From c444c620c62c51d65f7de0b2a3c351e61ab1e388 Mon Sep 17 00:00:00 2001 From: jtimon Date: Sun, 19 Oct 2014 02:57:02 +0200 Subject: [PATCH 1/5] Decouple CCoins from CTxInUndo --- src/coins.cpp | 22 ++++------------------ src/coins.h | 6 +----- src/main.cpp | 17 ++++++++++++++--- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index bc430c9c7..f4599ff39 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -31,29 +31,15 @@ void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) con nBytes += nLastUsedByte; } -bool CCoins::Spend(const COutPoint &out, CTxInUndo &undo) { - if (out.n >= vout.size()) +bool CCoins::Spend(uint32_t nPos) +{ + if (nPos >= vout.size() || vout[nPos].IsNull()) return false; - if (vout[out.n].IsNull()) - return false; - undo = CTxInUndo(vout[out.n]); - vout[out.n].SetNull(); + vout[nPos].SetNull(); Cleanup(); - if (vout.size() == 0) { - undo.nHeight = nHeight; - undo.fCoinBase = fCoinBase; - undo.nVersion = this->nVersion; - } return true; } -bool CCoins::Spend(int nPos) { - CTxInUndo undo; - COutPoint out(0, nPos); - return Spend(out, undo); -} - - bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; } bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; } uint256 CCoinsView::GetBestBlock() const { return uint256(0); } diff --git a/src/coins.h b/src/coins.h index 9b73ae3a8..2be52ad17 100644 --- a/src/coins.h +++ b/src/coins.h @@ -9,7 +9,6 @@ #include "compressor.h" #include "serialize.h" #include "uint256.h" -#include "undo.h" #include #include @@ -237,11 +236,8 @@ public: Cleanup(); } - //! mark an outpoint spent, and construct undo information - bool Spend(const COutPoint &out, CTxInUndo &undo); - //! mark a vout spent - bool Spend(int nPos); + bool Spend(uint32_t nPos); //! check whether a particular output is still available bool IsAvailable(unsigned int nPos) const { diff --git a/src/main.cpp b/src/main.cpp index 2410230ef..3f775e3d3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1383,9 +1383,20 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach if (!tx.IsCoinBase()) { txundo.vprevout.reserve(tx.vin.size()); BOOST_FOREACH(const CTxIn &txin, tx.vin) { - txundo.vprevout.push_back(CTxInUndo()); - bool ret = inputs.ModifyCoins(txin.prevout.hash)->Spend(txin.prevout, txundo.vprevout.back()); - assert(ret); + CCoinsModifier coins = inputs.ModifyCoins(txin.prevout.hash); + unsigned nPos = txin.prevout.n; + + if (nPos >= coins->vout.size() || coins->vout[nPos].IsNull()) + assert(false); + // 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; + undo.nVersion = coins->nVersion; + } } } From d7621ccf9d064db19de742ed1a0ac59fffa06c0d Mon Sep 17 00:00:00 2001 From: jtimon Date: Mon, 27 Oct 2014 16:07:50 +0100 Subject: [PATCH 2/5] Decouple miner.o and txmempool.o from CTxUndo --- src/main.cpp | 6 ++++++ src/main.h | 2 +- src/miner.cpp | 3 +-- src/txmempool.cpp | 7 +++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3f775e3d3..bcd3a5ff0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1404,6 +1404,12 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach inputs.ModifyCoins(tx.GetHash())->FromTx(tx, nHeight); } +void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight) +{ + CTxUndo txundo; + UpdateCoins(tx, state, inputs, txundo, nHeight); +} + bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingSignatureChecker(*ptxTo, nIn, cacheStore), &error)) { diff --git a/src/main.h b/src/main.h index 662d5756f..e38b413be 100644 --- a/src/main.h +++ b/src/main.h @@ -290,7 +290,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi unsigned int flags, bool cacheStore, std::vector *pvChecks = NULL); /** Apply the effects of this transaction on the UTXO set represented by view */ -void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight); +void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight); /** Context-independent validity checks */ bool CheckTransaction(const CTransaction& tx, CValidationState& state); diff --git a/src/miner.cpp b/src/miner.cpp index 2133b13e6..0ac974d6e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -279,8 +279,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true)) continue; - CTxUndo txundo; - UpdateCoins(tx, state, view, txundo, nHeight); + UpdateCoins(tx, state, view, nHeight); // Added pblock->vtx.push_back(tx); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 3071ab025..01bf1ec08 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -585,9 +585,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const if (fDependsWait) waitingOnDependants.push_back(&it->second); else { - CValidationState state; CTxUndo undo; + CValidationState state; assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL)); - UpdateCoins(tx, state, mempoolDuplicate, undo, 1000000); + UpdateCoins(tx, state, mempoolDuplicate, 1000000); } } unsigned int stepsSinceLastRemove = 0; @@ -601,8 +601,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const assert(stepsSinceLastRemove < waitingOnDependants.size()); } else { assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL)); - CTxUndo undo; - UpdateCoins(entry->GetTx(), state, mempoolDuplicate, undo, 1000000); + UpdateCoins(entry->GetTx(), state, mempoolDuplicate, 1000000); stepsSinceLastRemove = 0; } } From e035c6a7371027fe33c460ee2d0946a7f1e4e592 Mon Sep 17 00:00:00 2001 From: jtimon Date: Mon, 27 Oct 2014 14:35:52 +0100 Subject: [PATCH 3/5] Decouple CBlockUndo from CDiskBlockPos --- src/main.cpp | 31 ++++++++++++++++--------------- src/main.h | 3 --- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bcd3a5ff0..ec24e55ce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1520,7 +1520,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi return true; } - +bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock); +bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock); bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean) { @@ -1535,7 +1536,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex CDiskBlockPos pos = pindex->GetUndoPos(); if (pos.IsNull()) return error("DisconnectBlock() : no undo data available"); - if (!blockUndo.ReadFromDisk(pos, pindex->pprev->GetBlockHash())) + if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) return error("DisconnectBlock() : failure reading undo data"); if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) @@ -1777,7 +1778,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CDiskBlockPos pos; if (!FindUndoPos(state, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) return error("ConnectBlock() : FindUndoPos failed"); - if (!blockundo.WriteToDisk(pos, pindex->pprev->GetBlockHash())) + if (!UndoWriteToDisk(blockundo, pos, pindex->pprev->GetBlockHash())) return state.Abort("Failed to write undo data"); // update nUndoPos in block index @@ -2943,7 +2944,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth CBlockUndo undo; CDiskBlockPos pos = pindex->GetUndoPos(); if (!pos.IsNull()) { - if (!undo.ReadFromDisk(pos, pindex->pprev->GetBlockHash())) + if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash())) return error("VerifyDB() : *** found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); } } @@ -4509,44 +4510,44 @@ bool SendMessages(CNode* pto, bool fSendTrickle) } -bool CBlockUndo::WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock) +bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock) { // Open history file to append CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); if (fileout.IsNull()) - return error("CBlockUndo::WriteToDisk : OpenUndoFile failed"); + return error("%s : OpenUndoFile failed", __func__); // Write index header - unsigned int nSize = fileout.GetSerializeSize(*this); + unsigned int nSize = fileout.GetSerializeSize(blockundo); fileout << FLATDATA(Params().MessageStart()) << nSize; // Write undo data long fileOutPos = ftell(fileout.Get()); if (fileOutPos < 0) - return error("CBlockUndo::WriteToDisk : ftell failed"); + return error("%s : ftell failed", __func__); pos.nPos = (unsigned int)fileOutPos; - fileout << *this; + fileout << blockundo; // calculate & write checksum CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); hasher << hashBlock; - hasher << *this; + hasher << blockundo; fileout << hasher.GetHash(); return true; } -bool CBlockUndo::ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock) +bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock) { // Open history file to read CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); if (filein.IsNull()) - return error("CBlockUndo::ReadFromDisk : OpenBlockFile failed"); + return error("%s : OpenBlockFile failed", __func__); // Read block uint256 hashChecksum; try { - filein >> *this; + filein >> blockundo; filein >> hashChecksum; } catch (const std::exception& e) { @@ -4556,9 +4557,9 @@ bool CBlockUndo::ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock // Verify checksum CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); hasher << hashBlock; - hasher << *this; + hasher << blockundo; if (hashChecksum != hasher.GetHash()) - return error("CBlockUndo::ReadFromDisk : Checksum mismatch"); + return error("%s : Checksum mismatch", __func__); return true; } diff --git a/src/main.h b/src/main.h index e38b413be..7d6c293a3 100644 --- a/src/main.h +++ b/src/main.h @@ -314,9 +314,6 @@ public: inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { READWRITE(vtxundo); } - - bool WriteToDisk(CDiskBlockPos &pos, const uint256 &hashBlock); - bool ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock); }; From 937ba572d0758891f43c658d7d98d7bd747c3ce4 Mon Sep 17 00:00:00 2001 From: jtimon Date: Mon, 27 Oct 2014 14:42:49 +0100 Subject: [PATCH 4/5] MOVEONLY: CBlockUndo from main.h to undo.h --- src/main.cpp | 1 + src/main.h | 16 ---------------- src/undo.h | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ec24e55ce..24ed487af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ #include "txdb.h" #include "txmempool.h" #include "ui_interface.h" +#include "undo.h" #include "util.h" #include "utilmoneystr.h" diff --git a/src/main.h b/src/main.h index 7d6c293a3..9049f5bb7 100644 --- a/src/main.h +++ b/src/main.h @@ -25,7 +25,6 @@ #include "tinyformat.h" #include "txmempool.h" #include "uint256.h" -#include "undo.h" #include #include @@ -302,21 +301,6 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason); bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0); -/** Undo information for a CBlock */ -class CBlockUndo -{ -public: - std::vector vtxundo; // for all but the coinbase - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(vtxundo); - } -}; - - /** * Closure representing one script verification * Note that this stores references to the spending transaction diff --git a/src/undo.h b/src/undo.h index e6d8fd586..1c4ed95bf 100644 --- a/src/undo.h +++ b/src/undo.h @@ -68,4 +68,18 @@ public: } }; +/** Undo information for a CBlock */ +class CBlockUndo +{ +public: + std::vector vtxundo; // for all but the coinbase + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(vtxundo); + } +}; + #endif // BITCOIN_UNDO_H From 87fb31086d70e4902170976ce261a01c8c380c00 Mon Sep 17 00:00:00 2001 From: jtimon Date: Wed, 3 Dec 2014 00:39:03 +0100 Subject: [PATCH 5/5] Move UndoWriteToDisk() and UndoReadFromDisk() to anon namespace --- src/main.cpp | 114 +++++++++++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 24ed487af..f6033566e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1521,8 +1521,63 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi return true; } -bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock); -bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock); +namespace { + +bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock) +{ + // Open history file to append + CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); + if (fileout.IsNull()) + return error("%s : OpenUndoFile failed", __func__); + + // Write index header + unsigned int nSize = fileout.GetSerializeSize(blockundo); + fileout << FLATDATA(Params().MessageStart()) << nSize; + + // Write undo data + long fileOutPos = ftell(fileout.Get()); + if (fileOutPos < 0) + return error("%s : ftell failed", __func__); + pos.nPos = (unsigned int)fileOutPos; + fileout << blockundo; + + // calculate & write checksum + CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); + hasher << hashBlock; + hasher << blockundo; + fileout << hasher.GetHash(); + + return true; +} + +bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock) +{ + // Open history file to read + CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); + if (filein.IsNull()) + return error("%s : OpenBlockFile failed", __func__); + + // Read block + uint256 hashChecksum; + try { + filein >> blockundo; + filein >> hashChecksum; + } + catch (const std::exception& e) { + return error("%s : Deserialize or I/O error - %s", __func__, e.what()); + } + + // Verify checksum + CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); + hasher << hashBlock; + hasher << blockundo; + if (hashChecksum != hasher.GetHash()) + return error("%s : Checksum mismatch", __func__); + + return true; +} + +} // anon namespace bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean) { @@ -4510,61 +4565,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle) return true; } - -bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock) -{ - // Open history file to append - CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); - if (fileout.IsNull()) - return error("%s : OpenUndoFile failed", __func__); - - // Write index header - unsigned int nSize = fileout.GetSerializeSize(blockundo); - fileout << FLATDATA(Params().MessageStart()) << nSize; - - // Write undo data - long fileOutPos = ftell(fileout.Get()); - if (fileOutPos < 0) - return error("%s : ftell failed", __func__); - pos.nPos = (unsigned int)fileOutPos; - fileout << blockundo; - - // calculate & write checksum - CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); - hasher << hashBlock; - hasher << blockundo; - fileout << hasher.GetHash(); - - return true; -} - -bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock) -{ - // Open history file to read - CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); - if (filein.IsNull()) - return error("%s : OpenBlockFile failed", __func__); - - // Read block - uint256 hashChecksum; - try { - filein >> blockundo; - filein >> hashChecksum; - } - catch (const std::exception& e) { - return error("%s : Deserialize or I/O error - %s", __func__, e.what()); - } - - // Verify checksum - CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION); - hasher << hashBlock; - hasher << blockundo; - if (hashChecksum != hasher.GetHash()) - return error("%s : Checksum mismatch", __func__); - - return true; -} - std::string CBlockFileInfo::ToString() const { return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst), DateTimeStrFormat("%Y-%m-%d", nTimeLast)); }