Use standard C99 (and Qt) types for 64-bit integers
[novacoin.git] / src / script.h
index da904ef..e3c6b15 100644 (file)
@@ -1,8 +1,21 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2011 The Bitcoin developers
 // Distributed under the MIT/X11 software license, see the accompanying
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef H_BITCOIN_SCRIPT
+#define H_BITCOIN_SCRIPT
+
+#include <stdint.h>
+
+#include "base58.h"
+
+#include <string>
+#include <vector>
+
+#include <boost/foreach.hpp>
 
 class CTransaction;
+class CKeyStore;
 
 enum
 {
@@ -13,6 +26,17 @@ enum
 };
 
 
+enum txnouttype
+{
+    TX_NONSTANDARD,
+    // 'standard' transaction types:
+    TX_PUBKEY,
+    TX_PUBKEYHASH,
+    TX_SCRIPTHASH,
+    TX_MULTISIG,
+};
+
+const char* GetTxnOutputType(txnouttype t);
 
 enum opcodetype
 {
@@ -136,8 +160,10 @@ enum opcodetype
     OP_CHECKMULTISIG,
     OP_CHECKMULTISIGVERIFY,
 
+    // meta
+    OP_EVAL, // Was OP_NOP1
+
     // expansion
-    OP_NOP1,
     OP_NOP2,
     OP_NOP3,
     OP_NOP4,
@@ -151,166 +177,20 @@ enum opcodetype
 
 
     // template matching params
+    OP_SMALLINTEGER = 0xfa,
+    OP_PUBKEYS = 0xfb,
+    OP_SCRIPTHASH = 0xfc,
     OP_PUBKEYHASH = 0xfd,
     OP_PUBKEY = 0xfe,
 
     OP_INVALIDOPCODE = 0xff,
 };
 
+const char* GetOpName(opcodetype opcode);
 
 
 
-
-
-
-
-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";
-    }
-};
-
-
-
-
-inline string ValueString(const vector<unsigned char>& vch)
+inline std::string ValueString(const std::vector<unsigned char>& vch)
 {
     if (vch.size() <= 4)
         return strprintf("%d", CBigNum(vch).getint());
@@ -318,10 +198,10 @@ inline string ValueString(const vector<unsigned char>& vch)
         return HexStr(vch);
 }
 
