Skip to content

Commit

Permalink
[Main] Write to the zerocoinDB in batches
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Fuzzbawls committed Jun 12, 2018
1 parent 6b525f0 commit cd672cd
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 23 deletions.
16 changes: 5 additions & 11 deletions src/main.cpp
Expand Up @@ -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<std::pair<uint256, CDiskTxPos> > vPos;
std::vector<pair<CoinSpend, uint256> > vSpends;
vector<pair<PublicCoin, uint256> > vMints;
std::vector<std::pair<CoinSpend, uint256> > vSpends;
std::vector<std::pair<PublicCoin, uint256> > vMints;
vPos.reserve(block.vtx.size());
CBlockUndo blockundo;
blockundo.vtxundo.reserve(block.vtx.size() - 1);
Expand Down Expand Up @@ -3131,10 +3131,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
//Record zPIV serials
set<uint256> setAddedTx;
for (pair<CoinSpend, uint256> 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())) {
Expand All @@ -3159,11 +3155,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
}
}

//Record mints to db
for (pair<PublicCoin, uint256> 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);
Expand Down
33 changes: 25 additions & 8 deletions src/txdb.cpp
Expand Up @@ -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<std::pair<libzerocoin::PublicCoin, uint256> >& mintInfo)
{
uint256 hash = GetPubCoinHash(pubCoin.getValue());
return Write(make_pair('m', hash), hashTx, true);
CLevelDBBatch batch;
size_t count = 0;
for (std::vector<std::pair<libzerocoin::PublicCoin, uint256> >::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)
Expand All @@ -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<std::pair<libzerocoin::CoinSpend, uint256> >& spendInfo)
{
CDataStream ss(SER_GETHASH, 0);
ss << bnSerial;
uint256 hash = Hash(ss.begin(), ss.end());
CLevelDBBatch batch;
size_t count = 0;
for (std::vector<std::pair<libzerocoin::CoinSpend, uint256> >::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)
Expand Down
7 changes: 5 additions & 2 deletions src/txdb.h
Expand Up @@ -69,6 +69,7 @@ class CBlockTreeDB : public CLevelDBWrapper
bool LoadBlockIndexGuts();
};

/** Zerocoin database (zerocoin/) */
class CZerocoinDB : public CLevelDBWrapper
{
public:
Expand All @@ -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<std::pair<libzerocoin::PublicCoin, uint256> >& 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<std::pair<libzerocoin::CoinSpend, uint256> >& spendInfo);
bool ReadCoinSpend(const CBigNum& bnSerial, uint256& txHash);
bool ReadCoinSpend(const uint256& hashSerial, uint256 &txHash);
bool EraseCoinMint(const CBigNum& bnPubcoin);
Expand Down
21 changes: 19 additions & 2 deletions src/zpivchain.cpp
Expand Up @@ -260,6 +260,8 @@ std::string ReindexZerocoinDB()
}

CBlockIndex* pindex = chainActive[Params().Zerocoin_StartHeight()];
std::vector<std::pair<libzerocoin::CoinSpend, uint256> > vSpendInfo;
std::vector<std::pair<libzerocoin::PublicCoin, uint256> > vMintInfo;
while (pindex) {
if (pindex->nHeight % 1000 == 0)
LogPrintf("Reindexing zerocoin : block %d...\n", pindex->nHeight);
Expand All @@ -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));
}
}

Expand All @@ -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 "";
}

Expand Down

0 comments on commit cd672cd

Please sign in to comment.