From: MASM fan Date: Sat, 15 Feb 2014 15:56:59 +0000 (+0400) Subject: Pruned transactions serialization support. X-Git-Tag: v0.4.4.7-nvc-bugfix3~11 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=07db386d3402910e893ae37bdb64045234eb9b2d Pruned transactions serialization support. --- diff --git a/src/main.h b/src/main.h index a99e22b..6317b29 100644 --- a/src/main.h +++ b/src/main.h @@ -921,22 +921,33 @@ public: unsigned int GetSerializeSize(int nType, int nVersion) const { unsigned int nSize = 0; - unsigned int nMaskSize = 0, nMaskCode = 0; - CalcMaskSize(nMaskSize, nMaskCode); - bool fFirst = vout.size() > 0 && !vout[0].IsNull(); - bool fSecond = vout.size() > 1 && !vout[1].IsNull(); - assert(fFirst || fSecond || nMaskCode); - unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fCoinStake ? 1 : 0) + (fSecond ? 4 : 0); + // version nSize += ::GetSerializeSize(VARINT(this->nVersion), nType, nVersion); - // size of header code - nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion); - // spentness bitmask - nSize += nMaskSize; - // txouts themself - for (unsigned int i = 0; i < vout.size(); i++) - if (!vout[i].IsNull()) - nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion); + + if (!IsPruned()) { + unsigned int nMaskSize = 0, nMaskCode = 0; + CalcMaskSize(nMaskSize, nMaskCode); + bool fFirst = vout.size() > 0 && !vout[0].IsNull(); + bool fSecond = vout.size() > 1 && !vout[1].IsNull(); + + assert(fFirst || fSecond || nMaskCode); + unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fCoinStake ? 1 : 0) + (fSecond ? 4 : 0); + // size of header code + nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion); + // spentness bitmask + nSize += nMaskSize; + // txouts themself + for (unsigned int i = 0; i < vout.size(); i++) + if (!vout[i].IsNull()) + nSize += ::GetSerializeSize(CTxOutCompressor(REF(vout[i])), nType, nVersion); + } + else { + unsigned int nCode = UINT_MAX; + // size of header code + nSize += ::GetSerializeSize(VARINT(nCode), nType, nVersion); + } + // height nSize += ::GetSerializeSize(VARINT(nHeight), nType, nVersion); // timestamp and coinstake flag @@ -952,24 +963,33 @@ public: CalcMaskSize(nMaskSize, nMaskCode); bool fFirst = vout.size() > 0 && !vout[0].IsNull(); bool fSecond = vout.size() > 1 && !vout[1].IsNull(); - assert(fFirst || fSecond || nMaskCode); - unsigned int nCode = 8*(nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0); + // version ::Serialize(s, VARINT(this->nVersion), nType, nVersion); - // header code - ::Serialize(s, VARINT(nCode), nType, nVersion); - // spentness bitmask - for (unsigned int b = 0; bnVersion), nType, nVersion); // header code ::Unserialize(s, VARINT(nCode), nType, nVersion); - fCoinBase = nCode & 1; - std::vector vAvail(2, false); - vAvail[0] = nCode & 2; - vAvail[1] = nCode & 4; - unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1); - // spentness bitmask - while (nMaskCode > 0) { - unsigned char chAvail = 0; - ::Unserialize(s, chAvail, nType, nVersion); - for (unsigned int p = 0; p < 8; p++) { - bool f = (chAvail & (1 << p)) != 0; - vAvail.push_back(f); + if (nCode != UINT_MAX) + { + fCoinBase = nCode & 1; + std::vector vAvail(2, false); + vAvail[0] = nCode & 2; + vAvail[1] = nCode & 4; + unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1); + // spentness bitmask + while (nMaskCode > 0) { + unsigned char chAvail = 0; + ::Unserialize(s, chAvail, nType, nVersion); + for (unsigned int p = 0; p < 8; p++) { + bool f = (chAvail & (1 << p)) != 0; + vAvail.push_back(f); + } + if (chAvail != 0) + nMaskCode--; + } + // txouts themself + vout.assign(vAvail.size(), CTxOut()); + for (unsigned int i = 0; i < vAvail.size(); i++) { + if (vAvail[i]) + ::Unserialize(s, REF(CTxOutCompressor(vout[i])), nType, nVersion); } - if (chAvail != 0) - nMaskCode--; - } - // txouts themself - vout.assign(vAvail.size(), CTxOut()); - for (unsigned int i = 0; i < vAvail.size(); i++) { - if (vAvail[i]) - ::Unserialize(s, REF(CTxOutCompressor(vout[i])), nType, nVersion); } // coinbase height ::Unserialize(s, VARINT(nHeight), nType, nVersion); @@ -1054,6 +1077,9 @@ public: // check whether the entire CCoins is spent // note that only !IsPruned() CCoins can be serialized bool IsPruned() const { + if (vout.size() == 0) + return true; + BOOST_FOREACH(const CTxOut &out, vout) if (!out.IsNull()) return false; @@ -2064,10 +2090,11 @@ struct CCoinsStats { int nHeight; uint64 nTransactions; + uint64 nPrunedTransactions; uint64 nTransactionOutputs; uint64 nSerializedSize; - CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0) {} + CCoinsStats() : nHeight(0), nTransactions(0), nPrunedTransactions(0), nTransactionOutputs(0), nSerializedSize(0) {} }; /** Abstract view on the open txout dataset. */ diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 3420ed3..9b3c529 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -320,7 +320,8 @@ Value gettxoutsetinfo(const Array& params, bool fHelp) CCoinsStats stats; if (pcoinsTip->GetStats(stats)) { ret.push_back(Pair("bestblock", pcoinsTip->GetBestBlock()->GetBlockHash().GetHex())); - ret.push_back(Pair("transactions", (boost::int64_t)stats.nTransactions)); + ret.push_back(Pair("availabletx", (boost::int64_t)stats.nTransactions)); + ret.push_back(Pair("prunedtx", (boost::int64_t)stats.nPrunedTransactions)); ret.push_back(Pair("txouts", (boost::int64_t)stats.nTransactionOutputs)); ret.push_back(Pair("bytes_serialized", (boost::int64_t)stats.nSerializedSize)); } diff --git a/src/txdb.cpp b/src/txdb.cpp index ff40b6c..83bd898 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -9,10 +9,7 @@ using namespace std; void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) { - if (coins.IsPruned()) - batch.Erase(make_pair('c', hash)); - else - batch.Write(make_pair('c', hash), coins); + batch.Write(make_pair('c', hash), coins); } void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) { @@ -134,11 +131,15 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) { ssValue >> coins; uint256 txhash; ssKey >> txhash; - - stats.nTransactions++; - BOOST_FOREACH(const CTxOut &out, coins.vout) { - if (!out.IsNull()) - stats.nTransactionOutputs++; + if (!coins.IsPruned()) { + stats.nTransactions++; + BOOST_FOREACH(const CTxOut &out, coins.vout) { + if (!out.IsNull()) + stats.nTransactionOutputs++; + } + } + else { + stats.nPrunedTransactions++; } stats.nSerializedSize += 32 + slValue.size(); }