aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/compressor.cpp127
-rw-r--r--src/script/compressor.h84
-rw-r--r--src/script/interpreter.cpp58
-rw-r--r--src/script/interpreter.h10
-rw-r--r--src/script/script.cpp51
-rw-r--r--src/script/script.h113
-rw-r--r--src/script/sign.cpp4
-rw-r--r--src/script/standard.cpp15
-rw-r--r--src/script/standard.h14
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.