Merge remote branch 'upstream/master'
[novacoin.git] / src / bitcoinrpc.cpp
index 872f52e..5bc7353 100644 (file)
@@ -13,7 +13,7 @@
 #include <boost/iostreams/stream.hpp>
 #include <boost/algorithm/string.hpp>
 #ifdef USE_SSL
-#include <boost/asio/ssl.hpp>
+#include <boost/asio/ssl.hpp> 
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
@@ -342,7 +342,7 @@ Value getnewaddress(const Array& params, bool fHelp)
         strAccount = AccountFromValue(params[0]);
 
     // Generate a new key that is added to wallet
-    string strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool());
+    string strAddress = CBitcoinAddress(pwalletMain->GetOrReuseKeyFromPool()).ToString();
 
     // This could be done in the same main CS as GetKeyFromKeyPool.
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
@@ -353,7 +353,7 @@ Value getnewaddress(const Array& params, bool fHelp)
 
 
 // requires cs_main, cs_mapWallet, cs_mapAddressBook locks
-string GetAccountAddress(string strAccount, bool bForceNew=false)
+CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
 {
     string strAddress;
 
@@ -393,16 +393,14 @@ string GetAccountAddress(string strAccount, bool bForceNew=false)
             else
             {
                 account.vchPubKey = pwalletMain->GetOrReuseKeyFromPool();
-                string strAddress = PubKeyToAddress(account.vchPubKey);
+                string strAddress = CBitcoinAddress(account.vchPubKey).ToString();
                 pwalletMain->SetAddressBookName(strAddress, strAccount);
                 walletdb.WriteAccount(strAccount, account);
             }
         }
     }
 
-    strAddress = PubKeyToAddress(account.vchPubKey);
-
-    return strAddress;
+    return CBitcoinAddress(account.vchPubKey);
 }
 
 Value getaccountaddress(const Array& params, bool fHelp)
@@ -421,7 +419,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
     CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        ret = GetAccountAddress(strAccount);
+        ret = GetAccountAddress(strAccount).ToString();
     }
 
     return ret;
@@ -437,9 +435,8 @@ Value setaccount(const Array& params, bool fHelp)
             "Sets the account associated with the given address.");
 
     string strAddress = params[0].get_str();
-    uint160 hash160;
-    bool isValid = AddressToHash160(strAddress, hash160);
-    if (!isValid)
+    CBitcoinAddress address(strAddress);
+    if (!address.IsValid())
         throw JSONRPCError(-5, "Invalid bitcoin address");
 
 
@@ -452,10 +449,10 @@ Value setaccount(const Array& params, bool fHelp)
     CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        if (pwalletMain->mapAddressBook.count(strAddress))
+        if (pwalletMain->mapAddressBook.count(address))
         {
-            string strOldAccount = pwalletMain->mapAddressBook[strAddress];
-            if (strAddress == GetAccountAddress(strOldAccount))
+            string strOldAccount = pwalletMain->mapAddressBook[address];
+            if (address == GetAccountAddress(strOldAccount))
                 GetAccountAddress(strOldAccount, true);
         }
 
@@ -474,11 +471,12 @@ Value getaccount(const Array& params, bool fHelp)
             "Returns the account associated with the given address.");
 
     string strAddress = params[0].get_str();
+    CBitcoinAddress address(strAddress);
 
     string strAccount;
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        map<string, string>::iterator mi = pwalletMain->mapAddressBook.find(strAddress);
+        map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
         if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
             strAccount = (*mi).second;
     }
@@ -499,17 +497,12 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
     Array ret;
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
         {
-            const string& strAddress = item.first;
+            const CBitcoinAddress& address = item.first;
             const string& strName = item.second;
             if (strName == strAccount)
-            {
-                // We're only adding valid bitcoin addresses and not ip addresses
-                CScript scriptPubKey;
-                if (scriptPubKey.SetBitcoinAddress(strAddress))
-                    ret.push_back(strAddress);
-            }
+                ret.push_back(address.ToString());
         }
     }
     return ret;
@@ -578,10 +571,11 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
 
     // Bitcoin address
-    string strAddress = params[0].get_str();
+    CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
     CScript scriptPubKey;
-    if (!scriptPubKey.SetBitcoinAddress(strAddress))
+    if (!address.IsValid())
         throw JSONRPCError(-5, "Invalid bitcoin address");
+    scriptPubKey.SetBitcoinAddress(address);
     if (!IsMine(*pwalletMain,scriptPubKey))
         return (double)0.0;
 
@@ -611,22 +605,16 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
 }
 
 
