diff options
author | jtimon <jtimon@monetize.io> | 2014-08-14 13:54:05 +0200 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2014-09-08 20:19:31 +0200 |
commit | 86dbeea2cdd5749374c98afea3e4f5f49817f746 (patch) | |
tree | 66325232600dc519eef6244e6dc18bdafec41185 /src/script.cpp | |
parent | df623d83dad6aa39141b066ebd2f870ee05acf41 (diff) | |
download | bitcoin-86dbeea2cdd5749374c98afea3e4f5f49817f746.tar.xz |
Rename script.h/.cpp to scriptutils.h/.cpp (plus remove duplicated includes)
Diffstat (limited to 'src/script.cpp')
-rw-r--r-- | src/script.cpp | 2079 |
1 files changed, 0 insertions, 2079 deletions
diff --git a/src/script.cpp b/src/script.cpp deleted file mode 100644 index f3d423a424..0000000000 --- a/src/script.cpp +++ /dev/null @@ -1,2079 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "script.h" - -#include "crypto/ripemd160.h" -#include "crypto/sha1.h" -#include "crypto/sha2.h" -#include "core.h" -#include "hash.h" -#include "key.h" -#include "keystore.h" -#include "random.h" -#include "sync.h" -#include "uint256.h" -#include "util.h" - -#include <boost/foreach.hpp> -#include <boost/thread.hpp> -#include <boost/tuple/tuple.hpp> -#include <boost/tuple/tuple_comparison.hpp> - -using namespace std; -using namespace boost; - -typedef vector<unsigned char> valtype; -static const valtype vchFalse(0); -static const valtype vchZero(0); -static const valtype vchTrue(1, 1); -static const CScriptNum bnZero(0); -static const CScriptNum bnOne(1); -static const CScriptNum bnFalse(0); -static const CScriptNum bnTrue(1); - -bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags); - -bool CastToBool(const valtype& vch) -{ - for (unsigned int i = 0; i < vch.size(); i++) - { - if (vch[i] != 0) - { - // Can be negative zero - if (i == vch.size()-1 && vch[i] == 0x80) - return false; - return true; - } - } - return false; -} - - - -// -// Script is a stack machine (like Forth) that evaluates a predicate -// returning a bool indicating valid or not. There are no loops. -// -#define stacktop(i) (stack.at(stack.size()+(i))) -#define altstacktop(i) (altstack.at(altstack.size()+(i))) -static inline void popstack(vector<valtype>& stack) -{ - if (stack.empty()) - throw runtime_error("popstack() : stack empty"); - stack.pop_back(); -} - - -const char* GetTxnOutputType(txnouttype t) -{ - switch (t) - { - case TX_NONSTANDARD: return "nonstandard"; - case TX_PUBKEY: return "pubkey"; - case TX_PUBKEYHASH: return "pubkeyhash"; - case TX_SCRIPTHASH: return "scripthash"; - case TX_MULTISIG: return "multisig"; - case TX_NULL_DATA: return "nulldata"; - } - return NULL; -} - - -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"; - } -} - -bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) { - if (!(flags & SCRIPT_VERIFY_STRICTENC)) - return true; - - if (vchPubKey.size() < 33) - return error("Non-canonical public key: too short"); - if (vchPubKey[0] == 0x04) { - if (vchPubKey.size() != 65) - return error("Non-canonical public key: invalid length for uncompressed key"); - } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) { - if (vchPubKey.size() != 33) - return error("Non-canonical public key: invalid length for compressed key"); - } else { - return error("Non-canonical public key: neither compressed nor uncompressed"); - } - return true; -} - -bool IsCanonicalSignature(const valtype &vchSig, unsigned int flags) { - if (!(flags & SCRIPT_VERIFY_STRICTENC)) - return true; - - // See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 - // A canonical signature exists of: <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype> - // Where R and S are not negative (their first byte has its highest bit not set), and not - // excessively padded (do not start with a 0 byte, unless an otherwise negative number follows, - // in which case a single 0 byte is necessary and even required). - if (vchSig.size() < 9) - return error("Non-canonical signature: too short"); - if (vchSig.size() > 73) - return error("Non-canonical signature: too long"); - unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY)); - if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) - return error("Non-canonical signature: unknown hashtype byte"); - if (vchSig[0] != 0x30) - return error("Non-canonical signature: wrong type"); - if (vchSig[1] != vchSig.size()-3) - return error("Non-canonical signature: wrong length marker"); - unsigned int nLenR = vchSig[3]; - if (5 + nLenR >= vchSig.size()) - return error("Non-canonical signature: S length misplaced"); - unsigned int nLenS = vchSig[5+nLenR]; - if ((unsigned long)(nLenR+nLenS+7) != vchSig.size()) - return error("Non-canonical signature: R+S length mismatch"); - - const unsigned char *R = &vchSig[4]; - if (R[-2] != 0x02) - return error("Non-canonical signature: R value type mismatch"); - if (nLenR == 0) - return error("Non-canonical signature: R length is zero"); - if (R[0] & 0x80) - return error("Non-canonical signature: R value negative"); - if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) - return error("Non-canonical signature: R value excessively padded"); - - const unsigned char *S = &vchSig[6+nLenR]; - if (S[-2] != 0x02) - return error("Non-canonical signature: S value type mismatch"); - if (nLenS == 0) - return error("Non-canonical signature: S length is zero"); - if (S[0] & 0x80) - return error("Non-canonical signature: S value negative"); - if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) - return error("Non-canonical signature: S value excessively padded"); - - if (flags & SCRIPT_VERIFY_LOW_S) { - // If the S value is above the order of the curve divided by two, its - // complement modulo the order could have been used instead, which is - // one byte shorter when encoded correctly. - if (!CKey::CheckSignatureElement(S, nLenS, true)) - return error("Non-canonical signature: S value is unnecessarily high"); - } - - return true; -} - -bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType) -{ - CScript::const_iterator pc = script.begin(); - CScript::const_iterator pend = script.end(); - CScript::const_iterator pbegincodehash = script.begin(); - opcodetype opcode; - valtype vchPushValue; - vector<bool> vfExec; - vector<valtype> altstack; - if (script.size() > 10000) - return false; - int nOpCount = 0; - - try - { - while (pc < pend) - { - bool fExec = !count(vfExec.begin(), vfExec.end(), false); - - // - // Read instruction - // - if (!script.GetOp(pc, opcode, vchPushValue)) - return false; - if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) - return false; - - // Note how OP_RESERVED does not count towards the opcode limit. - if (opcode > OP_16 && ++nOpCount > 201) - return false; - - if (opcode == OP_CAT || - opcode == OP_SUBSTR || - opcode == OP_LEFT || - opcode == OP_RIGHT || - opcode == OP_INVERT || - opcode == OP_AND || - opcode == OP_OR || - opcode == OP_XOR || - opcode == OP_2MUL || - opcode == OP_2DIV || - opcode == OP_MUL || - opcode == OP_DIV || - opcode == OP_MOD || - opcode == OP_LSHIFT || - opcode == OP_RSHIFT) - return false; // Disabled opcodes. - - if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) - stack.push_back(vchPushValue); - else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) - switch (opcode) - { - // - // Push value - // - case OP_1NEGATE: - case OP_1: - case OP_2: - case OP_3: - case OP_4: - case OP_5: - case OP_6: - case OP_7: - case OP_8: - case OP_9: - case OP_10: - case OP_11: - case OP_12: - case OP_13: - case OP_14: - case OP_15: - case OP_16: - { - // ( -- value) - CScriptNum bn((int)opcode - (int)(OP_1 - 1)); - stack.push_back(bn.getvch()); - } - break; - - - // - // Control - // - case OP_NOP: - case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: - case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: - break; - - case OP_IF: - case OP_NOTIF: - { - // <expression> if [statements] [else [statements]] endif - bool fValue = false; - if (fExec) - { - if (stack.size() < 1) - return false; - valtype& vch = stacktop(-1); - fValue = CastToBool(vch); - if (opcode == OP_NOTIF) - fValue = !fValue; - popstack(stack); - } - vfExec.push_back(fValue); - } - break; - - case OP_ELSE: - { - if (vfExec.empty()) - return false; - vfExec.back() = !vfExec.back(); - } - break; - - case OP_ENDIF: - { - if (vfExec.empty()) - return false; - vfExec.pop_back(); - } - break; - - case OP_VERIFY: - { - // (true -- ) or - // (false -- false) and return - if (stack.size() < 1) - return false; - bool fValue = CastToBool(stacktop(-1)); - if (fValue) - popstack(stack); - else - return false; - } - break; - - case OP_RETURN: - { - return false; - } - break; - - - // - // Stack ops - // - case OP_TOALTSTACK: - { - if (stack.size() < 1) - return false; - altstack.push_back(stacktop(-1)); - popstack(stack); - } - break; - - case OP_FROMALTSTACK: - { - if (altstack.size() < 1) - return false; - stack.push_back(altstacktop(-1)); - popstack(altstack); - } - break; - - case OP_2DROP: - { - // (x1 x2 -- ) - if (stack.size() < 2) - return false; - popstack(stack); - popstack(stack); - } - break; - - case OP_2DUP: - { - // (x1 x2 -- x1 x2 x1 x2) - if (stack.size() < 2) - return false; - valtype vch1 = stacktop(-2); - valtype vch2 = stacktop(-1); - stack.push_back(vch1); - stack.push_back(vch2); - } - break; - - case OP_3DUP: - { - // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) - if (stack.size() < 3) - return false; - valtype vch1 = stacktop(-3); - valtype vch2 = stacktop(-2); - valtype vch3 = stacktop(-1); - stack.push_back(vch1); - stack.push_back(vch2); - stack.push_back(vch3); - } - break; - - case OP_2OVER: - { - // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) - if (stack.size() < 4) - return false; - valtype vch1 = stacktop(-4); - valtype vch2 = stacktop(-3); - stack.push_back(vch1); - stack.push_back(vch2); - } - break; - - case OP_2ROT: - { - // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) - if (stack.size() < 6) - return false; - valtype vch1 = stacktop(-6); - valtype vch2 = stacktop(-5); - stack.erase(stack.end()-6, stack.end()-4); - stack.push_back(vch1); - stack.push_back(vch2); - } - break; - - case OP_2SWAP: - { - // (x1 x2 x3 x4 -- x3 x4 x1 x2) - if (stack.size() < 4) - return false; - swap(stacktop(-4), stacktop(-2)); - swap(stacktop(-3), stacktop(-1)); - } - break; - - case OP_IFDUP: - { - // (x - 0 | x x) - if (stack.size() < 1) - return false; - valtype vch = stacktop(-1); - if (CastToBool(vch)) - stack.push_back(vch); - } - break; - - case OP_DEPTH: - { - // -- stacksize - CScriptNum bn(stack.size()); - stack.push_back(bn.getvch()); - } - break; - - case OP_DROP: - { - // (x -- ) - if (stack.size() < 1) - return false; - popstack(stack); - } - break; - - case OP_DUP: - { - // (x -- x x) - if (stack.size() < 1) - return false; - valtype vch = stacktop(-1); - stack.push_back(vch); - } - break; - - case OP_NIP: - { - // (x1 x2 -- x2) - if (stack.size() < 2) - return false; - stack.erase(stack.end() - 2); - } - break; - - case OP_OVER: - { - // (x1 x2 -- x1 x2 x1) - if (stack.size() < 2) - return false; - valtype vch = stacktop(-2); - stack.push_back(vch); - } - break; - - case OP_PICK: - case OP_ROLL: - { - // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) - // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) - if (stack.size() < 2) - return false; - int n = CScriptNum(stacktop(-1)).getint(); - popstack(stack); - if (n < 0 || n >= (int)stack.size()) - return false; - valtype vch = stacktop(-n-1); - if (opcode == OP_ROLL) - stack.erase(stack.end()-n-1); - stack.push_back(vch); - } - break; - - case OP_ROT: - { - // (x1 x2 x3 -- x2 x3 x1) - // x2 x1 x3 after first swap - // x2 x3 x1 after second swap - if (stack.size() < 3) - return false; - swap(stacktop(-3), stacktop(-2)); - swap(stacktop(-2), stacktop(-1)); - } - break; - - case OP_SWAP: - { - // (x1 x2 -- x2 x1) - if (stack.size() < 2) - return false; - swap(stacktop(-2), stacktop(-1)); - } - break; - - case OP_TUCK: - { - // (x1 x2 -- x2 x1 x2) - if (stack.size() < 2) - return false; - valtype vch = stacktop(-1); - stack.insert(stack.end()-2, vch); - } - break; - - - case OP_SIZE: - { - // (in -- in size) - if (stack.size() < 1) - return false; - CScriptNum bn(stacktop(-1).size()); - stack.push_back(bn.getvch()); - } - break; - - - // - // Bitwise logic - // - case OP_EQUAL: - case OP_EQUALVERIFY: - //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL - { - // (x1 x2 - bool) - if (stack.size() < 2) - return false; - valtype& vch1 = stacktop(-2); - valtype& vch2 = stacktop(-1); - bool fEqual = (vch1 == vch2); - // OP_NOTEQUAL is disabled because it would be too easy to say - // something like n != 1 and have some wiseguy pass in 1 with extra - // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) - //if (opcode == OP_NOTEQUAL) - // fEqual = !fEqual; - popstack(stack); - popstack(stack); - stack.push_back(fEqual ? vchTrue : vchFalse); - if (opcode == OP_EQUALVERIFY) - { - if (fEqual) - popstack(stack); - else - return false; - } - } - break; - - - // - // Numeric - // - case OP_1ADD: - case OP_1SUB: - case OP_NEGATE: - case OP_ABS: - case OP_NOT: - case OP_0NOTEQUAL: - { - // (in -- out) - if (stack.size() < 1) - return false; - CScriptNum bn(stacktop(-1)); - switch (opcode) - { - case OP_1ADD: bn += bnOne; break; - case OP_1SUB: bn -= bnOne; break; - case OP_NEGATE: bn = -bn; break; - case OP_ABS: if (bn < bnZero) bn = -bn; break; - case OP_NOT: bn = (bn == bnZero); break; - case OP_0NOTEQUAL: bn = (bn != bnZero); break; - default: assert(!"invalid opcode"); break; - } - popstack(stack); - stack.push_back(bn.getvch()); - } - break; - - case OP_ADD: - case OP_SUB: - case OP_BOOLAND: - case OP_BOOLOR: - case OP_NUMEQUAL: - case OP_NUMEQUALVERIFY: - case OP_NUMNOTEQUAL: - case OP_LESSTHAN: - case OP_GREATERTHAN: - case OP_LESSTHANOREQUAL: - case OP_GREATERTHANOREQUAL: - case OP_MIN: - case OP_MAX: - { - // (x1 x2 -- out) - if (stack.size() < 2) - return false; - CScriptNum bn1(stacktop(-2)); - CScriptNum bn2(stacktop(-1)); - CScriptNum bn(0); - switch (opcode) - { - case OP_ADD: - bn = bn1 + bn2; - break; - - case OP_SUB: - bn = bn1 - bn2; - break; - - case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; - case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; - case OP_NUMEQUAL: bn = (bn1 == bn2); break; - case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break; - case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break; - case OP_LESSTHAN: bn = (bn1 < bn2); break; - case OP_GREATERTHAN: bn = (bn1 > bn2); break; - case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break; - case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break; - case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break; - case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break; - default: assert(!"invalid opcode"); break; - } - popstack(stack); - popstack(stack); - stack.push_back(bn.getvch()); - - if (opcode == OP_NUMEQUALVERIFY) - { - if (CastToBool(stacktop(-1))) - popstack(stack); - else - return false; - } - } - break; - - case OP_WITHIN: - { - // (x min max -- out) - if (stack.size() < 3) - return false; - CScriptNum bn1(stacktop(-3)); - CScriptNum bn2(stacktop(-2)); - CScriptNum bn3(stacktop(-1)); - bool fValue = (bn2 <= bn1 && bn1 < bn3); - popstack(stack); - popstack(stack); - popstack(stack); - stack.push_back(fValue ? vchTrue : vchFalse); - } - break; - - - // - // Crypto - // - case OP_RIPEMD160: - case OP_SHA1: - case OP_SHA256: - case OP_HASH160: - case OP_HASH256: - { - // (in -- hash) - if (stack.size() < 1) - return false; - valtype& vch = stacktop(-1); - valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32); - if (opcode == OP_RIPEMD160) - CRIPEMD160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); - else if (opcode == OP_SHA1) - CSHA1().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); - else if (opcode == OP_SHA256) - CSHA256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); - else if (opcode == OP_HASH160) - CHash160().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); - else if (opcode == OP_HASH256) - CHash256().Write(&vch[0], vch.size()).Finalize(&vchHash[0]); - popstack(stack); - stack.push_back(vchHash); - } - break; - - case OP_CODESEPARATOR: - { - // Hash starts after the code separator - pbegincodehash = pc; - } - break; - - case OP_CHECKSIG: - case OP_CHECKSIGVERIFY: - { - // (sig pubkey -- bool) - if (stack.size() < 2) - return false; - - valtype& vchSig = stacktop(-2); - valtype& vchPubKey = stacktop(-1); - - // Subset of script starting at the most recent codeseparator - CScript scriptCode(pbegincodehash, pend); - - // Drop the signature, since there's no way for a signature to sign itself - scriptCode.FindAndDelete(CScript(vchSig)); - - bool fSuccess = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); - - popstack(stack); - popstack(stack); - stack.push_back(fSuccess ? vchTrue : vchFalse); - if (opcode == OP_CHECKSIGVERIFY) - { - if (fSuccess) - popstack(stack); - else - return false; - } - } - break; - - case OP_CHECKMULTISIG: - case OP_CHECKMULTISIGVERIFY: - { - // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) - - int i = 1; - if ((int)stack.size() < i) - return false; - - int nKeysCount = CScriptNum(stacktop(-i)).getint(); - if (nKeysCount < 0 || nKeysCount > 20) - return false; - nOpCount += nKeysCount; - if (nOpCount > 201) - return false; - int ikey = ++i; - i += nKeysCount; - if ((int)stack.size() < i) - return false; - - int nSigsCount = CScriptNum(stacktop(-i)).getint(); - if (nSigsCount < 0 || nSigsCount > nKeysCount) - return false; - int isig = ++i; - i += nSigsCount; - if ((int)stack.size() < i) - return false; - - // Subset of script starting at the most recent codeseparator - CScript scriptCode(pbegincodehash, pend); - - // Drop the signatures, since there's no way for a signature to sign itself - for (int k = 0; k < nSigsCount; k++) - { - valtype& vchSig = stacktop(-isig-k); - scriptCode.FindAndDelete(CScript(vchSig)); - } - - bool fSuccess = true; - while (fSuccess && nSigsCount > 0) - { - valtype& vchSig = stacktop(-isig); - valtype& vchPubKey = stacktop(-ikey); - - // Check signature - bool fOk = IsCanonicalSignature(vchSig, flags) && IsCanonicalPubKey(vchPubKey, flags) && - CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType, flags); - - if (fOk) { - isig++; - nSigsCount--; - } - ikey++; - nKeysCount--; - - // If there are more signatures left than keys left, - // then too many signatures have failed - if (nSigsCount > nKeysCount) - fSuccess = false; - } - - // Clean up stack of actual arguments - while (i-- > 1) - popstack(stack); - - // A bug causes CHECKMULTISIG to consume one extra argument - // whose contents were not checked in any way. - // - // Unfortunately this is a potential source of mutability, - // so optionally verify it is exactly equal to zero prior - // to removing it from the stack. - if (stack.size() < 1) - return false; - if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size()) - return error("CHECKMULTISIG dummy argument not null"); - popstack(stack); - - stack.push_back(fSuccess ? vchTrue : vchFalse); - - if (opcode == OP_CHECKMULTISIGVERIFY) - { - if (fSuccess) - popstack(stack); - else - return false; - } - } - break; - - default: - return false; - } - - // Size limits - if (stack.size() + altstack.size() > 1000) - return false; - } - } - catch (...) - { - return false; - } - - - if (!vfExec.empty()) - return false; - - return true; -} - - - - - - - -namespace { - -/** Wrapper that serializes like CTransaction, but with the modifications - * required for the signature hash done in-place - */ -class CTransactionSignatureSerializer { -private: - const CTransaction &txTo; // reference to the spending transaction (the one being serialized) - const CScript &scriptCode; // output script being consumed - const unsigned int nIn; // input index of txTo being signed - const bool fAnyoneCanPay; // whether the hashtype has the SIGHASH_ANYONECANPAY flag set - const bool fHashSingle; // whether the hashtype is SIGHASH_SINGLE - const bool fHashNone; // whether the hashtype is SIGHASH_NONE - -public: - CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) : - txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn), - fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)), - fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE), - fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {} - - /** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */ - template<typename S> - void SerializeScriptCode(S &s, int nType, int nVersion) const { - CScript::const_iterator it = scriptCode.begin(); - CScript::const_iterator itBegin = it; - opcodetype opcode; - unsigned int nCodeSeparators = 0; - while (scriptCode.GetOp(it, opcode)) { - if (opcode == OP_CODESEPARATOR) - nCodeSeparators++; - } - ::WriteCompactSize(s, scriptCode.size() - nCodeSeparators); - it = itBegin; - while (scriptCode.GetOp(it, opcode)) { - if (opcode == OP_CODESEPARATOR) { - s.write((char*)&itBegin[0], it-itBegin-1); - itBegin = it; - } - } - s.write((char*)&itBegin[0], it-itBegin); - } - - /** Serialize an input of txTo */ - template<typename S> - void SerializeInput(S &s, unsigned int nInput, int nType, int nVersion) const { - // In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized - if (fAnyoneCanPay) - nInput = nIn; - // Serialize the prevout - ::Serialize(s, txTo.vin[nInput].prevout, nType, nVersion); - // Serialize the script - if (nInput != nIn) - // Blank out other inputs' signatures - ::Serialize(s, CScript(), nType, nVersion); - else - SerializeScriptCode(s, nType, nVersion); - // Serialize the nSequence - if (nInput != nIn && (fHashSingle || fHashNone)) - // let the others update at will - ::Serialize(s, (int)0, nType, nVersion); - else - ::Serialize(s, txTo.vin[nInput].nSequence, nType, nVersion); - } - - /** Serialize an output of txTo */ - template<typename S> - void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const { - if (fHashSingle && nOutput != nIn) - // Do not lock-in the txout payee at other indices as txin - ::Serialize(s, CTxOut(), nType, nVersion); - else - ::Serialize(s, txTo.vout[nOutput], nType, nVersion); - } - - /** Serialize txTo */ - template<typename S> - void Serialize(S &s, int nType, int nVersion) const { - // Serialize nVersion - ::Serialize(s, txTo.nVersion, nType, nVersion); - // Serialize vin - unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size(); - ::WriteCompactSize(s, nInputs); - for (unsigned int nInput = 0; nInput < nInputs; nInput++) - SerializeInput(s, nInput, nType, nVersion); - // Serialize vout - unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size()); - ::WriteCompactSize(s, nOutputs); - for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++) - SerializeOutput(s, nOutput, nType, nVersion); - // Serialie nLockTime - ::Serialize(s, txTo.nLockTime, nType, nVersion); - } -}; - -} // anon namespace - -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) -{ - if (nIn >= txTo.vin.size()) { - LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn); - return 1; - } - - // Check for invalid use of SIGHASH_SINGLE - if ((nHashType & 0x1f) == SIGHASH_SINGLE) { - if (nIn >= txTo.vout.size()) { - LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nIn); - return 1; - } - } - - // Wrapper to serialize only the necessary parts of the transaction being signed - CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType); - - // Serialize and hash - CHashWriter ss(SER_GETHASH, 0); - ss << txTmp << nHashType; - return ss.GetHash(); -} - -// Valid signature cache, to avoid doing expensive ECDSA signature checking -// twice for every transaction (once when accepted into memory pool, and -// again when accepted into the block chain) -class CSignatureCache -{ -private: - // sigdata_type is (signature hash, signature, public key): - typedef boost::tuple<uint256, std::vector<unsigned char>, CPubKey> sigdata_type; - std::set< sigdata_type> setValid; - boost::shared_mutex cs_sigcache; - -public: - bool - Get(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) - { - boost::shared_lock<boost::shared_mutex> lock(cs_sigcache); - - sigdata_type k(hash, vchSig, pubKey); - std::set<sigdata_type>::iterator mi = setValid.find(k); - if (mi != setValid.end()) - return true; - return false; - } - - void Set(const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubKey) - { - // DoS prevention: limit cache size to less than 10MB - // (~200 bytes per cache entry times 50,000 entries) - // Since there are a maximum of 20,000 signature operations per block - // 50,000 is a reasonable default. - int64_t nMaxCacheSize = GetArg("-maxsigcachesize", 50000); - if (nMaxCacheSize <= 0) return; - - boost::unique_lock<boost::shared_mutex> lock(cs_sigcache); - - while (static_cast<int64_t>(setValid.size()) > nMaxCacheSize) - { - // Evict a random entry. Random because that helps - // foil would-be DoS attackers who might try to pre-generate - // and re-use a set of valid signatures just-slightly-greater - // than our cache size. - uint256 randomHash = GetRandHash(); - std::vector<unsigned char> unused; - std::set<sigdata_type>::iterator it = - setValid.lower_bound(sigdata_type(randomHash, unused, unused)); - if (it == setValid.end()) - it = setValid.begin(); - setValid.erase(*it); - } - - sigdata_type k(hash, vchSig, pubKey); - setValid.insert(k); - } -}; - -bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode, - const CTransaction& txTo, unsigned int nIn, int nHashType, int flags) -{ - static CSignatureCache signatureCache; - - CPubKey pubkey(vchPubKey); - if (!pubkey.IsValid()) - return false; - - // Hash type is one byte tacked on to the end of the signature - if (vchSig.empty()) - return false; - if (nHashType == 0) - nHashType = vchSig.back(); - else if (nHashType != vchSig.back()) - return false; - vchSig.pop_back(); - - uint256 sighash = SignatureHash(scriptCode, txTo, nIn, nHashType); - - if (signatureCache.Get(sighash, vchSig, pubkey)) - return true; - - if (!pubkey.Verify(sighash, vchSig)) - return false; - - if (!(flags & SCRIPT_VERIFY_NOCACHE)) - signatureCache.Set(sighash, vchSig, pubkey); - - return true; -} - - - - - - - - - -// -// Return public keys or hashes from scriptPubKey, for 'standard' transaction types. -// -bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet) -{ - // Templates - static multimap<txnouttype, CScript> mTemplates; - if (mTemplates.empty()) - { - // Standard tx, sender provides pubkey, receiver adds signature - mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG)); - - // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey - mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG)); - - // 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)); - } - - // 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()) - { - typeRet = TX_SCRIPTHASH; - vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22); - vSolutionsRet.push_back(hashBytes); - return true; - } - - // Scan templates - const CScript& script1 = scriptPubKey; - BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates) - { - const CScript& script2 = tplate.second; - vSolutionsRet.clear(); - - opcodetype opcode1, opcode2; - vector<unsigned char> vch1, vch2; - - // Compare - CScript::const_iterator pc1 = script1.begin(); - CScript::const_iterator pc2 = script2.begin(); - while (true) - { - if (pc1 == script1.end() && pc2 == script2.end()) - { - // Found a match - typeRet = tplate.first; - if (typeRet == TX_MULTISIG) - { - // Additional checks for TX_MULTISIG: - unsigned char m = vSolutionsRet.front()[0]; - unsigned char n = vSolutionsRet.back()[0]; - if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n) - return false; - } - return true; - } - if (!script1.GetOp(pc1, opcode1, vch1)) - break; - if (!script2.GetOp(pc2, opcode2, vch2)) - break; - - // Template matching opcodes: - if (opcode2 == OP_PUBKEYS) - { - while (vch1.size() >= 33 && vch1.size() <= 65) - { - vSolutionsRet.push_back(vch1); - if (!script1.GetOp(pc1, opcode1, vch1)) - break; - } - if (!script2.GetOp(pc2, opcode2, vch2)) - break; - // Normal situation is to fall through - // to other if/else statements - } - - if (opcode2 == OP_PUBKEY) - { - if (vch1.size() < 33 || vch1.size() > 65) - break; - vSolutionsRet.push_back(vch1); - } - else if (opcode2 == OP_PUBKEYHASH) - { - if (vch1.size() != sizeof(uint160)) - break; - vSolutionsRet.push_back(vch1); - } - else if (opcode2 == OP_SMALLINTEGER) - { // Single-byte small integer pushed onto vSolutions - if (opcode1 == OP_0 || - (opcode1 >= OP_1 && opcode1 <= OP_16)) - { - char n = (char)CScript::DecodeOP_N(opcode1); - vSolutionsRet.push_back(valtype(1, n)); - } - else - break; - } - else if (opcode2 == OP_SMALLDATA) - { - // small pushdata, <= MAX_OP_RETURN_RELAY bytes - if (vch1.size() > MAX_OP_RETURN_RELAY) - break; - } - else if (opcode1 != opcode2 || vch1 != vch2) - { - // Others must match exactly - break; - } - } - } - - vSolutionsRet.clear(); - typeRet = TX_NONSTANDARD; - return false; -} - - -bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) -{ - CKey key; - if (!keystore.GetKey(address, key)) - return false; - - vector<unsigned char> vchSig; - if (!key.Sign(hash, vchSig)) - return false; - vchSig.push_back((unsigned char)nHashType); - scriptSigRet << vchSig; - - return true; -} - -bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet) -{ - int nSigned = 0; - int nRequired = multisigdata.front()[0]; - for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++) - { - const valtype& pubkey = multisigdata[i]; - CKeyID keyID = CPubKey(pubkey).GetID(); - if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) - ++nSigned; - } - return nSigned==nRequired; -} - -// -// Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type. -// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed), -// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script. -// Returns false if scriptPubKey could not be completely satisfied. -// -bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, - CScript& scriptSigRet, txnouttype& whichTypeRet) -{ - scriptSigRet.clear(); - - vector<valtype> vSolutions; - if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) - return false; - - CKeyID keyID; - switch (whichTypeRet) - { - case TX_NONSTANDARD: - case TX_NULL_DATA: - return false; - case TX_PUBKEY: - keyID = CPubKey(vSolutions[0]).GetID(); - return Sign1(keyID, keystore, hash, nHashType, scriptSigRet); - case TX_PUBKEYHASH: - keyID = CKeyID(uint160(vSolutions[0])); - if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet)) - return false; - else - { - CPubKey vch; - keystore.GetPubKey(keyID, vch); - scriptSigRet << vch; - } - return true; - case TX_SCRIPTHASH: - return keystore.GetCScript(uint160(vSolutions[0]), scriptSigRet); - - case TX_MULTISIG: - scriptSigRet << OP_0; // workaround CHECKMULTISIG bug - return (SignN(vSolutions, keystore, hash, nHashType, scriptSigRet)); - } - return false; -} - -int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions) -{ - switch (t) - { - case TX_NONSTANDARD: - case TX_NULL_DATA: - return -1; - case TX_PUBKEY: - return 1; - case TX_PUBKEYHASH: - return 2; - case TX_MULTISIG: - if (vSolutions.size() < 1 || vSolutions[0].size() < 1) - return -1; - return vSolutions[0][0] + 1; - case TX_SCRIPTHASH: - return 1; // doesn't include args needed by the script - } - return -1; -} - -bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) -{ - vector<valtype> vSolutions; - if (!Solver(scriptPubKey, whichType, vSolutions)) - return false; - - if (whichType == TX_MULTISIG) - { - unsigned char m = vSolutions.front()[0]; - unsigned char n = vSolutions.back()[0]; - // Support up to x-of-3 multisig txns as standard - if (n < 1 || n > 3) - return false; - if (m < 1 || m > n) - return false; - } - - return whichType != TX_NONSTANDARD; -} - - -unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore) -{ - unsigned int nResult = 0; - BOOST_FOREACH(const valtype& pubkey, pubkeys) - { - CKeyID keyID = CPubKey(pubkey).GetID(); - if (keystore.HaveKey(keyID)) - ++nResult; - } - return nResult; -} - -isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest) -{ - CScript script; - script.SetDestination(dest); - return IsMine(keystore, script); -} - -isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) -{ - vector<valtype> vSolutions; - txnouttype whichType; - if (!Solver(scriptPubKey, whichType, vSolutions)) { - if (keystore.HaveWatchOnly(scriptPubKey)) - return ISMINE_WATCH_ONLY; - return ISMINE_NO; - } - - CKeyID keyID; - switch (whichType) - { - case TX_NONSTANDARD: - case TX_NULL_DATA: - break; - case TX_PUBKEY: - keyID = CPubKey(vSolutions[0]).GetID(); - if (keystore.HaveKey(keyID)) - return ISMINE_SPENDABLE; - break; - case TX_PUBKEYHASH: - keyID = CKeyID(uint160(vSolutions[0])); - if (keystore.HaveKey(keyID)) - return ISMINE_SPENDABLE; - break; - case TX_SCRIPTHASH: - { - CScriptID scriptID = CScriptID(uint160(vSolutions[0])); - CScript subscript; - if (keystore.GetCScript(scriptID, subscript)) { - isminetype ret = IsMine(keystore, subscript); - if (ret == ISMINE_SPENDABLE) - return ret; - } - break; - } - case TX_MULTISIG: - { - // Only consider transactions "mine" if we own ALL the - // keys involved. multi-signature transactions that are - // partially owned (somebody else has a key that can spend - // them) enable spend-out-from-under-you attacks, especially - // in shared-wallet situations. - vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); - if (HaveKeys(keys, keystore) == keys.size()) - return ISMINE_SPENDABLE; - break; - } - } - - if (keystore.HaveWatchOnly(scriptPubKey)) - return ISMINE_WATCH_ONLY; - return ISMINE_NO; -} - -bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) -{ - vector<valtype> vSolutions; - txnouttype whichType; - if (!Solver(scriptPubKey, whichType, vSolutions)) - return false; - - if (whichType == TX_PUBKEY) - { - addressRet = CPubKey(vSolutions[0]).GetID(); - return true; - } - else if (whichType == TX_PUBKEYHASH) - { - addressRet = CKeyID(uint160(vSolutions[0])); - return true; - } - else if (whichType == TX_SCRIPTHASH) - { - addressRet = CScriptID(uint160(vSolutions[0])); - return true; - } - // Multisig txns have more than one address... - return false; -} - -bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet) -{ - addressRet.clear(); - typeRet = TX_NONSTANDARD; - vector<valtype> vSolutions; - if (!Solver(scriptPubKey, typeRet, vSolutions)) - return false; - if (typeRet == TX_NULL_DATA){ - // This is data, not addresses - return false; - } - - if (typeRet == TX_MULTISIG) - { - nRequiredRet = vSolutions.front()[0]; - for (unsigned int i = 1; i < vSolutions.size()-1; i++) - { - CTxDestination address = CPubKey(vSolutions[i]).GetID(); - addressRet.push_back(address); - } - } - else - { - nRequiredRet = 1; - CTxDestination address; - if (!ExtractDestination(scriptPubKey, address)) - return false; - addressRet.push_back(address); - } - - return true; -} - -class CAffectedKeysVisitor : public boost::static_visitor<void> { -private: - const CKeyStore &keystore; - std::vector<CKeyID> &vKeys; - -public: - CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {} - - void Process(const CScript &script) { - txnouttype type; - std::vector<CTxDestination> vDest; - int nRequired; - if (ExtractDestinations(script, type, vDest, nRequired)) { - BOOST_FOREACH(const CTxDestination &dest, vDest) - boost::apply_visitor(*this, dest); - } - } - - void operator()(const CKeyID &keyId) { - if (keystore.HaveKey(keyId)) - vKeys.push_back(keyId); - } - - void operator()(const CScriptID &scriptId) { - CScript script; - if (keystore.GetCScript(scriptId, script)) - Process(script); - } - - void operator()(const CNoDestination &none) {} -}; - -void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys) { - CAffectedKeysVisitor(keystore, vKeys).Process(scriptPubKey); -} - -bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, - unsigned int flags, int nHashType) -{ - vector<vector<unsigned char> > stack, stackCopy; - if (!EvalScript(stack, scriptSig, txTo, nIn, flags, nHashType)) - return false; - if (flags & SCRIPT_VERIFY_P2SH) - stackCopy = stack; - if (!EvalScript(stack, scriptPubKey, txTo, nIn, flags, nHashType)) - return false; - if (stack.empty()) - return false; - - if (CastToBool(stack.back()) == false) - return false; - - // Additional validation for spend-to-script-hash transactions: - if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash()) - { - if (!scriptSig.IsPushOnly()) // scriptSig must be literals-only - return false; // or validation fails - - // stackCopy cannot be empty here, because if it was the - // P2SH HASH <> EQUAL scriptPubKey would be evaluated with - // an empty stack and the EvalScript above would return false. - assert(!stackCopy.empty()); - - const valtype& pubKeySerialized = stackCopy.back(); - CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); - popstack(stackCopy); - - if (!EvalScript(stackCopy, pubKey2, txTo, nIn, flags, nHashType)) - return false; - if (stackCopy.empty()) - return false; - return CastToBool(stackCopy.back()); - } - - return true; -} - - -bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType) -{ - assert(nIn < txTo.vin.size()); - CTxIn& txin = txTo.vin[nIn]; - - // Leave out the signature from the hash, since a signature can't sign itself. - // The checksig op will also drop the signatures from its hash. - uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType); - - txnouttype whichType; - if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType)) - return false; - - if (whichType == TX_SCRIPTHASH) - { - // Solver returns the subscript that need to be evaluated; - // the final scriptSig is the signatures from that - // and then the serialized subscript: - CScript subscript = txin.scriptSig; - - // Recompute txn hash using subscript in place of scriptPubKey: - uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType); - - txnouttype subType; - bool fSolved = - Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH; - // Append serialized subscript whether or not it is completely signed: - txin.scriptSig << static_cast<valtype>(subscript); - if (!fSolved) return false; - } - - // Test solution - return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0); -} - -bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType) -{ - assert(nIn < txTo.vin.size()); - CTxIn& txin = txTo.vin[nIn]; - assert(txin.prevout.n < txFrom.vout.size()); - const CTxOut& txout = txFrom.vout[txin.prevout.n]; - - return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType); -} - -static CScript PushAll(const vector<valtype>& values) -{ - CScript result; - BOOST_FOREACH(const valtype& v, values) - result << v; - return result; -} - -static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn, - const vector<valtype>& vSolutions, - vector<valtype>& sigs1, vector<valtype>& sigs2) -{ - // Combine all the signatures we've got: - set<valtype> allsigs; - BOOST_FOREACH(const valtype& v, sigs1) - { - if (!v.empty()) - allsigs.insert(v); - } - BOOST_FOREACH(const valtype& v, sigs2) - { - if (!v.empty()) - allsigs.insert(v); - } - - // Build a map of pubkey -> signature by matching sigs to pubkeys: - assert(vSolutions.size() > 1); - unsigned int nSigsRequired = vSolutions.front()[0]; - unsigned int nPubKeys = vSolutions.size()-2; - map<valtype, valtype> sigs; - BOOST_FOREACH(const valtype& sig, allsigs) - { - for (unsigned int i = 0; i < nPubKeys; i++) - { - const valtype& pubkey = vSolutions[i+1]; - if (sigs.count(pubkey)) - continue; // Already got a sig for this pubkey - - if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0, 0)) - { - sigs[pubkey] = sig; - break; - } - } - } - // Now build a merged CScript: - unsigned int nSigsHave = 0; - CScript result; result << OP_0; // pop-one-too-many workaround - for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++) - { - if (sigs.count(vSolutions[i+1])) - { - result << sigs[vSolutions[i+1]]; - ++nSigsHave; - } - } - // Fill any missing with OP_0: - for (unsigned int i = nSigsHave; i < nSigsRequired; i++) - result << OP_0; - - return result; -} - -static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, - const txnouttype txType, const vector<valtype>& vSolutions, - vector<valtype>& sigs1, vector<valtype>& sigs2) -{ - switch (txType) - { - case TX_NONSTANDARD: - case TX_NULL_DATA: - // Don't know anything about this, assume bigger one is correct: - if (sigs1.size() >= sigs2.size()) - return PushAll(sigs1); - return PushAll(sigs2); - case TX_PUBKEY: - case TX_PUBKEYHASH: - // Signatures are bigger than placeholders or empty scripts: - if (sigs1.empty() || sigs1[0].empty()) - return PushAll(sigs2); - return PushAll(sigs1); - case TX_SCRIPTHASH: - if (sigs1.empty() || sigs1.back().empty()) - return PushAll(sigs2); - else if (sigs2.empty() || sigs2.back().empty()) - return PushAll(sigs1); - else - { - // Recur to combine: - valtype spk = sigs1.back(); - CScript pubKey2(spk.begin(), spk.end()); - - txnouttype txType2; - vector<vector<unsigned char> > vSolutions2; - Solver(pubKey2, txType2, vSolutions2); - sigs1.pop_back(); - sigs2.pop_back(); - CScript result = CombineSignatures(pubKey2, txTo, nIn, txType2, vSolutions2, sigs1, sigs2); - result << spk; - return result; - } - case TX_MULTISIG: - return CombineMultisig(scriptPubKey, txTo, nIn, vSolutions, sigs1, sigs2); - } - - return CScript(); -} - -CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, - const CScript& scriptSig1, const CScript& scriptSig2) -{ - txnouttype txType; - vector<vector<unsigned char> > vSolutions; - Solver(scriptPubKey, txType, vSolutions); - - vector<valtype> stack1; - EvalScript(stack1, scriptSig1, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0); - vector<valtype> stack2; - EvalScript(stack2, scriptSig2, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0); - - return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2); -} - -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()) - { - // Note how a script with an invalid PUSHDATA returns False. - 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; -} - -bool CScriptCompressor::IsToKeyID(CKeyID &hash) const -{ - if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 - && script[2] == 20 && script[23] == OP_EQUALVERIFY - && script[24] == OP_CHECKSIG) { - memcpy(&hash, &script[3], 20); - return true; - } - return false; -} - -bool CScriptCompressor::IsToScriptID(CScriptID &hash) const -{ - if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20 - && script[22] == OP_EQUAL) { - memcpy(&hash, &script[2], 20); - return true; - } - return false; -} - -bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const -{ - if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG - && (script[1] == 0x02 || script[1] == 0x03)) { - pubkey.Set(&script[1], &script[34]); - return true; - } - if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG - && script[1] == 0x04) { - pubkey.Set(&script[1], &script[66]); - return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible - } - return false; -} - -bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const -{ - CKeyID keyID; - if (IsToKeyID(keyID)) { - out.resize(21); - out[0] = 0x00; - memcpy(&out[1], &keyID, 20); - return true; - } - CScriptID scriptID; - if (IsToScriptID(scriptID)) { - out.resize(21); - out[0] = 0x01; - memcpy(&out[1], &scriptID, 20); - return true; - } - CPubKey pubkey; - if (IsToPubKey(pubkey)) { - out.resize(33); - memcpy(&out[1], &pubkey[1], 32); - if (pubkey[0] == 0x02 || pubkey[0] == 0x03) { - out[0] = pubkey[0]; - return true; - } else if (pubkey[0] == 0x04) { - out[0] = 0x04 | (pubkey[64] & 0x01); - return true; - } - } - return false; -} - -unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const -{ - if (nSize == 0 || nSize == 1) - return 20; - if (nSize == 2 || nSize == 3 || nSize == 4 || nSize == 5) - return 32; - return 0; -} - -bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char> &in) -{ - switch(nSize) { - case 0x00: - script.resize(25); - script[0] = OP_DUP; - script[1] = OP_HASH160; - script[2] = 20; - memcpy(&script[3], &in[0], 20); - script[23] = OP_EQUALVERIFY; - script[24] = OP_CHECKSIG; - return true; - case 0x01: - script.resize(23); - script[0] = OP_HASH160; - script[1] = 20; - memcpy(&script[2], &in[0], 20); - script[22] = OP_EQUAL; - return true; - case 0x02: - case 0x03: - script.resize(35); - script[0] = 33; - script[1] = nSize; - memcpy(&script[2], &in[0], 32); - script[34] = OP_CHECKSIG; - return true; - case 0x04: - case 0x05: - unsigned char vch[33] = {}; - vch[0] = nSize - 2; - memcpy(&vch[1], &in[0], 32); - CPubKey pubkey(&vch[0], &vch[33]); - if (!pubkey.Decompress()) - return false; - assert(pubkey.size() == 65); - script.resize(67); - script[0] = 65; - memcpy(&script[1], pubkey.begin(), 65); - script[66] = OP_CHECKSIG; - return true; - } - return false; -} |