Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13114937
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
70 KB
Subscribers
None
View Options
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 9c47f7c6c9..fd4a5674cf 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1,1305 +1,1305 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 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 "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;
return true;
}
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)
{
// Can be negative zero
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");
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;
}
/**
* 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]
// * total-length: 1-byte length descriptor of everything that follows,
// 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).
// * 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)
// 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.
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;
return true;
}
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);
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;
return true;
}
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)) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
} 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)) {
return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE);
}
return true;
}
bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsCompressedOrUncompressedPubKey(vchSig)) {
return set_error(serror, SCRIPT_ERR_PUBKEYTYPE);
}
return true;
}
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).
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, 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() > 10000)
+ 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)
{
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 (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) {
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);
// 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;
}
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;
}
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);
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)
{
if (stack.size() < 1)
return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL);
valtype& vch = stacktop(-1);
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;
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))
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;
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)
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(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash));
else if (opcode == OP_SHA1)
CSHA1().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash));
else if (opcode == OP_SHA256)
CSHA256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash));
else if (opcode == OP_HASH160)
CHash160().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash));
else if (opcode == OP_HASH256)
CHash256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash));
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, since there's no way for a signature to sign itself
scriptCode.FindAndDelete(CScript(vchSig));
if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) {
//serror is set
return false;
}
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode);
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;
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 signatures, since there's no way for a signature to sign itself
for (int k = 0; k < nSigsCount; k++)
{
valtype& vchSig = stacktop(-isig-k);
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, serror)) {
// serror is set
return false;
}
// Check signature
bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode);
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;
}
// Clean up stack of actual arguments
while (i-- > 1)
popstack(stack);
// 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 (...)
{
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
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) {}
/** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
template<typename S>
void SerializeScriptCode(S &s, int nType, int nVersion) 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++;
}
::WriteCompactSize(s, scriptCode.size() - nCodeSeparators);
it = itBegin;
while (scriptCode.GetOp(it, opcode)) {
if (opcode == OP_CODESEPARATOR) {
s.write((char*)&itBegin[0], it-itBegin-1);
itBegin = it;
}
}
if (itBegin != scriptCode.end())
s.write((char*)&itBegin[0], it-itBegin);
}
/** Serialize an input of txTo */
template<typename S>
void SerializeInput(S &s, unsigned int nInput, int nType, int nVersion) 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, nType, nVersion);
// Serialize the script
if (nInput != nIn)
// Blank out other inputs' signatures
::Serialize(s, CScriptBase(), nType, nVersion);
else
SerializeScriptCode(s, nType, nVersion);
// Serialize the nSequence
if (nInput != nIn && (fHashSingle || fHashNone))
// let the others update at will
::Serialize(s, (int)0, nType, nVersion);
else
::Serialize(s, txTo.vin[nInput].nSequence, nType, nVersion);
}
/** Serialize an output of txTo */
template<typename S>
void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const {
if (fHashSingle && nOutput != nIn)
// Do not lock-in the txout payee at other indices as txin
::Serialize(s, CTxOut(), nType, nVersion);
else
::Serialize(s, txTo.vout[nOutput], nType, nVersion);
}
/** Serialize txTo */
template<typename S>
void Serialize(S &s, int nType, int nVersion) const {
// Serialize nVersion
::Serialize(s, txTo.nVersion, nType, 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, nType, nVersion);
// Serialize vout
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, nType, nVersion);
// Serialize nLockTime
::Serialize(s, txTo.nLockTime, nType, nVersion);
}
};
} // anon namespace
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
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
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
{
return pubkey.Verify(sighash, vchSig);
}
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode) const
{
CPubKey pubkey(vchPubKey);
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;
int nHashType = vchSig.back();
vchSig.pop_back();
uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType);
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.
//
// 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;
// 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.
//
// 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.
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;
// 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;
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.
//
// 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;
return true;
}
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
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;
if (!EvalScript(stack, scriptSig, flags, checker, serror))
// serror is set
return false;
if (flags & SCRIPT_VERIFY_P2SH)
stackCopy = stack;
if (!EvalScript(stack, scriptPubKey, flags, checker, serror))
// serror is set
return 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);
// Additional validation for spend-to-script-hash transactions:
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.
assert(!stack.empty());
const valtype& pubKeySerialized = stack.back();
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
popstack(stack);
if (!EvalScript(stack, pubKey2, flags, checker, serror))
// serror is set
return false;
if (stack.empty())
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
if (!CastToBool(stack.back()))
return set_error(serror, SCRIPT_ERR_EVAL_FALSE);
}
// 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).
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).
assert((flags & SCRIPT_VERIFY_P2SH) != 0);
if (stack.size() != 1) {
return set_error(serror, SCRIPT_ERR_CLEANSTACK);
}
}
return set_success(serror);
}
diff --git a/src/script/script.h b/src/script/script.h
index d2a68a07ba..68cde03e34 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,643 +1,646 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 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_SCRIPT_H
#define BITCOIN_SCRIPT_SCRIPT_H
#include "crypto/common.h"
#include "prevector.h"
#include <assert.h>
#include <climits>
#include <limits>
#include <stdexcept>
#include <stdint.h>
#include <string.h>
#include <string>
#include <vector>
// Maximum number of bytes pushable to the stack
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
// Maximum number of non-push operations per script
static const int MAX_OPS_PER_SCRIPT = 201;
// Maximum number of public keys per multisig
static const int MAX_PUBKEYS_PER_MULTISIG = 20;
+// Maximum script length in bytes
+static const int MAX_SCRIPT_SIZE = 10000;
+
// Threshold for nLockTime: below this value it is interpreted as block number,
// otherwise as UNIX timestamp.
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
template <typename T>
std::vector<unsigned char> ToByteVector(const T& in)
{
return std::vector<unsigned char>(in.begin(), in.end());
}
/** Script opcodes */
enum opcodetype
{
// push value
OP_0 = 0x00,
OP_FALSE = OP_0,
OP_PUSHDATA1 = 0x4c,
OP_PUSHDATA2 = 0x4d,
OP_PUSHDATA4 = 0x4e,
OP_1NEGATE = 0x4f,
OP_RESERVED = 0x50,
OP_1 = 0x51,
OP_TRUE=OP_1,
OP_2 = 0x52,
OP_3 = 0x53,
OP_4 = 0x54,
OP_5 = 0x55,
OP_6 = 0x56,
OP_7 = 0x57,
OP_8 = 0x58,
OP_9 = 0x59,
OP_10 = 0x5a,
OP_11 = 0x5b,
OP_12 = 0x5c,
OP_13 = 0x5d,
OP_14 = 0x5e,
OP_15 = 0x5f,
OP_16 = 0x60,
// control
OP_NOP = 0x61,
OP_VER = 0x62,
OP_IF = 0x63,
OP_NOTIF = 0x64,
OP_VERIF = 0x65,
OP_VERNOTIF = 0x66,
OP_ELSE = 0x67,
OP_ENDIF = 0x68,
OP_VERIFY = 0x69,
OP_RETURN = 0x6a,
// stack ops
OP_TOALTSTACK = 0x6b,
OP_FROMALTSTACK = 0x6c,
OP_2DROP = 0x6d,
OP_2DUP = 0x6e,
OP_3DUP = 0x6f,
OP_2OVER = 0x70,
OP_2ROT = 0x71,
OP_2SWAP = 0x72,
OP_IFDUP = 0x73,
OP_DEPTH = 0x74,
OP_DROP = 0x75,
OP_DUP = 0x76,
OP_NIP = 0x77,
OP_OVER = 0x78,
OP_PICK = 0x79,
OP_ROLL = 0x7a,
OP_ROT = 0x7b,
OP_SWAP = 0x7c,
OP_TUCK = 0x7d,
// splice ops
OP_CAT = 0x7e,
OP_SUBSTR = 0x7f,
OP_LEFT = 0x80,
OP_RIGHT = 0x81,
OP_SIZE = 0x82,
// bit logic
OP_INVERT = 0x83,
OP_AND = 0x84,
OP_OR = 0x85,
OP_XOR = 0x86,
OP_EQUAL = 0x87,
OP_EQUALVERIFY = 0x88,
OP_RESERVED1 = 0x89,
OP_RESERVED2 = 0x8a,
// numeric
OP_1ADD = 0x8b,
OP_1SUB = 0x8c,
OP_2MUL = 0x8d,
OP_2DIV = 0x8e,
OP_NEGATE = 0x8f,
OP_ABS = 0x90,
OP_NOT = 0x91,
OP_0NOTEQUAL = 0x92,
OP_ADD = 0x93,
OP_SUB = 0x94,
OP_MUL = 0x95,
OP_DIV = 0x96,
OP_MOD = 0x97,
OP_LSHIFT = 0x98,
OP_RSHIFT = 0x99,
OP_BOOLAND = 0x9a,
OP_BOOLOR = 0x9b,
OP_NUMEQUAL = 0x9c,
OP_NUMEQUALVERIFY = 0x9d,
OP_NUMNOTEQUAL = 0x9e,
OP_LESSTHAN = 0x9f,
OP_GREATERTHAN = 0xa0,
OP_LESSTHANOREQUAL = 0xa1,
OP_GREATERTHANOREQUAL = 0xa2,
OP_MIN = 0xa3,
OP_MAX = 0xa4,
OP_WITHIN = 0xa5,
// crypto
OP_RIPEMD160 = 0xa6,
OP_SHA1 = 0xa7,
OP_SHA256 = 0xa8,
OP_HASH160 = 0xa9,
OP_HASH256 = 0xaa,
OP_CODESEPARATOR = 0xab,
OP_CHECKSIG = 0xac,
OP_CHECKSIGVERIFY = 0xad,
OP_CHECKMULTISIG = 0xae,
OP_CHECKMULTISIGVERIFY = 0xaf,
// expansion
OP_NOP1 = 0xb0,
OP_CHECKLOCKTIMEVERIFY = 0xb1,
OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
OP_NOP3 = 0xb2,
OP_CHECKSEQUENCEVERIFY = OP_NOP3,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
OP_NOP7 = 0xb6,
OP_NOP8 = 0xb7,
OP_NOP9 = 0xb8,
OP_NOP10 = 0xb9,
// template matching params
OP_SMALLINTEGER = 0xfa,
OP_PUBKEYS = 0xfb,
OP_PUBKEYHASH = 0xfd,
OP_PUBKEY = 0xfe,
OP_INVALIDOPCODE = 0xff,
};
const char* GetOpName(opcodetype opcode);
class scriptnum_error : public std::runtime_error
{
public:
explicit scriptnum_error(const std::string& str) : std::runtime_error(str) {}
};
class CScriptNum
{
/**
* Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte integers.
* The semantics are subtle, though: operands must be in the range [-2^31 +1...2^31 -1],
* but results may overflow (and are valid as long as they are not used in a subsequent
* numeric operation). CScriptNum enforces those semantics by storing results as
* an int64 and allowing out-of-range values to be returned as a vector of bytes but
* throwing an exception if arithmetic is done or the result is interpreted as an integer.
*/
public:
explicit CScriptNum(const int64_t& n)
{
m_value = n;
}
static const size_t nDefaultMaxNumSize = 4;
explicit CScriptNum(const std::vector<unsigned char>& vch, bool fRequireMinimal,
const size_t nMaxNumSize = nDefaultMaxNumSize)
{
if (vch.size() > nMaxNumSize) {
throw scriptnum_error("script number overflow");
}
if (fRequireMinimal && vch.size() > 0) {
// Check that the number is encoded with the minimum possible
// number of bytes.
//
// If the most-significant-byte - excluding the sign bit - is zero
// then we're not minimal. Note how this test also rejects the
// negative-zero encoding, 0x80.
if ((vch.back() & 0x7f) == 0) {
// One exception: if there's more than one byte and the most
// significant bit of the second-most-significant-byte is set
// it would conflict with the sign bit. An example of this case
// is +-255, which encode to 0xff00 and 0xff80 respectively.
// (big-endian).
if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) {
throw scriptnum_error("non-minimally encoded script number");
}
}
}
m_value = set_vch(vch);
}
inline bool operator==(const int64_t& rhs) const { return m_value == rhs; }
inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; }
inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; }
inline bool operator< (const int64_t& rhs) const { return m_value < rhs; }
inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; }
inline bool operator> (const int64_t& rhs) const { return m_value > rhs; }
inline bool operator==(const CScriptNum& rhs) const { return operator==(rhs.m_value); }
inline bool operator!=(const CScriptNum& rhs) const { return operator!=(rhs.m_value); }
inline bool operator<=(const CScriptNum& rhs) const { return operator<=(rhs.m_value); }
inline bool operator< (const CScriptNum& rhs) const { return operator< (rhs.m_value); }
inline bool operator>=(const CScriptNum& rhs) const { return operator>=(rhs.m_value); }
inline bool operator> (const CScriptNum& rhs) const { return operator> (rhs.m_value); }
inline CScriptNum operator+( const int64_t& rhs) const { return CScriptNum(m_value + rhs);}
inline CScriptNum operator-( const int64_t& rhs) const { return CScriptNum(m_value - rhs);}
inline CScriptNum operator+( const CScriptNum& rhs) const { return operator+(rhs.m_value); }
inline CScriptNum operator-( const CScriptNum& rhs) const { return operator-(rhs.m_value); }
inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); }
inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); }
inline CScriptNum operator&( const int64_t& rhs) const { return CScriptNum(m_value & rhs);}
inline CScriptNum operator&( const CScriptNum& rhs) const { return operator&(rhs.m_value); }
inline CScriptNum& operator&=( const CScriptNum& rhs) { return operator&=(rhs.m_value); }
inline CScriptNum operator-() const
{
assert(m_value != std::numeric_limits<int64_t>::min());
return CScriptNum(-m_value);
}
inline CScriptNum& operator=( const int64_t& rhs)
{
m_value = rhs;
return *this;
}
inline CScriptNum& operator+=( const int64_t& rhs)
{
assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
m_value += rhs;
return *this;
}
inline CScriptNum& operator-=( const int64_t& rhs)
{
assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
m_value -= rhs;
return *this;
}
inline CScriptNum& operator&=( const int64_t& rhs)
{
m_value &= rhs;
return *this;
}
int getint() const
{
if (m_value > std::numeric_limits<int>::max())
return std::numeric_limits<int>::max();
else if (m_value < std::numeric_limits<int>::min())
return std::numeric_limits<int>::min();
return m_value;
}
std::vector<unsigned char> getvch() const
{
return serialize(m_value);
}
static std::vector<unsigned char> serialize(const int64_t& value)
{
if(value == 0)
return std::vector<unsigned char>();
std::vector<unsigned char> result;
const bool neg = value < 0;
uint64_t absvalue = neg ? -value : value;
while(absvalue)
{
result.push_back(absvalue & 0xff);
absvalue >>= 8;
}
// - If the most significant byte is >= 0x80 and the value is positive, push a
// new zero-byte to make the significant byte < 0x80 again.
// - If the most significant byte is >= 0x80 and the value is negative, push a
// new 0x80 byte that will be popped off when converting to an integral.
// - If the most significant byte is < 0x80 and the value is negative, add
// 0x80 to it, since it will be subtracted and interpreted as a negative when
// converting to an integral.
if (result.back() & 0x80)
result.push_back(neg ? 0x80 : 0);
else if (neg)
result.back() |= 0x80;
return result;
}
private:
static int64_t set_vch(const std::vector<unsigned char>& vch)
{
if (vch.empty())
return 0;
int64_t result = 0;
for (size_t i = 0; i != vch.size(); ++i)
result |= static_cast<int64_t>(vch[i]) << 8*i;
// If the input vector's most significant byte is 0x80, remove it from
// the result's msb and return a negative.
if (vch.back() & 0x80)
return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));
return result;
}
int64_t m_value;
};
typedef prevector<28, unsigned char> CScriptBase;
/** Serialized script, used inside transaction inputs and outputs */
class CScript : public CScriptBase
{
protected:
CScript& push_int64(int64_t n)
{
if (n == -1 || (n >= 1 && n <= 16))
{
push_back(n + (OP_1 - 1));
}
else if (n == 0)
{
push_back(OP_0);
}
else
{
*this << CScriptNum::serialize(n);
}
return *this;
}
public:
CScript() { }
CScript(const CScript& b) : CScriptBase(b.begin(), b.end()) { }
CScript(const_iterator pbegin, const_iterator pend) : CScriptBase(pbegin, pend) { }
CScript(std::vector<unsigned char>::const_iterator pbegin, std::vector<unsigned char>::const_iterator pend) : CScriptBase(pbegin, pend) { }
CScript(const unsigned char* pbegin, const unsigned char* pend) : CScriptBase(pbegin, pend) { }
CScript& operator+=(const CScript& b)
{
insert(end(), b.begin(), b.end());
return *this;
}
friend CScript operator+(const CScript& a, const CScript& b)
{
CScript ret = a;
ret += b;
return ret;
}
CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); }
explicit CScript(const CScriptNum& b) { operator<<(b); }
explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); }
CScript& operator<<(int64_t b) { return push_int64(b); }
CScript& operator<<(opcodetype opcode)
{
if (opcode < 0 || opcode > 0xff)
throw std::runtime_error("CScript::operator<<(): invalid opcode");
insert(end(), (unsigned char)opcode);
return *this;
}
CScript& operator<<(const CScriptNum& b)
{
*this << b.getvch();
return *this;
}
CScript& operator<<(const std::vector<unsigned char>& b)
{
if (b.size() < OP_PUSHDATA1)
{
insert(end(), (unsigned char)b.size());
}
else if (b.size() <= 0xff)
{
insert(end(), OP_PUSHDATA1);
insert(end(), (unsigned char)b.size());
}
else if (b.size() <= 0xffff)
{
insert(end(), OP_PUSHDATA2);
uint8_t data[2];
WriteLE16(data, b.size());
insert(end(), data, data + sizeof(data));
}
else
{
insert(end(), OP_PUSHDATA4);
uint8_t data[4];
WriteLE32(data, b.size());
insert(end(), data, data + sizeof(data));
}
insert(end(), b.begin(), b.end());
return *this;
}
CScript& operator<<(const CScript& b)
{
// I'm not sure if this should push the script or concatenate scripts.
// If there's ever a use for pushing a script onto a script, delete this member fn
assert(!"Warning: Pushing a CScript onto a CScript with << is probably not intended, use + to concatenate!");
return *this;
}
bool GetOp(iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet)
{
// Wrapper so it can be called with either iterator or const_iterator
const_iterator pc2 = pc;
bool fRet = GetOp2(pc2, opcodeRet, &vchRet);
pc = begin() + (pc2 - begin());
return fRet;
}
bool GetOp(iterator& pc, opcodetype& opcodeRet)
{
const_iterator pc2 = pc;
bool fRet = GetOp2(pc2, opcodeRet, NULL);
pc = begin() + (pc2 - begin());
return fRet;
}
bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
{
return GetOp2(pc, opcodeRet, &vchRet);
}
bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const
{
return GetOp2(pc, opcodeRet, NULL);
}
bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) const
{
opcodeRet = OP_INVALIDOPCODE;
if (pvchRet)
pvchRet->clear();
if (pc >= end())
return false;
// Read instruction
if (end() - pc < 1)
return false;
unsigned int opcode = *pc++;
// Immediate operand
if (opcode <= OP_PUSHDATA4)
{
unsigned int nSize = 0;
if (opcode < OP_PUSHDATA1)
{
nSize = opcode;
}
else if (opcode == OP_PUSHDATA1)
{
if (end() - pc < 1)
return false;
nSize = *pc++;
}
else if (opcode == OP_PUSHDATA2)
{
if (end() - pc < 2)
return false;
nSize = ReadLE16(&pc[0]);
pc += 2;
}
else if (opcode == OP_PUSHDATA4)
{
if (end() - pc < 4)
return false;
nSize = ReadLE32(&pc[0]);
pc += 4;
}
if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize)
return false;
if (pvchRet)
pvchRet->assign(pc, pc + nSize);
pc += nSize;
}
opcodeRet = (opcodetype)opcode;
return true;
}
/** Encode/decode small integers: */
static int DecodeOP_N(opcodetype opcode)
{
if (opcode == OP_0)
return 0;
assert(opcode >= OP_1 && opcode <= OP_16);
return (int)opcode - (int)(OP_1 - 1);
}
static opcodetype EncodeOP_N(int n)
{
assert(n >= 0 && n <= 16);
if (n == 0)
return OP_0;
return (opcodetype)(OP_1+n-1);
}
int FindAndDelete(const CScript& b)
{
int nFound = 0;
if (b.empty())
return nFound;
iterator pc = begin();
opcodetype opcode;
do
{
while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0)
{
pc = erase(pc, pc + b.size());
++nFound;
}
}
while (GetOp(pc, opcode));
return nFound;
}
int Find(opcodetype op) const
{
int nFound = 0;
opcodetype opcode;
for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);)
if (opcode == op)
++nFound;
return nFound;
}
/**
* Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
* as 20 sigops. With pay-to-script-hash, that changed:
* CHECKMULTISIGs serialized in scriptSigs are
* counted more accurately, assuming they are of the form
* ... OP_N CHECKMULTISIG ...
*/
unsigned int GetSigOpCount(bool fAccurate) const;
/**
* Accurately count sigOps, including sigOps in
* pay-to-script-hash transactions:
*/
unsigned int GetSigOpCount(const CScript& scriptSig) const;
bool IsPayToScriptHash() const;
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
bool IsPushOnly(const_iterator pc) const;
bool IsPushOnly() const;
/**
* Returns whether the script is guaranteed to fail at execution,
* regardless of the initial stack. This allows outputs to be pruned
* instantly when entering the UTXO set.
*/
bool IsUnspendable() const
{
return (size() > 0 && *begin() == OP_RETURN);
}
void clear()
{
// The default std::vector::clear() does not release memory.
CScriptBase().swap(*this);
}
};
class CReserveScript
{
public:
CScript reserveScript;
virtual void KeepScript() {}
CReserveScript() {}
virtual ~CReserveScript() {}
};
#endif // BITCOIN_SCRIPT_SCRIPT_H
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Mar 2, 08:43 (21 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187119
Default Alt Text
(70 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment