From cd672cdd15cf096ab3f65978ca53e9cd5ddbba3b Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Mon, 11 Jun 2018 20:37:21 -0700 Subject: [PATCH] [Main] Write to the zerocoinDB in batches instead of using a separate write operation for each and every bit of data that needs to be flushed to disk, utilize leveldb's batch writing capability. --- src/main.cpp | 16 +++++----------- src/txdb.cpp | 33 +++++++++++++++++++++++++-------- src/txdb.h | 7 +++++-- src/zpivchain.cpp | 21 +++++++++++++++++++-- 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 983e0bad45ff9..251b39d064c33 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2933,8 +2933,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin unsigned int nSigOps = 0; CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); std::vector > vPos; - std::vector > vSpends; - vector > vMints; + std::vector > vSpends; + std::vector > vMints; vPos.reserve(block.vtx.size()); CBlockUndo blockundo; blockundo.vtxundo.reserve(block.vtx.size() - 1); @@ -3131,10 +3131,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin //Record zPIV serials set setAddedTx; for (pair pSpend : vSpends) { - //record spend to database - if (!zerocoinDB->WriteCoinSpend(pSpend.first.getCoinSerialNumber(), pSpend.second)) - return state.Abort(("Failed to record coin serial to database")); - // Send signal to wallet if this is ours if (pwalletMain) { if (pwalletMain->IsMyZerocoinSpend(pSpend.first.getCoinSerialNumber())) { @@ -3159,11 +3155,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } - //Record mints to db - for (pair pMint : vMints) { - if (!zerocoinDB->WriteCoinMint(pMint.first, pMint.second)) - return state.Abort(("Failed to record new mint to database")); - } + // Flush spend/mint info to disk + if (!zerocoinDB->WriteCoinSpendBatch(vSpends)) return state.Abort(("Failed to record coin serials to database")); + if (!zerocoinDB->WriteCoinMintBatch(vMints)) return state.Abort(("Failed to record new mints to database")); //Record accumulator checksums DatabaseChecksums(mapAccumulators); diff --git a/src/txdb.cpp b/src/txdb.cpp index 125ac29bd8c2b..b6212feab4937 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -294,10 +294,19 @@ CZerocoinDB::CZerocoinDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDB { } -bool CZerocoinDB::WriteCoinMint(const PublicCoin& pubCoin, const uint256& hashTx) +bool CZerocoinDB::WriteCoinMintBatch(const std::vector >& mintInfo) { - uint256 hash = GetPubCoinHash(pubCoin.getValue()); - return Write(make_pair('m', hash), hashTx, true); + CLevelDBBatch batch; + size_t count = 0; + for (std::vector >::const_iterator it=mintInfo.begin(); it != mintInfo.end(); it++) { + PublicCoin pubCoin = it->first; + uint256 hash = GetPubCoinHash(pubCoin.getValue()); + batch.Write(make_pair('m', hash), it->second); + ++count; + } + + LogPrint("zero", "Writing %u coin mints to db.\n", (unsigned int)count); + return WriteBatch(batch, true); } bool CZerocoinDB::ReadCoinMint(const CBigNum& bnPubcoin, uint256& hashTx) @@ -316,13 +325,21 @@ bool CZerocoinDB::EraseCoinMint(const CBigNum& bnPubcoin) return Erase(make_pair('m', hash)); } -bool CZerocoinDB::WriteCoinSpend(const CBigNum& bnSerial, const uint256& txHash) +bool CZerocoinDB::WriteCoinSpendBatch(const std::vector >& spendInfo) { - CDataStream ss(SER_GETHASH, 0); - ss << bnSerial; - uint256 hash = Hash(ss.begin(), ss.end()); + CLevelDBBatch batch; + size_t count = 0; + for (std::vector >::const_iterator it=spendInfo.begin(); it != spendInfo.end(); it++) { + CBigNum bnSerial = it->first.getCoinSerialNumber(); + CDataStream ss(SER_GETHASH, 0); + ss << bnSerial; + uint256 hash = Hash(ss.begin(), ss.end()); + batch.Write(make_pair('s', hash), it->second); + ++count; + } - return Write(make_pair('s', hash), txHash, true); + LogPrint("zero", "Writing %u coin spends to db.\n", (unsigned int)count); + return WriteBatch(batch, true); } bool CZerocoinDB::ReadCoinSpend(const CBigNum& bnSerial, uint256& txHash) diff --git a/src/txdb.h b/src/txdb.h index f47d69915fde2..7728e29a63cbc 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -69,6 +69,7 @@ class CBlockTreeDB : public CLevelDBWrapper bool LoadBlockIndexGuts(); }; +/** Zerocoin database (zerocoin/) */ class CZerocoinDB : public CLevelDBWrapper { public: @@ -79,10 +80,12 @@ class CZerocoinDB : public CLevelDBWrapper void operator=(const CZerocoinDB&); public: - bool WriteCoinMint(const libzerocoin::PublicCoin& pubCoin, const uint256& txHash); + /** Write zPIV mints to the zerocoinDB in a batch */ + bool WriteCoinMintBatch(const std::vector >& mintInfo); bool ReadCoinMint(const CBigNum& bnPubcoin, uint256& txHash); bool ReadCoinMint(const uint256& hashPubcoin, uint256& hashTx); - bool WriteCoinSpend(const CBigNum& bnSerial, const uint256& txHash); + /** Write zPIV spends to the zerocoinDB in a batch */ + bool WriteCoinSpendBatch(const std::vector >& spendInfo); bool ReadCoinSpend(const CBigNum& bnSerial, uint256& txHash); bool ReadCoinSpend(const uint256& hashSerial, uint256 &txHash); bool EraseCoinMint(const CBigNum& bnPubcoin); diff --git a/src/zpivchain.cpp b/src/zpivchain.cpp index 985e33927ca9c..a304d0b080df3 100644 --- a/src/zpivchain.cpp +++ b/src/zpivchain.cpp @@ -260,6 +260,8 @@ std::string ReindexZerocoinDB() } CBlockIndex* pindex = chainActive[Params().Zerocoin_StartHeight()]; + std::vector > vSpendInfo; + std::vector > vMintInfo; while (pindex) { if (pindex->nHeight % 1000 == 0) LogPrintf("Reindexing zerocoin : block %d...\n", pindex->nHeight); @@ -283,7 +285,7 @@ std::string ReindexZerocoinDB() continue; libzerocoin::CoinSpend spend = TxInToZerocoinSpend(in); - zerocoinDB->WriteCoinSpend(spend.getCoinSerialNumber(), txid); + vSpendInfo.push_back(make_pair(spend, txid)); } } @@ -296,15 +298,30 @@ std::string ReindexZerocoinDB() CValidationState state; libzerocoin::PublicCoin coin(Params().Zerocoin_Params(pindex->nHeight < Params().Zerocoin_Block_V2_Start())); TxOutToPublicCoin(out, coin, state); - zerocoinDB->WriteCoinMint(coin, txid); + vMintInfo.push_back(make_pair(coin, txid)); } } } } } + + // Flush the zerocoinDB to disk every 100 blocks + if (pindex->nHeight % 100 == 0) { + if ((!vSpendInfo.empty() && !zerocoinDB->WriteCoinSpendBatch(vSpendInfo)) || (!vMintInfo.empty() && !zerocoinDB->WriteCoinMintBatch(vMintInfo))) + return _("Error writing zerocoinDB to disk"); + vSpendInfo.clear(); + vMintInfo.clear(); + } + pindex = chainActive.Next(pindex); } + // Final flush to disk in case any remaining information exists + if ((!vSpendInfo.empty() && !zerocoinDB->WriteCoinSpendBatch(vSpendInfo)) || (!vMintInfo.empty() && !zerocoinDB->WriteCoinMintBatch(vMintInfo))) + return _("Error writing zerocoinDB to disk"); + + uiInterface.ShowProgress("", 100); + return ""; }