-void GetAccountPubKeys(string strAccount, set<CScript>& setPubKey)
+void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
 {
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
         {
-            const string& strAddress = item.first;
+            const CBitcoinAddress& address = item.first;
             const string& strName = item.second;
             if (strName == strAccount)
-            {
-                // We're only counting our own valid bitcoin addresses and not ip addresses
-                CScript scriptPubKey;
-                if (scriptPubKey.SetBitcoinAddress(strAddress))
-                    if (IsMine(*pwalletMain,scriptPubKey))
-                        setPubKey.insert(scriptPubKey);
-            }
+                setAddress.insert(address);
         }
     }
 }
@@ -646,8 +634,8 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
 
     // Get the set of pub keys that have the label
     string strAccount = AccountFromValue(params[0]);
-    set<CScript> setPubKey;
-    GetAccountPubKeys(strAccount, setPubKey);
+    set<CBitcoinAddress> setAddress;
+    GetAccountAddresses(strAccount, setAddress);
 
     // Tally
     int64 nAmount = 0;
@@ -660,9 +648,12 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
                 continue;
 
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
-                if (setPubKey.count(txout.scriptPubKey))
+            {
+                CBitcoinAddress address;
+                if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
                     if (wtx.GetDepthInMainChain() >= nMinDepth)
                         nAmount += txout.nValue;
+            }
         }
     }
 
@@ -733,13 +724,13 @@ Value getbalance(const Array& params, bool fHelp)
             int64 allGeneratedImmature, allGeneratedMature, allFee;
             allGeneratedImmature = allGeneratedMature = allFee = 0;
             string strSentAccount;
-            list<pair<string, int64> > listReceived;
-            list<pair<string, int64> > listSent;
+            list<pair<CBitcoinAddress, int64> > listReceived;
+            list<pair<CBitcoinAddress, int64> > listSent;
             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
             if (wtx.GetDepthInMainChain() >= nMinDepth)
-                BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listReceived)
+                BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
                     nBalance += r.second;
-            BOOST_FOREACH(const PAIRTYPE(string,int64)& r, listSent)
+            BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
                 nBalance -= r.second;
             nBalance -= allFee;
             nBalance += allGeneratedMature;
@@ -874,23 +865,23 @@ Value sendmany(const Array& params, bool fHelp)
     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
         wtx.mapValue["comment"] = params[3].get_str();
 
-    set<string> setAddress;
+    set<CBitcoinAddress> setAddress;
     vector<pair<CScript, int64> > vecSend;
 
     int64 totalAmount = 0;
     BOOST_FOREACH(const Pair& s, sendTo)
     {
-        uint160 hash160;
-        string strAddress = s.name_;
+        CBitcoinAddress address(s.name_);
+        if (!address.IsValid())
+            throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
 
-        if (setAddress.count(strAddress))
-            throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+strAddress);
-        setAddress.insert(strAddress);
+        if (setAddress.count(address))
+            throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
+        setAddress.insert(address);
 
         CScript scriptPubKey;
-        if (!scriptPubKey.SetBitcoinAddress(strAddress))
-            throw JSONRPCError(-5, string("Invalid bitcoin address:")+strAddress);
-        int64 nAmount = AmountFromValue(s.value_);
+        scriptPubKey.SetBitcoinAddress(address);
+        int64 nAmount = AmountFromValue(s.value_); 
         totalAmount += nAmount;
 
         vecSend.push_back(make_pair(scriptPubKey, nAmount));
@@ -950,7 +941,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
         fIncludeEmpty = params[1].get_bool();
 
     // Tally
