SurjectionProof caching

This commit is contained in:
Gregory Sanders 2016-11-29 13:59:01 -05:00
parent 33bc0906ad
commit bb2f08d84e
3 changed files with 52 additions and 7 deletions

View file

@ -1175,8 +1175,9 @@ private:
secp256k1_surjectionproof proof;
std::vector<secp256k1_generator> vTags;
secp256k1_generator gen;
const bool store;
public:
CSurjectionCheck(secp256k1_surjectionproof& proofIn, std::vector<secp256k1_generator>& vTags_, secp256k1_generator& genIn) : proof(proofIn), gen(genIn) {
CSurjectionCheck(secp256k1_surjectionproof& proofIn, std::vector<secp256k1_generator>& vTags_, secp256k1_generator& genIn, const bool storeIn) : proof(proofIn), gen(genIn), store(storeIn) {
vTags.swap(vTags_);
}
@ -1216,11 +1217,7 @@ bool CBalanceCheck::operator()()
bool CSurjectionCheck::operator()()
{
if (secp256k1_surjectionproof_verify(secp256k1_ctx_verify_amounts, &proof, vTags.data(), vTags.size(), &gen) != 1) {
return false;
}
return true;
return CachingSurjectionProofChecker(store).VerifySurjectionProof(proof, vTags, gen, secp256k1_ctx_verify_amounts);
}
} // namespace
@ -1409,7 +1406,7 @@ bool VerifyAmounts(const CCoinsViewCache& cache, const CTransaction& tx, const C
if (secp256k1_surjectionproof_parse(secp256k1_ctx_verify_amounts, &proof, &asset.vchSurjectionproof[0], asset.vchSurjectionproof.size()) != 1)
return false;
if (!QueueCheck(pvChecks, new CSurjectionCheck(proof, ephemeral_input_tags, gen))) {
if (!QueueCheck(pvChecks, new CSurjectionCheck(proof, ephemeral_input_tags, gen, cacheStore))) {
return false;
}
// Each CSurjectionCheck uses swap to keep pointers valid.

View file

@ -146,3 +146,37 @@ bool CachingRangeProofChecker::VerifyRangeProof(const std::vector<unsigned char>
return true;
}
bool CachingSurjectionProofChecker::VerifySurjectionProof(secp256k1_surjectionproof& proof, std::vector<secp256k1_generator>& vTags, secp256k1_generator& gen, const secp256k1_context* secp256k1_ctx_verify_amounts) const
{
static CSignatureCache surjectionProofCache;
std::vector<unsigned char> vchproof;
size_t proof_len = 0;
vchproof.resize(secp256k1_surjectionproof_serialized_size(secp256k1_ctx_verify_amounts, &proof));
secp256k1_surjectionproof_serialize(secp256k1_ctx_verify_amounts, &vchproof[0], &proof_len, &proof);
std::vector<unsigned char> vchGen;
vchGen.resize(CTxOutValue::nCommittedSize);
secp256k1_generator_serialize(secp256k1_ctx_verify_amounts, &vchGen[0], &gen);
CPubKey pubkey(vchGen);
uint256 entry;
surjectionProofCache.ComputeEntry(entry, uint256(), vchproof, pubkey);
if (surjectionProofCache.Get(entry)) {
if (!store) {
surjectionProofCache.Erase(entry);
}
return true;
}
if (secp256k1_surjectionproof_verify(secp256k1_ctx_verify_amounts, &proof, vTags.data(), vTags.size(), &gen) != 1) {
return false;
}
if (store) {
surjectionProofCache.Set(entry);
}
return true;
}

View file

@ -10,6 +10,7 @@
#include <secp256k1.h>
#include <secp256k1_rangeproof.h>
#include <secp256k1_surjectionproof.h>
#include <vector>
// DoS prevention: limit cache size to less than 40MB (over 500000
@ -42,4 +43,17 @@ public:
};
class CachingSurjectionProofChecker
{
private:
bool store;
public:
CachingSurjectionProofChecker(bool storeIn){
store = storeIn;
};
bool VerifySurjectionProof(secp256k1_surjectionproof& proof, std::vector<secp256k1_generator>& vTags, secp256k1_generator& gen, const secp256k1_context* ctx) const;
};
#endif // BITCOIN_SCRIPT_SIGCACHE_H