1cffb8a7ec
* Add simple test for p2pk script refs #1767 * Add p2pk transaction addresses indexing Addresses from p2pk transaction are now indexed by transations pubkeys hashes. Even if it isn't strict behavior and the p2pk are rare and obsolete, it is transaction that should be able to be looked up. fixes #1767 * Add p2pk script checking tests refs #1767
259 lines
9.8 KiB
C++
259 lines
9.8 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2015 The Bitcoin Core 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 "tinyformat.h"
|
|
#include "utilstrencodings.h"
|
|
|
|
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_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY";
|
|
case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY";
|
|
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_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.
|
|
|
|
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 += MAX_PUBKEYS_PER_MULTISIG;
|
|
}
|
|
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::IsPayToPublicKeyHash() const
|
|
{
|
|
// Extra-fast test for pay-to-pubkey-hash CScripts:
|
|
return (this->size() == 25 &&
|
|
(*this)[0] == OP_DUP &&
|
|
(*this)[1] == OP_HASH160 &&
|
|
(*this)[2] == 0x14 &&
|
|
(*this)[23] == OP_EQUALVERIFY &&
|
|
(*this)[24] == OP_CHECKSIG);
|
|
}
|
|
|
|
bool CScript::IsPayToScriptHash() const
|
|
{
|
|
// Extra-fast test for pay-to-script-hash CScripts:
|
|
return (this->size() == 23 &&
|
|
(*this)[0] == OP_HASH160 &&
|
|
(*this)[1] == 0x14 &&
|
|
(*this)[22] == OP_EQUAL);
|
|
}
|
|
|
|
bool CScript::IsPayToPublicKey() const
|
|
{
|
|
// Test for pay-to-pubkey CScript with both
|
|
// compressed or uncompressed pubkey
|
|
if (this->size() == 35) {
|
|
return ((*this)[1] == 0x02 || (*this)[1] == 0x03) &&
|
|
(*this)[34] == OP_CHECKSIG;
|
|
}
|
|
if (this->size() == 67) {
|
|
return (*this)[1] == 0x04 &&
|
|
(*this)[66] == OP_CHECKSIG;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CScript::IsPushOnly(const_iterator pc) const
|
|
{
|
|
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/BIP62 as the scriptSig would fail prior to
|
|
// the P2SH special validation code being executed.
|
|
if (opcode > OP_16)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CScript::IsPushOnly() const
|
|
{
|
|
return this->IsPushOnly(begin());
|
|
}
|