mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-12-14 06:32:33 +01:00
OP_EVAL implementation
OP_EVAL is a new opcode that evaluates an item on the stack as a script. It enables a new type of bitcoin address that needs an arbitrarily complex script to redeem.
This commit is contained in:
224
src/script.h
224
src/script.h
@@ -24,6 +24,17 @@ enum
|
||||
};
|
||||
|
||||
|
||||
enum txntype
|
||||
{
|
||||
TX_NONSTANDARD,
|
||||
// 'standard' transaction types:
|
||||
TX_PUBKEY,
|
||||
TX_PUBKEYHASH,
|
||||
TX_SCRIPTHASH,
|
||||
TX_MULTISIG,
|
||||
};
|
||||
|
||||
const char* GetTxnTypeName(txntype t);
|
||||
|
||||
enum opcodetype
|
||||
{
|
||||
@@ -147,8 +158,10 @@ enum opcodetype
|
||||
OP_CHECKMULTISIG,
|
||||
OP_CHECKMULTISIGVERIFY,
|
||||
|
||||
// meta
|
||||
OP_EVAL, // Was OP_NOP1
|
||||
|
||||
// expansion
|
||||
OP_NOP1,
|
||||
OP_NOP2,
|
||||
OP_NOP3,
|
||||
OP_NOP4,
|
||||
@@ -162,162 +175,16 @@ enum opcodetype
|
||||
|
||||
|
||||
// template matching params
|
||||
OP_SMALLINTEGER = 0xfa,
|
||||
OP_PUBKEYS = 0xfb,
|
||||
OP_SCRIPTHASH = 0xfc,
|
||||
OP_PUBKEYHASH = 0xfd,
|
||||
OP_PUBKEY = 0xfe,
|
||||
|
||||
OP_INVALIDOPCODE = 0xff,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline 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";
|
||||
|
||||
|
||||
|
||||
// template matching params
|
||||
case OP_PUBKEYHASH : return "OP_PUBKEYHASH";
|
||||
case OP_PUBKEY : return "OP_PUBKEY";
|
||||
|
||||
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
|
||||
default:
|
||||
return "OP_UNKNOWN";
|
||||
}
|
||||
};
|
||||
|
||||
const char* GetOpName(opcodetype opcode);
|
||||
|
||||
|
||||
|
||||
@@ -574,6 +441,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Encode/decode small integers:
|
||||
static int DecodeOP_N(opcodetype opcode)
|
||||
{
|
||||
if (opcode == OP_0)
|
||||
@@ -581,22 +449,44 @@ public:
|
||||
assert(opcode >= OP_1 && opcode <= OP_16);
|
||||
return (int)opcode - (int)(OP_1 - 1);
|
||||
}
|
||||
|
||||
void FindAndDelete(const CScript& b)
|
||||
static opcodetype EncodeOP_N(int n)
|
||||
{
|
||||
assert(n >= 0 && n <= 16);
|
||||
if (n == 0)
|
||||
return OP_0;
|
||||
return (opcodetype)(OP_1+n-1);
|
||||
}
|
||||
|
||||
int FindAndDelete(const CScript& b)
|
||||
{
|
||||
int nFound = 0;
|
||||
if (b.empty())
|
||||
return;
|
||||
return nFound;
|
||||
iterator pc = begin();
|
||||
opcodetype opcode;
|
||||
do
|
||||
{
|
||||
while (end() - pc >= b.size() && memcmp(&pc[0], &b[0], b.size()) == 0)
|
||||
{
|
||||
erase(pc, pc + b.size());
|
||||
++nFound;
|
||||
}
|
||||
}
|
||||
while (GetOp(pc, opcode));
|
||||
return nFound;
|
||||
}
|
||||
int Find(opcodetype op) const
|
||||
{
|
||||
int nFound = 0;
|
||||
opcodetype opcode;
|
||||
for (const_iterator pc = begin(); pc != end() && GetOp(pc, opcode);)
|
||||
if (opcode == op)
|
||||
++nFound;
|
||||
return nFound;
|
||||
}
|
||||
|
||||
|
||||
// This method should be removed when a compatibility-breaking block chain split has passed.
|
||||
// Compatibility method for old clients that count sigops differently:
|
||||
int GetSigOpCount() const
|
||||
{
|
||||
int n = 0;
|
||||
@@ -614,11 +504,9 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
// Called by CTransaction::IsStandard
|
||||
bool IsPushOnly() const
|
||||
{
|
||||
if (size() > 200)
|
||||
return false;
|
||||
const_iterator pc = begin();
|
||||
while (pc < end())
|
||||
{
|
||||
@@ -632,19 +520,13 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void SetBitcoinAddress(const CBitcoinAddress& address)
|
||||
{
|
||||
this->clear();
|
||||
*this << OP_DUP << OP_HASH160 << address.GetHash160() << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
}
|
||||
|
||||
void SetBitcoinAddress(const CBitcoinAddress& address);
|
||||
void SetBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
|
||||
{
|
||||
SetBitcoinAddress(CBitcoinAddress(vchPubKey));
|
||||
}
|
||||
void SetMultisigAnd(const std::vector<CKey>& keys);
|
||||
void SetMultisigOr(const std::vector<CKey>& keys);
|
||||
void SetMultisigEscrow(const std::vector<CKey>& keys);
|
||||
void SetMultisig(int nRequired, const std::vector<CKey>& keys);
|
||||
void SetEval(const CScript& subscript);
|
||||
|
||||
|
||||
void PrintHex() const
|
||||
@@ -685,14 +567,14 @@ public:
|
||||
|
||||
|
||||
|
||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType, int& nSigOpCountRet);
|
||||
|
||||
|
||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
|
||||
bool Solver(const CScript& scriptPubKey, txntype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
|
||||
bool IsStandard(const CScript& scriptPubKey);
|
||||
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
|
||||
bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* pkeystore, CBitcoinAddress& addressRet);
|
||||
bool ExtractAddresses(const CScript& scriptPubKey, const CKeyStore* pkeystore, txntype& typeRet, std::vector<CBitcoinAddress>& addressRet, int& nRequiredRet);
|
||||
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript());
|
||||
bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0);
|
||||
bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int& nSigOpCountRet, int nHashType=0);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user