split off CBase58Data from CBitcoinAddress
[novacoin.git] / src / script.cpp
index a85c371..652240f 100644 (file)
@@ -1,9 +1,11 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Distributed under the MIT/X11 software license, see the accompanying
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
-
 #include "headers.h"
 
+using namespace std;
+using namespace boost;
+
 bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
 
 
@@ -578,6 +580,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
                     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());
@@ -657,6 +660,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
                     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);
@@ -974,7 +978,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
 
     // Scan templates
     const CScript& script1 = scriptPubKey;
-    foreach(const CScript& script2, vTemplates)
+    BOOST_FOREACH(const CScript& script2, vTemplates)
     {
         vSolutionRet.clear();
         opcodetype opcode1, opcode2;
@@ -1019,7 +1023,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
 }
 
 
-bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
+bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& scriptSigRet)
 {
     scriptSigRet.clear();
 
@@ -1028,20 +1032,23 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
         return false;
 
     // Compile solution
-    CRITICAL_BLOCK(cs_mapKeys)
+    CRITICAL_BLOCK(keystore.cs_KeyStore)
     {
-        foreach(PAIRTYPE(opcodetype, valtype)& item, vSolution)
+        BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
             if (item.first == OP_PUBKEY)
             {
                 // Sign
                 const valtype& vchPubKey = item.second;
-                if (!mapKeys.count(vchPubKey))
+                CKey key;
+                if (!keystore.GetKey(Hash160(vchPubKey), key))
+                    return false;
+                if (key.GetPubKey() != vchPubKey)
                     return false;
                 if (hash != 0)
                 {
                     vector<unsigned char> vchSig;
-                    if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
+                    if (!key.Sign(hash, vchSig))
                         return false;
                     vchSig.push_back((unsigned char)nHashType);
                     scriptSigRet << vchSig;
@@ -1050,19 +1057,16 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
             else if (item.first == OP_PUBKEYHASH)
             {
                 // Sign and give pubkey
-                map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
-                if (mi == mapPubKeys.end())
-                    return false;
-                const vector<unsigned char>& vchPubKey = (*mi).second;
-                if (!mapKeys.count(vchPubKey))
+                CKey key;
+                if (!keystore.GetKey(uint160(item.second), key))
                     return false;
                 if (hash != 0)
                 {
                     vector<unsigned char> vchSig;
-                    if (!CKey::Sign(mapKeys[vchPubKey], hash, vchSig))
+                    if (!key.Sign(hash, vchSig))
                         return false;
                     vchSig.push_back((unsigned char)nHashType);
-                    scriptSigRet << vchSig << vchPubKey;
+                    scriptSigRet << vchSig << key.GetPubKey();
                 }
             }
             else
@@ -1083,62 +1087,59 @@ bool IsStandard(const CScript& scriptPubKey)
 }
 
 
-bool IsMine(const CScript& scriptPubKey)
+bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
 {
-    CScript scriptSig;
-    return Solver(scriptPubKey, 0, 0, scriptSig);
-}
-
-
-bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, vector<unsigned char>& vchPubKeyRet)
-{
-    vchPubKeyRet.clear();
-
     vector<pair<opcodetype, valtype> > vSolution;
     if (!Solver(scriptPubKey, vSolution))
         return false;
 
-    CRITICAL_BLOCK(cs_mapKeys)
+    // Compile solution
+    CRITICAL_BLOCK(keystore.cs_KeyStore)
     {
-        foreach(PAIRTYPE(opcodetype, valtype)& item, vSolution)
+        BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
-            valtype vchPubKey;
             if (item.first == OP_PUBKEY)
             {
-                vchPubKey = item.second;
+                const valtype& vchPubKey = item.second;
+                vector<unsigned char> vchPubKeyFound;
+                if (!keystore.GetPubKey(Hash160(vchPubKey), vchPubKeyFound))
+                    return false;
+                if (vchPubKeyFound != vchPubKey)
+                    return false;
             }
             else if (item.first == OP_PUBKEYHASH)
             {
-                map<uint160, valtype>::iterator mi = mapPubKeys.find(uint160(item.second));
-                if (mi == mapPubKeys.end())
-                    continue;
-                vchPubKey = (*mi).second;
+                if (!keystore.HaveKey(uint160(item.second)))
+                    return false;
             }
-            if (!fMineOnly || mapKeys.count(vchPubKey))
+            else
             {
-                vchPubKeyRet = vchPubKey;
-                return true;
+                return false;
             }
         }
     }
-    return false;
+
+    return true;
 }
 
 
-bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret)
+bool ExtractAddress(const CScript& scriptPubKey, const CKeyStore* keystore, CBitcoinAddress& addressRet)
 {
-    hash160Ret = 0;
-
     vector<pair<opcodetype, valtype> > vSolution;
     if (!Solver(scriptPubKey, vSolution))
         return false;
 
-    foreach(PAIRTYPE(opcodetype, valtype)& item, vSolution)
+    CRITICAL_BLOCK(keystore->cs_KeyStore)
     {
-        if (item.first == OP_PUBKEYHASH)
+        BOOST_FOREACH(PAIRTYPE(opcodetype, valtype)& item, vSolution)
         {
-            hash160Ret = uint160(item.second);
-            return true;
+            uint160 hash160;
+            if (item.first == OP_PUBKEY)
+                addressRet.SetPubKey(item.second);
+            else if (item.first == OP_PUBKEYHASH)
+                addressRet.SetHash160((uint160)item.second);
+            if (keystore == NULL || keystore->HaveKey(addressRet))
+                return true;
         }
     }
     return false;
@@ -1158,7 +1159,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
 }
 
 
-bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
+bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType, CScript scriptPrereq)
 {
     assert(nIn < txTo.vin.size());
     CTxIn& txin = txTo.vin[nIn];
@@ -1169,7 +1170,7 @@ bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int
     // The checksig op will also drop the signatures from its hash.
     uint256 hash = SignatureHash(scriptPrereq + txout.scriptPubKey, txTo, nIn, nHashType);
 
-    if (!Solver(txout.scriptPubKey, hash, nHashType, txin.scriptSig))
+    if (!Solver(keystore, txout.scriptPubKey, hash, nHashType, txin.scriptSig))
         return false;
 
     txin.scriptSig = scriptPrereq + txin.scriptSig;
@@ -1197,10 +1198,5 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
     if (!VerifyScript(txin.scriptSig, txout.scriptPubKey, txTo, nIn, nHashType))
         return false;
 
-    // Anytime a signature is successfully verified, it's proof the outpoint is spent,
-    // so lets update the wallet spent flag if it doesn't know due to wallet.dat being
-    // restored from backup or the user making copies of wallet.dat.
-    WalletUpdateSpent(txin.prevout);
-
     return true;
 }