diff options
Diffstat (limited to 'src/script')
| -rw-r--r-- | src/script/compressor.cpp | 127 | ||||
| -rw-r--r-- | src/script/compressor.h | 84 | ||||
| -rw-r--r-- | src/script/interpreter.cpp | 58 | ||||
| -rw-r--r-- | src/script/interpreter.h | 10 | ||||
| -rw-r--r-- | src/script/script.cpp | 51 | ||||
| -rw-r--r-- | src/script/script.h | 113 | ||||
| -rw-r--r-- | src/script/sign.cpp | 4 | ||||
| -rw-r--r-- | src/script/standard.cpp | 15 | ||||
| -rw-r--r-- | src/script/standard.h | 14 |
9 files changed, 152 insertions, 324 deletions
diff --git a/src/script/compressor.cpp b/src/script/compressor.cpp deleted file mode 100644 index 51a3cf602..000000000 --- a/src/script/compressor.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "compressor.h" - -bool CScriptCompressor::IsToKeyID(CKeyID &hash) const -{ - if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 - && script[2] == 20 && script[23] == OP_EQUALVERIFY - && script[24] == OP_CHECKSIG) { - memcpy(&hash, &script[3], 20); - return true; - } - return false; -} - -bool CScriptCompressor::IsToScriptID(CScriptID &hash) const -{ - if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20 - && script[22] == OP_EQUAL) { - memcpy(&hash, &script[2], 20); - return true; - } - return false; -} - -bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const -{ - if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG - && (script[1] == 0x02 || script[1] == 0x03)) { - pubkey.Set(&script[1], &script[34]); - return true; - } - if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG - && script[1] == 0x04) { - pubkey.Set(&script[1], &script[66]); - return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible - } - return false; -} - -bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const -{ - CKeyID keyID; - if (IsToKeyID(keyID)) { - out.resize(21); - out[0] = 0x00; - memcpy(&out[1], &keyID, 20); - return true; - } - CScriptID scriptID; - if (IsToScriptID(scriptID)) { - out.resize(21); - out[0] = 0x01; - memcpy(&out[1], &scriptID, 20); - return true; - } - CPubKey pubkey; - if (IsToPubKey(pubkey)) { - out.resize(33); - memcpy(&out[1], &pubkey[1], 32); - if (pubkey[0] == 0x02 || pubkey[0] == 0x03) { - out[0] = pubkey[0]; - return true; - } else if (pubkey[0] == 0x04) { - out[0] = 0x04 | (pubkey[64] & 0x01); - return true; - } - } - return false; -} - -unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const -{ - if (nSize == 0 || nSize == 1) - return 20; - if (nSize == 2 || nSize == 3 || nSize == 4 || nSize == 5) - return 32; - return 0; -} - -bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char> &in) -{ - switch(nSize) { - case 0x00: - script.resize(25); - script[0] = OP_DUP; - script[1] = OP_HASH160; - script[2] = 20; - memcpy(&script[3], &in[0], 20); - script[23] = OP_EQUALVERIFY; - script[24] = OP_CHECKSIG; - return true; - case 0x01: - script.resize(23); - script[0] = OP_HASH160; - script[1] = 20; - memcpy(&script[2], &in[0], 20); - script[22] = OP_EQUAL; - return true; - case 0x02: - case 0x03: - script.resize(35); - script[0] = 33; - script[1] = nSize; - memcpy(&script[2], &in[0], 32); - script[34] = OP_CHECKSIG; - return true; - case 0x04: - case 0x05: - unsigned char vch[33] = {}; - vch[0] = nSize - 2; - memcpy(&vch[1], &in[0], 32); - CPubKey pubkey(&vch[0], &vch[33]); - if (!pubkey.Decompress()) - return false; - assert(pubkey.size() == 65); - script.resize(67); - script[0] = 65; - memcpy(&script[1], pubkey.begin(), 65); - script[66] = OP_CHECKSIG; - return true; - } - return false; -} diff --git a/src/script/compressor.h b/src/script/compressor.h deleted file mode 100644 index 53c6bf3ec..000000000 --- a/src/script/compressor.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef H_BITCOIN_SCRIPT_COMPRESSOR -#define H_BITCOIN_SCRIPT_COMPRESSOR - -#include "script/script.h" - -/** Compact serializer for scripts. - * - * It detects common cases and encodes them much more efficiently. - * 3 special cases are defined: - * * Pay to pubkey hash (encoded as 21 bytes) - * * Pay to script hash (encoded as 21 bytes) - * * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes) - * - * Other scripts up to 121 bytes require 1 byte + script length. Above - * that, scripts up to 16505 bytes require 2 bytes + script length. - */ -class CScriptCompressor -{ -private: - // make this static for now (there are only 6 special scripts defined) - // this can potentially be extended together with a new nVersion for - // transactions, in which case this value becomes dependent on nVersion - // and nHeight of the enclosing transaction. - static const unsigned int nSpecialScripts = 6; - - CScript &script; -protected: - // These check for scripts for which a special case with a shorter encoding is defined. - // They are implemented separately from the CScript test, as these test for exact byte - // sequence correspondences, and are more strict. For example, IsToPubKey also verifies - // whether the public key is valid (as invalid ones cannot be represented in compressed - // form). - bool IsToKeyID(CKeyID &hash) const; - bool IsToScriptID(CScriptID &hash) const; - bool IsToPubKey(CPubKey &pubkey) const; - - bool Compress(std::vector<unsigned char> &out) const; - unsigned int GetSpecialSize(unsigned int nSize) const; - bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out); -public: - CScriptCompressor(CScript &scriptIn) : script(scriptIn) { } - - unsigned int GetSerializeSize(int nType, int nVersion) const { - std::vector<unsigned char> compr; - if (Compress(compr)) - return compr.size(); - unsigned int nSize = script.size() + nSpecialScripts; - return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion); - } - - template<typename Stream> - void Serialize(Stream &s, int nType, int nVersion) const { - std::vector<unsigned char> compr; - if (Compress(compr)) { - s << CFlatData(compr); - return; - } - unsigned int nSize = script.size() + nSpecialScripts; - s << VARINT(nSize); - s << CFlatData(script); - } - - template<typename Stream> - void Unserialize(Stream &s, int nType, int nVersion) { - unsigned int nSize = 0; - s >> VARINT(nSize); - if (nSize < nSpecialScripts) { - std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00); - s >> REF(CFlatData(vch)); - Decompress(nSize, vch); - return; - } - nSize -= nSpecialScripts; - script.resize(nSize); - s >> REF(CFlatData(script)); - } -}; - -#endif // H_BITCOIN_SCRIPT_COMPRESSOR diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index ae66217b7..3625972eb 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -5,10 +5,11 @@ #include "interpreter.h" -#include "core.h" +#include "core/transaction.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha2.h" +#include "key.h" #include "script/script.h" #include "uint256.h" #include "util.h" @@ -156,6 +157,29 @@ bool static CheckPubKeyEncoding(const valtype &vchSig, unsigned int flags) { 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) { CScript::const_iterator pc = script.begin(); @@ -168,6 +192,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if (script.size() > 10000) return false; int nOpCount = 0; + bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; try { @@ -204,9 +229,12 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un opcode == OP_RSHIFT) return false; // Disabled opcodes. - if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) + if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { + if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) { + return false; + } stack.push_back(vchPushValue); - else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) + } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // @@ -233,6 +261,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // ( -- 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; @@ -457,7 +487,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack.size() < 2) return false; - int n = CScriptNum(stacktop(-1)).getint(); + int n = CScriptNum(stacktop(-1), fRequireMinimal).getint(); popstack(stack); if (n < 0 || n >= (int)stack.size()) return false; @@ -556,7 +586,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (in -- out) if (stack.size() < 1) return false; - CScriptNum bn(stacktop(-1)); + CScriptNum bn(stacktop(-1), fRequireMinimal); switch (opcode) { case OP_1ADD: bn += bnOne; break; @@ -589,8 +619,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (x1 x2 -- out) if (stack.size() < 2) return false; - CScriptNum bn1(stacktop(-2)); - CScriptNum bn2(stacktop(-1)); + CScriptNum bn1(stacktop(-2), fRequireMinimal); + CScriptNum bn2(stacktop(-1), fRequireMinimal); CScriptNum bn(0); switch (opcode) { @@ -634,9 +664,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un // (x min max -- out) if (stack.size() < 3) return false; - CScriptNum bn1(stacktop(-3)); - CScriptNum bn2(stacktop(-2)); - CScriptNum bn3(stacktop(-1)); + 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); @@ -726,7 +756,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if ((int)stack.size() < i) return false; - int nKeysCount = CScriptNum(stacktop(-i)).getint(); + int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nKeysCount < 0 || nKeysCount > 20) return false; nOpCount += nKeysCount; @@ -737,7 +767,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un if ((int)stack.size() < i) return false; - int nSigsCount = CScriptNum(stacktop(-i)).getint(); + int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) return false; int isig = ++i; @@ -979,6 +1009,10 @@ bool SignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vec bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker) { + if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) { + return false; + } + vector<vector<unsigned char> > stack, stackCopy; if (!EvalScript(stack, scriptSig, flags, checker)) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index de5ce2ced..5133c80aa 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -46,6 +46,16 @@ enum // 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). + 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). + // (softfork safe) + SCRIPT_VERIFY_MINIMALDATA = (1U << 6) }; uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); diff --git a/src/script/script.cpp b/src/script/script.cpp index a5126e7cc..b879d72d6 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -5,7 +5,18 @@ #include "script.h" -#include <boost/foreach.hpp> +#include "tinyformat.h" +#include "utilstrencodings.h" + +namespace { +inline std::string ValueString(const std::vector<unsigned char>& vch) +{ + if (vch.size() <= 4) + return strprintf("%d", CScriptNum(vch, false).getint()); + else + return HexStr(vch); +} +} // anon namespace using namespace std; @@ -219,7 +230,7 @@ bool CScript::IsPushOnly() const return false; // Note that IsPushOnly() *does* consider OP_RESERVED to be a // push-type opcode, however execution of OP_RESERVED fails, so - // it's not relevant to P2SH as the scriptSig would fail prior to + // it's not relevant to P2SH/BIP62 as the scriptSig would fail prior to // the P2SH special validation code being executed. if (opcode > OP_16) return false; @@ -227,29 +238,25 @@ bool CScript::IsPushOnly() const return true; } -bool CScript::HasCanonicalPushes() const +std::string CScript::ToString() const { + std::string str; + opcodetype opcode; + std::vector<unsigned char> vch; const_iterator pc = begin(); while (pc < end()) { - opcodetype opcode; - std::vector<unsigned char> data; - if (!GetOp(pc, opcode, data)) - return false; - if (opcode > OP_16) - continue; - if (opcode < OP_PUSHDATA1 && opcode > OP_0 && (data.size() == 1 && data[0] <= 16)) - // Could have used an OP_n code, rather than a 1-byte push. - return false; - if (opcode == OP_PUSHDATA1 && data.size() < OP_PUSHDATA1) - // Could have used a normal n-byte push, rather than OP_PUSHDATA1. - return false; - if (opcode == OP_PUSHDATA2 && data.size() <= 0xFF) - // Could have used an OP_PUSHDATA1. - return false; - if (opcode == OP_PUSHDATA4 && data.size() <= 0xFFFF) - // Could have used an OP_PUSHDATA2. - return false; + 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 true; + return str; } diff --git a/src/script/script.h b/src/script/script.h index caf176476..05f2e7e3a 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -6,16 +6,23 @@ #ifndef H_BITCOIN_SCRIPT #define H_BITCOIN_SCRIPT -#include "key.h" -#include "tinyformat.h" -#include "utilstrencodings.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 { @@ -185,10 +192,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 +338,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 +348,10 @@ protected: { push_back(n + (OP_1 - 1)); } + else if (n == 0) + { + push_back(OP_0); + } else { *this << CScriptNum::serialize(n); @@ -358,7 +380,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 +394,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(); @@ -574,12 +573,9 @@ public: 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. @@ -588,34 +584,7 @@ public: 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. diff --git a/src/script/sign.cpp b/src/script/sign.cpp index da77e7d1f..0eab0626e 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -5,7 +5,7 @@ #include "script/sign.h" -#include "core.h" +#include "core/transaction.h" #include "key.h" #include "keystore.h" #include "script/standard.h" @@ -78,7 +78,7 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash { CPubKey vch; keystore.GetPubKey(keyID, vch); - scriptSigRet << vch; + scriptSigRet << ToByteVector(vch); } return true; case TX_SCRIPTHASH: diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 53ae254d5..7356e541a 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -7,6 +7,7 @@ #include "script/script.h" #include "util.h" +#include "utilstrencodings.h" #include <boost/foreach.hpp> @@ -14,6 +15,10 @@ using namespace std; typedef vector<unsigned char> valtype; +unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY; + +CScriptID::CScriptID(const CScript& in) : uint160(in.size() ? Hash160(in.begin(), in.end()) : 0) {} + const char* GetTxnOutputType(txnouttype t) { switch (t) @@ -136,8 +141,8 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi } else if (opcode2 == OP_SMALLDATA) { - // small pushdata, <= MAX_OP_RETURN_RELAY bytes - if (vch1.size() > MAX_OP_RETURN_RELAY) + // small pushdata, <= nMaxDatacarrierBytes + if (vch1.size() > nMaxDatacarrierBytes) break; } else if (opcode1 != opcode2 || vch1 != vch2) @@ -280,13 +285,13 @@ public: bool operator()(const CKeyID &keyID) const { script->clear(); - *script << OP_DUP << OP_HASH160 << keyID << OP_EQUALVERIFY << OP_CHECKSIG; + *script << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; return true; } bool operator()(const CScriptID &scriptID) const { script->clear(); - *script << OP_HASH160 << scriptID << OP_EQUAL; + *script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; return true; } }; @@ -306,7 +311,7 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys) script << CScript::EncodeOP_N(nRequired); BOOST_FOREACH(const CPubKey& key, keys) - script << key; + script << ToByteVector(key); script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; return script; } diff --git a/src/script/standard.h b/src/script/standard.h index ead79b82a..504d98c68 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -6,14 +6,27 @@ #ifndef H_BITCOIN_SCRIPT_STANDARD #define H_BITCOIN_SCRIPT_STANDARD +#include "key.h" #include "script/script.h" #include "script/interpreter.h" +#include <boost/variant.hpp> + #include <stdint.h> class CScript; +/** A reference to a CScript: the Hash160 of its serialization (see script.h) */ +class CScriptID : public uint160 +{ +public: + CScriptID() : uint160(0) {} + CScriptID(const CScript& in); + CScriptID(const uint160& in) : uint160(in) {} +}; + static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes +extern unsigned nMaxDatacarrierBytes; // Mandatory script verification flags that all new blocks must comply with for // them to be valid. (but old blocks may not comply with) Currently just P2SH, @@ -29,6 +42,7 @@ static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH; // blocks and we must accept those blocks. static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_STRICTENC | + SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_NULLDUMMY; // For convenience, standard but not mandatory verify flags. |