-    map<uint160, tallyitem> mapTally;
+    map<CBitcoinAddress, tallyitem> mapTally;
     CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     {
         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
@@ -965,12 +956,11 @@ Value ListReceived(const Array& params, bool fByAccounts)
 
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
             {
-                // Only counting our own bitcoin addresses and not ip addresses
-                uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
-                if (hash160 == 0 || !mapPubKeys.count(hash160)) // IsMine
+                CBitcoinAddress address;
+                if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
                     continue;
 
-                tallyitem& item = mapTally[hash160];
+                tallyitem& item = mapTally[address];
                 item.nAmount += txout.nValue;
                 item.nConf = min(item.nConf, nDepth);
             }
@@ -982,14 +972,11 @@ Value ListReceived(const Array& params, bool fByAccounts)
     map<string, tallyitem> mapAccountTally;
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& item, pwalletMain->mapAddressBook)
+        BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
         {
-            const string& strAddress = item.first;
+            const CBitcoinAddress& address = item.first;
             const string& strAccount = item.second;
-            uint160 hash160;
-            if (!AddressToHash160(strAddress, hash160))
-                continue;
-            map<uint160, tallyitem>::iterator it = mapTally.find(hash160);
+            map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
             if (it == mapTally.end() && !fIncludeEmpty)
                 continue;
 
@@ -1010,7 +997,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
             else
             {
                 Object obj;
-                obj.push_back(Pair("address",       strAddress));
+                obj.push_back(Pair("address",       address.ToString()));
                 obj.push_back(Pair("account",       strAccount));
                 obj.push_back(Pair("label",         strAccount)); // deprecated
                 obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
@@ -1073,8 +1060,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
 {
     int64 nGeneratedImmature, nGeneratedMature, nFee;
     string strSentAccount;
-    list<pair<string, int64> > listReceived;
-    list<pair<string, int64> > listSent;
+    list<pair<CBitcoinAddress, int64> > listReceived;
+    list<pair<CBitcoinAddress, int64> > listSent;
     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
 
     bool fAllAccounts = (strAccount == string("*"));
@@ -1102,11 +1089,11 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
     // Sent
     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
     {
-        BOOST_FOREACH(const PAIRTYPE(string, int64)& s, listSent)
+        BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
         {
             Object entry;
             entry.push_back(Pair("account", strSentAccount));
-            entry.push_back(Pair("address", s.first));
+            entry.push_back(Pair("address", s.first.ToString()));
             entry.push_back(Pair("category", "send"));
             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
@@ -1120,7 +1107,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
         CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
         {
-            BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
+            BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
             {
                 string account;
                 if (pwalletMain->mapAddressBook.count(r.first))
@@ -1129,7 +1116,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
                 {
                     Object entry;
                     entry.push_back(Pair("account", account));
-                    entry.push_back(Pair("address", r.first));
+                    entry.push_back(Pair("address", r.first.ToString()));
                     entry.push_back(Pair("category", "receive"));
                     entry.push_back(Pair("amount", ValueFromAmount(r.second)));
                     if (fLong)
@@ -1212,7 +1199,7 @@ Value listtransactions(const Array& params, bool fHelp)
         }
         // ret is now newest to oldest
     }
-
+    
     // Make sure we return only last nCount items (sends-to-self might give us an extra):
     if (ret.size() > nCount)
     {
@@ -1240,9 +1227,8 @@ Value listaccounts(const Array& params, bool fHelp)
     CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
     {
-        BOOST_FOREACH(const PAIRTYPE(string, string)& entry, pwalletMain->mapAddressBook) {
-            uint160 hash160;
-            if(AddressToHash160(entry.first, hash160) && mapPubKeys.count(hash160)) // This address belongs to me
+        BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
+            if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
                 mapAccountBalances[entry.second] = 0;
         }
 
@@ -1251,16 +1237,16 @@ Value listaccounts(const Array& params, bool fHelp)
             const CWalletTx& wtx = (*it).second;
             int64 nGeneratedImmature, nGeneratedMature, nFee;
             string strSentAccount;
-            list<pair<string, int64> > listReceived;
-            list<pair<string, int64> > listSent;
+            list<pair<CBitcoinAddress, int64> > listReceived;
+            list<pair<CBitcoinAddress, int64> > listSent;
             wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
             mapAccountBalances[strSentAccount] -= nFee;
-            BOOST_FOREACH(const PAIRTYPE(string, int64)& s, listSent)
+            BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
                 mapAccountBalances[strSentAccount] -= s.second;
             if (wtx.GetDepthInMainChain() >= nMinDepth)
             {
                 mapAccountBalances[""] += nGeneratedMature;
-                BOOST_FOREACH(const PAIRTYPE(string, int64)& r, listReceived)
+                BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
                     if (pwalletMain->mapAddressBook.count(r.first))
                         mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
                     else
@@ -1553,8 +1539,8 @@ Value validateaddress(const Array& params, bool fHelp)
             "Return information about <bitcoinaddress>.");
 
     string strAddress = params[0].get_str();
-    uint160 hash160;
-    bool isValid = AddressToHash160(strAddress, hash160);
+    CBitcoinAddress address(strAddress);
+    bool isValid = address.IsValid();
 
     Object ret;
     ret.push_back(Pair("isvalid", isValid));
@@ -1562,13 +1548,13 @@ Value validateaddress(const Array& params, bool fHelp)
     {
         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
         // version of the address:
-        string currentAddress = Hash160ToAddress(hash160);
+        string currentAddress = address.ToString();
         ret.push_back(Pair("address", currentAddress));
-        ret.push_back(Pair("ismine", (mapPubKeys.count(hash160) > 0)));
+        ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
         CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
         {
-            if (pwalletMain->mapAddressBook.count(currentAddress))
-                ret.push_back(Pair("account", pwalletMain->mapAddressBook[currentAddress]));
+            if (pwalletMain->mapAddressBook.count(address))
+                ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
         }
     }
     return ret;