Skip to content

Commit ef0f422

Browse files
committed
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
1 parent f9cae83 commit ef0f422

File tree

3 files changed

+16
-10
lines changed

3 files changed

+16
-10
lines changed

src/main.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,9 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
16271627
int64 nBIP16SwitchTime = 1333238400;
16281628
bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime);
16291629

1630+
unsigned int flags = SCRIPT_VERIFY_NOCACHE |
1631+
(fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE);
1632+
16301633
CBlockUndo blockundo;
16311634

16321635
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
@@ -1663,7 +1666,7 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
16631666
nFees += tx.GetValueIn(view)-tx.GetValueOut();
16641667

16651668
std::vector<CScriptCheck> vChecks;
1666-
if (!tx.CheckInputs(view, fScriptChecks, fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, nScriptCheckThreads ? &vChecks : NULL))
1669+
if (!tx.CheckInputs(view, fScriptChecks, flags, nScriptCheckThreads ? &vChecks : NULL))
16671670
return false;
16681671
control.Add(vChecks);
16691672
}

src/script.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ using namespace boost;
1616
#include "sync.h"
1717
#include "util.h"
1818

19-
bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
19+
bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
2020

2121

2222

@@ -1007,7 +1007,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
10071007

10081008
bool fSuccess = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
10091009
if (fSuccess)
1010-
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
1010+
fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags);
10111011

10121012
popstack(stack);
10131013
popstack(stack);
@@ -1069,7 +1069,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
10691069
// Check signature
10701070
bool fOk = (!fStrictEncodings || (IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey)));
10711071
if (fOk)
1072-
fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
1072+
fOk = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags);
10731073

10741074
if (fOk) {
10751075
isig++;
@@ -1199,13 +1199,13 @@ class CSignatureCache
11991199
// sigdata_type is (signature hash, signature, public key):
12001200
typedef boost::tuple<uint256, std::vector<unsigned char>, std::vector<unsigned char> > sigdata_type;
12011201
std::set< sigdata_type> setValid;
1202-
CCriticalSection cs_sigcache;
1202+
boost::shared_mutex cs_sigcache;
12031203

12041204
public:
12051205
bool
12061206
Get(uint256 hash, const std::vector<unsigned char>& vchSig, const std::vector<unsigned char>& pubKey)
12071207
{
1208-
LOCK(cs_sigcache);
1208+
boost::shared_lock<boost::shared_mutex> lock(cs_sigcache);
12091209

12101210
sigdata_type k(hash, vchSig, pubKey);
12111211
std::set<sigdata_type>::iterator mi = setValid.find(k);
@@ -1223,7 +1223,7 @@ class CSignatureCache
12231223
int64 nMaxCacheSize = GetArg("-maxsigcachesize", 50000);
12241224
if (nMaxCacheSize <= 0) return;
12251225

1226-
LOCK(cs_sigcache);
1226+
boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
12271227

12281228
while (static_cast<int64>(setValid.size()) > nMaxCacheSize)
12291229
{
@@ -1246,7 +1246,7 @@ class CSignatureCache
12461246
};
12471247

12481248
bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode,
1249-
const CTransaction& txTo, unsigned int nIn, int nHashType)
1249+
const CTransaction& txTo, unsigned int nIn, int nHashType, int flags)
12501250
{
12511251
static CSignatureCache signatureCache;
12521252

@@ -1271,7 +1271,9 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc
12711271
if (!key.Verify(sighash, vchSig))
12721272
return false;
12731273

1274-
signatureCache.Set(sighash, vchSig, vchPubKey);
1274+
if (!(flags & SCRIPT_VERIFY_NOCACHE))
1275+
signatureCache.Set(sighash, vchSig, vchPubKey);
1276+
12751277
return true;
12761278
}
12771279

@@ -1761,7 +1763,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, u
17611763
if (sigs.count(pubkey))
17621764
continue; // Already got a sig for this pubkey
17631765

1764-
if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0))
1766+
if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0, 0))
17651767
{
17661768
sigs[pubkey] = sig;
17671769
break;

src/script.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum
3232
SCRIPT_VERIFY_NONE = 0,
3333
SCRIPT_VERIFY_P2SH = (1U << 0),
3434
SCRIPT_VERIFY_STRICTENC = (1U << 1),
35+
SCRIPT_VERIFY_NOCACHE = (1U << 2),
3536
};
3637

3738
enum txnouttype

0 commit comments

Comments
 (0)