Skip to content

Commit 8319c4a

Browse files
committed
Cache hashes
1 parent d6e62d0 commit 8319c4a

File tree

5 files changed

+67
-19
lines changed

5 files changed

+67
-19
lines changed

src/main.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
15991599
bool CScriptCheck::operator()() {
16001600
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
16011601
const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL;
1602-
if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore), &error)) {
1602+
if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *cachedHashes), &error)) {
16031603
return false;
16041604
}
16051605
return true;
@@ -1675,14 +1675,16 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
16751675
// Skip ECDSA signature verification when connecting blocks
16761676
// before the last block chain checkpoint. This is safe because block merkle hashes are
16771677
// still computed and checked, and any change will be caught at the next checkpoint.
1678+
16781679
if (fScriptChecks) {
1680+
CachedHashes cachedHashes;
16791681
for (unsigned int i = 0; i < tx.vin.size(); i++) {
16801682
const COutPoint &prevout = tx.vin[i].prevout;
16811683
const CCoins* coins = inputs.AccessCoins(prevout.hash);
16821684
assert(coins);
16831685

16841686
// Verify signature
1685-
CScriptCheck check(*coins, tx, i, flags, cacheStore);
1687+
CScriptCheck check(*coins, tx, i, flags, cacheStore, cachedHashes);
16861688
if (pvChecks) {
16871689
pvChecks->push_back(CScriptCheck());
16881690
check.swap(pvChecks->back());
@@ -1695,7 +1697,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
16951697
// avoid splitting the network between upgraded and
16961698
// non-upgraded nodes.
16971699
CScriptCheck check2(*coins, tx, i,
1698-
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore);
1700+
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, cachedHashes);
16991701
if (check2())
17001702
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
17011703
}

src/main.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class CScriptCheck;
3737
class CTxMemPool;
3838
class CValidationInterface;
3939
class CValidationState;
40+
class CachedHashes;
4041

4142
struct CNodeStateStats;
4243

@@ -362,12 +363,13 @@ class CScriptCheck
362363
unsigned int nFlags;
363364
bool cacheStore;
364365
ScriptError error;
366+
CachedHashes *cachedHashes;
365367

366368
public:
367369
CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
368-
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) :
370+
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, CachedHashes& cachedHashesIn) :
369371
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
370-
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { }
372+
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), cachedHashes(&cachedHashesIn) { }
371373

372374
bool operator()();
373375

src/script/interpreter.cpp

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,35 +1066,65 @@ class CTransactionSignatureSerializer {
10661066

10671067
} // anon namespace
10681068

1069-
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, int sigversion)
1069+
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, int sigversion, CachedHashes* cache)
10701070
{
1071+
CachedHashes empty;
1072+
if(cache == NULL)
1073+
{
1074+
cache = &empty;
1075+
}
1076+
10711077
if (sigversion == 1) {
10721078
uint256 hashPrevouts;
10731079
uint256 hashSequence;
10741080
uint256 hashOutputs;
10751081

10761082
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
1077-
CHashWriter ss(SER_GETHASH, 0);
1078-
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
1079-
ss << txTo.vin[n].prevout;
1083+
if(cache->hashPrevouts == uint256())
1084+
{
1085+
CHashWriter ss(SER_GETHASH, 0);
1086+
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
1087+
ss << txTo.vin[n].prevout;
1088+
}
1089+
hashPrevouts = ss.GetHash();
1090+
cache->hashPrevouts = hashPrevouts;
1091+
}
1092+
else
1093+
{
1094+
hashPrevouts = cache->hashPrevouts;
10801095
}
1081-
hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
10821096
}
10831097

10841098
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
1085-
CHashWriter ss(SER_GETHASH, 0);
1086-
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
1087-
ss << txTo.vin[n].nSequence;
1099+
if(cache->hashSequence == uint256())
1100+
{
1101+
CHashWriter ss(SER_GETHASH, 0);
1102+
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
1103+
ss << txTo.vin[n].nSequence;
1104+
}
1105+
hashSequence = ss.GetHash();
1106+
cache->hashSequence = hashSequence;
1107+
}
1108+
else
1109+
{
1110+
hashSequence = cache->hashSequence;
10881111
}
1089-
hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
10901112
}
10911113

10921114
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
1093-
CHashWriter ss(SER_GETHASH, 0);
1094-
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
1095-
ss << txTo.vout[n];
1115+
if(cache->hashOutputs == uint256())
1116+
{
1117+
CHashWriter ss(SER_GETHASH, 0);
1118+
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
1119+
ss << txTo.vout[n];
1120+
}
1121+
hashOutputs = ss.GetHash();
1122+
cache->hashOutputs = hashOutputs;
1123+
}
1124+
else
1125+
{
1126+
hashOutputs = cache->hashOutputs;
10961127
}
1097-
hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
10981128
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
10991129
CHashWriter ss(SER_GETHASH, 0);
11001130
ss << txTo.vout[nIn];
@@ -1146,6 +1176,10 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
11461176
ss << txTmp << nHashType;
11471177
return ss.GetHash();
11481178
}
1179+
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, int sigversion)
1180+
{
1181+
return SignatureHash(scriptCode, txTo, nIn, nHashType, amount, sigversion, NULL);
1182+
}
11491183

11501184
bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
11511185
{
@@ -1165,7 +1199,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
11651199
int nHashType = vchSig.back();
11661200
vchSig.pop_back();
11671201

1168-
uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
1202+
uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, cachedHashes);
11691203

11701204
if (!VerifySignature(vchSig, pubkey, sighash))
11711205
return false;

src/script/interpreter.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,14 @@ enum
9393

9494
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
9595

96+
class CachedHashes
97+
{
98+
public:
99+
uint256 hashPrevouts,hashSequence,hashOutputs;
100+
};
101+
96102
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, int sigversion);
103+
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, int sigversion, CachedHashes& cache);
97104

98105
class BaseSignatureChecker
99106
{
@@ -117,12 +124,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker
117124
const CTransaction* txTo;
118125
unsigned int nIn;
119126
const CAmount amount;
127+
mutable CachedHashes* cachedHashes;
120128

121129
protected:
122130
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
123131

124132
public:
125133
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn) {}
134+
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, CachedHashes& cachedHashesIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), cachedHashes(&cachedHashesIn) {}
126135
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, int sigversion) const;
127136
bool CheckLockTime(const CScriptNum& nLockTime) const;
128137
};

src/script/sigcache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker
2323

2424
public:
2525
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {}
26+
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, CachedHashes& cachedHashesIn) : TransactionSignatureChecker(txToIn, nInIn, amount, cachedHashesIn), store(storeIn) {}
2627

2728
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
2829
};

0 commit comments

Comments
 (0)