aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/bitcoinconsensus.cpp4
-rw-r--r--src/script/interpreter.cpp54
-rw-r--r--src/script/interpreter.h13
-rw-r--r--src/script/sigcache.h2
-rw-r--r--src/script/sign.h2
5 files changed, 52 insertions, 23 deletions
diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp
index 62fd9031f8..b629f4278b 100644
--- a/src/script/bitcoinconsensus.cpp
+++ b/src/script/bitcoinconsensus.cpp
@@ -84,8 +84,8 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP
// Regardless of the verification result, the tx did not error.
set_error(err, bitcoinconsensus_ERR_OK);
-
- return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount), NULL);
+ PrecomputedTransactionData txdata(tx);
+ return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata), NULL);
} catch (const std::exception&) {
return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
}
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index bc027e9f0c..47ea261e31 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1108,9 +1108,40 @@ public:
}
};
+uint256 GetPrevoutHash(const CTransaction& txTo) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].prevout;
+ }
+ return ss.GetHash();
+}
+
+uint256 GetSequenceHash(const CTransaction& txTo) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vin.size(); n++) {
+ ss << txTo.vin[n].nSequence;
+ }
+ return ss.GetHash();
+}
+
+uint256 GetOutputsHash(const CTransaction& txTo) {
+ CHashWriter ss(SER_GETHASH, 0);
+ for (unsigned int n = 0; n < txTo.vout.size(); n++) {
+ ss << txTo.vout[n];
+ }
+ return ss.GetHash();
+}
+
} // anon namespace
-uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion)
+PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
+{
+ hashPrevouts = GetPrevoutHash(txTo);
+ hashSequence = GetSequenceHash(txTo);
+ hashOutputs = GetOutputsHash(txTo);
+}
+
+uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
{
if (sigversion == SIGVERSION_WITNESS_V0) {
uint256 hashPrevouts;
@@ -1118,27 +1149,16 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
uint256 hashOutputs;
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
- CHashWriter ss(SER_GETHASH, 0);
- for (unsigned int n = 0; n < txTo.vin.size(); n++) {
- ss << txTo.vin[n].prevout;
- }
- hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo);
}
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
- CHashWriter ss(SER_GETHASH, 0);
- for (unsigned int n = 0; n < txTo.vin.size(); n++) {
- ss << txTo.vin[n].nSequence;
- }
- hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo);
}
+
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
- CHashWriter ss(SER_GETHASH, 0);
- for (unsigned int n = 0; n < txTo.vout.size(); n++) {
- ss << txTo.vout[n];
- }
- hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction
+ hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo);
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
CHashWriter ss(SER_GETHASH, 0);
ss << txTo.vout[nIn];
@@ -1209,7 +1229,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
int nHashType = vchSig.back();
vchSig.pop_back();
- uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
+ uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata);
if (!VerifySignature(vchSig, pubkey, sighash))
return false;
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index bd2f211663..e5d7865cd3 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -98,13 +98,20 @@ enum
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
+struct PrecomputedTransactionData
+{
+ uint256 hashPrevouts, hashSequence, hashOutputs;
+
+ PrecomputedTransactionData(const CTransaction& tx);
+};
+
enum SigVersion
{
SIGVERSION_BASE = 0,
SIGVERSION_WITNESS_V0 = 1,
};
-uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion);
+uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = NULL);
class BaseSignatureChecker
{
@@ -133,12 +140,14 @@ private:
const CTransaction* txTo;
unsigned int nIn;
const CAmount amount;
+ const PrecomputedTransactionData* txdata;
protected:
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
public:
- TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn) {}
+ TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {}
+ TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const;
bool CheckLockTime(const CScriptNum& nLockTime) const;
bool CheckSequence(const CScriptNum& nSequence) const;
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index 050bf8cc42..44551ec2bc 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -22,7 +22,7 @@ private:
bool store;
public:
- CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {}
+ CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, txdataIn), store(storeIn) {}
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
};
diff --git a/src/script/sign.h b/src/script/sign.h
index 6404b4523e..f9aa6fca27 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -51,7 +51,7 @@ public:
MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {}
};
-/** A signature creator that just produces 72-byte empty signatyres. */
+/** A signature creator that just produces 72-byte empty signatures. */
class DummySignatureCreator : public BaseSignatureCreator {
public:
DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {}