else
nTxPos = ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - (2 * GetSizeOfCompactSize(0)) + GetSizeOfCompactSize(vtx.size());
+ CBlockUndo blockundo;
+
map<uint256, CTxIndex> mapQueuedChanges;
int64 nFees = 0;
int64 nValueIn = 0;
nValueOut += tx.GetValueOut();
else
{
+ CTxUndo undo;
+
bool fInvalid;
if (!tx.FetchInputs(txdb, mapQueuedChanges, true, false, mapInputs, fInvalid))
return false;
if (!tx.IsCoinStake())
nFees += nTxValueIn - nTxValueOut;
+
+ BOOST_FOREACH(const CTxIn &in, tx.vin) {
+ undo.vprevout.push_back(CTxInUndo(mapInputs[in.prevout.hash].second.vout[in.prevout.n], pindex->nHeight));
+ }
+
if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false, fStrictPayToScriptHash))
return false;
+
+ blockundo.vtxundo.push_back(undo);
}
mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size());
return error("ConnectBlock() : WriteBlockIndex failed");
}
+ // Write undo information to disk
+ if (pindex->nHeight > Checkpoints::GetTotalBlocksEstimate())
+ {
+ CAutoFile fileUndo(fopen(pindex->GetBlockPos().GetUndoFile(GetDataDir()).string().c_str(), "wb"), SER_DISK, CLIENT_VERSION);
+ fileUndo << blockundo;
+ }
+
// Watch for transactions paying to me
BOOST_FOREACH(CTransaction& tx, vtx)
SyncWithWallets(tx, this, true);
return GetDirectory(base) / strprintf("%08u%s.blk", nHeight, GetAlternative().c_str());
}
+ boost::filesystem::path GetUndoFile(const boost::filesystem::path &base) const {
+ return GetDirectory(base) / strprintf("%08u%s.und", nHeight, GetAlternative().c_str());
+ }
+
// TODO: make thread-safe (lockfile, atomic file creation, ...?)
void MakeUnique(const boost::filesystem::path &base) {
while (boost::filesystem::exists(GetFileName(base)))
)
};
+/** Undo information for a CBlock */
+class CBlockUndo
+{
+public:
+ std::vector<CTxUndo> vtxundo;
+
+ IMPLEMENT_SERIALIZE(
+ READWRITE(vtxundo);
+ )
+};
/** pruned version of CTransaction: only retains metadata and unspent transaction outputs
*