aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
Diffstat (limited to 'src/script')
-rw-r--r--src/script/interpreter.cpp10
-rw-r--r--src/script/interpreter.h2
-rw-r--r--src/script/script.cpp39
-rw-r--r--src/script/script.h12
-rw-r--r--src/script/standard.cpp28
-rw-r--r--src/script/standard.h3
6 files changed, 40 insertions, 54 deletions
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 0b78fdf5a8..6a20d497c0 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -188,7 +188,7 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
return true;
}
-bool static CheckSignatureEncoding(const valtype &vchSig, unsigned int flags, ScriptError* serror) {
+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) {
@@ -273,7 +273,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
// Note how OP_RESERVED does not count towards the opcode limit.
- if (opcode > OP_16 && ++nOpCount > 201)
+ if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
if (opcode == OP_CAT ||
@@ -869,10 +869,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
- if (nKeysCount < 0 || nKeysCount > 20)
+ if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG)
return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
nOpCount += nKeysCount;
- if (nOpCount > 201)
+ if (nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
int ikey = ++i;
i += nKeysCount;
@@ -1128,7 +1128,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
{
- // There are two times of nLockTime: lock-by-blockheight
+ // There are two kinds of nLockTime: lock-by-blockheight
// and lock-by-blocktime, distinguished by whether
// nLockTime < LOCKTIME_THRESHOLD.
//
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 35d572f0ad..213e8c7651 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -83,6 +83,8 @@ enum
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
};
+bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
+
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
class BaseSignatureChecker
diff --git a/src/script/script.cpp b/src/script/script.cpp
index fd33924732..263c89defe 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -8,16 +8,6 @@
#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;
const char* GetOpName(opcodetype opcode)
@@ -154,7 +144,7 @@ const char* GetOpName(opcodetype opcode)
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
// Note:
- // The template matching params OP_SMALLDATA/etc are defined in opcodetype enum
+ // The template matching params OP_SMALLINTEGER/etc are defined in opcodetype enum
// as kind of implementation hack, they are *NOT* real opcodes. If found in real
// Script, just let the default: case deal with them.
@@ -180,7 +170,7 @@ unsigned int CScript::GetSigOpCount(bool fAccurate) const
if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
n += DecodeOP_N(lastOpcode);
else
- n += 20;
+ n += MAX_PUBKEYS_PER_MULTISIG;
}
lastOpcode = opcode;
}
@@ -220,9 +210,8 @@ bool CScript::IsPayToScriptHash() const
this->at(22) == OP_EQUAL);
}
-bool CScript::IsPushOnly() const
+bool CScript::IsPushOnly(const_iterator pc) const
{
- const_iterator pc = begin();
while (pc < end())
{
opcodetype opcode;
@@ -238,25 +227,7 @@ bool CScript::IsPushOnly() const
return true;
}
-std::string CScript::ToString() const
+bool CScript::IsPushOnly() 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;
+ return this->IsPushOnly(begin());
}
diff --git a/src/script/script.h b/src/script/script.h
index e39ca57f4f..a38d33a189 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -17,7 +17,14 @@
#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;
// Threshold for nLockTime: below this value it is interpreted as block number,
// otherwise as UNIX timestamp.
@@ -167,7 +174,6 @@ enum opcodetype
// template matching params
- OP_SMALLDATA = 0xf9,
OP_SMALLINTEGER = 0xfa,
OP_PUBKEYS = 0xfb,
OP_PUBKEYHASH = 0xfd,
@@ -589,6 +595,7 @@ public:
bool IsPayToScriptHash() const;
/** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */
+ bool IsPushOnly(const_iterator pc) const;
bool IsPushOnly() const;
/**
@@ -601,7 +608,6 @@ public:
return (size() > 0 && *begin() == OP_RETURN);
}
- std::string ToString() const;
void clear()
{
// The default std::vector::clear() does not release memory.
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 66657127ab..bfef8afa17 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -51,13 +51,10 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
// Sender provides N pubkeys, receivers provides M signatures
mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
-
- // Empty, provably prunable, data-carrying output
- if (GetBoolArg("-datacarrier", true))
- mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA));
- mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN));
}
+ vSolutionsRet.clear();
+
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
// it is always OP_HASH160 20 [20 byte hash] OP_EQUAL
if (scriptPubKey.IsPayToScriptHash())
@@ -68,6 +65,16 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
return true;
}
+ // Provably prunable, data-carrying output
+ //
+ // So long as script passes the IsUnspendable() test and all but the first
+ // byte passes the IsPushOnly() test we don't care what exactly is in the
+ // script.
+ if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) {
+ typeRet = TX_NULL_DATA;
+ return true;
+ }
+
// Scan templates
const CScript& script1 = scriptPubKey;
BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
@@ -140,12 +147,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
else
break;
}
- else if (opcode2 == OP_SMALLDATA)
- {
- // small pushdata, <= nMaxDatacarrierBytes
- if (vch1.size() > nMaxDatacarrierBytes)
- break;
- }
else if (opcode1 != opcode2 || vch1 != vch2)
{
// Others must match exactly
@@ -286,6 +287,11 @@ CScript GetScriptForDestination(const CTxDestination& dest)
return script;
}
+CScript GetScriptForRawPubKey(const CPubKey& pubKey)
+{
+ return CScript() << std::vector<unsigned char>(pubKey.begin(), pubKey.end()) << OP_CHECKSIG;
+}
+
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
{
CScript script;
diff --git a/src/script/standard.h b/src/script/standard.h
index 46ae5f9f10..ae1bbecca0 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -25,7 +25,7 @@ public:
CScriptID(const uint160& in) : uint160(in) {}
};
-static const unsigned int MAX_OP_RETURN_RELAY = 80; //! bytes
+static const unsigned int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
extern unsigned nMaxDatacarrierBytes;
/**
@@ -73,6 +73,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
CScript GetScriptForDestination(const CTxDestination& dest);
+CScript GetScriptForRawPubKey(const CPubKey& pubkey);
CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
#endif // BITCOIN_SCRIPT_STANDARD_H