Remove contention on signature cache during block validation
Since block validation happens in parallel, multiple threads may be accessing the signature cache simultaneously. To prevent contention: * Turn the signature cache lock into a shared mutex * Make reading from the cache only acquire a shared lock * Let block validations not store their results in the cache
This commit is contained in:
parent
f9cae832e6
commit
ef0f422519
@ -1627,6 +1627,9 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
|
||||
int64 nBIP16SwitchTime = 1333238400;
|
||||
bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime);
|
||||
|
||||
unsigned int flags = SCRIPT_VERIFY_NOCACHE |
|
||||
(fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE);
|
||||
|
||||
CBlockUndo blockundo;
|
||||
|
||||
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
|
||||
@ -1663,7 +1666,7 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
|
||||
nFees += tx.GetValueIn(view)-tx.GetValueOut();
|
||||
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
if (!tx.CheckInputs(view, fScriptChecks, fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, nScriptCheckThreads ? &vChecks : NULL))
|
||||
if (!tx.CheckInputs(view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL))
|
||||
return false;
|
||||
control.Add(vChecks);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ using namespace boost;
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
|
||||
bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
|
||||
|
||||
|
||||
|
||||
@ -1007,7 +1007,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
|
||||
bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
|
||||
if (fSuccess)
|
||||
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
|
||||
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags);
|
||||
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
@ -1069,7 +1069,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
||||
// Check signature
|
||||
bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
|
||||
if (fOk)
|
||||
fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
|
||||
fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags);
|
||||
|
||||
if (fOk) {
|
||||
isig++;
|
||||
@ -1199,13 +1199,13 @@ private:
|
||||
// sigdata_type is (signature hash, signature, public key):
|
||||
typedef boost::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type;
|
||||
std::set< sigdata_type> setValid;
|
||||
CCriticalSection cs_sigcache;
|
||||
boost::shared_mutex cs_sigcache;
|
||||
|
||||
public:
|
||||
bool
|
||||
Get(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
|
||||
{
|
||||
LOCK(cs_sigcache);
|
||||
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
|
||||
|
||||
sigdata_type k(hash, vchSig, pubKey);
|
||||
std::set<sigdata_type>::iterator mi = setValid.find(k);
|
||||
@ -1223,7 +1223,7 @@ public:
|
||||
int64 nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
|
||||
if (nMaxCacheSize <= 0) return;
|
||||
|
||||
LOCK(cs_sigcache);
|
||||
boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
|
||||
|
||||
while (static_cast<int64>(setValid.size()) > nMaxCacheSize)
|
||||
{
|
||||
@ -1246,7 +1246,7 @@ public:
|
||||
};
|
||||
|
||||
bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode,
|
||||
const CTransaction& txTo, unsigned int nIn, int nHashType)
|
||||
const CTransaction& txTo, unsigned int nIn, int nHashType, int flags)
|
||||
{
|
||||
static CSignatureCache signatureCache;
|
||||
|
||||
@ -1271,7 +1271,9 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc
|
||||
if (!key.Verify(sighash, vchSig))
|
||||
return false;
|
||||
|
||||
signatureCache.Set(sighash, vchSig, vchPubKey);
|
||||
if (!(flags & SCRIPT_VERIFY_NOCACHE))
|
||||
signatureCache.Set(sighash, vchSig, vchPubKey);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1761,7 +1763,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, u
|
||||
if (sigs.count(pubkey))
|
||||
continue; // Already got a sig for this pubkey
|
||||
|
||||
if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0))
|
||||
if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0, 0))
|
||||
{
|
||||
sigs[pubkey] = sig;
|
||||
break;
|
||||
|
@ -32,6 +32,7 @@ enum
|
||||
SCRIPT_VERIFY_NONE = 0,
|
||||
SCRIPT_VERIFY_P2SH = (1U << 0),
|
||||
SCRIPT_VERIFY_STRICTENC = (1U << 1),
|
||||
SCRIPT_VERIFY_NOCACHE = (1U << 2),
|
||||
};
|
||||
|
||||
enum txnouttype
|
||||
|
Loading…
Reference in New Issue
Block a user