2d79bba36b
- add missing header end comments - ensure alphabetical ordering - update copyright year and license
295 lines
11 KiB
C++
295 lines
11 KiB
C++
// 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 "script.h"
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
using namespace std;
|
|
|
|
const char* GetOpName(opcodetype opcode)
|
|
{
|
|
switch (opcode)
|
|
{
|
|
// push value
|
|
case OP_0 : return "0";
|
|
case OP_PUSHDATA1 : return "OP_PUSHDATA1";
|
|
case OP_PUSHDATA2 : return "OP_PUSHDATA2";
|
|
case OP_PUSHDATA4 : return "OP_PUSHDATA4";
|
|
case OP_1NEGATE : return "-1";
|
|
case OP_RESERVED : return "OP_RESERVED";
|
|
case OP_1 : return "1";
|
|
case OP_2 : return "2";
|
|
case OP_3 : return "3";
|
|
case OP_4 : return "4";
|
|
case OP_5 : return "5";
|
|
case OP_6 : return "6";
|
|
case OP_7 : return "7";
|
|
case OP_8 : return "8";
|
|
case OP_9 : return "9";
|
|
case OP_10 : return "10";
|
|
case OP_11 : return "11";
|
|
case OP_12 : return "12";
|
|
case OP_13 : return "13";
|
|
case OP_14 : return "14";
|
|
case OP_15 : return "15";
|
|
case OP_16 : return "16";
|
|
|
|
// control
|
|
case OP_NOP : return "OP_NOP";
|
|
case OP_VER : return "OP_VER";
|
|
case OP_IF : return "OP_IF";
|
|
case OP_NOTIF : return "OP_NOTIF";
|
|
case OP_VERIF : return "OP_VERIF";
|
|
case OP_VERNOTIF : return "OP_VERNOTIF";
|
|
case OP_ELSE : return "OP_ELSE";
|
|
case OP_ENDIF : return "OP_ENDIF";
|
|
case OP_VERIFY : return "OP_VERIFY";
|
|
case OP_RETURN : return "OP_RETURN";
|
|
|
|
// stack ops
|
|
case OP_TOALTSTACK : return "OP_TOALTSTACK";
|
|
case OP_FROMALTSTACK : return "OP_FROMALTSTACK";
|
|
case OP_2DROP : return "OP_2DROP";
|
|
case OP_2DUP : return "OP_2DUP";
|
|
case OP_3DUP : return "OP_3DUP";
|
|
case OP_2OVER : return "OP_2OVER";
|
|
case OP_2ROT : return "OP_2ROT";
|
|
case OP_2SWAP : return "OP_2SWAP";
|
|
case OP_IFDUP : return "OP_IFDUP";
|
|
case OP_DEPTH : return "OP_DEPTH";
|
|
case OP_DROP : return "OP_DROP";
|
|
case OP_DUP : return "OP_DUP";
|
|
case OP_NIP : return "OP_NIP";
|
|
case OP_OVER : return "OP_OVER";
|
|
case OP_PICK : return "OP_PICK";
|
|
case OP_ROLL : return "OP_ROLL";
|
|
case OP_ROT : return "OP_ROT";
|
|
case OP_SWAP : return "OP_SWAP";
|
|
case OP_TUCK : return "OP_TUCK";
|
|
|
|
// splice ops
|
|
case OP_CAT : return "OP_CAT";
|
|
case OP_SUBSTR : return "OP_SUBSTR";
|
|
case OP_LEFT : return "OP_LEFT";
|
|
case OP_RIGHT : return "OP_RIGHT";
|
|
case OP_SIZE : return "OP_SIZE";
|
|
|
|
// bit logic
|
|
case OP_INVERT : return "OP_INVERT";
|
|
case OP_AND : return "OP_AND";
|
|
case OP_OR : return "OP_OR";
|
|
case OP_XOR : return "OP_XOR";
|
|
case OP_EQUAL : return "OP_EQUAL";
|
|
case OP_EQUALVERIFY : return "OP_EQUALVERIFY";
|
|
case OP_RESERVED1 : return "OP_RESERVED1";
|
|
case OP_RESERVED2 : return "OP_RESERVED2";
|
|
|
|
// numeric
|
|
case OP_1ADD : return "OP_1ADD";
|
|
case OP_1SUB : return "OP_1SUB";
|
|
case OP_2MUL : return "OP_2MUL";
|
|
case OP_2DIV : return "OP_2DIV";
|
|
case OP_NEGATE : return "OP_NEGATE";
|
|
case OP_ABS : return "OP_ABS";
|
|
case OP_NOT : return "OP_NOT";
|
|
case OP_0NOTEQUAL : return "OP_0NOTEQUAL";
|
|
case OP_ADD : return "OP_ADD";
|
|
case OP_SUB : return "OP_SUB";
|
|
case OP_MUL : return "OP_MUL";
|
|
case OP_DIV : return "OP_DIV";
|
|
case OP_MOD : return "OP_MOD";
|
|
case OP_LSHIFT : return "OP_LSHIFT";
|
|
case OP_RSHIFT : return "OP_RSHIFT";
|
|
case OP_BOOLAND : return "OP_BOOLAND";
|
|
case OP_BOOLOR : return "OP_BOOLOR";
|
|
case OP_NUMEQUAL : return "OP_NUMEQUAL";
|
|
case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY";
|
|
case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL";
|
|
case OP_LESSTHAN : return "OP_LESSTHAN";
|
|
case OP_GREATERTHAN : return "OP_GREATERTHAN";
|
|
case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL";
|
|
case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL";
|
|
case OP_MIN : return "OP_MIN";
|
|
case OP_MAX : return "OP_MAX";
|
|
case OP_WITHIN : return "OP_WITHIN";
|
|
|
|
// crypto
|
|
case OP_RIPEMD160 : return "OP_RIPEMD160";
|
|
case OP_SHA1 : return "OP_SHA1";
|
|
case OP_SHA256 : return "OP_SHA256";
|
|
case OP_HASH160 : return "OP_HASH160";
|
|
case OP_HASH256 : return "OP_HASH256";
|
|
case OP_CODESEPARATOR : return "OP_CODESEPARATOR";
|
|
case OP_CHECKSIG : return "OP_CHECKSIG";
|
|
case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
|
|
case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
|
|
case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
|
|
|
|
// expanson
|
|
case OP_NOP1 : return "OP_NOP1";
|
|
case OP_NOP2 : return "OP_NOP2";
|
|
case OP_NOP3 : return "OP_NOP3";
|
|
case OP_NOP4 : return "OP_NOP4";
|
|
case OP_NOP5 : return "OP_NOP5";
|
|
case OP_NOP6 : return "OP_NOP6";
|
|
case OP_NOP7 : return "OP_NOP7";
|
|
case OP_NOP8 : return "OP_NOP8";
|
|
case OP_NOP9 : return "OP_NOP9";
|
|
case OP_NOP10 : return "OP_NOP10";
|
|
|
|
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
|
|
|
|
// Note:
|
|
// The template matching params OP_SMALLDATA/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.
|
|
|
|
default:
|
|
return "OP_UNKNOWN";
|
|
}
|
|
}
|
|
|
|
unsigned int CScript::GetSigOpCount(bool fAccurate) const
|
|
{
|
|
unsigned int n = 0;
|
|
const_iterator pc = begin();
|
|
opcodetype lastOpcode = OP_INVALIDOPCODE;
|
|
while (pc < end())
|
|
{
|
|
opcodetype opcode;
|
|
if (!GetOp(pc, opcode))
|
|
break;
|
|
if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY)
|
|
n++;
|
|
else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY)
|
|
{
|
|
if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
|
|
n += DecodeOP_N(lastOpcode);
|
|
else
|
|
n += 20;
|
|
}
|
|
lastOpcode = opcode;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
|
|
{
|
|
if (!IsPayToScriptHash())
|
|
return GetSigOpCount(true);
|
|
|
|
// This is a pay-to-script-hash scriptPubKey;
|
|
// get the last item that the scriptSig
|
|
// pushes onto the stack:
|
|
const_iterator pc = scriptSig.begin();
|
|
vector<unsigned char> data;
|
|
while (pc < scriptSig.end())
|
|
{
|
|
opcodetype opcode;
|
|
if (!scriptSig.GetOp(pc, opcode, data))
|
|
return 0;
|
|
if (opcode > OP_16)
|
|
return 0;
|
|
}
|
|
|
|
/// ... and return its opcount:
|
|
CScript subscript(data.begin(), data.end());
|
|
return subscript.GetSigOpCount(true);
|
|
}
|
|
|
|
bool CScript::IsPayToScriptHash() const
|
|
{
|
|
// Extra-fast test for pay-to-script-hash CScripts:
|
|
return (this->size() == 23 &&
|
|
this->at(0) == OP_HASH160 &&
|
|
this->at(1) == 0x14 &&
|
|
this->at(22) == OP_EQUAL);
|
|
}
|
|
|
|
bool CScript::IsPushOnly() const
|
|
{
|
|
const_iterator pc = begin();
|
|
while (pc < end())
|
|
{
|
|
opcodetype opcode;
|
|
if (!GetOp(pc, opcode))
|
|
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
|
|
// the P2SH special validation code being executed.
|
|
if (opcode > OP_16)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CScript::HasCanonicalPushes() const
|
|
{
|
|
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;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
class CScriptVisitor : public boost::static_visitor<bool>
|
|
{
|
|
private:
|
|
CScript *script;
|
|
public:
|
|
CScriptVisitor(CScript *scriptin) { script = scriptin; }
|
|
|
|
bool operator()(const CNoDestination &dest) const {
|
|
script->clear();
|
|
return false;
|
|
}
|
|
|
|
bool operator()(const CKeyID &keyID) const {
|
|
script->clear();
|
|
*script << OP_DUP << OP_HASH160 << keyID << OP_EQUALVERIFY << OP_CHECKSIG;
|
|
return true;
|
|
}
|
|
|
|
bool operator()(const CScriptID &scriptID) const {
|
|
script->clear();
|
|
*script << OP_HASH160 << scriptID << OP_EQUAL;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
void CScript::SetDestination(const CTxDestination& dest)
|
|
{
|
|
boost::apply_visitor(CScriptVisitor(this), dest);
|
|
}
|
|
|
|
void CScript::SetMultisig(int nRequired, const std::vector<CPubKey>& keys)
|
|
{
|
|
this->clear();
|
|
|
|
*this << EncodeOP_N(nRequired);
|
|
BOOST_FOREACH(const CPubKey& key, keys)
|
|
*this << key;
|
|
*this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
|
|
}
|