ImportPayout cc eval code and alot of general cc polish. tests to write

This commit is contained in:
Scott Sadler
2018-03-30 15:46:41 -03:00
parent 991c422a9d
commit 2c8d8268dd
25 changed files with 389 additions and 116 deletions

View File

@@ -0,0 +1,113 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "serverchecker.h"
#include "komodo_cc.h"
#include "cc/eval.h"
#include "pubkey.h"
#include "random.h"
#include "uint256.h"
#include "util.h"
#include <boost/thread.hpp>
#include <boost/tuple/tuple_comparison.hpp>
namespace {
/**
* Valid signature cache, to avoid doing expensive ECDSA signature checking
* twice for every transaction (once when accepted into memory pool, and
* again when accepted into the block chain)
*/
class CSignatureCache
{
private:
//! sigdata_type is (signature hash, signature, public key):
typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type;
std::set< sigdata_type> setValid;
boost::shared_mutex cs_serverchecker;
public:
bool
Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
{
boost::shared_lock<boost::shared_mutex> lock(cs_serverchecker);
sigdata_type k(hash, vchSig, pubKey);
std::set<sigdata_type>::iterator mi = setValid.find(k);
if (mi != setValid.end())
return true;
return false;
}
void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey)
{
// DoS prevention: limit cache size to less than 10MB
// (~200 bytes per cache entry times 50,000 entries)
// Since there can be no more than 20,000 signature operations per block
// 50,000 is a reasonable default.
int64_t nMaxCacheSize = GetArg("-maxservercheckersize", 50000);
if (nMaxCacheSize <= 0) return;
boost::unique_lock<boost::shared_mutex> lock(cs_serverchecker);
while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize)
{
// Evict a random entry. Random because that helps
// foil would-be DoS attackers who might try to pre-generate
// and re-use a set of valid signatures just-slightly-greater
// than our cache size.
uint256 randomHash = GetRandHash();
std::vector<unsigned char> unused;
std::set<sigdata_type>::iterator it =
setValid.lower_bound(sigdata_type(randomHash, unused, unused));
if (it == setValid.end())
it = setValid.begin();
setValid.erase(*it);
}
sigdata_type k(hash, vchSig, pubKey);
setValid.insert(k);
}
};
}
bool ServerTransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
{
static CSignatureCache signatureCache;
if (signatureCache.Get(sighash, vchSig, pubkey))
return true;
if (!TransactionSignatureChecker::VerifySignature(vchSig, pubkey, sighash))
return false;
if (store)
signatureCache.Set(sighash, vchSig, pubkey);
return true;
}
/*
* The reason that these functions are here is that the what used to be the
* CachingTransactionSignatureChecker, now the ServerTransactionSignatureChecker,
* is an entry point that the server uses to validate signatures and which is not
* included as part of bitcoin common libs. Since Crypto-Condtions eval methods
* may call server code (GetTransaction etc), the best way to get it to run this
* code without pulling the whole bitcoin server code into bitcoin common was
* using this class. Thus it has been renamed to ServerTransactionSignatureChecker.
*/
VerifyEval ServerTransactionSignatureChecker::GetCCEval() const
{
return [] (CC *cond, void *checker) {
return ((ServerTransactionSignatureChecker*)checker)->CheckEvalCondition(cond);
};
}
int ServerTransactionSignatureChecker::CheckEvalCondition(CC *cond) const
{
return EvalConditionValidity(cond, txTo, nIn);
}