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;
|
int64 nBIP16SwitchTime = 1333238400;
|
||||||
bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime);
|
bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime);
|
||||||
|
|
||||||
|
unsigned int flags = SCRIPT_VERIFY_NOCACHE |
|
||||||
|
(fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE);
|
||||||
|
|
||||||
CBlockUndo blockundo;
|
CBlockUndo blockundo;
|
||||||
|
|
||||||
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
|
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();
|
nFees += tx.GetValueIn(view)-tx.GetValueOut();
|
||||||
|
|
||||||
std::vector<CScriptCheck> vChecks;
|
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;
|
return false;
|
||||||
control.Add(vChecks);
|
control.Add(vChecks);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ using namespace boost;
|
|||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "util.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)));
|
bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
|
||||||
if (fSuccess)
|
if (fSuccess)
|
||||||
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
|
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags);
|
||||||
|
|
||||||
popstack(stack);
|
popstack(stack);
|
||||||
popstack(stack);
|
popstack(stack);
|
||||||
@ -1069,7 +1069,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
|
|||||||
// Check signature
|
// Check signature
|
||||||
bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
|
bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
|
||||||
if (fOk)
|
if (fOk)
|
||||||
fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
|
fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags);
|
||||||
|
|
||||||
if (fOk) {
|
if (fOk) {
|
||||||
isig++;
|
isig++;
|
||||||
@ -1199,13 +1199,13 @@ private:
|
|||||||
// sigdata_type is (signature hash, signature, public key):
|
// sigdata_type is (signature hash, signature, public key):
|
||||||
typedef boost::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type;
|
typedef boost::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type;
|
||||||
std::set< sigdata_type> setValid;
|
std::set< sigdata_type> setValid;
|
||||||
CCriticalSection cs_sigcache;
|
boost::shared_mutex cs_sigcache;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool
|
bool
|
||||||
Get(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
|
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);
|
sigdata_type k(hash, vchSig, pubKey);
|
||||||
std::set<sigdata_type>::iterator mi = setValid.find(k);
|
std::set<sigdata_type>::iterator mi = setValid.find(k);
|
||||||
@ -1223,7 +1223,7 @@ public:
|
|||||||
int64 nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
|
int64 nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
|
||||||
if (nMaxCacheSize <= 0) return;
|
if (nMaxCacheSize <= 0) return;
|
||||||
|
|
||||||
LOCK(cs_sigcache);
|
boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
|
||||||
|
|
||||||
while (static_cast<int64>(setValid.size()) > nMaxCacheSize)
|
while (static_cast<int64>(setValid.size()) > nMaxCacheSize)
|
||||||
{
|
{
|
||||||
@ -1246,7 +1246,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode,
|
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;
|
static CSignatureCache signatureCache;
|
||||||
|
|
||||||
@ -1271,7 +1271,9 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc
|
|||||||
if (!key.Verify(sighash, vchSig))
|
if (!key.Verify(sighash, vchSig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!(flags & SCRIPT_VERIFY_NOCACHE))
|
||||||
signatureCache.Set(sighash, vchSig, vchPubKey);
|
signatureCache.Set(sighash, vchSig, vchPubKey);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1761,7 +1763,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, u
|
|||||||
if (sigs.count(pubkey))
|
if (sigs.count(pubkey))
|
||||||
continue; // Already got a sig for this 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;
|
sigs[pubkey] = sig;
|
||||||
break;
|
break;
|
||||||
|
@ -32,6 +32,7 @@ enum
|
|||||||
SCRIPT_VERIFY_NONE = 0,
|
SCRIPT_VERIFY_NONE = 0,
|
||||||
SCRIPT_VERIFY_P2SH = (1U << 0),
|
SCRIPT_VERIFY_P2SH = (1U << 0),
|
||||||
SCRIPT_VERIFY_STRICTENC = (1U << 1),
|
SCRIPT_VERIFY_STRICTENC = (1U << 1),
|
||||||
|
SCRIPT_VERIFY_NOCACHE = (1U << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum txnouttype
|
enum txnouttype
|
||||||
|
Loading…
Reference in New Issue
Block a user