Merge #5111 from
branch 'core2' of git://github.com/jtimon/bitcoin into merge-5111
This commit is contained in:
commit
aa5c0d34b7
7 changed files with 104 additions and 110 deletions
|
@ -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); }
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "compressor.h"
|
||||
#include "serialize.h"
|
||||
#include "uint256.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
@ -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 {
|
||||
|
|
141
src/main.cpp
141
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"
|
||||
|
||||
|
@ -1383,9 +1384,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1393,6 +1405,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)) {
|
||||
|
@ -1503,7 +1521,63 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
|
|||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1518,7 +1592,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())
|
||||
|
@ -1760,7 +1834,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
|
||||
|
@ -2926,7 +3000,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());
|
||||
}
|
||||
}
|
||||
|
@ -4491,61 +4565,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBlockUndo::WriteToDisk(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");
|
||||
|
||||
// Write index header
|
||||
unsigned int nSize = fileout.GetSerializeSize(*this);
|
||||
fileout << FLATDATA(Params().MessageStart()) << nSize;
|
||||
|
||||
// Write undo data
|
||||
long fileOutPos = ftell(fileout.Get());
|
||||
if (fileOutPos < 0)
|
||||
return error("CBlockUndo::WriteToDisk : ftell failed");
|
||||
pos.nPos = (unsigned int)fileOutPos;
|
||||
fileout << *this;
|
||||
|
||||
// calculate & write checksum
|
||||
CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
|
||||
hasher << hashBlock;
|
||||
hasher << *this;
|
||||
fileout << hasher.GetHash();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBlockUndo::ReadFromDisk(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");
|
||||
|
||||
// Read block
|
||||
uint256 hashChecksum;
|
||||
try {
|
||||
filein >> *this;
|
||||
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 << *this;
|
||||
if (hashChecksum != hasher.GetHash())
|
||||
return error("CBlockUndo::ReadFromDisk : Checksum mismatch");
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
21
src/main.h
21
src/main.h
|
@ -25,7 +25,6 @@
|
|||
#include "tinyformat.h"
|
||||
#include "txmempool.h"
|
||||
#include "uint256.h"
|
||||
#include "undo.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
|
@ -290,7 +289,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
|
|||
unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *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);
|
||||
|
@ -302,24 +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<CTxUndo> vtxundo; // for all but the coinbase
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Closure representing one script verification
|
||||
* Note that this stores references to the spending transaction
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
14
src/undo.h
14
src/undo.h
|
@ -68,4 +68,18 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/** Undo information for a CBlock */
|
||||
class CBlockUndo
|
||||
{
|
||||
public:
|
||||
std::vector<CTxUndo> vtxundo; // for all but the coinbase
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||
READWRITE(vtxundo);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_UNDO_H
|
||||
|
|
Loading…
Reference in a new issue