You are on page 1of 14

Skip to content

bitcoin / bitcoin
Sign up

Code Issues 706 Pull requests 279 Projects 8 Security Pulse

Dismiss

Join GitHub today


GitHub is home to over 40 million developers working together to host and review code, manage
projects, and build software together.
Sign up
Branch: master

Find file Copy path

bitcoin/src/script/script.cpp
practicalswift Make reasoning about dependencies easier by not including unused
depe…eca9767 on 2 Jun

18 contributors

329 lines (301 sloc) 11.5 KB

RawBlame History

// Copyright (c) 2009-2010 Satoshi Nakamoto

// Copyright (c) 2009-2018 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/script.h>

#include <util/strencodings.h>
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";

// expansion

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";

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();

std::vector<unsigned char> vData;

while (pc < scriptSig.end())

opcodetype opcode;

if (!scriptSig.GetOp(pc, opcode, vData))

return 0;

if (opcode > OP_16)

return 0;

/// ... and return its opcount:


CScript subscript(vData.begin(), vData.end());

return subscript.GetSigOpCount(true);

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::IsPayToWitnessScriptHash() const

// Extra-fast test for pay-to-witness-script-hash CScripts:

return (this->size() == 34 &&

(*this)[0] == OP_0 &&

(*this)[1] == 0x20);

// A witness program is any valid CScript that consists of a 1-byte push opcode

// followed by a data push between 2 and 40 bytes.

bool CScript::IsWitnessProgram(int& version, std::vector<unsigned char>& program)


const
{

if (this->size() < 4 || this->size() > 42) {

return false;

if ((*this)[0] != OP_0 && ((*this)[0] < OP_1 || (*this)[0] > OP_16)) {

return false;

if ((size_t)((*this)[1] + 2) == this->size()) {

version = DecodeOP_N((opcodetype)(*this)[0]);

program = std::vector<unsigned char>(this->begin() + 2, this->end());

return true;

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());

std::string CScriptWitness::ToString() const

std::string ret = "CScriptWitness(";

for (unsigned int i = 0; i < stack.size(); i++) {

if (i) {

ret += ", ";

ret += HexStr(stack[i]);

return ret + ")";

bool CScript::HasValidOps() const

CScript::const_iterator it = begin();
while (it < end()) {

opcodetype opcode;

std::vector<unsigned char> item;

if (!GetOp(it, opcode, item) || opcode > MAX_OPCODE || item.size() >


MAX_SCRIPT_ELEMENT_SIZE) {

return false;

return true;

bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end,


opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)

opcodeRet = OP_INVALIDOPCODE;

if (pvchRet)

pvchRet->clear();

if (pc >= end)

return false;

// Read instruction

if (end - pc < 1)

return false;

unsigned int opcode = *pc++;


// Immediate operand

if (opcode <= OP_PUSHDATA4)

unsigned int nSize = 0;

if (opcode < OP_PUSHDATA1)

nSize = opcode;

else if (opcode == OP_PUSHDATA1)

if (end - pc < 1)

return false;

nSize = *pc++;

else if (opcode == OP_PUSHDATA2)

if (end - pc < 2)

return false;

nSize = ReadLE16(&pc[0]);

pc += 2;

else if (opcode == OP_PUSHDATA4)

if (end - pc < 4)

return false;

nSize = ReadLE32(&pc[0]);

pc += 4;

}
if (end - pc < 0 || (unsigned int)(end - pc) < nSize)

return false;

if (pvchRet)

pvchRet->assign(pc, pc + nSize);

pc += nSize;

opcodeRet = static_cast<opcodetype>(opcode);

return true;

 © 2019 GitHub, Inc.


 Terms
 Privacy
 Security
 Status
 Help

 Contact GitHub
 Pricing
 API
 Training
 Blog
 About

You might also like