diff options
Diffstat (limited to 'src/script/script.h')
| -rw-r--r-- | src/script/script.h | 102 |
1 files changed, 84 insertions, 18 deletions
diff --git a/src/script/script.h b/src/script/script.h index d5045005b..654dff462 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers +// 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. @@ -7,6 +7,7 @@ #define BITCOIN_SCRIPT_SCRIPT_H #include "crypto/common.h" +#include "prevector.h" #include <assert.h> #include <climits> @@ -17,7 +18,21 @@ #include <string> #include <vector> -static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes +// 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) @@ -150,8 +165,10 @@ enum opcodetype // expansion OP_NOP1 = 0xb0, - OP_NOP2 = 0xb1, - OP_NOP3 = 0xb2, + OP_CHECKLOCKTIMEVERIFY = 0xb1, + OP_NOP2 = OP_CHECKLOCKTIMEVERIFY, + OP_CHECKSEQUENCEVERIFY = 0xb2, + OP_NOP3 = OP_CHECKSEQUENCEVERIFY, OP_NOP4 = 0xb3, OP_NOP5 = 0xb4, OP_NOP6 = 0xb5, @@ -162,7 +179,6 @@ enum opcodetype // template matching params - OP_SMALLDATA = 0xf9, OP_SMALLINTEGER = 0xfa, OP_PUBKEYS = 0xfb, OP_PUBKEYHASH = 0xfd, @@ -196,7 +212,10 @@ public: m_value = n; } - explicit CScriptNum(const std::vector<unsigned char>& vch, bool fRequireMinimal) + 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"); @@ -244,6 +263,11 @@ public: 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()); @@ -272,6 +296,12 @@ public: 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()) @@ -319,8 +349,6 @@ public: return result; } - static const size_t nMaxNumSize = 4; - private: static int64_t set_vch(const std::vector<unsigned char>& vch) { @@ -342,8 +370,10 @@ private: int64_t m_value; }; +typedef prevector<28, unsigned char> CScriptBase; + /** Serialized script, used inside transaction inputs and outputs */ -class CScript : public std::vector<unsigned char> +class CScript : public CScriptBase { protected: CScript& push_int64(int64_t n) @@ -364,9 +394,9 @@ protected: } public: CScript() { } - CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { } - CScript(const_iterator pbegin, const_iterator pend) : std::vector<unsigned char>(pbegin, pend) { } - CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { } + 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) { @@ -542,17 +572,26 @@ public: int nFound = 0; if (b.empty()) return nFound; - iterator pc = begin(); + CScript result; + iterator pc = begin(), pc2 = begin(); opcodetype opcode; do { - while (end() - pc >= (long)b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) + result.insert(result.end(), pc2, pc); + while (static_cast<size_t>(end() - pc) >= b.size() && std::equal(b.begin(), b.end(), pc)) { - pc = erase(pc, pc + b.size()); + pc = pc + b.size(); ++nFound; } + pc2 = pc; } while (GetOp(pc, opcode)); + + if (nFound > 0) { + result.insert(result.end(), pc2, end()); + *this = result; + } + return nFound; } int Find(opcodetype op) const @@ -581,8 +620,11 @@ public: unsigned int GetSigOpCount(const CScript& scriptSig) const; bool IsPayToScriptHash() const; + bool IsPayToWitnessScriptHash() const; + bool IsWitnessProgram(int& version, std::vector<unsigned char>& program) const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ + bool IsPushOnly(const_iterator pc) const; bool IsPushOnly() const; /** @@ -592,15 +634,39 @@ public: */ bool IsUnspendable() const { - return (size() > 0 && *begin() == OP_RETURN); + return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE); } - std::string ToString() const; void clear() { // The default std::vector::clear() does not release memory. - std::vector<unsigned char>().swap(*this); + CScriptBase().swap(*this); } }; +struct CScriptWitness +{ + // Note that this encodes the data elements being pushed, rather than + // encoding them as a CScript that pushes them. + std::vector<std::vector<unsigned char> > stack; + + // Some compilers complain without a default constructor + CScriptWitness() { } + + bool IsNull() const { return stack.empty(); } + + void SetNull() { stack.clear(); stack.shrink_to_fit(); } + + std::string ToString() const; +}; + +class CReserveScript +{ +public: + CScript reserveScript; + virtual void KeepScript() {} + CReserveScript() {} + virtual ~CReserveScript() {} +}; + #endif // BITCOIN_SCRIPT_SCRIPT_H |