aboutsummaryrefslogtreecommitdiff
path: root/src/script/interpreter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/interpreter.cpp')
-rw-r--r--src/script/interpreter.cpp63
1 files changed, 48 insertions, 15 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index e0d193fa38..4b982d647d 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -336,6 +336,10 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
opcode == OP_RSHIFT)
return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes.
+ // With SCRIPT_VERIFY_CONST_SCRIPTCODE, OP_CODESEPARATOR in non-segwit script is rejected even in an unexecuted branch
+ if (opcode == OP_CODESEPARATOR && sigversion == SigVersion::BASE && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
+ return set_error(serror, SCRIPT_ERR_OP_CODESEPARATOR);
+
if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) {
if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) {
return set_error(serror, SCRIPT_ERR_MINIMALDATA);
@@ -899,6 +903,9 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
case OP_CODESEPARATOR:
{
+ // If SCRIPT_VERIFY_CONST_SCRIPTCODE flag is set, use of OP_CODESEPARATOR is rejected in pre-segwit
+ // script, even in an unexecuted branch (this is checked above the opcode case statement).
+
// Hash starts after the code separator
pbegincodehash = pc;
}
@@ -919,7 +926,9 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
// Drop the signature in pre-segwit scripts but not segwit scripts
if (sigversion == SigVersion::BASE) {
- FindAndDelete(scriptCode, CScript(vchSig));
+ int found = FindAndDelete(scriptCode, CScript(vchSig));
+ if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
+ return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE);
}
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
@@ -983,7 +992,9 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
{
valtype& vchSig = stacktop(-isig-k);
if (sigversion == SigVersion::BASE) {
- FindAndDelete(scriptCode, CScript(vchSig));
+ int found = FindAndDelete(scriptCode, CScript(vchSig));
+ if (found > 0 && (flags & SCRIPT_VERIFY_CONST_SCRIPTCODE))
+ return set_error(serror, SCRIPT_ERR_SIG_FINDANDDELETE);
}
}
@@ -1078,9 +1089,11 @@ namespace {
* Wrapper that serializes like CTransaction, but with the modifications
* required for the signature hash done in-place
*/
-class CTransactionSignatureSerializer {
+template <class T>
+class CTransactionSignatureSerializer
+{
private:
- const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
+ const T& txTo; //!< reference to the spending transaction (the one being serialized)
const CScript& scriptCode; //!< output script being consumed
const unsigned int nIn; //!< input index of txTo being signed
const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
@@ -1088,7 +1101,7 @@ private:
const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
public:
- CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
+ CTransactionSignatureSerializer(const T& txToIn, const CScript& scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
@@ -1169,7 +1182,9 @@ public:
}
};
-uint256 GetPrevoutHash(const CTransaction& txTo) {
+template <class T>
+uint256 GetPrevoutHash(const T& txTo)
+{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) {
ss << txin.prevout;
@@ -1177,7 +1192,9 @@ uint256 GetPrevoutHash(const CTransaction& txTo) {
return ss.GetHash();
}
-uint256 GetSequenceHash(const CTransaction& txTo) {
+template <class T>
+uint256 GetSequenceHash(const T& txTo)
+{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) {
ss << txin.nSequence;
@@ -1185,7 +1202,9 @@ uint256 GetSequenceHash(const CTransaction& txTo) {
return ss.GetHash();
}
-uint256 GetOutputsHash(const CTransaction& txTo) {
+template <class T>
+uint256 GetOutputsHash(const T& txTo)
+{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txout : txTo.vout) {
ss << txout;
@@ -1195,7 +1214,8 @@ uint256 GetOutputsHash(const CTransaction& txTo) {
} // namespace
-PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
+template <class T>
+PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
{
// Cache is calculated only for transactions with witness
if (txTo.HasWitness()) {
@@ -1206,7 +1226,12 @@ PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
}
}
-uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
+// explicit instantiation
+template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
+template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
+
+template <class T>
+uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
{
assert(nIn < txTo.vin.size());
@@ -1267,7 +1292,7 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
}
// Wrapper to serialize only the necessary parts of the transaction being signed
- CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
+ CTransactionSignatureSerializer<T> txTmp(txTo, scriptCode, nIn, nHashType);
// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
@@ -1275,12 +1300,14 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
return ss.GetHash();
}
-bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
{
return pubkey.Verify(sighash, vchSig);
}
-bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@@ -1301,7 +1328,8 @@ bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vch
return true;
}
-bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::CheckLockTime(const CScriptNum& nLockTime) const
{
// There are two kinds of nLockTime: lock-by-blockheight
// and lock-by-blocktime, distinguished by whether
@@ -1337,7 +1365,8 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
return true;
}
-bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSequence) const
{
// Relative lock times are supported by comparing the passed
// in operand to the sequence number of the input.
@@ -1383,6 +1412,10 @@ bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) con
return true;
}
+// explicit instantiation
+template class GenericTransactionSignatureChecker<CTransaction>;
+template class GenericTransactionSignatureChecker<CMutableTransaction>;
+
static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
std::vector<std::vector<unsigned char> > stack;