Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13711193
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
122 KB
Subscribers
None
View Options
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index b88ca36ba..de8c327ae 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1,1525 +1,1602 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "interpreter.h"
-#include "primitives/transaction.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
+#include "primitives/transaction.h"
#include "pubkey.h"
#include "script/script.h"
#include "uint256.h"
using namespace std;
typedef vector<unsigned char> valtype;
namespace {
-inline bool set_success(ScriptError* ret)
-{
- if (ret)
- *ret = SCRIPT_ERR_OK;
+inline bool set_success(ScriptError *ret) {
+ if (ret) *ret = SCRIPT_ERR_OK;
return true;
}
-inline bool set_error(ScriptError* ret, const ScriptError serror)
-{
- if (ret)
- *ret = serror;
+inline bool set_error(ScriptError *ret, const ScriptError serror) {
+ if (ret) *ret = serror;
return false;
}
} // anon namespace
-bool CastToBool(const valtype& vch)
-{
- for (unsigned int i = 0; i < vch.size(); i++)
- {
- if (vch[i] != 0)
- {
+bool CastToBool(const valtype &vch) {
+ for (unsigned int i = 0; i < vch.size(); i++) {
+ if (vch[i] != 0) {
// Can be negative zero
- if (i == vch.size()-1 && vch[i] == 0x80)
- return false;
+ if (i == vch.size() - 1 && vch[i] == 0x80) return false;
return true;
}
}
return false;
}
/**
* Script is a stack machine (like Forth) that evaluates a predicate
* returning a bool indicating valid or not. There are no loops.
*/
-#define stacktop(i) (stack.at(stack.size()+(i)))
-#define altstacktop(i) (altstack.at(altstack.size()+(i)))
-static inline void popstack(vector<valtype>& stack)
-{
- if (stack.empty())
- throw runtime_error("popstack(): stack empty");
+#define stacktop(i) (stack.at(stack.size() + (i)))
+#define altstacktop(i) (altstack.at(altstack.size() + (i)))
+static inline void popstack(vector<valtype> &stack) {
+ if (stack.empty()) throw runtime_error("popstack(): stack empty");
stack.pop_back();
}
bool static IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) {
if (vchPubKey.size() < 33) {
// Non-canonical public key: too short
return false;
}
if (vchPubKey[0] == 0x04) {
if (vchPubKey.size() != 65) {
// Non-canonical public key: invalid length for uncompressed key
return false;
}
} else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) {
if (vchPubKey.size() != 33) {
// Non-canonical public key: invalid length for compressed key
return false;
}
} else {
// Non-canonical public key: neither compressed nor uncompressed
return false;
}
return true;
}
bool static IsCompressedPubKey(const valtype &vchPubKey) {
if (vchPubKey.size() != 33) {
// Non-canonical public key: invalid length for compressed key
return false;
}
if (vchPubKey[0] != 0x02 && vchPubKey[0] != 0x03) {
// Non-canonical public key: invalid prefix for compressed key
return false;
}
return true;
}
/**
- * A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype>
- * Where R and S are not negative (their first byte has its highest bit not set), and not
- * excessively padded (do not start with a 0 byte, unless an otherwise negative number follows,
- * in which case a single 0 byte is necessary and even required).
- *
+ * A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len
+ * S> <S> <hashtype>, where R and S are not negative (their first byte has its
+ * highest bit not set), and not excessively padded (do not start with a 0 byte,
+ * unless an otherwise negative number follows, in which case a single 0 byte is
+ * necessary and even required).
+ *
* See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623
*
* This function is consensus-critical since BIP66.
*/
bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
- // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] [sighash]
+ // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]
+ // [sighash]
// * total-length: 1-byte length descriptor of everything that follows,
- // excluding the sighash byte.
+ // excluding the sighash byte.
// * R-length: 1-byte length descriptor of the R value that follows.
- // * R: arbitrary-length big-endian encoded R value. It must use the shortest
- // possible encoding for a positive integers (which means no null bytes at
- // the start, except a single one when the next byte has its highest bit set).
+ // * R: arbitrary-length big-endian encoded R value. It must use the
+ // shortest possible encoding for a positive integers (which means no null
+ // bytes at the start, except a single one when the next byte has its
+ // highest bit set).
// * S-length: 1-byte length descriptor of the S value that follows.
// * S: arbitrary-length big-endian encoded S value. The same rules apply.
- // * sighash: 1-byte value indicating what data is hashed (not part of the DER
- // signature)
+ // * sighash: 1-byte value indicating what data is hashed (not part of the
+ // DER signature)
// Minimum and maximum size constraints.
if (sig.size() < 9) return false;
if (sig.size() > 73) return false;
// A signature is of type 0x30 (compound).
if (sig[0] != 0x30) return false;
// Make sure the length covers the entire signature.
if (sig[1] != sig.size() - 3) return false;
// Extract the length of the R element.
unsigned int lenR = sig[3];
// Make sure the length of the S element is still inside the signature.
if (5 + lenR >= sig.size()) return false;
// Extract the length of the S element.
unsigned int lenS = sig[5 + lenR];
// Verify that the length of the signature matches the sum of the length
// of the elements.
if ((size_t)(lenR + lenS + 7) != sig.size()) return false;
-
+
// Check whether the R element is an integer.
if (sig[2] != 0x02) return false;
// Zero-length integers are not allowed for R.
if (lenR == 0) return false;
// Negative numbers are not allowed for R.
if (sig[4] & 0x80) return false;
- // Null bytes at the start of R are not allowed, unless R would
- // otherwise be interpreted as a negative number.
+ // Null bytes at the start of R are not allowed, unless R would otherwise be
+ // interpreted as a negative number.
if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false;
// Check whether the S element is an integer.
if (sig[lenR + 4] != 0x02) return false;
// Zero-length integers are not allowed for S.
if (lenS == 0) return false;
// Negative numbers are not allowed for S.
if (sig[lenR + 6] & 0x80) return false;
// Null bytes at the start of S are not allowed, unless S would otherwise be
// interpreted as a negative number.
- if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) return false;
+ if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80))
+ return false;
return true;
}
-bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
+bool static IsLowDERSignature(const valtype &vchSig, ScriptError *serror) {
if (!IsValidSignatureEncoding(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
}
- std::vector<unsigned char> vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - 1);
+ std::vector<unsigned char> vchSigCopy(vchSig.begin(),
+ vchSig.begin() + vchSig.size() - 1);
if (!CPubKey::CheckLowS(vchSigCopy)) {
return set_error(serror, SCRIPT_ERR_SIG_HIGH_S);
}
return true;
}
bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
if (vchSig.size() == 0) {
return false;
}
- unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
- if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE)
- return false;
+ unsigned char nHashType =
+ vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY));
+ if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) return false;
return true;
}
-bool CheckSignatureEncoding(const vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror) {
+bool CheckSignatureEncoding(const vector<unsigned char> &vchSig,
+ unsigned int flags, ScriptError *serror) {
// Empty signature. Not strictly DER encoded, but allowed to provide a
// compact way to provide an invalid signature for use with CHECK(MULTI)SIG
if (vchSig.size() == 0) {
return true;
}
- if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) != 0 && !IsValidSignatureEncoding(vchSig)) {
+ if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S |
+ SCRIPT_VERIFY_STRICTENC)) != 0 &&
+ !IsValidSignatureEncoding(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
- } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && !IsLowDERSignature(vchSig, serror)) {
+ } else if ((flags & SCRIPT_VERIFY_LOW_S) != 0 &&
+ !IsLowDERSignature(vchSig, serror)) {
// serror is set
return false;
- } else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) {
+ } else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 &&
+ !IsDefinedHashtypeSignature(vchSig)) {
return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
}
return true;
}
-bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags, const SigVersion &sigversion, ScriptError* serror) {
- if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchPubKey)) {
+bool static CheckPubKeyEncoding(const valtype &vchPubKey, unsigned int flags,
+ const SigVersion &sigversion,
+ ScriptError *serror) {
+ if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 &&
+ !IsCompressedOrUncompressedPubKey(vchPubKey)) {
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
}
// Only compressed keys are accepted in segwit
- if ((flags & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 && sigversion == SIGVERSION_WITNESS_V0 && !IsCompressedPubKey(vchPubKey)) {
+ if ((flags & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 &&
+ sigversion == SIGVERSION_WITNESS_V0 && !IsCompressedPubKey(vchPubKey)) {
return set_error(serror, SCRIPT_ERR_WITNESS_PUBKEYTYPE);
}
return true;
}
-bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
+bool static CheckMinimalPush(const valtype &data, opcodetype opcode) {
if (data.size() == 0) {
// Could have used OP_0.
return opcode == OP_0;
} else if (data.size() == 1 && data[0] >= 1 && data[0] <= 16) {
// Could have used OP_1 .. OP_16.
return opcode == OP_1 + (data[0] - 1);
} else if (data.size() == 1 && data[0] == 0x81) {
// Could have used OP_1NEGATE.
return opcode == OP_1NEGATE;
} else if (data.size() <= 75) {
- // Could have used a direct push (opcode indicating number of bytes pushed + those bytes).
+ // Could have used a direct push (opcode indicating number of bytes
+ // pushed + those bytes).
return opcode == data.size();
} else if (data.size() <= 255) {
// Could have used OP_PUSHDATA.
return opcode == OP_PUSHDATA1;
} else if (data.size() <= 65535) {
// Could have used OP_PUSHDATA2.
return opcode == OP_PUSHDATA2;
}
return true;
}
-bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
-{
+bool EvalScript(vector<vector<unsigned char>> &stack, const CScript &script,
+ unsigned int flags, const BaseSignatureChecker &checker,
+ SigVersion sigversion, ScriptError *serror) {
static const CScriptNum bnZero(0);
static const CScriptNum bnOne(1);
static const CScriptNum bnFalse(0);
static const CScriptNum bnTrue(1);
static const valtype vchFalse(0);
static const valtype vchZero(0);
static const valtype vchTrue(1, 1);
CScript::const_iterator pc = script.begin();
CScript::const_iterator pend = script.end();
CScript::const_iterator pbegincodehash = script.begin();
opcodetype opcode;
valtype vchPushValue;
vector<bool> vfExec;
vector<valtype> altstack;
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if (script.size() > MAX_SCRIPT_SIZE)
return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE);
int nOpCount = 0;
bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0;
- try
- {
- while (pc < pend)
- {
+ try {
+ while (pc < pend) {
bool fExec = !count(vfExec.begin(), vfExec.end(), false);
//
// Read instruction
//
if (!script.GetOp(pc, opcode, vchPushValue))
return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE)
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
// Note how OP_RESERVED does not count towards the opcode limit.
if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
- if (opcode == OP_CAT ||
- opcode == OP_SUBSTR ||
- opcode == OP_LEFT ||
- opcode == OP_RIGHT ||
- opcode == OP_INVERT ||
- opcode == OP_AND ||
- opcode == OP_OR ||
- opcode == OP_XOR ||
- opcode == OP_2MUL ||
- opcode == OP_2DIV ||
- opcode == OP_MUL ||
- opcode == OP_DIV ||
- opcode == OP_MOD ||
- opcode == OP_LSHIFT ||
- opcode == OP_RSHIFT)
- return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes.
+ if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT ||
+ opcode == OP_RIGHT || opcode == OP_INVERT || opcode == OP_AND ||
+ opcode == OP_OR || opcode == OP_XOR || opcode == OP_2MUL ||
+ opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV ||
+ opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT)
+ return set_error(
+ serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes.
if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) {
- if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) {
+ if (fRequireMinimal &&
+ !CheckMinimalPush(vchPushValue, opcode)) {
return set_error(serror, SCRIPT_ERR_MINIMALDATA);
}
stack.push_back(vchPushValue);
} else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
- switch (opcode)
- {
- //
- // Push value
- //
- case OP_1NEGATE:
- case OP_1:
- case OP_2:
- case OP_3:
- case OP_4:
- case OP_5:
- case OP_6:
- case OP_7:
- case OP_8:
- case OP_9:
- case OP_10:
- case OP_11:
- case OP_12:
- case OP_13:
- case OP_14:
- case OP_15:
- case OP_16:
- {
- // ( -- value)
- CScriptNum bn((int)opcode - (int)(OP_1 - 1));
- stack.push_back(bn.getvch());
- // The result of these opcodes should always be the minimal way to push the data
- // they push, so no need for a CheckMinimalPush here.
- }
- break;
-
-
- //
- // Control
- //
- case OP_NOP:
- break;
-
- case OP_CHECKLOCKTIMEVERIFY:
- {
- if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
- // not enabled; treat as a NOP2
- if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
- return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
- }
- break;
- }
-
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ switch (opcode) {
+ //
+ // Push value
+ //
+ case OP_1NEGATE:
+ case OP_1:
+ case OP_2:
+ case OP_3:
+ case OP_4:
+ case OP_5:
+ case OP_6:
+ case OP_7:
+ case OP_8:
+ case OP_9:
+ case OP_10:
+ case OP_11:
+ case OP_12:
+ case OP_13:
+ case OP_14:
+ case OP_15:
+ case OP_16: {
+ // ( -- value)
+ CScriptNum bn((int)opcode - (int)(OP_1 - 1));
+ stack.push_back(bn.getvch());
+ // The result of these opcodes should always be the
+ // minimal way to push the data they push, so no need
+ // for a CheckMinimalPush here.
+ } break;
- // Note that elsewhere numeric opcodes are limited to
- // operands in the range -2**31+1 to 2**31-1, however it is
- // legal for opcodes to produce results exceeding that
- // range. This limitation is implemented by CScriptNum's
- // default 4-byte limit.
//
- // If we kept to that limit we'd have a year 2038 problem,
- // even though the nLockTime field in transactions
- // themselves is uint32 which only becomes meaningless
- // after the year 2106.
+ // Control
//
- // Thus as a special case we tell CScriptNum to accept up
- // to 5-byte bignums, which are good until 2**39-1, well
- // beyond the 2**32-1 limit of the nLockTime field itself.
- const CScriptNum nLockTime(stacktop(-1), fRequireMinimal, 5);
-
- // In the rare event that the argument may be < 0 due to
- // some arithmetic being done first, you can always use
- // 0 MAX CHECKLOCKTIMEVERIFY.
- if (nLockTime < 0)
- return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
-
- // Actually compare the specified lock time with the transaction.
- if (!checker.CheckLockTime(nLockTime))
- return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
-
- break;
- }
+ case OP_NOP:
+ break;
- case OP_CHECKSEQUENCEVERIFY:
- {
- if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
- // not enabled; treat as a NOP3
- if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
- return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ case OP_CHECKLOCKTIMEVERIFY: {
+ if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
+ // not enabled; treat as a NOP2
+ if (flags &
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
+ return set_error(
+ serror,
+ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
}
+
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // Note that elsewhere numeric opcodes are limited to
+ // operands in the range -2**31+1 to 2**31-1, however it
+ // is legal for opcodes to produce results exceeding
+ // that range. This limitation is implemented by
+ // CScriptNum's default 4-byte limit.
+ //
+ // If we kept to that limit we'd have a year 2038
+ // problem, even though the nLockTime field in
+ // transactions themselves is uint32 which only becomes
+ // meaningless after the year 2106.
+ //
+ // Thus as a special case we tell CScriptNum to accept
+ // up to 5-byte bignums, which are good until 2**39-1,
+ // well beyond the 2**32-1 limit of the nLockTime field
+ // itself.
+ const CScriptNum nLockTime(stacktop(-1),
+ fRequireMinimal, 5);
+
+ // In the rare event that the argument may be < 0 due to
+ // some arithmetic being done first, you can always use
+ // 0 MAX CHECKLOCKTIMEVERIFY.
+ if (nLockTime < 0)
+ return set_error(serror,
+ SCRIPT_ERR_NEGATIVE_LOCKTIME);
+
+ // Actually compare the specified lock time with the
+ // transaction.
+ if (!checker.CheckLockTime(nLockTime))
+ return set_error(serror,
+ SCRIPT_ERR_UNSATISFIED_LOCKTIME);
+
break;
}
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
-
- // nSequence, like nLockTime, is a 32-bit unsigned integer
- // field. See the comment in CHECKLOCKTIMEVERIFY regarding
- // 5-byte numeric operands.
- const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
+ case OP_CHECKSEQUENCEVERIFY: {
+ if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
+ // not enabled; treat as a NOP3
+ if (flags &
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
+ return set_error(
+ serror,
+ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
+ }
- // In the rare event that the argument may be < 0 due to
- // some arithmetic being done first, you can always use
- // 0 MAX CHECKSEQUENCEVERIFY.
- if (nSequence < 0)
- return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // nSequence, like nLockTime, is a 32-bit unsigned
+ // integer field. See the comment in CHECKLOCKTIMEVERIFY
+ // regarding 5-byte numeric operands.
+ const CScriptNum nSequence(stacktop(-1),
+ fRequireMinimal, 5);
+
+ // In the rare event that the argument may be < 0 due to
+ // some arithmetic being done first, you can always use
+ // 0 MAX CHECKSEQUENCEVERIFY.
+ if (nSequence < 0)
+ return set_error(serror,
+ SCRIPT_ERR_NEGATIVE_LOCKTIME);
+
+ // To provide for future soft-fork extensibility, if the
+ // operand has the disabled lock-time flag set,
+ // CHECKSEQUENCEVERIFY behaves as a NOP.
+ if ((nSequence &
+ CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
+ break;
+
+ // Compare the specified sequence number with the input.
+ if (!checker.CheckSequence(nSequence))
+ return set_error(serror,
+ SCRIPT_ERR_UNSATISFIED_LOCKTIME);
- // To provide for future soft-fork extensibility, if the
- // operand has the disabled lock-time flag set,
- // CHECKSEQUENCEVERIFY behaves as a NOP.
- if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
break;
+ }
- // Compare the specified sequence number with the input.
- if (!checker.CheckSequence(nSequence))
- return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
+ case OP_NOP1:
+ case OP_NOP4:
+ case OP_NOP5:
+ case OP_NOP6:
+ case OP_NOP7:
+ case OP_NOP8:
+ case OP_NOP9:
+ case OP_NOP10: {
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
+ return set_error(
+ serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ } break;
+
+ case OP_IF:
+ case OP_NOTIF: {
+ // <expression> if [statements] [else [statements]]
+ // endif
+ bool fValue = false;
+ if (fExec) {
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
+ valtype &vch = stacktop(-1);
+ if (sigversion == SIGVERSION_WITNESS_V0 &&
+ (flags & SCRIPT_VERIFY_MINIMALIF)) {
+ if (vch.size() > 1)
+ return set_error(serror,
+ SCRIPT_ERR_MINIMALIF);
+ if (vch.size() == 1 && vch[0] != 1)
+ return set_error(serror,
+ SCRIPT_ERR_MINIMALIF);
+ }
+ fValue = CastToBool(vch);
+ if (opcode == OP_NOTIF) fValue = !fValue;
+ popstack(stack);
+ }
+ vfExec.push_back(fValue);
+ } break;
+
+ case OP_ELSE: {
+ if (vfExec.empty())
+ return set_error(serror,
+ SCRIPT_ERR_UNBALANCED_CONDITIONAL);
+ vfExec.back() = !vfExec.back();
+ } break;
+
+ case OP_ENDIF: {
+ if (vfExec.empty())
+ return set_error(serror,
+ SCRIPT_ERR_UNBALANCED_CONDITIONAL);
+ vfExec.pop_back();
+ } break;
+
+ case OP_VERIFY: {
+ // (true -- ) or
+ // (false -- false) and return
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ bool fValue = CastToBool(stacktop(-1));
+ if (fValue)
+ popstack(stack);
+ else
+ return set_error(serror, SCRIPT_ERR_VERIFY);
+ } break;
- break;
- }
+ case OP_RETURN: {
+ return set_error(serror, SCRIPT_ERR_OP_RETURN);
+ } break;
- case OP_NOP1: case OP_NOP4: case OP_NOP5:
- case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
- {
- if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
- return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
- }
- break;
-
- case OP_IF:
- case OP_NOTIF:
- {
- // <expression> if [statements] [else [statements]] endif
- bool fValue = false;
- if (fExec)
- {
+ //
+ // Stack ops
+ //
+ case OP_TOALTSTACK: {
if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
- valtype& vch = stacktop(-1);
- if (sigversion == SIGVERSION_WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) {
- if (vch.size() > 1)
- return set_error(serror, SCRIPT_ERR_MINIMALIF);
- if (vch.size() == 1 && vch[0] != 1)
- return set_error(serror, SCRIPT_ERR_MINIMALIF);
- }
- fValue = CastToBool(vch);
- if (opcode == OP_NOTIF)
- fValue = !fValue;
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ altstack.push_back(stacktop(-1));
popstack(stack);
- }
- vfExec.push_back(fValue);
- }
- break;
-
- case OP_ELSE:
- {
- if (vfExec.empty())
- return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
- vfExec.back() = !vfExec.back();
- }
- break;
-
- case OP_ENDIF:
- {
- if (vfExec.empty())
- return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
- vfExec.pop_back();
- }
- break;
-
- case OP_VERIFY:
- {
- // (true -- ) or
- // (false -- false) and return
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- bool fValue = CastToBool(stacktop(-1));
- if (fValue)
+ } break;
+
+ case OP_FROMALTSTACK: {
+ if (altstack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION);
+ stack.push_back(altstacktop(-1));
+ popstack(altstack);
+ } break;
+
+ case OP_2DROP: {
+ // (x1 x2 -- )
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
popstack(stack);
- else
- return set_error(serror, SCRIPT_ERR_VERIFY);
- }
- break;
+ popstack(stack);
+ } break;
+
+ case OP_2DUP: {
+ // (x1 x2 -- x1 x2 x1 x2)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-2);
+ valtype vch2 = stacktop(-1);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ } break;
+
+ case OP_3DUP: {
+ // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
+ if (stack.size() < 3)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-3);
+ valtype vch2 = stacktop(-2);
+ valtype vch3 = stacktop(-1);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ stack.push_back(vch3);
+ } break;
+
+ case OP_2OVER: {
+ // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
+ if (stack.size() < 4)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-4);
+ valtype vch2 = stacktop(-3);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ } break;
+
+ case OP_2ROT: {
+ // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
+ if (stack.size() < 6)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch1 = stacktop(-6);
+ valtype vch2 = stacktop(-5);
+ stack.erase(stack.end() - 6, stack.end() - 4);
+ stack.push_back(vch1);
+ stack.push_back(vch2);
+ } break;
+
+ case OP_2SWAP: {
+ // (x1 x2 x3 x4 -- x3 x4 x1 x2)
+ if (stack.size() < 4)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ swap(stacktop(-4), stacktop(-2));
+ swap(stacktop(-3), stacktop(-1));
+ } break;
+
+ case OP_IFDUP: {
+ // (x - 0 | x x)
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-1);
+ if (CastToBool(vch)) stack.push_back(vch);
+ } break;
+
+ case OP_DEPTH: {
+ // -- stacksize
+ CScriptNum bn(stack.size());
+ stack.push_back(bn.getvch());
+ } break;
+
+ case OP_DROP: {
+ // (x -- )
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ popstack(stack);
+ } break;
- case OP_RETURN:
- {
- return set_error(serror, SCRIPT_ERR_OP_RETURN);
- }
- break;
-
-
- //
- // Stack ops
- //
- case OP_TOALTSTACK:
- {
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- altstack.push_back(stacktop(-1));
- popstack(stack);
- }
- break;
-
- case OP_FROMALTSTACK:
- {
- if (altstack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION);
- stack.push_back(altstacktop(-1));
- popstack(altstack);
- }
- break;
-
- case OP_2DROP:
- {
- // (x1 x2 -- )
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- popstack(stack);
- popstack(stack);
- }
- break;
-
- case OP_2DUP:
- {
- // (x1 x2 -- x1 x2 x1 x2)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch1 = stacktop(-2);
- valtype vch2 = stacktop(-1);
- stack.push_back(vch1);
- stack.push_back(vch2);
- }
- break;
-
- case OP_3DUP:
- {
- // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
- if (stack.size() < 3)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch1 = stacktop(-3);
- valtype vch2 = stacktop(-2);
- valtype vch3 = stacktop(-1);
- stack.push_back(vch1);
- stack.push_back(vch2);
- stack.push_back(vch3);
- }
- break;
-
- case OP_2OVER:
- {
- // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
- if (stack.size() < 4)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch1 = stacktop(-4);
- valtype vch2 = stacktop(-3);
- stack.push_back(vch1);
- stack.push_back(vch2);
- }
- break;
-
- case OP_2ROT:
- {
- // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
- if (stack.size() < 6)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch1 = stacktop(-6);
- valtype vch2 = stacktop(-5);
- stack.erase(stack.end()-6, stack.end()-4);
- stack.push_back(vch1);
- stack.push_back(vch2);
- }
- break;
-
- case OP_2SWAP:
- {
- // (x1 x2 x3 x4 -- x3 x4 x1 x2)
- if (stack.size() < 4)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- swap(stacktop(-4), stacktop(-2));
- swap(stacktop(-3), stacktop(-1));
- }
- break;
-
- case OP_IFDUP:
- {
- // (x - 0 | x x)
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch = stacktop(-1);
- if (CastToBool(vch))
+ case OP_DUP: {
+ // (x -- x x)
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-1);
stack.push_back(vch);
- }
- break;
-
- case OP_DEPTH:
- {
- // -- stacksize
- CScriptNum bn(stack.size());
- stack.push_back(bn.getvch());
- }
- break;
-
- case OP_DROP:
- {
- // (x -- )
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- popstack(stack);
- }
- break;
-
- case OP_DUP:
- {
- // (x -- x x)
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch = stacktop(-1);
- stack.push_back(vch);
- }
- break;
-
- case OP_NIP:
- {
- // (x1 x2 -- x2)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- stack.erase(stack.end() - 2);
- }
- break;
-
- case OP_OVER:
- {
- // (x1 x2 -- x1 x2 x1)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch = stacktop(-2);
- stack.push_back(vch);
- }
- break;
-
- case OP_PICK:
- case OP_ROLL:
- {
- // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
- // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- int n = CScriptNum(stacktop(-1), fRequireMinimal).getint();
- popstack(stack);
- if (n < 0 || n >= (int)stack.size())
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch = stacktop(-n-1);
- if (opcode == OP_ROLL)
- stack.erase(stack.end()-n-1);
- stack.push_back(vch);
- }
- break;
-
- case OP_ROT:
- {
- // (x1 x2 x3 -- x2 x3 x1)
- // x2 x1 x3 after first swap
- // x2 x3 x1 after second swap
- if (stack.size() < 3)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- swap(stacktop(-3), stacktop(-2));
- swap(stacktop(-2), stacktop(-1));
- }
- break;
-
- case OP_SWAP:
- {
- // (x1 x2 -- x2 x1)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- swap(stacktop(-2), stacktop(-1));
- }
- break;
-
- case OP_TUCK:
- {
- // (x1 x2 -- x2 x1 x2)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype vch = stacktop(-1);
- stack.insert(stack.end()-2, vch);
- }
- break;
-
+ } break;
+
+ case OP_NIP: {
+ // (x1 x2 -- x2)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ stack.erase(stack.end() - 2);
+ } break;
+
+ case OP_OVER: {
+ // (x1 x2 -- x1 x2 x1)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-2);
+ stack.push_back(vch);
+ } break;
+
+ case OP_PICK:
+ case OP_ROLL: {
+ // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
+ // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ int n =
+ CScriptNum(stacktop(-1), fRequireMinimal).getint();
+ popstack(stack);
+ if (n < 0 || n >= (int)stack.size())
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-n - 1);
+ if (opcode == OP_ROLL) stack.erase(stack.end() - n - 1);
+ stack.push_back(vch);
+ } break;
+
+ case OP_ROT: {
+ // (x1 x2 x3 -- x2 x3 x1)
+ // x2 x1 x3 after first swap
+ // x2 x3 x1 after second swap
+ if (stack.size() < 3)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ swap(stacktop(-3), stacktop(-2));
+ swap(stacktop(-2), stacktop(-1));
+ } break;
+
+ case OP_SWAP: {
+ // (x1 x2 -- x2 x1)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ swap(stacktop(-2), stacktop(-1));
+ } break;
+
+ case OP_TUCK: {
+ // (x1 x2 -- x2 x1 x2)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype vch = stacktop(-1);
+ stack.insert(stack.end() - 2, vch);
+ } break;
+
+ case OP_SIZE: {
+ // (in -- in size)
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn(stacktop(-1).size());
+ stack.push_back(bn.getvch());
+ } break;
- case OP_SIZE:
- {
- // (in -- in size)
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- CScriptNum bn(stacktop(-1).size());
- stack.push_back(bn.getvch());
- }
- break;
-
-
- //
- // Bitwise logic
- //
- case OP_EQUAL:
- case OP_EQUALVERIFY:
- //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL
- {
- // (x1 x2 - bool)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype& vch1 = stacktop(-2);
- valtype& vch2 = stacktop(-1);
- bool fEqual = (vch1 == vch2);
- // OP_NOTEQUAL is disabled because it would be too easy to say
- // something like n != 1 and have some wiseguy pass in 1 with extra
- // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
- //if (opcode == OP_NOTEQUAL)
- // fEqual = !fEqual;
- popstack(stack);
- popstack(stack);
- stack.push_back(fEqual ? vchTrue : vchFalse);
- if (opcode == OP_EQUALVERIFY)
- {
- if (fEqual)
+ //
+ // Bitwise logic
+ //
+ case OP_EQUAL:
+ case OP_EQUALVERIFY:
+ // case OP_NOTEQUAL: // use OP_NUMNOTEQUAL
+ {
+ // (x1 x2 - bool)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype &vch1 = stacktop(-2);
+ valtype &vch2 = stacktop(-1);
+ bool fEqual = (vch1 == vch2);
+ // OP_NOTEQUAL is disabled because it would be too
+ // easy to say something like n != 1 and have some
+ // wiseguy pass in 1 with extra zero bytes after it
+ // (numerically, 0x01 == 0x0001 == 0x000001)
+ // if (opcode == OP_NOTEQUAL)
+ // fEqual = !fEqual;
popstack(stack);
- else
- return set_error(serror, SCRIPT_ERR_EQUALVERIFY);
- }
- }
- break;
-
-
- //
- // Numeric
- //
- case OP_1ADD:
- case OP_1SUB:
- case OP_NEGATE:
- case OP_ABS:
- case OP_NOT:
- case OP_0NOTEQUAL:
- {
- // (in -- out)
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- CScriptNum bn(stacktop(-1), fRequireMinimal);
- switch (opcode)
- {
- case OP_1ADD: bn += bnOne; break;
- case OP_1SUB: bn -= bnOne; break;
- case OP_NEGATE: bn = -bn; break;
- case OP_ABS: if (bn < bnZero) bn = -bn; break;
- case OP_NOT: bn = (bn == bnZero); break;
- case OP_0NOTEQUAL: bn = (bn != bnZero); break;
- default: assert(!"invalid opcode"); break;
- }
- popstack(stack);
- stack.push_back(bn.getvch());
- }
- break;
-
- case OP_ADD:
- case OP_SUB:
- case OP_BOOLAND:
- case OP_BOOLOR:
- case OP_NUMEQUAL:
- case OP_NUMEQUALVERIFY:
- case OP_NUMNOTEQUAL:
- case OP_LESSTHAN:
- case OP_GREATERTHAN:
- case OP_LESSTHANOREQUAL:
- case OP_GREATERTHANOREQUAL:
- case OP_MIN:
- case OP_MAX:
- {
- // (x1 x2 -- out)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- CScriptNum bn1(stacktop(-2), fRequireMinimal);
- CScriptNum bn2(stacktop(-1), fRequireMinimal);
- CScriptNum bn(0);
- switch (opcode)
- {
- case OP_ADD:
- bn = bn1 + bn2;
- break;
-
- case OP_SUB:
- bn = bn1 - bn2;
- break;
-
- case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break;
- case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break;
- case OP_NUMEQUAL: bn = (bn1 == bn2); break;
- case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break;
- case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break;
- case OP_LESSTHAN: bn = (bn1 < bn2); break;
- case OP_GREATERTHAN: bn = (bn1 > bn2); break;
- case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break;
- case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break;
- case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break;
- case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break;
- default: assert(!"invalid opcode"); break;
- }
- popstack(stack);
- popstack(stack);
- stack.push_back(bn.getvch());
-
- if (opcode == OP_NUMEQUALVERIFY)
- {
- if (CastToBool(stacktop(-1)))
popstack(stack);
- else
- return set_error(serror, SCRIPT_ERR_NUMEQUALVERIFY);
- }
- }
- break;
-
- case OP_WITHIN:
- {
- // (x min max -- out)
- if (stack.size() < 3)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- CScriptNum bn1(stacktop(-3), fRequireMinimal);
- CScriptNum bn2(stacktop(-2), fRequireMinimal);
- CScriptNum bn3(stacktop(-1), fRequireMinimal);
- bool fValue = (bn2 <= bn1 && bn1 < bn3);
- popstack(stack);
- popstack(stack);
- popstack(stack);
- stack.push_back(fValue ? vchTrue : vchFalse);
- }
- break;
-
-
- //
- // Crypto
- //
- case OP_RIPEMD160:
- case OP_SHA1:
- case OP_SHA256:
- case OP_HASH160:
- case OP_HASH256:
- {
- // (in -- hash)
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- valtype& vch = stacktop(-1);
- valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
- if (opcode == OP_RIPEMD160)
- CRIPEMD160().Write(vch.data(), vch.size()).Finalize(vchHash.data());
- else if (opcode == OP_SHA1)
- CSHA1().Write(vch.data(), vch.size()).Finalize(vchHash.data());
- else if (opcode == OP_SHA256)
- CSHA256().Write(vch.data(), vch.size()).Finalize(vchHash.data());
- else if (opcode == OP_HASH160)
- CHash160().Write(vch.data(), vch.size()).Finalize(vchHash.data());
- else if (opcode == OP_HASH256)
- CHash256().Write(vch.data(), vch.size()).Finalize(vchHash.data());
- popstack(stack);
- stack.push_back(vchHash);
- }
- break;
-
- case OP_CODESEPARATOR:
- {
- // Hash starts after the code separator
- pbegincodehash = pc;
- }
- break;
-
- case OP_CHECKSIG:
- case OP_CHECKSIGVERIFY:
- {
- // (sig pubkey -- bool)
- if (stack.size() < 2)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
-
- valtype& vchSig = stacktop(-2);
- valtype& vchPubKey = stacktop(-1);
-
- // Subset of script starting at the most recent codeseparator
- CScript scriptCode(pbegincodehash, pend);
-
- // Drop the signature in pre-segwit scripts but not segwit scripts
- if (sigversion == SIGVERSION_BASE) {
- scriptCode.FindAndDelete(CScript(vchSig));
- }
+ stack.push_back(fEqual ? vchTrue : vchFalse);
+ if (opcode == OP_EQUALVERIFY) {
+ if (fEqual)
+ popstack(stack);
+ else
+ return set_error(serror,
+ SCRIPT_ERR_EQUALVERIFY);
+ }
+ }
+ break;
- if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
- //serror is set
- return false;
- }
- bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
+ //
+ // Numeric
+ //
+ case OP_1ADD:
+ case OP_1SUB:
+ case OP_NEGATE:
+ case OP_ABS:
+ case OP_NOT:
+ case OP_0NOTEQUAL: {
+ // (in -- out)
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn(stacktop(-1), fRequireMinimal);
+ switch (opcode) {
+ case OP_1ADD:
+ bn += bnOne;
+ break;
+ case OP_1SUB:
+ bn -= bnOne;
+ break;
+ case OP_NEGATE:
+ bn = -bn;
+ break;
+ case OP_ABS:
+ if (bn < bnZero) bn = -bn;
+ break;
+ case OP_NOT:
+ bn = (bn == bnZero);
+ break;
+ case OP_0NOTEQUAL:
+ bn = (bn != bnZero);
+ break;
+ default:
+ assert(!"invalid opcode");
+ break;
+ }
+ popstack(stack);
+ stack.push_back(bn.getvch());
+ } break;
- if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size())
- return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
+ case OP_ADD:
+ case OP_SUB:
+ case OP_BOOLAND:
+ case OP_BOOLOR:
+ case OP_NUMEQUAL:
+ case OP_NUMEQUALVERIFY:
+ case OP_NUMNOTEQUAL:
+ case OP_LESSTHAN:
+ case OP_GREATERTHAN:
+ case OP_LESSTHANOREQUAL:
+ case OP_GREATERTHANOREQUAL:
+ case OP_MIN:
+ case OP_MAX: {
+ // (x1 x2 -- out)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn1(stacktop(-2), fRequireMinimal);
+ CScriptNum bn2(stacktop(-1), fRequireMinimal);
+ CScriptNum bn(0);
+ switch (opcode) {
+ case OP_ADD:
+ bn = bn1 + bn2;
+ break;
+
+ case OP_SUB:
+ bn = bn1 - bn2;
+ break;
+
+ case OP_BOOLAND:
+ bn = (bn1 != bnZero && bn2 != bnZero);
+ break;
+ case OP_BOOLOR:
+ bn = (bn1 != bnZero || bn2 != bnZero);
+ break;
+ case OP_NUMEQUAL:
+ bn = (bn1 == bn2);
+ break;
+ case OP_NUMEQUALVERIFY:
+ bn = (bn1 == bn2);
+ break;
+ case OP_NUMNOTEQUAL:
+ bn = (bn1 != bn2);
+ break;
+ case OP_LESSTHAN:
+ bn = (bn1 < bn2);
+ break;
+ case OP_GREATERTHAN:
+ bn = (bn1 > bn2);
+ break;
+ case OP_LESSTHANOREQUAL:
+ bn = (bn1 <= bn2);
+ break;
+ case OP_GREATERTHANOREQUAL:
+ bn = (bn1 >= bn2);
+ break;
+ case OP_MIN:
+ bn = (bn1 < bn2 ? bn1 : bn2);
+ break;
+ case OP_MAX:
+ bn = (bn1 > bn2 ? bn1 : bn2);
+ break;
+ default:
+ assert(!"invalid opcode");
+ break;
+ }
+ popstack(stack);
+ popstack(stack);
+ stack.push_back(bn.getvch());
+
+ if (opcode == OP_NUMEQUALVERIFY) {
+ if (CastToBool(stacktop(-1)))
+ popstack(stack);
+ else
+ return set_error(serror,
+ SCRIPT_ERR_NUMEQUALVERIFY);
+ }
+ } break;
+
+ case OP_WITHIN: {
+ // (x min max -- out)
+ if (stack.size() < 3)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ CScriptNum bn1(stacktop(-3), fRequireMinimal);
+ CScriptNum bn2(stacktop(-2), fRequireMinimal);
+ CScriptNum bn3(stacktop(-1), fRequireMinimal);
+ bool fValue = (bn2 <= bn1 && bn1 < bn3);
+ popstack(stack);
+ popstack(stack);
+ popstack(stack);
+ stack.push_back(fValue ? vchTrue : vchFalse);
+ } break;
- popstack(stack);
- popstack(stack);
- stack.push_back(fSuccess ? vchTrue : vchFalse);
- if (opcode == OP_CHECKSIGVERIFY)
- {
- if (fSuccess)
- popstack(stack);
- else
- return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY);
- }
- }
- break;
-
- case OP_CHECKMULTISIG:
- case OP_CHECKMULTISIGVERIFY:
- {
- // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
-
- int i = 1;
- if ((int)stack.size() < i)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
-
- int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
- if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG)
- return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
- nOpCount += nKeysCount;
- if (nOpCount > MAX_OPS_PER_SCRIPT)
- return set_error(serror, SCRIPT_ERR_OP_COUNT);
- int ikey = ++i;
- // ikey2 is the position of last non-signature item in the stack. Top stack item = 1.
- // With SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if operation fails.
- int ikey2 = nKeysCount + 2;
- i += nKeysCount;
- if ((int)stack.size() < i)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
-
- int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
- if (nSigsCount < 0 || nSigsCount > nKeysCount)
- return set_error(serror, SCRIPT_ERR_SIG_COUNT);
- int isig = ++i;
- i += nSigsCount;
- if ((int)stack.size() < i)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
-
- // Subset of script starting at the most recent codeseparator
- CScript scriptCode(pbegincodehash, pend);
-
- // Drop the signature in pre-segwit scripts but not segwit scripts
- for (int k = 0; k < nSigsCount; k++)
- {
- valtype& vchSig = stacktop(-isig-k);
+ //
+ // Crypto
+ //
+ case OP_RIPEMD160:
+ case OP_SHA1:
+ case OP_SHA256:
+ case OP_HASH160:
+ case OP_HASH256: {
+ // (in -- hash)
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ valtype &vch = stacktop(-1);
+ valtype vchHash((opcode == OP_RIPEMD160 ||
+ opcode == OP_SHA1 ||
+ opcode == OP_HASH160)
+ ? 20
+ : 32);
+ if (opcode == OP_RIPEMD160)
+ CRIPEMD160()
+ .Write(vch.data(), vch.size())
+ .Finalize(vchHash.data());
+ else if (opcode == OP_SHA1)
+ CSHA1()
+ .Write(vch.data(), vch.size())
+ .Finalize(vchHash.data());
+ else if (opcode == OP_SHA256)
+ CSHA256()
+ .Write(vch.data(), vch.size())
+ .Finalize(vchHash.data());
+ else if (opcode == OP_HASH160)
+ CHash160()
+ .Write(vch.data(), vch.size())
+ .Finalize(vchHash.data());
+ else if (opcode == OP_HASH256)
+ CHash256()
+ .Write(vch.data(), vch.size())
+ .Finalize(vchHash.data());
+ popstack(stack);
+ stack.push_back(vchHash);
+ } break;
+
+ case OP_CODESEPARATOR: {
+ // Hash starts after the code separator
+ pbegincodehash = pc;
+ } break;
+
+ case OP_CHECKSIG:
+ case OP_CHECKSIGVERIFY: {
+ // (sig pubkey -- bool)
+ if (stack.size() < 2)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ valtype &vchSig = stacktop(-2);
+ valtype &vchPubKey = stacktop(-1);
+
+ // Subset of script starting at the most recent
+ // codeseparator
+ CScript scriptCode(pbegincodehash, pend);
+
+ // Drop the signature in pre-segwit scripts but not
+ // segwit scripts
if (sigversion == SIGVERSION_BASE) {
scriptCode.FindAndDelete(CScript(vchSig));
}
- }
-
- bool fSuccess = true;
- while (fSuccess && nSigsCount > 0)
- {
- valtype& vchSig = stacktop(-isig);
- valtype& vchPubKey = stacktop(-ikey);
- // Note how this makes the exact order of pubkey/signature evaluation
- // distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set.
- // See the script_(in)valid tests for details.
- if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) {
+ if (!CheckSignatureEncoding(vchSig, flags, serror) ||
+ !CheckPubKeyEncoding(vchPubKey, flags, sigversion,
+ serror)) {
// serror is set
return false;
}
+ bool fSuccess = checker.CheckSig(
+ vchSig, vchPubKey, scriptCode, sigversion);
- // Check signature
- bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode, sigversion);
+ if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) &&
+ vchSig.size())
+ return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
- if (fOk) {
- isig++;
- nSigsCount--;
+ popstack(stack);
+ popstack(stack);
+ stack.push_back(fSuccess ? vchTrue : vchFalse);
+ if (opcode == OP_CHECKSIGVERIFY) {
+ if (fSuccess)
+ popstack(stack);
+ else
+ return set_error(serror,
+ SCRIPT_ERR_CHECKSIGVERIFY);
+ }
+ } break;
+
+ case OP_CHECKMULTISIG:
+ case OP_CHECKMULTISIGVERIFY: {
+ // ([sig ...] num_of_signatures [pubkey ...]
+ // num_of_pubkeys -- bool)
+
+ int i = 1;
+ if ((int)stack.size() < i)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ int nKeysCount =
+ CScriptNum(stacktop(-i), fRequireMinimal).getint();
+ if (nKeysCount < 0 ||
+ nKeysCount > MAX_PUBKEYS_PER_MULTISIG)
+ return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
+ nOpCount += nKeysCount;
+ if (nOpCount > MAX_OPS_PER_SCRIPT)
+ return set_error(serror, SCRIPT_ERR_OP_COUNT);
+ int ikey = ++i;
+ // ikey2 is the position of last non-signature item in
+ // the stack. Top stack item = 1. With
+ // SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if
+ // operation fails.
+ int ikey2 = nKeysCount + 2;
+ i += nKeysCount;
+ if ((int)stack.size() < i)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ int nSigsCount =
+ CScriptNum(stacktop(-i), fRequireMinimal).getint();
+ if (nSigsCount < 0 || nSigsCount > nKeysCount)
+ return set_error(serror, SCRIPT_ERR_SIG_COUNT);
+ int isig = ++i;
+ i += nSigsCount;
+ if ((int)stack.size() < i)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // Subset of script starting at the most recent
+ // codeseparator
+ CScript scriptCode(pbegincodehash, pend);
+
+ // Drop the signature in pre-segwit scripts but not
+ // segwit scripts
+ for (int k = 0; k < nSigsCount; k++) {
+ valtype &vchSig = stacktop(-isig - k);
+ if (sigversion == SIGVERSION_BASE) {
+ scriptCode.FindAndDelete(CScript(vchSig));
+ }
}
- ikey++;
- nKeysCount--;
-
- // If there are more signatures left than keys left,
- // then too many signatures have failed. Exit early,
- // without checking any further signatures.
- if (nSigsCount > nKeysCount)
- fSuccess = false;
- }
- // Clean up stack of actual arguments
- while (i-- > 1) {
- // If the operation failed, we require that all signatures must be empty vector
- if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && !ikey2 && stacktop(-1).size())
- return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL);
- if (ikey2 > 0)
- ikey2--;
- popstack(stack);
- }
+ bool fSuccess = true;
+ while (fSuccess && nSigsCount > 0) {
+ valtype &vchSig = stacktop(-isig);
+ valtype &vchPubKey = stacktop(-ikey);
+
+ // Note how this makes the exact order of
+ // pubkey/signature evaluation distinguishable by
+ // CHECKMULTISIG NOT if the STRICTENC flag is set.
+ // See the script_(in)valid tests for details.
+ if (!CheckSignatureEncoding(vchSig, flags,
+ serror) ||
+ !CheckPubKeyEncoding(vchPubKey, flags,
+ sigversion, serror)) {
+ // serror is set
+ return false;
+ }
+
+ // Check signature
+ bool fOk = checker.CheckSig(vchSig, vchPubKey,
+ scriptCode, sigversion);
+
+ if (fOk) {
+ isig++;
+ nSigsCount--;
+ }
+ ikey++;
+ nKeysCount--;
+
+ // If there are more signatures left than keys left,
+ // then too many signatures have failed. Exit early,
+ // without checking any further signatures.
+ if (nSigsCount > nKeysCount) fSuccess = false;
+ }
- // A bug causes CHECKMULTISIG to consume one extra argument
- // whose contents were not checked in any way.
- //
- // Unfortunately this is a potential source of mutability,
- // so optionally verify it is exactly equal to zero prior
- // to removing it from the stack.
- if (stack.size() < 1)
- return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
- if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size())
- return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY);
- popstack(stack);
-
- stack.push_back(fSuccess ? vchTrue : vchFalse);
-
- if (opcode == OP_CHECKMULTISIGVERIFY)
- {
- if (fSuccess)
+ // Clean up stack of actual arguments
+ while (i-- > 1) {
+ // If the operation failed, we require that all
+ // signatures must be empty vector
+ if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) &&
+ !ikey2 && stacktop(-1).size())
+ return set_error(serror,
+ SCRIPT_ERR_SIG_NULLFAIL);
+ if (ikey2 > 0) ikey2--;
popstack(stack);
- else
- return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY);
- }
- }
- break;
+ }
- default:
- return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
- }
+ // A bug causes CHECKMULTISIG to consume one extra
+ // argument whose contents were not checked in any way.
+ //
+ // Unfortunately this is a potential source of
+ // mutability, so optionally verify it is exactly equal
+ // to zero prior to removing it from the stack.
+ if (stack.size() < 1)
+ return set_error(
+ serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+ if ((flags & SCRIPT_VERIFY_NULLDUMMY) &&
+ stacktop(-1).size())
+ return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY);
+ popstack(stack);
+
+ stack.push_back(fSuccess ? vchTrue : vchFalse);
+
+ if (opcode == OP_CHECKMULTISIGVERIFY) {
+ if (fSuccess)
+ popstack(stack);
+ else
+ return set_error(
+ serror, SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+ } break;
+
+ default:
+ return set_error(serror, SCRIPT_ERR_BAD_OPCODE);
+ }
// Size limits
if (stack.size() + altstack.size() > 1000)
return set_error(serror, SCRIPT_ERR_STACK_SIZE);
}
- }
- catch (...)
- {
+ } catch (...) {
return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
}
if (!vfExec.empty())
return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
return set_success(serror);
}
namespace {
/**
* Wrapper that serializes like CTransaction, but with the modifications
* required for the signature hash done in-place
*/
class CTransactionSignatureSerializer {
private:
- const CTransaction& 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
- const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE
- const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
+ //!< reference to the spending transaction (the one being serialized)
+ const CTransaction &txTo;
+ //!< output script being consumed
+ const CScript &scriptCode;
+ //!< input index of txTo being signed
+ const unsigned int nIn;
+ //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fAnyoneCanPay;
+ //!< whether the hashtype is SIGHASH_SINGLE
+ const bool fHashSingle;
+ //!< whether the hashtype is SIGHASH_NONE
+ const bool fHashNone;
public:
- CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
- txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
- fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
- fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
- fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {}
+ CTransactionSignatureSerializer(const CTransaction &txToIn,
+ const CScript &scriptCodeIn,
+ unsigned int nInIn, int nHashTypeIn)
+ : txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
+ fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
+ fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
+ fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {}
/** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
- template<typename S>
- void SerializeScriptCode(S &s) const {
+ template <typename S> void SerializeScriptCode(S &s) const {
CScript::const_iterator it = scriptCode.begin();
CScript::const_iterator itBegin = it;
opcodetype opcode;
unsigned int nCodeSeparators = 0;
while (scriptCode.GetOp(it, opcode)) {
- if (opcode == OP_CODESEPARATOR)
- nCodeSeparators++;
+ if (opcode == OP_CODESEPARATOR) nCodeSeparators++;
}
::WriteCompactSize(s, scriptCode.size() - nCodeSeparators);
it = itBegin;
while (scriptCode.GetOp(it, opcode)) {
if (opcode == OP_CODESEPARATOR) {
- s.write((char*)&itBegin[0], it-itBegin-1);
+ s.write((char *)&itBegin[0], it - itBegin - 1);
itBegin = it;
}
}
if (itBegin != scriptCode.end())
- s.write((char*)&itBegin[0], it-itBegin);
+ s.write((char *)&itBegin[0], it - itBegin);
}
/** Serialize an input of txTo */
- template<typename S>
- void SerializeInput(S &s, unsigned int nInput) const {
- // In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
- if (fAnyoneCanPay)
- nInput = nIn;
+ template <typename S> void SerializeInput(S &s, unsigned int nInput) const {
+ // In case of SIGHASH_ANYONECANPAY, only the input being signed is
+ // serialized
+ if (fAnyoneCanPay) nInput = nIn;
// Serialize the prevout
::Serialize(s, txTo.vin[nInput].prevout);
// Serialize the script
if (nInput != nIn)
// Blank out other inputs' signatures
::Serialize(s, CScriptBase());
else
SerializeScriptCode(s);
// Serialize the nSequence
if (nInput != nIn && (fHashSingle || fHashNone))
// let the others update at will
::Serialize(s, (int)0);
else
::Serialize(s, txTo.vin[nInput].nSequence);
}
/** Serialize an output of txTo */
- template<typename S>
+ template <typename S>
void SerializeOutput(S &s, unsigned int nOutput) const {
if (fHashSingle && nOutput != nIn)
// Do not lock-in the txout payee at other indices as txin
::Serialize(s, CTxOut());
else
::Serialize(s, txTo.vout[nOutput]);
}
/** Serialize txTo */
- template<typename S>
- void Serialize(S &s) const {
+ template <typename S> void Serialize(S &s) const {
// Serialize nVersion
::Serialize(s, txTo.nVersion);
// Serialize vin
unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
::WriteCompactSize(s, nInputs);
for (unsigned int nInput = 0; nInput < nInputs; nInput++)
- SerializeInput(s, nInput);
+ SerializeInput(s, nInput);
// Serialize vout
- unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size());
+ unsigned int nOutputs =
+ fHashNone ? 0 : (fHashSingle ? nIn + 1 : txTo.vout.size());
::WriteCompactSize(s, nOutputs);
for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
- SerializeOutput(s, nOutput);
+ SerializeOutput(s, nOutput);
// Serialize nLockTime
::Serialize(s, txTo.nLockTime);
}
};
-uint256 GetPrevoutHash(const CTransaction& txTo) {
+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) {
+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) {
+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
-PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
-{
+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)
-{
+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;
uint256 hashSequence;
uint256 hashOutputs;
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo);
}
- if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ if (!(nHashType & SIGHASH_ANYONECANPAY) &&
+ (nHashType & 0x1f) != SIGHASH_SINGLE &&
+ (nHashType & 0x1f) != SIGHASH_NONE) {
hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo);
}
-
- if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
+ if ((nHashType & 0x1f) != SIGHASH_SINGLE &&
+ (nHashType & 0x1f) != SIGHASH_NONE) {
hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo);
- } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
+ } else if ((nHashType & 0x1f) == SIGHASH_SINGLE &&
+ nIn < txTo.vout.size()) {
CHashWriter ss(SER_GETHASH, 0);
ss << txTo.vout[nIn];
hashOutputs = ss.GetHash();
}
CHashWriter ss(SER_GETHASH, 0);
// Version
ss << txTo.nVersion;
// Input prevouts/nSequence (none/all, depending on flags)
ss << hashPrevouts;
ss << hashSequence;
- // The input being signed (replacing the scriptSig with scriptCode + amount)
- // The prevout may already be contained in hashPrevout, and the nSequence
- // may already be contain in hashSequence.
+ // The input being signed (replacing the scriptSig with scriptCode +
+ // amount). The prevout may already be contained in hashPrevout, and the
+ // nSequence may already be contain in hashSequence.
ss << txTo.vin[nIn].prevout;
- ss << static_cast<const CScriptBase&>(scriptCode);
+ ss << static_cast<const CScriptBase &>(scriptCode);
ss << amount;
ss << txTo.vin[nIn].nSequence;
// Outputs (none/one/all, depending on flags)
ss << hashOutputs;
// Locktime
ss << txTo.nLockTime;
// Sighash type
ss << nHashType;
return ss.GetHash();
}
- static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
+ static const uint256 one(uint256S(
+ "0000000000000000000000000000000000000000000000000000000000000001"));
if (nIn >= txTo.vin.size()) {
// nIn out of range
return one;
}
// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
// nOut out of range
return one;
}
}
- // Wrapper to serialize only the necessary parts of the transaction being signed
+ // Wrapper to serialize only the necessary parts of the transaction being
+ // signed
CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
ss << txTmp << nHashType;
return ss.GetHash();
}
-bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
-{
+bool TransactionSignatureChecker::VerifySignature(
+ const std::vector<unsigned char> &vchSig, const CPubKey &pubkey,
+ const uint256 &sighash) const {
return pubkey.Verify(sighash, vchSig);
}
-bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
-{
+bool TransactionSignatureChecker::CheckSig(
+ const vector<unsigned char> &vchSigIn,
+ const vector<unsigned char> &vchPubKey, const CScript &scriptCode,
+ SigVersion sigversion) const {
CPubKey pubkey(vchPubKey);
- if (!pubkey.IsValid())
- return false;
+ if (!pubkey.IsValid()) return false;
// Hash type is one byte tacked on to the end of the signature
vector<unsigned char> vchSig(vchSigIn);
- if (vchSig.empty())
- return false;
+ if (vchSig.empty()) return false;
int nHashType = vchSig.back();
vchSig.pop_back();
- uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata);
+ uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount,
+ sigversion, this->txdata);
- if (!VerifySignature(vchSig, pubkey, sighash))
- return false;
+ if (!VerifySignature(vchSig, pubkey, sighash)) return false;
return true;
}
-bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
-{
- // There are two kinds of nLockTime: lock-by-blockheight
- // and lock-by-blocktime, distinguished by whether
- // nLockTime < LOCKTIME_THRESHOLD.
+bool TransactionSignatureChecker::CheckLockTime(
+ const CScriptNum &nLockTime) const {
+ // There are two kinds of nLockTime: lock-by-blockheight and
+ // lock-by-blocktime, distinguished by whether nLockTime <
+ // LOCKTIME_THRESHOLD.
//
- // We want to compare apples to apples, so fail the script
- // unless the type of nLockTime being tested is the same as
- // the nLockTime in the transaction.
- if (!(
- (txTo->nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
- (txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
- ))
+ // We want to compare apples to apples, so fail the script unless the type
+ // of nLockTime being tested is the same as the nLockTime in the
+ // transaction.
+ if (!((txTo->nLockTime < LOCKTIME_THRESHOLD &&
+ nLockTime < LOCKTIME_THRESHOLD) ||
+ (txTo->nLockTime >= LOCKTIME_THRESHOLD &&
+ nLockTime >= LOCKTIME_THRESHOLD)))
return false;
- // Now that we know we're comparing apples-to-apples, the
- // comparison is a simple numeric one.
- if (nLockTime > (int64_t)txTo->nLockTime)
- return false;
+ // Now that we know we're comparing apples-to-apples, the comparison is a
+ // simple numeric one.
+ if (nLockTime > (int64_t)txTo->nLockTime) return false;
// Finally the nLockTime feature can be disabled and thus
- // CHECKLOCKTIMEVERIFY bypassed if every txin has been
- // finalized by setting nSequence to maxint. The
- // transaction would be allowed into the blockchain, making
- // the opcode ineffective.
+ // CHECKLOCKTIMEVERIFY bypassed if every txin has been finalized by setting
+ // nSequence to maxint. The transaction would be allowed into the
+ // blockchain, making the opcode ineffective.
//
- // Testing if this vin is not final is sufficient to
- // prevent this condition. Alternatively we could test all
- // inputs, but testing just this input minimizes the data
- // required to prove correct CHECKLOCKTIMEVERIFY execution.
- if (CTxIn::SEQUENCE_FINAL == txTo->vin[nIn].nSequence)
- return false;
+ // Testing if this vin is not final is sufficient to prevent this condition.
+ // Alternatively we could test all inputs, but testing just this input
+ // minimizes the data required to prove correct CHECKLOCKTIMEVERIFY
+ // execution.
+ if (CTxIn::SEQUENCE_FINAL == txTo->vin[nIn].nSequence) return false;
return true;
}
-bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
-{
- // Relative lock times are supported by comparing the passed
- // in operand to the sequence number of the input.
+bool TransactionSignatureChecker::CheckSequence(
+ const CScriptNum &nSequence) const {
+ // Relative lock times are supported by comparing the passed in operand to
+ // the sequence number of the input.
const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
- // Fail if the transaction's version number is not set high
- // enough to trigger BIP 68 rules.
- if (static_cast<uint32_t>(txTo->nVersion) < 2)
- return false;
+ // Fail if the transaction's version number is not set high enough to
+ // trigger BIP 68 rules.
+ if (static_cast<uint32_t>(txTo->nVersion) < 2) return false;
- // Sequence numbers with their most significant bit set are not
- // consensus constrained. Testing that the transaction's sequence
- // number do not have this bit set prevents using this property
- // to get around a CHECKSEQUENCEVERIFY check.
- if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
- return false;
+ // Sequence numbers with their most significant bit set are not consensus
+ // constrained. Testing that the transaction's sequence number do not have
+ // this bit set prevents using this property to get around a
+ // CHECKSEQUENCEVERIFY check.
+ if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) return false;
- // Mask off any bits that do not have consensus-enforced meaning
- // before doing the integer comparisons
- const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
+ // Mask off any bits that do not have consensus-enforced meaning before
+ // doing the integer comparisons
+ const uint32_t nLockTimeMask =
+ CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
const int64_t txToSequenceMasked = txToSequence & nLockTimeMask;
const CScriptNum nSequenceMasked = nSequence & nLockTimeMask;
- // There are two kinds of nSequence: lock-by-blockheight
- // and lock-by-blocktime, distinguished by whether
- // nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
+ // There are two kinds of nSequence: lock-by-blockheight and
+ // lock-by-blocktime, distinguished by whether nSequenceMasked <
+ // CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
//
- // We want to compare apples to apples, so fail the script
- // unless the type of nSequenceMasked being tested is the same as
- // the nSequenceMasked in the transaction.
- if (!(
- (txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
- (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)
- )) {
+ // We want to compare apples to apples, so fail the script unless the type
+ // of nSequenceMasked being tested is the same as the nSequenceMasked in the
+ // transaction.
+ if (!((txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG &&
+ nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
+ (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG &&
+ nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG))) {
return false;
}
- // Now that we know we're comparing apples-to-apples, the
- // comparison is a simple numeric one.
- if (nSequenceMasked > txToSequenceMasked)
- return false;
+ // Now that we know we're comparing apples-to-apples, the comparison is a
+ // simple numeric one.
+ if (nSequenceMasked > txToSequenceMasked) return false;
return true;
}
-static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
-{
- vector<vector<unsigned char> > stack;
+static bool VerifyWitnessProgram(const CScriptWitness &witness, int witversion,
+ const std::vector<unsigned char> &program,
+ unsigned int flags,
+ const BaseSignatureChecker &checker,
+ ScriptError *serror) {
+ vector<vector<unsigned char>> stack;
CScript scriptPubKey;
if (witversion == 0) {
if (program.size() == 32) {
- // Version 0 segregated witness program: SHA256(CScript) inside the program, CScript + inputs in witness
+ // Version 0 segregated witness program: SHA256(CScript) inside the
+ // program, CScript + inputs in witness
if (witness.stack.size() == 0) {
- return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
+ return set_error(serror,
+ SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
}
- scriptPubKey = CScript(witness.stack.back().begin(), witness.stack.back().end());
- stack = std::vector<std::vector<unsigned char> >(witness.stack.begin(), witness.stack.end() - 1);
+ scriptPubKey = CScript(witness.stack.back().begin(),
+ witness.stack.back().end());
+ stack = std::vector<std::vector<unsigned char>>(
+ witness.stack.begin(), witness.stack.end() - 1);
uint256 hashScriptPubKey;
- CSHA256().Write(&scriptPubKey[0], scriptPubKey.size()).Finalize(hashScriptPubKey.begin());
+ CSHA256()
+ .Write(&scriptPubKey[0], scriptPubKey.size())
+ .Finalize(hashScriptPubKey.begin());
if (memcmp(hashScriptPubKey.begin(), &program[0], 32)) {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH);
}
} else if (program.size() == 20) {
// Special case for pay-to-pubkeyhash; signature + pubkey in witness
if (witness.stack.size() != 2) {
- return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness
+ return set_error(
+ serror,
+ SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH); // 2 items in witness
}
- scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY << OP_CHECKSIG;
+ scriptPubKey << OP_DUP << OP_HASH160 << program << OP_EQUALVERIFY
+ << OP_CHECKSIG;
stack = witness.stack;
} else {
return set_error(serror, SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH);
}
} else if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM) {
- return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
+ return set_error(serror,
+ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM);
} else {
- // Higher version witness scripts return true for future softfork compatibility
+ // Higher version witness scripts return true for future softfork
+ // compatibility
return set_success(serror);
}
// Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
for (unsigned int i = 0; i < stack.size(); i++) {
if (stack.at(i).size() > MAX_SCRIPT_ELEMENT_SIZE)
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
}
- if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_WITNESS_V0, serror)) {
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_WITNESS_V0,
+ serror)) {
return false;
}
// Scripts inside witness implicitly require cleanstack behaviour
- if (stack.size() != 1)
- return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (stack.size() != 1) return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
if (!CastToBool(stack.back()))
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
return true;
}
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
-{
+bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey,
+ unsigned int flags, const BaseSignatureChecker &checker,
+ ScriptError *serror) {
static const CScriptWitness emptyWitness;
- const CScriptWitness* witness = &emptyWitness;
+ const CScriptWitness *witness = &emptyWitness;
bool hadWitness = false;
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) {
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
}
- vector<vector<unsigned char> > stack, stackCopy;
+ vector<vector<unsigned char>> stack, stackCopy;
if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
// serror is set
return false;
- if (flags & SCRIPT_VERIFY_P2SH)
- stackCopy = stack;
- if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
+ if (flags & SCRIPT_VERIFY_P2SH) stackCopy = stack;
+ if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE,
+ serror))
// serror is set
return false;
- if (stack.empty())
- return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (stack.empty()) return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
if (CastToBool(stack.back()) == false)
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
// Bare witness programs
int witnessversion;
std::vector<unsigned char> witnessprogram;
if (flags & SCRIPT_VERIFY_WITNESS) {
if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
hadWitness = true;
if (scriptSig.size() != 0) {
- // The scriptSig must be _exactly_ CScript(), otherwise we reintroduce malleability.
+ // The scriptSig must be _exactly_ CScript(), otherwise we
+ // reintroduce malleability.
return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED);
}
- if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram,
+ flags, checker, serror)) {
return false;
}
- // Bypass the cleanstack check at the end. The actual stack is obviously not clean
- // for witness programs.
+ // Bypass the cleanstack check at the end. The actual stack is
+ // obviously not clean for witness programs.
stack.resize(1);
}
}
// Additional validation for spend-to-script-hash transactions:
- if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash())
- {
+ if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash()) {
// scriptSig must be literals-only or validation fails
if (!scriptSig.IsPushOnly())
return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY);
// Restore stack.
swap(stack, stackCopy);
- // stack cannot be empty here, because if it was the
- // P2SH HASH <> EQUAL scriptPubKey would be evaluated with
- // an empty stack and the EvalScript above would return false.
+ // stack cannot be empty here, because if it was the P2SH HASH <> EQUAL
+ // scriptPubKey would be evaluated with an empty stack and the
+ // EvalScript above would return false.
assert(!stack.empty());
- const valtype& pubKeySerialized = stack.back();
+ const valtype &pubKeySerialized = stack.back();
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stack);
- if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
+ if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE,
+ serror))
// serror is set
return false;
- if (stack.empty())
- return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
+ if (stack.empty()) return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
if (!CastToBool(stack.back()))
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
// P2SH witness program
if (flags & SCRIPT_VERIFY_WITNESS) {
if (pubKey2.IsWitnessProgram(witnessversion, witnessprogram)) {
hadWitness = true;
- if (scriptSig != CScript() << std::vector<unsigned char>(pubKey2.begin(), pubKey2.end())) {
- // The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we
- // reintroduce malleability.
+ if (scriptSig !=
+ CScript() << std::vector<unsigned char>(pubKey2.begin(),
+ pubKey2.end())) {
+ // The scriptSig must be _exactly_ a single push of the
+ // redeemScript. Otherwise we reintroduce malleability.
return set_error(serror, SCRIPT_ERR_WITNESS_MALLEATED_P2SH);
}
- if (!VerifyWitnessProgram(*witness, witnessversion, witnessprogram, flags, checker, serror)) {
+ if (!VerifyWitnessProgram(*witness, witnessversion,
+ witnessprogram, flags, checker,
+ serror)) {
return false;
}
- // Bypass the cleanstack check at the end. The actual stack is obviously not clean
- // for witness programs.
+ // Bypass the cleanstack check at the end. The actual stack is
+ // obviously not clean for witness programs.
stack.resize(1);
}
}
}
// The CLEANSTACK check is only performed after potential P2SH evaluation,
// as the non-P2SH evaluation of a P2SH script will obviously not result in
- // a clean stack (the P2SH inputs remain). The same holds for witness evaluation.
+ // a clean stack (the P2SH inputs remain). The same holds for witness
+ // evaluation.
if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) {
- // Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK
- // would be possible, which is not a softfork (and P2SH should be one).
+ // Disallow CLEANSTACK without P2SH, as otherwise a switch
+ // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a
+ // softfork (and P2SH should be one).
assert((flags & SCRIPT_VERIFY_P2SH) != 0);
assert((flags & SCRIPT_VERIFY_WITNESS) != 0);
if (stack.size() != 1) {
return set_error(serror, SCRIPT_ERR_CLEANSTACK);
}
}
if (flags & SCRIPT_VERIFY_WITNESS) {
- // We can't check for correct unexpected witness data if P2SH was off, so require
- // that WITNESS implies P2SH. Otherwise, going from WITNESS->P2SH+WITNESS would be
- // possible, which is not a softfork.
+ // We can't check for correct unexpected witness data if P2SH was off,
+ // so require that WITNESS implies P2SH. Otherwise, going from
+ // WITNESS->P2SH+WITNESS would be possible, which is not a softfork.
assert((flags & SCRIPT_VERIFY_P2SH) != 0);
if (!hadWitness && !witness->IsNull()) {
return set_error(serror, SCRIPT_ERR_WITNESS_UNEXPECTED);
}
}
return set_success(serror);
}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 7eaeb4d92..25e2b9162 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -1,180 +1,205 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SCRIPT_INTERPRETER_H
#define BITCOIN_SCRIPT_INTERPRETER_H
-#include "script_error.h"
#include "primitives/transaction.h"
+#include "script_error.h"
-#include <vector>
#include <stdint.h>
#include <string>
+#include <vector>
class CPubKey;
class CScript;
class CTransaction;
class uint256;
/** Signature hash types/flags */
-enum
-{
+enum {
SIGHASH_ALL = 1,
SIGHASH_NONE = 2,
SIGHASH_SINGLE = 3,
SIGHASH_ANYONECANPAY = 0x80,
};
/** Script verification flags */
-enum
-{
- SCRIPT_VERIFY_NONE = 0,
+enum {
+ SCRIPT_VERIFY_NONE = 0,
// Evaluate P2SH subscripts (softfork safe, BIP16).
- SCRIPT_VERIFY_P2SH = (1U << 0),
+ SCRIPT_VERIFY_P2SH = (1U << 0),
- // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
- // Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure.
+ // Passing a non-strict-DER signature or one with undefined hashtype to a
+ // checksig operation causes script failure. Evaluating a pubkey that is not
+ // (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script
+ // failure.
// (softfork safe, but not used or intended as a consensus rule).
SCRIPT_VERIFY_STRICTENC = (1U << 1),
- // Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
- SCRIPT_VERIFY_DERSIG = (1U << 2),
+ // Passing a non-strict-DER signature to a checksig operation causes script
+ // failure (softfork safe, BIP62 rule 1)
+ SCRIPT_VERIFY_DERSIG = (1U << 2),
- // Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
+ // Passing a non-strict-DER signature or one with S > order/2 to a checksig
+ // operation causes script failure
// (softfork safe, BIP62 rule 5).
- SCRIPT_VERIFY_LOW_S = (1U << 3),
+ SCRIPT_VERIFY_LOW_S = (1U << 3),
- // verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
+ // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
+ // (softfork safe, BIP62 rule 7).
SCRIPT_VERIFY_NULLDUMMY = (1U << 4),
- // Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
+ // Using a non-push operator in the scriptSig causes script failure
+ // (softfork safe, BIP62 rule 2).
SCRIPT_VERIFY_SIGPUSHONLY = (1U << 5),
- // Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
- // pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
- // any other push causes the script to fail (BIP62 rule 3).
- // In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
+ // Require minimal encodings for all push operations (OP_0... OP_16,
+ // OP_1NEGATE where possible, direct pushes up to 75 bytes, OP_PUSHDATA up
+ // to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating any other
+ // push causes the script to fail (BIP62 rule 3). In addition, whenever a
+ // stack element is interpreted as a number, it must be of minimal length
+ // (BIP62 rule 4).
// (softfork safe)
SCRIPT_VERIFY_MINIMALDATA = (1U << 6),
// Discourage use of NOPs reserved for upgrades (NOP1-10)
//
// Provided so that nodes can avoid accepting or mining transactions
// containing executed NOP's whose meaning may change after a soft-fork,
// thus rendering the script invalid; with this flag set executing
- // discouraged NOPs fails the script. This verification flag will never be
- // a mandatory flag applied to scripts in a block. NOPs that are not
- // executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
- SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7),
-
- // Require that only a single stack element remains after evaluation. This changes the success criterion from
- // "At least one stack element must remain, and when interpreted as a boolean, it must be true" to
- // "Exactly one stack element must remain, and when interpreted as a boolean, it must be true".
+ // discouraged NOPs fails the script. This verification flag will never be a
+ // mandatory flag applied to scripts in a block. NOPs that are not executed,
+ // e.g. within an unexecuted IF ENDIF block, are *not* rejected.
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7),
+
+ // Require that only a single stack element remains after evaluation. This
+ // changes the success criterion from "At least one stack element must
+ // remain, and when interpreted as a boolean, it must be true" to "Exactly
+ // one stack element must remain, and when interpreted as a boolean, it must
+ // be true".
// (softfork safe, BIP62 rule 6)
// Note: CLEANSTACK should never be used without P2SH or WITNESS.
SCRIPT_VERIFY_CLEANSTACK = (1U << 8),
// Verify CHECKLOCKTIMEVERIFY
//
// See BIP65 for details.
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
// support CHECKSEQUENCEVERIFY opcode
//
// See BIP112 for details
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10),
// Support segregated witness
//
SCRIPT_VERIFY_WITNESS = (1U << 11),
// Making v1-v16 witness program non-standard
//
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1U << 12),
- // Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector
+ // Segwit script only: Require the argument of OP_IF/NOTIF to be exactly
+ // 0x01 or empty vector
//
SCRIPT_VERIFY_MINIMALIF = (1U << 13),
// Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed
//
SCRIPT_VERIFY_NULLFAIL = (1U << 14),
// Public keys in segregated witness scripts must be compressed
//
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1U << 15),
};
-bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
+bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig,
+ unsigned int flags, ScriptError *serror);
-struct PrecomputedTransactionData
-{
+struct PrecomputedTransactionData {
uint256 hashPrevouts, hashSequence, hashOutputs;
- PrecomputedTransactionData(const CTransaction& tx);
+ PrecomputedTransactionData(const CTransaction &tx);
};
-enum SigVersion
-{
+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, const PrecomputedTransactionData* cache = NULL);
+uint256 SignatureHash(const CScript &scriptCode, const CTransaction &txTo,
+ unsigned int nIn, int nHashType, const CAmount &amount,
+ SigVersion sigversion,
+ const PrecomputedTransactionData *cache = NULL);
-class BaseSignatureChecker
-{
+class BaseSignatureChecker {
public:
- virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
- {
+ virtual bool CheckSig(const std::vector<unsigned char> &scriptSig,
+ const std::vector<unsigned char> &vchPubKey,
+ const CScript &scriptCode,
+ SigVersion sigversion) const {
return false;
}
- virtual bool CheckLockTime(const CScriptNum& nLockTime) const
- {
- return false;
+ virtual bool CheckLockTime(const CScriptNum &nLockTime) const {
+ return false;
}
- virtual bool CheckSequence(const CScriptNum& nSequence) const
- {
- return false;
+ virtual bool CheckSequence(const CScriptNum &nSequence) const {
+ return false;
}
virtual ~BaseSignatureChecker() {}
};
-class TransactionSignatureChecker : public BaseSignatureChecker
-{
+class TransactionSignatureChecker : public BaseSignatureChecker {
private:
- const CTransaction* txTo;
+ const CTransaction *txTo;
unsigned int nIn;
const CAmount amount;
- const PrecomputedTransactionData* txdata;
+ const PrecomputedTransactionData *txdata;
protected:
- virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
+ 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), 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;
+ 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;
};
-class MutableTransactionSignatureChecker : public TransactionSignatureChecker
-{
+class MutableTransactionSignatureChecker : public TransactionSignatureChecker {
private:
const CTransaction txTo;
public:
- MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
+ MutableTransactionSignatureChecker(const CMutableTransaction *txToIn,
+ unsigned int nInIn,
+ const CAmount &amount)
+ : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
};
-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = NULL);
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = NULL);
+bool EvalScript(std::vector<std::vector<unsigned char>> &stack,
+ const CScript &script, unsigned int flags,
+ const BaseSignatureChecker &checker, SigVersion sigversion,
+ ScriptError *error = NULL);
+bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey,
+ unsigned int flags, const BaseSignatureChecker &checker,
+ ScriptError *serror = NULL);
#endif // BITCOIN_SCRIPT_INTERPRETER_H
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Apr 27, 10:49 (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5573331
Default Alt Text
(122 KB)
Attached To
rABC Bitcoin ABC
Event Timeline
Log In to Comment