diff options
Diffstat (limited to 'src/script/script.h')
-rw-r--r-- | src/script/script.h | 161 |
1 files changed, 69 insertions, 92 deletions
diff --git a/src/script/script.h b/src/script/script.h index caf176476f..9c22cb908c 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -3,19 +3,26 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef H_BITCOIN_SCRIPT -#define H_BITCOIN_SCRIPT - -#include "key.h" -#include "tinyformat.h" -#include "utilstrencodings.h" +#ifndef BITCOIN_SCRIPT_SCRIPT_H +#define BITCOIN_SCRIPT_SCRIPT_H +#include <assert.h> +#include <climits> +#include <limits> #include <stdexcept> - -#include <boost/variant.hpp> +#include <stdint.h> +#include <string.h> +#include <string> +#include <vector> static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes +template <typename T> +std::vector<unsigned char> ToByteVector(const T& in) +{ + return std::vector<unsigned char>(in.begin(), in.end()); +} + /** Script opcodes */ enum opcodetype { @@ -172,12 +179,14 @@ public: 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. +/** + * 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) @@ -185,10 +194,29 @@ public: m_value = n; } - explicit CScriptNum(const std::vector<unsigned char>& vch) + explicit CScriptNum(const std::vector<unsigned char>& vch, bool fRequireMinimal) { - if (vch.size() > nMaxNumSize) - throw scriptnum_error("CScriptNum(const std::vector<unsigned char>&) : overflow"); + 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); } @@ -312,14 +340,6 @@ private: int64_t m_value; }; -inline std::string ValueString(const std::vector<unsigned char>& vch) -{ - if (vch.size() <= 4) - return strprintf("%d", CScriptNum(vch).getint()); - else - return HexStr(vch); -} - /** Serialized script, used inside transaction inputs and outputs */ class CScript : public std::vector<unsigned char> { @@ -330,6 +350,10 @@ protected: { push_back(n + (OP_1 - 1)); } + else if (n == 0) + { + push_back(OP_0); + } else { *this << CScriptNum::serialize(n); @@ -358,7 +382,6 @@ public: CScript(int64_t b) { operator<<(b); } explicit CScript(opcodetype b) { operator<<(b); } - explicit CScript(const uint256& b) { operator<<(b); } explicit CScript(const CScriptNum& b) { operator<<(b); } explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); } @@ -373,28 +396,6 @@ public: return *this; } - CScript& operator<<(const uint160& b) - { - insert(end(), sizeof(b)); - insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); - return *this; - } - - CScript& operator<<(const uint256& b) - { - insert(end(), sizeof(b)); - insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); - return *this; - } - - CScript& operator<<(const CPubKey& key) - { - assert(key.size() < OP_PUSHDATA1); - insert(end(), (unsigned char)key.size()); - insert(end(), key.begin(), key.end()); - return *this; - } - CScript& operator<<(const CScriptNum& b) { *this << b.getvch(); @@ -517,7 +518,7 @@ public: return true; } - // Encode/decode small integers: + /** Encode/decode small integers: */ static int DecodeOP_N(opcodetype opcode) { if (opcode == OP_0) @@ -561,61 +562,37 @@ public: 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 ... + /** + * 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: + /** + * 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 VerifyScript (which makes it consensus-critical). + /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ bool IsPushOnly() const; - // Called by IsStandardTx. - bool HasCanonicalPushes() 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. + /** + * 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); } - std::string ToString() const - { - std::string str; - opcodetype opcode; - std::vector<unsigned char> vch; - const_iterator pc = begin(); - while (pc < end()) - { - if (!str.empty()) - str += " "; - if (!GetOp(pc, opcode, vch)) - { - str += "[error]"; - return str; - } - if (0 <= opcode && opcode <= OP_PUSHDATA4) - str += ValueString(vch); - else - str += GetOpName(opcode); - } - return str; - } - - CScriptID GetID() const - { - return CScriptID(Hash160(*this)); - } - + std::string ToString() const; void clear() { // The default std::vector::clear() does not release memory. @@ -623,4 +600,4 @@ public: } }; -#endif // H_BITCOIN_SCRIPT +#endif // BITCOIN_SCRIPT_SCRIPT_H |