Skip to content

Commit

Permalink
validation: create coinspends cache
Browse files Browse the repository at this point in the history
  • Loading branch information
furszy committed Jan 9, 2022
1 parent 4d2d770 commit 6b803fb
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1691,10 +1691,15 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
pindex->nHeight < consensus.height_last_ZC_AccumCheckpoint) {
// Legacy Zerocoin DB: If Accumulators Checkpoint is changed, cache the checksums
CacheAccChecksum(pindex, true);
// Clean coinspends cache every 50k blocks, so it does not grow unnecessarily
if (pindex->nHeight % 50000 == 0) {
ZPIVModule::CleanCoinSpendsCache();
}
} else if (accumulatorCache && pindex->nHeight > consensus.height_last_ZC_AccumCheckpoint + 100) {
// 100 blocks After last Checkpoint block, wipe the checksum database and cache
accumulatorCache->Wipe();
accumulatorCache.reset();
ZPIVModule::CleanCoinSpendsCache();
}

// 100 blocks after the last invalid out, clean the map contents
Expand Down
44 changes: 43 additions & 1 deletion src/zpiv/zpivmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,34 @@ static bool TxOutToPublicCoin(const CTxOut& txout, libzerocoin::PublicCoin& pubC
return true;
}

// TODO: do not create g_coinspends_cache if the node passed the last zc checkpoint.
class CoinSpendCache {
private:
mutable Mutex cs;
std::map<CScript, libzerocoin::CoinSpend> cache_coinspend;
std::map<CScript, PublicCoinSpend> cache_public_coinspend;

template<typename T>
Optional<T> Get(const CScript& in, const std::map<CScript, T>& map) const {
LOCK(cs);
auto it = map.find(in);
return it != map.end() ? Optional<T>{it->second} : nullopt;
}

public:
void Add(const CScript& in, libzerocoin::CoinSpend& spend) { WITH_LOCK(cs, cache_coinspend.emplace(in, spend)); }
void AddPub(const CScript& in, PublicCoinSpend& spend) { WITH_LOCK(cs, cache_public_coinspend.emplace(in, spend)); }

Optional<libzerocoin::CoinSpend> Get(const CScript& in) const { return Get<libzerocoin::CoinSpend>(in, cache_coinspend); }
Optional<PublicCoinSpend> GetPub(const CScript& in) const { return Get<PublicCoinSpend>(in, cache_public_coinspend); }
void Clear() {
LOCK(cs);
cache_coinspend.clear();
cache_public_coinspend.clear();
}
};
std::unique_ptr<CoinSpendCache> g_coinspends_cache = std::make_unique<CoinSpendCache>();

namespace ZPIVModule {

// Return stream of CoinSpend from tx input scriptsig
Expand All @@ -134,6 +162,11 @@ namespace ZPIVModule {
}

bool parseCoinSpend(const CTxIn &in, const CTransaction &tx, const CTxOut &prevOut, PublicCoinSpend &publicCoinSpend) {
if (auto op = g_coinspends_cache->GetPub(in.scriptSig)) {
publicCoinSpend = *op;
return true;
}

if (!in.IsZerocoinPublicSpend() || !prevOut.IsZerocoinMint())
return error("%s: invalid argument/s", __func__);

Expand All @@ -151,13 +184,17 @@ namespace ZPIVModule {

spend.setDenom(spend.pubCoin.getDenomination());
publicCoinSpend = spend;
g_coinspends_cache->AddPub(in.scriptSig, publicCoinSpend);
return true;
}

libzerocoin::CoinSpend TxInToZerocoinSpend(const CTxIn& txin)
{
if (auto op = g_coinspends_cache->Get(txin.scriptSig)) return *op;
CDataStream serializedCoinSpend = ScriptSigToSerializedSpend(txin.scriptSig);
return libzerocoin::CoinSpend(serializedCoinSpend);
libzerocoin::CoinSpend spend(serializedCoinSpend);
g_coinspends_cache->Add(txin.scriptSig, spend);
return spend;
}

bool validateInput(const CTxIn &in, const CTxOut &prevOut, const CTransaction &tx, PublicCoinSpend &publicSpend) {
Expand Down Expand Up @@ -185,4 +222,9 @@ namespace ZPIVModule {
}
return true;
}

void CleanCoinSpendsCache()
{
g_coinspends_cache->Clear();
}
}
3 changes: 3 additions & 0 deletions src/zpiv/zpivmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ namespace ZPIVModule {
* @return true if everything went ok
*/
bool ParseZerocoinPublicSpend(const CTxIn &in, const CTransaction& tx, CValidationState& state, PublicCoinSpend& publicCoinSpend);

// Clear the coinspend cache
void CleanCoinSpendsCache();
};


Expand Down

0 comments on commit 6b803fb

Please sign in to comment.