Verus Coin - this coin was backdoored by it's lead dev and should not be trusted! https://git.hush.is/duke/backdoors/src/branch/master/vrsc.md
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

193 lines
7.7 KiB

// 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 <univalue.h>
#include "serverchecker.h"
#include "script/cc.h"
#include "cc/eval.h"
#include "pubkey.h"
#include "random.h"
#include "uint256.h"
#include "util.h"
#include "pbaas/identity.h"
#include "chain.h"
#undef __cpuid
#include <boost/thread.hpp>
#include <boost/tuple/tuple_comparison.hpp>
extern uint32_t KOMODO_STOPAT;
extern CChain chainActive;
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);
}
};
}
// uses blockchain lookup
std::map<uint160, std::pair<int, std::vector<std::vector<unsigned char>>>> ServerTransactionSignatureChecker::ExtractIDMap(const CScript &scriptPubKeyIn, uint32_t spendHeight, bool isStake)
{
// create an ID map here, which late binds to the IDs on the blockchain as of the spend height,
// and substitute the correct addresses when checking signatures
COptCCParams p;
std::map<uint160, std::pair<int, std::vector<std::vector<unsigned char>>>> idAddresses;
if (scriptPubKeyIn.IsPayToCryptoCondition(p) && p.IsValid() && p.n >= 1 && p.vKeys.size() >= p.n && p.version >= p.VERSION_V3 && p.vData.size())
{
// get mapping to any identities used that are available. if a signing identity is unavailable, a transaction may still be able to be spent
COptCCParams master = COptCCParams(p.vData.back());
bool ccValid = master.IsValid();
CIdentity selfIdentity;
uint160 selfID;
if (p.evalCode == EVAL_IDENTITY_PRIMARY)
{
selfIdentity = CIdentity(p.vData[0]);
selfID = selfIdentity.GetID();
}
// if we are sign-only, "p" will have no data object of its own, so we do not have to subtract 1
int loopMax = p.evalCode ? p.vData.size() - 1 : p.vData.size();
for (int i = 0; ccValid && i < loopMax; i++)
{
COptCCParams oneP(i ? p.vData[i] : p);
ccValid = oneP.IsValid();
if (ccValid)
{
for (auto dest : oneP.vKeys)
{
uint160 destId = GetDestinationID(dest);
if (dest.which() == COptCCParams::ADDRTYPE_ID)
{
// lookup identity
CIdentity id;
std::pair<CIdentityMapKey, CIdentityMapValue> idMapEntry;
bool sourceIsSelf = selfIdentity.IsValid() && destId == selfID;
if (selfIdentity.IsValidUnrevoked() && destId == selfID)
{
id = selfIdentity;
}
else
{
id = CIdentity::LookupIdentity(destId, spendHeight);
}
if (id.IsValidUnrevoked() && (isStake || sourceIsSelf || !id.IsLocked(spendHeight)))
{
// TODO: POST HARDENING - in next upgrade, consider adding limits on what can be modified in an ID
std::vector<std::vector<unsigned char>> idAddrBytes;
for (auto &oneAddr : id.primaryAddresses)
{
idAddrBytes.push_back(GetDestinationBytes(oneAddr));
}
idAddresses[destId] = make_pair(id.minSigs, idAddrBytes);
}
else if (!id.IsValid())
{
uint32_t idHeightDef;
if ((id = CIdentity::LookupFirstIdentity(destId, &idHeightDef)).IsValid())
{
LogPrintf("%s: ERROR - ACTION REQUIRED: Corrupt Index, should not move forward as a node. Please bootstrap, sync from scratch, or reindex to continue\n", __func__);
printf("%s: ERROR - ACTION REQUIRED: Corrupt Index, should not move forward as a node. Please bootstrap, sync from scratch, or reindex to continue\n", __func__);
KOMODO_STOPAT = chainActive.Height();
}
}
}
}
}
}
}
return idAddresses;
}
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-Conditions 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.
*/
int ServerTransactionSignatureChecker::CheckEvalCondition(const CC *cond, int fulfilled) const
{
//fprintf(stderr,"call RunCCeval from ServerTransactionSignatureChecker::CheckEvalCondition\n");
return RunCCEval(cond, *txTo, nIn, fulfilled != 0);
}