-inline string StackString(const vector<vector<unsigned char> >& vStack)
+inline std::string StackString(const std::vector<std::vector<unsigned char> >& vStack)
 {
-    string str;
-    foreach(const vector<unsigned char>& vch, vStack)
+    std::string str;
+    BOOST_FOREACH(const std::vector<unsigned char>& vch, vStack)
     {
         if (!str.empty())
             str += " ";
@@ -338,10 +218,10 @@ inline string StackString(const vector<vector<unsigned char> >& vStack)
 
 
 
-class CScript : public vector<unsigned char>
+class CScript : public std::vector<unsigned char>
 {
 protected:
-    CScript& push_int64(int64 n)
+    CScript& push_int64(int64_t n)
     {
         if (n == -1 || (n >= 1 && n <= 16))
         {
@@ -355,7 +235,7 @@ protected:
         return *this;
     }
 
-    CScript& push_uint64(uint64 n)
+    CScript& push_uint64(uint64_t n)
     {
         if (n >= 1 && n <= 16)
         {
@@ -371,10 +251,10 @@ protected:
 
 public:
     CScript() { }
-    CScript(const CScript& b) : vector<unsigned char>(b.begin(), b.end()) { }
-    CScript(const_iterator pbegin, const_iterator pend) : vector<unsigned char>(pbegin, pend) { }
+    CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { }
+    CScript(const_iterator pbegin, const_iterator pend) : std::vector<unsigned char>(pbegin, pend) { }
 #ifndef _MSC_VER
-    CScript(const unsigned char* pbegin, const unsigned char* pend) : vector<unsigned char>(pbegin, pend) { }
+    CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { }
 #endif
 
     CScript& operator+=(const CScript& b)
@@ -395,34 +275,34 @@ public:
     explicit CScript(short b)          { operator<<(b); }
     explicit CScript(int b)            { operator<<(b); }
     explicit CScript(long b)           { operator<<(b); }
-    explicit CScript(int64 b)          { operator<<(b); }
+    explicit CScript(int64_t b)        { operator<<(b); }
     explicit CScript(unsigned char b)  { operator<<(b); }
     explicit CScript(unsigned int b)   { operator<<(b); }
     explicit CScript(unsigned short b) { operator<<(b); }
     explicit CScript(unsigned long b)  { operator<<(b); }
-    explicit CScript(uint64 b)         { operator<<(b); }
+    explicit CScript(uint64_t b)       { operator<<(b); }
 
     explicit CScript(opcodetype b)     { operator<<(b); }
     explicit CScript(const uint256& b) { operator<<(b); }
     explicit CScript(const CBigNum& b) { operator<<(b); }
-    explicit CScript(const vector<unsigned char>& b) { operator<<(b); }
+    explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); }
 
 
     CScript& operator<<(char b)           { return push_int64(b); }
     CScript& operator<<(short b)          { return push_int64(b); }
     CScript& operator<<(int b)            { return push_int64(b); }
     CScript& operator<<(long b)           { return push_int64(b); }
-    CScript& operator<<(int64 b)          { return push_int64(b); }
+    CScript& operator<<(int64_t b)        { return push_int64(b); }
     CScript& operator<<(unsigned char b)  { return push_uint64(b); }
     CScript& operator<<(unsigned int b)   { return push_uint64(b); }
     CScript& operator<<(unsigned short b) { return push_uint64(b); }
     CScript& operator<<(unsigned long b)  { return push_uint64(b); }
-    CScript& operator<<(uint64 b)         { return push_uint64(b); }
+    CScript& operator<<(uint64_t b)       { return push_uint64(b); }
 
     CScript& operator<<(opcodetype opcode)
     {
         if (opcode < 0 || opcode > 0xff)
-            throw runtime_error("CScript::operator<<() : invalid opcode");
+            throw std::runtime_error("CScript::operator<<() : invalid opcode");
         insert(end(), (unsigned char)opcode);
         return *this;
     }
@@ -447,7 +327,7 @@ public:
         return *this;
     }
 
-    CScript& operator<<(const vector<unsigned char>& b)
+    CScript& operator<<(const std::vector<unsigned char>& b)
     {
         if (b.size() < OP_PUSHDATA1)
         {
@@ -478,12 +358,12 @@ public:
     {
         // I'm not sure if this should push the script or concatenate scripts.
         // If there's ever a use for pushing a script onto a script, delete this member fn
-        assert(("warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate", false));
+        assert(!"warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate");
         return *this;
     }
 
 
-    bool GetOp(iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet)
+    bool GetOp(iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet)
     {
          // Wrapper so it can be called with either iterator or const_iterator
          const_iterator pc2 = pc;
@@ -500,7 +380,7 @@ public:
          return fRet;
     }
 
-    bool GetOp(const_iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet) const
+    bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const
     {
         return GetOp2(pc, opcodeRet, &vchRet);
     }
@@ -510,7 +390,7 @@ public:
         return GetOp2(pc, opcodeRet, NULL);
     }
 
-    bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, vector<unsigned char>* pvchRet) const
+    bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) const
     {
         opcodeRet = OP_INVALIDOPCODE;
         if (pvchRet)
@@ -563,22 +443,52 @@ public:
         return true;
     }
 
+    // Encode/decode small integers:
+    static int DecodeOP_N(opcodetype opcode)
+    {
+        if (opcode == OP_0)
+            return 0;
+        assert(opcode >= OP_1 && opcode <= OP_16);
+        return (int)opcode - (int)(OP_1 - 1);
+    }
+    static opcodetype EncodeOP_N(int n)
+    {
+        assert(n >= 0 && n <= 16);
+        if (n == 0)
+            return OP_0;
+        return (opcodetype)(OP_1+n-1);
+    }
 
-    void FindAndDelete(const CScript& b)
+    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;
@@ -596,11 +506,9 @@ public:
         return n;
     }
 
-
+    // Called by CTransaction::IsStandard
     bool IsPushOnly() const
     {
-        if (size() > 200)
-            return false;
         const_iterator pc = begin();
         while (pc < end())
         {
@@ -614,49 +522,13 @@ public:
     }
 
 
-    uint160 GetBitcoinAddressHash160() const
-    {
-        opcodetype opcode;
-        vector<unsigned char> vch;
-        CScript::const_iterator pc = begin();
-        if (!GetOp(pc, opcode, vch) || opcode != OP_DUP) return 0;
-        if (!GetOp(pc, opcode, vch) || opcode != OP_HASH160) return 0;
-        if (!GetOp(pc, opcode, vch) || vch.size() != sizeof(uint160)) return 0;
-        uint160 hash160 = uint160(vch);
-        if (!GetOp(pc, opcode, vch) || opcode != OP_EQUALVERIFY) return 0;
-        if (!GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG) return 0;
-        if (pc != end()) return 0;
-        return hash160;
-    }
-
-    string GetBitcoinAddress() const
-    {
-        uint160 hash160 = GetBitcoinAddressHash160();
-        if (hash160 == 0)
-            return "";
-        return Hash160ToAddress(hash160);
-    }
-
-    void SetBitcoinAddress(const uint160& hash160)
+    void SetBitcoinAddress(const CBitcoinAddress& address);
+    void SetBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
     {
-        this->clear();
-        *this << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
-    }
-
-    void SetBitcoinAddress(const vector<unsigned char>& vchPubKey)
-    {
-        SetBitcoinAddress(Hash160(vchPubKey));
-    }
-
-    bool SetBitcoinAddress(const string& strAddress)
-    {
-        this->clear();
-        uint160 hash160;
-        if (!AddressToHash160(strAddress, hash160))
-            return false;
-        SetBitcoinAddress(hash160);
-        return true;
+        SetBitcoinAddress(CBitcoinAddress(vchPubKey));
     }
+    void SetMultisig(int nRequired, const std::vector<CKey>& keys);
+    void SetEval(const CScript& subscript);
 
 
     void PrintHex() const
@@ -664,11 +536,11 @@ public:
         printf("CScript(%s)\n", HexStr(begin(), end(), true).c_str());
     }
 
-    string ToString() const
+    std::string ToString() const
     {
-        string str;
+        std::string str;
         opcodetype opcode;
-        vector<unsigned char> vch;
+        std::vector<unsigned char> vch;
         const_iterator pc = begin();
         while (pc < end())
         {
@@ -697,13 +569,14 @@ public:
 
 
 
+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType, bool fStrictOpEval, int& nSigOpCountRet);
 
-
-
-uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
 bool IsStandard(const CScript& scriptPubKey);
-bool IsMine(const CScript& scriptPubKey);
-bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet);
-bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret);
-bool SignSignature(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 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, txnouttype& 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& nSigOpCountRet, int nHashType=0, bool fStrictOpEval=true);
+
+#endif