genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
genesis                 5 
genesis                 6 #include "headers.h"
genesis                 7 #include "db.h"
genesis                 8 #include "net.h"
genesis                 9 #include "init.h"
genesis                10 #undef printf
genesis                11 #include <boost/asio.hpp>
genesis                12 #include <boost/iostreams/concepts.hpp>
genesis                13 #include <boost/iostreams/stream.hpp>
genesis                14 #include <boost/algorithm/string.hpp>
genesis                15 #ifdef USE_SSL
genesis                16 #include <boost/asio/ssl.hpp> 
genesis                17 #include <boost/filesystem.hpp>
genesis                18 #include <boost/filesystem/fstream.hpp>
genesis                19 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
genesis                20 #endif
genesis                21 #include "json/json_spirit_reader_template.h"
genesis                22 #include "json/json_spirit_writer_template.h"
genesis                23 #include "json/json_spirit_utils.h"
genesis                24 #define printf OutputDebugStringF
genesis                25 
genesis                26 
genesis                27 
genesis                28 
genesis                29 
genesis                30 using namespace std;
genesis                31 using namespace boost;
genesis                32 using namespace boost::asio;
genesis                33 using namespace json_spirit;
genesis                34 
genesis                35 void ThreadRPCServer2(void* parg);
genesis                36 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
genesis                37 extern map<string, rpcfn_type> mapCallTable;
genesis                38 
genesis                39 static std::string strRPCUserColonPass;
genesis                40 
genesis                41 static int64 nWalletUnlockTime;
genesis                42 static CCriticalSection cs_nWalletUnlockTime;
genesis                43 
genesis                44 
genesis                45 Object JSONRPCError(int code, const string& message)
genesis                46 {
genesis                47     Object error;
genesis                48     error.push_back(Pair("code", code));
genesis                49     error.push_back(Pair("message", message));
genesis                50     return error;
genesis                51 }
genesis                52 
genesis                53 
genesis                54 void PrintConsole(const std::string &format, ...)
genesis                55 {
genesis                56     char buffer[50000];
genesis                57     int limit = sizeof(buffer);
genesis                58     va_list arg_ptr;
genesis                59     va_start(arg_ptr, format);
genesis                60     int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
genesis                61     va_end(arg_ptr);
genesis                62     if (ret < 0 || ret >= limit)
genesis                63     {
genesis                64         ret = limit - 1;
genesis                65         buffer[limit-1] = 0;
genesis                66     }
genesis                67     printf("%s", buffer);
genesis                68     fprintf(stdout, "%s", buffer);
genesis                69 }
genesis                70 
genesis                71 
genesis                72 int64 AmountFromValue(const Value& value)
genesis                73 {
genesis                74     double dAmount = value.get_real();
genesis                75     if (dAmount <= 0.0 || dAmount > 21000000.0)
genesis                76         throw JSONRPCError(-3, "Invalid amount");
genesis                77     int64 nAmount = roundint64(dAmount * COIN);
genesis                78     if (!MoneyRange(nAmount))
genesis                79         throw JSONRPCError(-3, "Invalid amount");
genesis                80     return nAmount;
genesis                81 }
genesis                82 
genesis                83 Value ValueFromAmount(int64 amount)
genesis                84 {
genesis                85     return (double)amount / (double)COIN;
genesis                86 }
genesis                87 
genesis                88 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
genesis                89 {
genesis                90     entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
genesis                91     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
genesis                92     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
genesis                93     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
genesis                94         entry.push_back(Pair(item.first, item.second));
genesis                95 }
genesis                96 
genesis                97 string AccountFromValue(const Value& value)
genesis                98 {
genesis                99     string strAccount = value.get_str();
genesis               100     if (strAccount == "*")
genesis               101         throw JSONRPCError(-11, "Invalid account name");
genesis               102     return strAccount;
genesis               103 }
genesis               104 
genesis               105 
genesis               106 
genesis               107 
genesis               108 
genesis               109 
genesis               110 
genesis               111 
genesis               112 Value help(const Array& params, bool fHelp)
genesis               113 {
genesis               114     if (fHelp || params.size() > 1)
genesis               115         throw runtime_error(
genesis               116             "help [command]\n"
genesis               117             "List commands, or get help for a command.");
genesis               118 
genesis               119     string strCommand;
genesis               120     if (params.size() > 0)
genesis               121         strCommand = params[0].get_str();
genesis               122 
genesis               123     string strRet;
genesis               124     set<rpcfn_type> setDone;
genesis               125     for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
genesis               126     {
genesis               127         string strMethod = (*mi).first;
genesis               128         
genesis               129         if (strMethod == "getamountreceived" ||
genesis               130             strMethod == "getallreceived" ||
genesis               131             strMethod == "getblocknumber" || 
genesis               132             (strMethod.find("label") != string::npos))
genesis               133             continue;
genesis               134         if (strCommand != "" && strMethod != strCommand)
genesis               135             continue;
genesis               136         try
genesis               137         {
genesis               138             Array params;
genesis               139             rpcfn_type pfn = (*mi).second;
genesis               140             if (setDone.insert(pfn).second)
genesis               141                 (*pfn)(params, true);
genesis               142         }
genesis               143         catch (std::exception& e)
genesis               144         {
genesis               145             
genesis               146             string strHelp = string(e.what());
genesis               147             if (strCommand == "")
genesis               148                 if (strHelp.find('\n') != -1)
genesis               149                     strHelp = strHelp.substr(0, strHelp.find('\n'));
genesis               150             strRet += strHelp + "\n";
genesis               151         }
genesis               152     }
genesis               153     if (strRet == "")
genesis               154         strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
genesis               155     strRet = strRet.substr(0,strRet.size()-1);
genesis               156     return strRet;
genesis               157 }
genesis               158 
genesis               159 
genesis               160 Value stop(const Array& params, bool fHelp)
genesis               161 {
genesis               162     if (fHelp || params.size() != 0)
genesis               163         throw runtime_error(
genesis               164             "stop\n"
genesis               165             "Stop bitcoin server.");
genesis               166     
genesis               167     CreateThread(Shutdown, NULL);
genesis               168     return "bitcoin server stopping";
genesis               169 }
genesis               170 
genesis               171 
genesis               172 Value getblockcount(const Array& params, bool fHelp)
genesis               173 {
genesis               174     if (fHelp || params.size() != 0)
genesis               175         throw runtime_error(
genesis               176             "getblockcount\n"
genesis               177             "Returns the number of blocks in the longest block chain.");
genesis               178 
genesis               179     return nBestHeight;
genesis               180 }
genesis               181 
genesis               182 
genesis               183 
genesis               184 Value getblocknumber(const Array& params, bool fHelp)
genesis               185 {
genesis               186     if (fHelp || params.size() != 0)
genesis               187         throw runtime_error(
genesis               188             "getblocknumber\n"
genesis               189             "Deprecated.  Use getblockcount.");
genesis               190 
genesis               191     return nBestHeight;
genesis               192 }
genesis               193 
genesis               194 
genesis               195 Value getconnectioncount(const Array& params, bool fHelp)
genesis               196 {
genesis               197     if (fHelp || params.size() != 0)
genesis               198         throw runtime_error(
genesis               199             "getconnectioncount\n"
genesis               200             "Returns the number of connections to other nodes.");
genesis               201 
genesis               202     return (int)vNodes.size();
genesis               203 }
genesis               204 
genesis               205 
genesis               206 double GetDifficulty()
genesis               207 {
genesis               208     
genesis               209     
genesis               210 
genesis               211     if (pindexBest == NULL)
genesis               212         return 1.0;
genesis               213     int nShift = (pindexBest->nBits >> 24) & 0xff;
genesis               214 
genesis               215     double dDiff =
genesis               216         (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
genesis               217 
genesis               218     while (nShift < 29)
genesis               219     {
genesis               220         dDiff *= 256.0;
genesis               221         nShift++;
genesis               222     }
genesis               223     while (nShift > 29)
genesis               224     {
genesis               225         dDiff /= 256.0;
genesis               226         nShift--;
genesis               227     }
genesis               228 
genesis               229     return dDiff;
genesis               230 }
genesis               231 
genesis               232 Value getdifficulty(const Array& params, bool fHelp)
genesis               233 {
genesis               234     if (fHelp || params.size() != 0)
genesis               235         throw runtime_error(
genesis               236             "getdifficulty\n"
genesis               237             "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
genesis               238 
genesis               239     return GetDifficulty();
genesis               240 }
genesis               241 
genesis               242 
genesis               243 Value getgenerate(const Array& params, bool fHelp)
genesis               244 {
genesis               245     if (fHelp || params.size() != 0)
genesis               246         throw runtime_error(
genesis               247             "getgenerate\n"
genesis               248             "Returns true or false.");
genesis               249 
genesis               250     return (bool)fGenerateBitcoins;
genesis               251 }
genesis               252 
genesis               253 
genesis               254 Value setgenerate(const Array& params, bool fHelp)
genesis               255 {
genesis               256     if (fHelp || params.size() < 1 || params.size() > 2)
genesis               257         throw runtime_error(
genesis               258             "setgenerate <generate> [genproclimit]\n"
genesis               259             "<generate> is true or false to turn generation on or off.\n"
genesis               260             "Generation is limited to [genproclimit] processors, -1 is unlimited.");
genesis               261 
genesis               262     bool fGenerate = true;
genesis               263     if (params.size() > 0)
genesis               264         fGenerate = params[0].get_bool();
genesis               265 
genesis               266     if (params.size() > 1)
genesis               267     {
genesis               268         int nGenProcLimit = params[1].get_int();
genesis               269         fLimitProcessors = (nGenProcLimit != -1);
genesis               270         WriteSetting("fLimitProcessors", fLimitProcessors);
genesis               271         if (nGenProcLimit != -1)
genesis               272             WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
genesis               273         if (nGenProcLimit == 0)
genesis               274             fGenerate = false;
genesis               275     }
genesis               276 
genesis               277     GenerateBitcoins(fGenerate, pwalletMain);
genesis               278     return Value::null;
genesis               279 }
genesis               280 
genesis               281 
genesis               282 Value gethashespersec(const Array& params, bool fHelp)
genesis               283 {
genesis               284     if (fHelp || params.size() != 0)
genesis               285         throw runtime_error(
genesis               286             "gethashespersec\n"
genesis               287             "Returns a recent hashes per second performance measurement while generating.");
genesis               288 
genesis               289     if (GetTimeMillis() - nHPSTimerStart > 8000)
genesis               290         return (boost::int64_t)0;
genesis               291     return (boost::int64_t)dHashesPerSec;
genesis               292 }
genesis               293 
genesis               294 
genesis               295 Value getinfo(const Array& params, bool fHelp)
genesis               296 {
genesis               297     if (fHelp || params.size() != 0)
genesis               298         throw runtime_error(
genesis               299             "getinfo\n"
genesis               300             "Returns an object containing various state info.");
genesis               301 
genesis               302     Object obj;
genesis               303     obj.push_back(Pair("version",       (int)VERSION));
genesis               304     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
genesis               305     obj.push_back(Pair("blocks",        (int)nBestHeight));
genesis               306     obj.push_back(Pair("connections",   (int)vNodes.size()));
genesis               307     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
genesis               308     obj.push_back(Pair("generate",      (bool)fGenerateBitcoins));
genesis               309     obj.push_back(Pair("genproclimit",  (int)(fLimitProcessors ? nLimitProcessors : -1)));
genesis               310     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
genesis               311     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
genesis               312     obj.push_back(Pair("testnet",       fTestNet));
genesis               313     obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
genesis               314     obj.push_back(Pair("keypoolsize",   pwalletMain->GetKeyPoolSize()));
genesis               315     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
genesis               316     if (pwalletMain->IsCrypted())
genesis               317         obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
genesis               318     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
genesis               319     return obj;
genesis               320 }
genesis               321 
genesis               322 
genesis               323 Value getnewaddress(const Array& params, bool fHelp)
genesis               324 {
genesis               325     if (fHelp || params.size() > 1)
genesis               326         throw runtime_error(
genesis               327             "getnewaddress [account]\n"
genesis               328             "Returns a new bitcoin address for receiving payments.  "
genesis               329             "If [account] is specified (recommended), it is added to the address book "
genesis               330             "so payments received with the address will be credited to [account].");
genesis               331 
genesis               332     
genesis               333     string strAccount;
genesis               334     if (params.size() > 0)
genesis               335         strAccount = AccountFromValue(params[0]);
genesis               336 
genesis               337     if (!pwalletMain->IsLocked())
genesis               338         pwalletMain->TopUpKeyPool();
genesis               339 
genesis               340     
genesis               341     std::vector<unsigned char> newKey;
genesis               342     if (!pwalletMain->GetKeyFromPool(newKey, false))
genesis               343         throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
genesis               344     CBitcoinAddress address(newKey);
genesis               345 
genesis               346     pwalletMain->SetAddressBookName(address, strAccount);
genesis               347 
genesis               348     return address.ToString();
genesis               349 }
genesis               350 
genesis               351 
genesis               352 CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
genesis               353 {
genesis               354     CWalletDB walletdb(pwalletMain->strWalletFile);
genesis               355 
genesis               356     CAccount account;
genesis               357     walletdb.ReadAccount(strAccount, account);
genesis               358 
genesis               359     bool bKeyUsed = false;
genesis               360 
genesis               361     
genesis               362     if (!account.vchPubKey.empty())
genesis               363     {
genesis               364         CScript scriptPubKey;
genesis               365         scriptPubKey.SetBitcoinAddress(account.vchPubKey);
genesis               366         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
genesis               367              it != pwalletMain->mapWallet.end() && !account.vchPubKey.empty();
genesis               368              ++it)
genesis               369         {
genesis               370             const CWalletTx& wtx = (*it).second;
genesis               371             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
genesis               372                 if (txout.scriptPubKey == scriptPubKey)
genesis               373                     bKeyUsed = true;
genesis               374         }
genesis               375     }
genesis               376 
genesis               377     
genesis               378     if (account.vchPubKey.empty() || bForceNew || bKeyUsed)
genesis               379     {
genesis               380         if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false))
genesis               381             throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first");
genesis               382 
genesis               383         pwalletMain->SetAddressBookName(CBitcoinAddress(account.vchPubKey), strAccount);
genesis               384         walletdb.WriteAccount(strAccount, account);
genesis               385     }
genesis               386 
genesis               387     return CBitcoinAddress(account.vchPubKey);
genesis               388 }
genesis               389 
genesis               390 Value getaccountaddress(const Array& params, bool fHelp)
genesis               391 {
genesis               392     if (fHelp || params.size() != 1)
genesis               393         throw runtime_error(
genesis               394             "getaccountaddress <account>\n"
genesis               395             "Returns the current bitcoin address for receiving payments to this account.");
genesis               396 
genesis               397     
genesis               398     string strAccount = AccountFromValue(params[0]);
genesis               399 
genesis               400     Value ret;
genesis               401 
genesis               402     ret = GetAccountAddress(strAccount).ToString();
genesis               403 
genesis               404     return ret;
genesis               405 }
genesis               406 
genesis               407 
genesis               408 
genesis               409 Value setaccount(const Array& params, bool fHelp)
genesis               410 {
genesis               411     if (fHelp || params.size() < 1 || params.size() > 2)
genesis               412         throw runtime_error(
genesis               413             "setaccount <bitcoinaddress> <account>\n"
genesis               414             "Sets the account associated with the given address.");
genesis               415 
genesis               416     CBitcoinAddress address(params[0].get_str());
genesis               417     if (!address.IsValid())
genesis               418         throw JSONRPCError(-5, "Invalid bitcoin address");
genesis               419 
genesis               420 
genesis               421     string strAccount;
genesis               422     if (params.size() > 1)
genesis               423         strAccount = AccountFromValue(params[1]);
genesis               424 
genesis               425     
genesis               426     if (pwalletMain->mapAddressBook.count(address))
genesis               427     {
genesis               428         string strOldAccount = pwalletMain->mapAddressBook[address];
genesis               429         if (address == GetAccountAddress(strOldAccount))
genesis               430             GetAccountAddress(strOldAccount, true);
genesis               431     }
genesis               432 
genesis               433     pwalletMain->SetAddressBookName(address, strAccount);
genesis               434 
genesis               435     return Value::null;
genesis               436 }
genesis               437 
genesis               438 
genesis               439 Value getaccount(const Array& params, bool fHelp)
genesis               440 {
genesis               441     if (fHelp || params.size() != 1)
genesis               442         throw runtime_error(
genesis               443             "getaccount <bitcoinaddress>\n"
genesis               444             "Returns the account associated with the given address.");
genesis               445 
genesis               446     CBitcoinAddress address(params[0].get_str());
genesis               447     if (!address.IsValid())
genesis               448         throw JSONRPCError(-5, "Invalid bitcoin address");
genesis               449 
genesis               450     string strAccount;
genesis               451     map<CBitcoinAddress, string>::iterator mi = pwalletMain->mapAddressBook.find(address);
genesis               452     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.empty())
genesis               453         strAccount = (*mi).second;
genesis               454     return strAccount;
genesis               455 }
genesis               456 
genesis               457 
genesis               458 Value getaddressesbyaccount(const Array& params, bool fHelp)
genesis               459 {
genesis               460     if (fHelp || params.size() != 1)
genesis               461         throw runtime_error(
genesis               462             "getaddressesbyaccount <account>\n"
genesis               463             "Returns the list of addresses for the given account.");
genesis               464 
genesis               465     string strAccount = AccountFromValue(params[0]);
genesis               466 
genesis               467     
genesis               468     Array ret;
genesis               469     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
genesis               470     {
genesis               471         const CBitcoinAddress& address = item.first;
genesis               472         const string& strName = item.second;
genesis               473         if (strName == strAccount)
genesis               474             ret.push_back(address.ToString());
genesis               475     }
genesis               476     return ret;
genesis               477 }
genesis               478 
genesis               479 Value settxfee(const Array& params, bool fHelp)
genesis               480 {
genesis               481     if (fHelp || params.size() < 1 || params.size() > 1)
genesis               482         throw runtime_error(
genesis               483             "settxfee <amount>\n"
genesis               484             "<amount> is a real and is rounded to the nearest 0.00000001");
genesis               485 
genesis               486     
genesis               487     int64 nAmount = 0;
genesis               488     if (params[0].get_real() != 0.0)
genesis               489         nAmount = AmountFromValue(params[0]);        
genesis               490 
genesis               491     nTransactionFee = nAmount;
genesis               492     return true;
genesis               493 }
genesis               494 
genesis               495 Value sendtoaddress(const Array& params, bool fHelp)
genesis               496 {
genesis               497     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
genesis               498         throw runtime_error(
genesis               499             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
genesis               500             "<amount> is a real and is rounded to the nearest 0.00000001\n"
genesis               501             "requires wallet passphrase to be set with walletpassphrase first");
genesis               502     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
genesis               503         throw runtime_error(
genesis               504             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
genesis               505             "<amount> is a real and is rounded to the nearest 0.00000001");
genesis               506 
genesis               507     CBitcoinAddress address(params[0].get_str());
genesis               508     if (!address.IsValid())
genesis               509         throw JSONRPCError(-5, "Invalid bitcoin address");
genesis               510 
genesis               511     
genesis               512     int64 nAmount = AmountFromValue(params[1]);
genesis               513 
genesis               514     
genesis               515     CWalletTx wtx;
genesis               516     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
genesis               517         wtx.mapValue["comment"] = params[2].get_str();
genesis               518     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
genesis               519         wtx.mapValue["to"]      = params[3].get_str();
genesis               520 
genesis               521     if (pwalletMain->IsLocked())
genesis               522         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
genesis               523 
genesis               524     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
genesis               525     if (strError != "")
genesis               526         throw JSONRPCError(-4, strError);
genesis               527 
genesis               528     return wtx.GetHash().GetHex();
genesis               529 }
genesis               530 
genesis               531 static const string strMessageMagic = "Bitcoin Signed Message:\n";
genesis               532 
genesis               533 Value signmessage(const Array& params, bool fHelp)
genesis               534 {
genesis               535     if (fHelp || params.size() != 2)
genesis               536         throw runtime_error(
genesis               537             "signmessage <bitcoinaddress> <message>\n"
genesis               538             "Sign a message with the private key of an address");
genesis               539 
genesis               540     if (pwalletMain->IsLocked())
genesis               541         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
genesis               542 
genesis               543     string strAddress = params[0].get_str();
genesis               544     string strMessage = params[1].get_str();
genesis               545 
genesis               546     CBitcoinAddress addr(strAddress);
genesis               547     if (!addr.IsValid())
genesis               548         throw JSONRPCError(-3, "Invalid address");
genesis               549 
genesis               550     CKey key;
genesis               551     if (!pwalletMain->GetKey(addr, key))
genesis               552         throw JSONRPCError(-4, "Private key not available");
genesis               553 
genesis               554     CDataStream ss(SER_GETHASH);
genesis               555     ss << strMessageMagic;
genesis               556     ss << strMessage;
genesis               557 
genesis               558     vector<unsigned char> vchSig;
genesis               559     if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig))
genesis               560         throw JSONRPCError(-5, "Sign failed");
genesis               561 
genesis               562     return EncodeBase64(&vchSig[0], vchSig.size());
genesis               563 }
genesis               564 
genesis               565 Value verifymessage(const Array& params, bool fHelp)
genesis               566 {
genesis               567     if (fHelp || params.size() != 3)
genesis               568         throw runtime_error(
genesis               569             "verifymessage <bitcoinaddress> <signature> <message>\n"
genesis               570             "Verify a signed message");
genesis               571 
genesis               572     string strAddress  = params[0].get_str();
genesis               573     string strSign     = params[1].get_str();
genesis               574     string strMessage  = params[2].get_str();
genesis               575 
genesis               576     CBitcoinAddress addr(strAddress);
genesis               577     if (!addr.IsValid())
genesis               578         throw JSONRPCError(-3, "Invalid address");
genesis               579 
genesis               580     bool fInvalid = false;
genesis               581     vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
genesis               582 
genesis               583     if (fInvalid)
genesis               584         throw JSONRPCError(-5, "Malformed base64 encoding");
genesis               585 
genesis               586     CDataStream ss(SER_GETHASH);
genesis               587     ss << strMessageMagic;
genesis               588     ss << strMessage;
genesis               589 
genesis               590     CKey key;
genesis               591     if (!key.SetCompactSignature(Hash(ss.begin(), ss.end()), vchSig))
genesis               592         return false;
genesis               593 
genesis               594     return (key.GetAddress() == addr);
genesis               595 }
genesis               596 
genesis               597 
genesis               598 Value getreceivedbyaddress(const Array& params, bool fHelp)
genesis               599 {
genesis               600     if (fHelp || params.size() < 1 || params.size() > 2)
genesis               601         throw runtime_error(
genesis               602             "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
genesis               603             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
genesis               604 
genesis               605     
genesis               606     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
genesis               607     CScript scriptPubKey;
genesis               608     if (!address.IsValid())
genesis               609         throw JSONRPCError(-5, "Invalid bitcoin address");
genesis               610     scriptPubKey.SetBitcoinAddress(address);
genesis               611     if (!IsMine(*pwalletMain,scriptPubKey))
genesis               612         return (double)0.0;
genesis               613 
genesis               614     
genesis               615     int nMinDepth = 1;
genesis               616     if (params.size() > 1)
genesis               617         nMinDepth = params[1].get_int();
genesis               618 
genesis               619     
genesis               620     int64 nAmount = 0;
genesis               621     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
genesis               622     {
genesis               623         const CWalletTx& wtx = (*it).second;
genesis               624         if (wtx.IsCoinBase() || !wtx.IsFinal())
genesis               625             continue;
genesis               626 
genesis               627         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
genesis               628             if (txout.scriptPubKey == scriptPubKey)
genesis               629                 if (wtx.GetDepthInMainChain() >= nMinDepth)
genesis               630                     nAmount += txout.nValue;
genesis               631     }
genesis               632 
genesis               633     return  ValueFromAmount(nAmount);
genesis               634 }
genesis               635 
genesis               636 
genesis               637 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
genesis               638 {
genesis               639     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
genesis               640     {
genesis               641         const CBitcoinAddress& address = item.first;
genesis               642         const string& strName = item.second;
genesis               643         if (strName == strAccount)
genesis               644             setAddress.insert(address);
genesis               645     }
genesis               646 }
genesis               647 
genesis               648 
genesis               649 Value getreceivedbyaccount(const Array& params, bool fHelp)
genesis               650 {
genesis               651     if (fHelp || params.size() < 1 || params.size() > 2)
genesis               652         throw runtime_error(
genesis               653             "getreceivedbyaccount <account> [minconf=1]\n"
genesis               654             "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
genesis               655 
genesis               656     
genesis               657     int nMinDepth = 1;
genesis               658     if (params.size() > 1)
genesis               659         nMinDepth = params[1].get_int();
genesis               660 
genesis               661     
genesis               662     string strAccount = AccountFromValue(params[0]);
genesis               663     set<CBitcoinAddress> setAddress;
genesis               664     GetAccountAddresses(strAccount, setAddress);
genesis               665 
genesis               666     
genesis               667     int64 nAmount = 0;
genesis               668     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
genesis               669     {
genesis               670         const CWalletTx& wtx = (*it).second;
genesis               671         if (wtx.IsCoinBase() || !wtx.IsFinal())
genesis               672             continue;
genesis               673 
genesis               674         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
genesis               675         {
genesis               676             CBitcoinAddress address;
genesis               677             if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
genesis               678                 if (wtx.GetDepthInMainChain() >= nMinDepth)
genesis               679                     nAmount += txout.nValue;
genesis               680         }
genesis               681     }
genesis               682 
genesis               683     return (double)nAmount / (double)COIN;
genesis               684 }
genesis               685 
genesis               686 
genesis               687 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
genesis               688 {
genesis               689     int64 nBalance = 0;
genesis               690 
genesis               691     
genesis               692     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
genesis               693     {
genesis               694         const CWalletTx& wtx = (*it).second;
genesis               695         if (!wtx.IsFinal())
genesis               696             continue;
genesis               697 
genesis               698         int64 nGenerated, nReceived, nSent, nFee;
genesis               699         wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
genesis               700 
genesis               701         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
genesis               702             nBalance += nReceived;
genesis               703         nBalance += nGenerated - nSent - nFee;
genesis               704     }
genesis               705 
genesis               706     
genesis               707     nBalance += walletdb.GetAccountCreditDebit(strAccount);
genesis               708 
genesis               709     return nBalance;
genesis               710 }
genesis               711 
genesis               712 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
genesis               713 {
genesis               714     CWalletDB walletdb(pwalletMain->strWalletFile);
genesis               715     return GetAccountBalance(walletdb, strAccount, nMinDepth);
genesis               716 }
genesis               717 
genesis               718 
genesis               719 Value getbalance(const Array& params, bool fHelp)
genesis               720 {
genesis               721     if (fHelp || params.size() > 2)
genesis               722         throw runtime_error(
genesis               723             "getbalance [account] [minconf=1]\n"
genesis               724             "If [account] is not specified, returns the server's total available balance.\n"
genesis               725             "If [account] is specified, returns the balance in the account.");
genesis               726 
genesis               727     if (params.size() == 0)
genesis               728         return  ValueFromAmount(pwalletMain->GetBalance());
genesis               729 
genesis               730     int nMinDepth = 1;
genesis               731     if (params.size() > 1)
genesis               732         nMinDepth = params[1].get_int();
genesis               733 
genesis               734     if (params[0].get_str() == "*") {
genesis               735         
genesis               736         
genesis               737         
genesis               738         int64 nBalance = 0;
genesis               739         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
genesis               740         {
genesis               741             const CWalletTx& wtx = (*it).second;
genesis               742             if (!wtx.IsFinal())
genesis               743                 continue;
genesis               744 
genesis               745             int64 allGeneratedImmature, allGeneratedMature, allFee;
genesis               746             allGeneratedImmature = allGeneratedMature = allFee = 0;
genesis               747             string strSentAccount;
genesis               748             list<pair<CBitcoinAddress, int64> > listReceived;
genesis               749             list<pair<CBitcoinAddress, int64> > listSent;
genesis               750             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
genesis               751             if (wtx.GetDepthInMainChain() >= nMinDepth)
genesis               752                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
genesis               753                     nBalance += r.second;
genesis               754             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
genesis               755                 nBalance -= r.second;
genesis               756             nBalance -= allFee;
genesis               757             nBalance += allGeneratedMature;
genesis               758         }
genesis               759         return  ValueFromAmount(nBalance);
genesis               760     }
genesis               761 
genesis               762     string strAccount = AccountFromValue(params[0]);
genesis               763 
genesis               764     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
genesis               765 
genesis               766     return ValueFromAmount(nBalance);
genesis               767 }
genesis               768 
genesis               769 
genesis               770 Value movecmd(const Array& params, bool fHelp)
genesis               771 {
genesis               772     if (fHelp || params.size() < 3 || params.size() > 5)
genesis               773         throw runtime_error(
genesis               774             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
genesis               775             "Move from one account in your wallet to another.");
genesis               776 
genesis               777     string strFrom = AccountFromValue(params[0]);
genesis               778     string strTo = AccountFromValue(params[1]);
genesis               779     int64 nAmount = AmountFromValue(params[2]);
genesis               780     if (params.size() > 3)
genesis               781         
genesis               782         (void)params[3].get_int();
genesis               783     string strComment;
genesis               784     if (params.size() > 4)
genesis               785         strComment = params[4].get_str();
genesis               786 
genesis               787     CWalletDB walletdb(pwalletMain->strWalletFile);
genesis               788     walletdb.TxnBegin();
genesis               789 
genesis               790     int64 nNow = GetAdjustedTime();
genesis               791 
genesis               792     
genesis               793     CAccountingEntry debit;
genesis               794     debit.strAccount = strFrom;
genesis               795     debit.nCreditDebit = -nAmount;
genesis               796     debit.nTime = nNow;
genesis               797     debit.strOtherAccount = strTo;
genesis               798     debit.strComment = strComment;
genesis               799     walletdb.WriteAccountingEntry(debit);
genesis               800 
genesis               801     
genesis               802     CAccountingEntry credit;
genesis               803     credit.strAccount = strTo;
genesis               804     credit.nCreditDebit = nAmount;
genesis               805     credit.nTime = nNow;
genesis               806     credit.strOtherAccount = strFrom;
genesis               807     credit.strComment = strComment;
genesis               808     walletdb.WriteAccountingEntry(credit);
genesis               809 
genesis               810     walletdb.TxnCommit();
genesis               811 
genesis               812     return true;
genesis               813 }
genesis               814 
genesis               815 
genesis               816 Value sendfrom(const Array& params, bool fHelp)
genesis               817 {
genesis               818     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
genesis               819         throw runtime_error(
genesis               820             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
genesis               821             "<amount> is a real and is rounded to the nearest 0.00000001\n"
genesis               822             "requires wallet passphrase to be set with walletpassphrase first");
genesis               823     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
genesis               824         throw runtime_error(
genesis               825             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
genesis               826             "<amount> is a real and is rounded to the nearest 0.00000001");
genesis               827 
genesis               828     string strAccount = AccountFromValue(params[0]);
genesis               829     CBitcoinAddress address(params[1].get_str());
genesis               830     if (!address.IsValid())
genesis               831         throw JSONRPCError(-5, "Invalid bitcoin address");
genesis               832     int64 nAmount = AmountFromValue(params[2]);
genesis               833     int nMinDepth = 1;
genesis               834     if (params.size() > 3)
genesis               835         nMinDepth = params[3].get_int();
genesis               836 
genesis               837     CWalletTx wtx;
genesis               838     wtx.strFromAccount = strAccount;
genesis               839     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
genesis               840         wtx.mapValue["comment"] = params[4].get_str();
genesis               841     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
genesis               842         wtx.mapValue["to"]      = params[5].get_str();
genesis               843 
genesis               844     if (pwalletMain->IsLocked())
genesis               845         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
genesis               846 
genesis               847     
genesis               848     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
genesis               849     if (nAmount > nBalance)
genesis               850         throw JSONRPCError(-6, "Account has insufficient funds");
genesis               851 
genesis               852     
genesis               853     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
genesis               854     if (strError != "")
genesis               855         throw JSONRPCError(-4, strError);
genesis               856 
genesis               857     return wtx.GetHash().GetHex();
genesis               858 }
genesis               859 
genesis               860 
genesis               861 Value sendmany(const Array& params, bool fHelp)
genesis               862 {
genesis               863     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
genesis               864         throw runtime_error(
genesis               865             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
genesis               866             "amounts are double-precision floating point numbers\n"
genesis               867             "requires wallet passphrase to be set with walletpassphrase first");
genesis               868     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
genesis               869         throw runtime_error(
genesis               870             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
genesis               871             "amounts are double-precision floating point numbers");
genesis               872 
genesis               873     string strAccount = AccountFromValue(params[0]);
genesis               874     Object sendTo = params[1].get_obj();
genesis               875     int nMinDepth = 1;
genesis               876     if (params.size() > 2)
genesis               877         nMinDepth = params[2].get_int();
genesis               878 
genesis               879     CWalletTx wtx;
genesis               880     wtx.strFromAccount = strAccount;
genesis               881     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
genesis               882         wtx.mapValue["comment"] = params[3].get_str();
genesis               883 
genesis               884     set<CBitcoinAddress> setAddress;
genesis               885     vector<pair<CScript, int64> > vecSend;
genesis               886 
genesis               887     int64 totalAmount = 0;
genesis               888     BOOST_FOREACH(const Pair& s, sendTo)
genesis               889     {
genesis               890         CBitcoinAddress address(s.name_);
genesis               891         if (!address.IsValid())
genesis               892             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
genesis               893 
genesis               894         if (setAddress.count(address))
genesis               895             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
genesis               896         setAddress.insert(address);
genesis               897 
genesis               898         CScript scriptPubKey;
genesis               899         scriptPubKey.SetBitcoinAddress(address);
genesis               900         int64 nAmount = AmountFromValue(s.value_); 
genesis               901         totalAmount += nAmount;
genesis               902 
genesis               903         vecSend.push_back(make_pair(scriptPubKey, nAmount));
genesis               904     }
genesis               905 
genesis               906     if (pwalletMain->IsLocked())
genesis               907         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
genesis               908 
genesis               909     
genesis               910     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
genesis               911     if (totalAmount > nBalance)
genesis               912         throw JSONRPCError(-6, "Account has insufficient funds");
genesis               913 
genesis               914     
genesis               915     CReserveKey keyChange(pwalletMain);
genesis               916     int64 nFeeRequired = 0;
genesis               917     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
genesis               918     if (!fCreated)
genesis               919     {
genesis               920         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
genesis               921             throw JSONRPCError(-6, "Insufficient funds");
genesis               922         throw JSONRPCError(-4, "Transaction creation failed");
genesis               923     }
genesis               924     if (!pwalletMain->CommitTransaction(wtx, keyChange))
genesis               925         throw JSONRPCError(-4, "Transaction commit failed");
genesis               926 
genesis               927     return wtx.GetHash().GetHex();
genesis               928 }
genesis               929 
genesis               930 
genesis               931 struct tallyitem
genesis               932 {
genesis               933     int64 nAmount;
genesis               934     int nConf;
genesis               935     tallyitem()
genesis               936     {
genesis               937         nAmount = 0;
genesis               938         nConf = INT_MAX;
genesis               939     }
genesis               940 };
genesis               941 
genesis               942 Value ListReceived(const Array& params, bool fByAccounts)
genesis               943 {
genesis               944     
genesis               945     int nMinDepth = 1;
genesis               946     if (params.size() > 0)
genesis               947         nMinDepth = params[0].get_int();
genesis               948 
genesis               949     
genesis               950     bool fIncludeEmpty = false;
genesis               951     if (params.size() > 1)
genesis               952         fIncludeEmpty = params[1].get_bool();
genesis               953 
genesis               954     
genesis               955     map<CBitcoinAddress, tallyitem> mapTally;
genesis               956     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
genesis               957     {
genesis               958         const CWalletTx& wtx = (*it).second;
genesis               959         if (wtx.IsCoinBase() || !wtx.IsFinal())
genesis               960             continue;
genesis               961 
genesis               962         int nDepth = wtx.GetDepthInMainChain();
genesis               963         if (nDepth < nMinDepth)
genesis               964             continue;
genesis               965 
genesis               966         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
genesis               967         {
genesis               968             CBitcoinAddress address;
genesis               969             if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
genesis               970                 continue;
genesis               971 
genesis               972             tallyitem& item = mapTally[address];
genesis               973             item.nAmount += txout.nValue;
genesis               974             item.nConf = min(item.nConf, nDepth);
genesis               975         }
genesis               976     }
genesis               977 
genesis               978     
genesis               979     Array ret;
genesis               980     map<string, tallyitem> mapAccountTally;
genesis               981     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
genesis               982     {
genesis               983         const CBitcoinAddress& address = item.first;
genesis               984         const string& strAccount = item.second;
genesis               985         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
genesis               986         if (it == mapTally.end() && !fIncludeEmpty)
genesis               987             continue;
genesis               988 
genesis               989         int64 nAmount = 0;
genesis               990         int nConf = INT_MAX;
genesis               991         if (it != mapTally.end())
genesis               992         {
genesis               993             nAmount = (*it).second.nAmount;
genesis               994             nConf = (*it).second.nConf;
genesis               995         }
genesis               996 
genesis               997         if (fByAccounts)
genesis               998         {
genesis               999             tallyitem& item = mapAccountTally[strAccount];
genesis              1000             item.nAmount += nAmount;
genesis              1001             item.nConf = min(item.nConf, nConf);
genesis              1002         }
genesis              1003         else
genesis              1004         {
genesis              1005             Object obj;
genesis              1006             obj.push_back(Pair("address",       address.ToString()));
genesis              1007             obj.push_back(Pair("account",       strAccount));
genesis              1008             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
genesis              1009             obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
genesis              1010             ret.push_back(obj);
genesis              1011         }
genesis              1012     }
genesis              1013 
genesis              1014     if (fByAccounts)
genesis              1015     {
genesis              1016         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
genesis              1017         {
genesis              1018             int64 nAmount = (*it).second.nAmount;
genesis              1019             int nConf = (*it).second.nConf;
genesis              1020             Object obj;
genesis              1021             obj.push_back(Pair("account",       (*it).first));
genesis              1022             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
genesis              1023             obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
genesis              1024             ret.push_back(obj);
genesis              1025         }
genesis              1026     }
genesis              1027 
genesis              1028     return ret;
genesis              1029 }
genesis              1030 
genesis              1031 Value listreceivedbyaddress(const Array& params, bool fHelp)
genesis              1032 {
genesis              1033     if (fHelp || params.size() > 2)
genesis              1034         throw runtime_error(
genesis              1035             "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
genesis              1036             "[minconf] is the minimum number of confirmations before payments are included.\n"
genesis              1037             "[includeempty] whether to include addresses that haven't received any payments.\n"
genesis              1038             "Returns an array of objects containing:\n"
genesis              1039             "  \"address\" : receiving address\n"
genesis              1040             "  \"account\" : the account of the receiving address\n"
genesis              1041             "  \"amount\" : total amount received by the address\n"
genesis              1042             "  \"confirmations\" : number of confirmations of the most recent transaction included");
genesis              1043 
genesis              1044     return ListReceived(params, false);
genesis              1045 }
genesis              1046 
genesis              1047 Value listreceivedbyaccount(const Array& params, bool fHelp)
genesis              1048 {
genesis              1049     if (fHelp || params.size() > 2)
genesis              1050         throw runtime_error(
genesis              1051             "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
genesis              1052             "[minconf] is the minimum number of confirmations before payments are included.\n"
genesis              1053             "[includeempty] whether to include accounts that haven't received any payments.\n"
genesis              1054             "Returns an array of objects containing:\n"
genesis              1055             "  \"account\" : the account of the receiving addresses\n"
genesis              1056             "  \"amount\" : total amount received by addresses with this account\n"
genesis              1057             "  \"confirmations\" : number of confirmations of the most recent transaction included");
genesis              1058 
genesis              1059     return ListReceived(params, true);
genesis              1060 }
genesis              1061 
genesis              1062 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
genesis              1063 {
genesis              1064     int64 nGeneratedImmature, nGeneratedMature, nFee;
genesis              1065     string strSentAccount;
genesis              1066     list<pair<CBitcoinAddress, int64> > listReceived;
genesis              1067     list<pair<CBitcoinAddress, int64> > listSent;
genesis              1068     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
genesis              1069 
genesis              1070     bool fAllAccounts = (strAccount == string("*"));
genesis              1071 
genesis              1072     
genesis              1073     if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
genesis              1074     {
genesis              1075         Object entry;
genesis              1076         entry.push_back(Pair("account", string("")));
genesis              1077         if (nGeneratedImmature)
genesis              1078         {
genesis              1079             entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
genesis              1080             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
genesis              1081         }
genesis              1082         else
genesis              1083         {
genesis              1084             entry.push_back(Pair("category", "generate"));
genesis              1085             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
genesis              1086         }
genesis              1087         if (fLong)
genesis              1088             WalletTxToJSON(wtx, entry);
genesis              1089         ret.push_back(entry);
genesis              1090     }
genesis              1091 
genesis              1092     
genesis              1093     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
genesis              1094     {
genesis              1095         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
genesis              1096         {
genesis              1097             Object entry;
genesis              1098             entry.push_back(Pair("account", strSentAccount));
genesis              1099             entry.push_back(Pair("address", s.first.ToString()));
genesis              1100             entry.push_back(Pair("category", "send"));
genesis              1101             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
genesis              1102             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
genesis              1103             if (fLong)
genesis              1104                 WalletTxToJSON(wtx, entry);
genesis              1105             ret.push_back(entry);
genesis              1106         }
genesis              1107     }
genesis              1108 
genesis              1109     
genesis              1110     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
genesis              1111         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
genesis              1112         {
genesis              1113             string account;
genesis              1114             if (pwalletMain->mapAddressBook.count(r.first))
genesis              1115                 account = pwalletMain->mapAddressBook[r.first];
genesis              1116             if (fAllAccounts || (account == strAccount))
genesis              1117             {
genesis              1118                 Object entry;
genesis              1119                 entry.push_back(Pair("account", account));
genesis              1120                 entry.push_back(Pair("address", r.first.ToString()));
genesis              1121                 entry.push_back(Pair("category", "receive"));
genesis              1122                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
genesis              1123                 if (fLong)
genesis              1124                     WalletTxToJSON(wtx, entry);
genesis              1125                 ret.push_back(entry);
genesis              1126             }
genesis              1127         }
genesis              1128 }
genesis              1129 
genesis              1130 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
genesis              1131 {
genesis              1132     bool fAllAccounts = (strAccount == string("*"));
genesis              1133 
genesis              1134     if (fAllAccounts || acentry.strAccount == strAccount)
genesis              1135     {
genesis              1136         Object entry;
genesis              1137         entry.push_back(Pair("account", acentry.strAccount));
genesis              1138         entry.push_back(Pair("category", "move"));
genesis              1139         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
genesis              1140         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
genesis              1141         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
genesis              1142         entry.push_back(Pair("comment", acentry.strComment));
genesis              1143         ret.push_back(entry);
genesis              1144     }
genesis              1145 }
genesis              1146 
genesis              1147 Value listtransactions(const Array& params, bool fHelp)
genesis              1148 {
genesis              1149     if (fHelp || params.size() > 3)
genesis              1150         throw runtime_error(
genesis              1151             "listtransactions [account] [count=10] [from=0]\n"
genesis              1152             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
genesis              1153 
genesis              1154     string strAccount = "*";
genesis              1155     if (params.size() > 0)
genesis              1156         strAccount = params[0].get_str();
genesis              1157     int nCount = 10;
genesis              1158     if (params.size() > 1)
genesis              1159         nCount = params[1].get_int();
genesis              1160     int nFrom = 0;
genesis              1161     if (params.size() > 2)
genesis              1162         nFrom = params[2].get_int();
genesis              1163 
genesis              1164     Array ret;
genesis              1165     CWalletDB walletdb(pwalletMain->strWalletFile);
genesis              1166 
genesis              1167     
genesis              1168     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
genesis              1169     typedef multimap<int64, TxPair > TxItems;
genesis              1170     TxItems txByTime;
genesis              1171 
genesis              1172     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
genesis              1173     {
genesis              1174         CWalletTx* wtx = &((*it).second);
genesis              1175         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
genesis              1176     }
genesis              1177     list<CAccountingEntry> acentries;
genesis              1178     walletdb.ListAccountCreditDebit(strAccount, acentries);
genesis              1179     BOOST_FOREACH(CAccountingEntry& entry, acentries)
genesis              1180     {
genesis              1181         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
genesis              1182     }
genesis              1183 
genesis              1184     
genesis              1185     TxItems::reverse_iterator it = txByTime.rbegin();
genesis              1186     if (txByTime.size() > nFrom) std::advance(it, nFrom);
genesis              1187     for (; it != txByTime.rend(); ++it)
genesis              1188     {
genesis              1189         CWalletTx *const pwtx = (*it).second.first;
genesis              1190         if (pwtx != 0)
genesis              1191             ListTransactions(*pwtx, strAccount, 0, true, ret);
genesis              1192         CAccountingEntry *const pacentry = (*it).second.second;
genesis              1193         if (pacentry != 0)
genesis              1194             AcentryToJSON(*pacentry, strAccount, ret);
genesis              1195 
genesis              1196         if (ret.size() >= nCount) break;
genesis              1197     }
genesis              1198     
genesis              1199     
genesis              1200     
genesis              1201     if (ret.size() > nCount)
genesis              1202     {
genesis              1203         Array::iterator last = ret.begin();
genesis              1204         std::advance(last, nCount);
genesis              1205         ret.erase(last, ret.end());
genesis              1206     }
genesis              1207     std::reverse(ret.begin(), ret.end()); 
genesis              1208 
genesis              1209     return ret;
genesis              1210 }
genesis              1211 
genesis              1212 Value listaccounts(const Array& params, bool fHelp)
genesis              1213 {
genesis              1214     if (fHelp || params.size() > 1)
genesis              1215         throw runtime_error(
genesis              1216             "listaccounts [minconf=1]\n"
genesis              1217             "Returns Object that has account names as keys, account balances as values.");
genesis              1218 
genesis              1219     int nMinDepth = 1;
genesis              1220     if (params.size() > 0)
genesis              1221         nMinDepth = params[0].get_int();
genesis              1222 
genesis              1223     map<string, int64> mapAccountBalances;
genesis              1224     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
genesis              1225         if (pwalletMain->HaveKey(entry.first)) 
genesis              1226             mapAccountBalances[entry.second] = 0;
genesis              1227     }
genesis              1228 
genesis              1229     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
genesis              1230     {
genesis              1231         const CWalletTx& wtx = (*it).second;
genesis              1232         int64 nGeneratedImmature, nGeneratedMature, nFee;
genesis              1233         string strSentAccount;
genesis              1234         list<pair<CBitcoinAddress, int64> > listReceived;
genesis              1235         list<pair<CBitcoinAddress, int64> > listSent;
genesis              1236         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
genesis              1237         mapAccountBalances[strSentAccount] -= nFee;
genesis              1238         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
genesis              1239             mapAccountBalances[strSentAccount] -= s.second;
genesis              1240         if (wtx.GetDepthInMainChain() >= nMinDepth)
genesis              1241         {
genesis              1242             mapAccountBalances[""] += nGeneratedMature;
genesis              1243             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
genesis              1244                 if (pwalletMain->mapAddressBook.count(r.first))
genesis              1245                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
genesis              1246                 else
genesis              1247                     mapAccountBalances[""] += r.second;
genesis              1248         }
genesis              1249     }
genesis              1250 
genesis              1251     list<CAccountingEntry> acentries;
genesis              1252     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
genesis              1253     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
genesis              1254         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
genesis              1255 
genesis              1256     Object ret;
genesis              1257     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
genesis              1258         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
genesis              1259     }
genesis              1260     return ret;
genesis              1261 }
genesis              1262 
genesis              1263 Value listsinceblock(const Array& params, bool fHelp)
genesis              1264 {
genesis              1265     if (fHelp)
genesis              1266         throw runtime_error(
genesis              1267             "listsinceblock [blockid] [target-confirmations]\n"
genesis              1268             "Get all transactions in blocks since block [blockid], or all transactions if omitted");
genesis              1269 
genesis              1270     CBlockIndex *pindex = NULL;
genesis              1271     int target_confirms = 1;
genesis              1272 
genesis              1273     if (params.size() > 0)
genesis              1274     {
genesis              1275         uint256 blockId = 0;
genesis              1276 
genesis              1277         blockId.SetHex(params[0].get_str());
genesis              1278         pindex = CBlockLocator(blockId).GetBlockIndex();
genesis              1279     }
genesis              1280 
genesis              1281     if (params.size() > 1)
genesis              1282     {
genesis              1283         target_confirms = params[1].get_int();
genesis              1284 
genesis              1285         if (target_confirms < 1)
genesis              1286             throw JSONRPCError(-8, "Invalid parameter");
genesis              1287     }
genesis              1288 
genesis              1289     int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
genesis              1290 
genesis              1291     Array transactions;
genesis              1292 
genesis              1293     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
genesis              1294     {
genesis              1295         CWalletTx tx = (*it).second;
genesis              1296 
genesis              1297         if (depth == -1 || tx.GetDepthInMainChain() < depth)
genesis              1298             ListTransactions(tx, "*", 0, true, transactions);
genesis              1299     }
genesis              1300 
genesis              1301     uint256 lastblock;
genesis              1302 
genesis              1303     if (target_confirms == 1)
genesis              1304     {
genesis              1305         printf("oops!\n");
genesis              1306         lastblock = hashBestChain;
genesis              1307     }
genesis              1308     else
genesis              1309     {
genesis              1310         int target_height = pindexBest->nHeight + 1 - target_confirms;
genesis              1311 
genesis              1312         CBlockIndex *block;
genesis              1313         for (block = pindexBest;
genesis              1314              block && block->nHeight > target_height;
genesis              1315              block = block->pprev)  { }
genesis              1316 
genesis              1317         lastblock = block ? block->GetBlockHash() : 0;
genesis              1318     }
genesis              1319 
genesis              1320     Object ret;
genesis              1321     ret.push_back(Pair("transactions", transactions));
genesis              1322     ret.push_back(Pair("lastblock", lastblock.GetHex()));
genesis              1323 
genesis              1324     return ret;
genesis              1325 }
genesis              1326 
genesis              1327 Value gettransaction(const Array& params, bool fHelp)
genesis              1328 {
genesis              1329     if (fHelp || params.size() != 1)
genesis              1330         throw runtime_error(
genesis              1331             "gettransaction <txid>\n"
genesis              1332             "Get detailed information about <txid>");
genesis              1333 
genesis              1334     uint256 hash;
genesis              1335     hash.SetHex(params[0].get_str());
genesis              1336 
genesis              1337     Object entry;
genesis              1338 
genesis              1339     if (!pwalletMain->mapWallet.count(hash))
genesis              1340         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
genesis              1341     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
genesis              1342 
genesis              1343     int64 nCredit = wtx.GetCredit();
genesis              1344     int64 nDebit = wtx.GetDebit();
genesis              1345     int64 nNet = nCredit - nDebit;
genesis              1346     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
genesis              1347 
genesis              1348     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
genesis              1349     if (wtx.IsFromMe())
genesis              1350         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
genesis              1351 
genesis              1352     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
genesis              1353 
genesis              1354     Array details;
genesis              1355     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
genesis              1356     entry.push_back(Pair("details", details));
genesis              1357 
genesis              1358     return entry;
genesis              1359 }
genesis              1360 
genesis              1361 
genesis              1362 Value backupwallet(const Array& params, bool fHelp)
genesis              1363 {
genesis              1364     if (fHelp || params.size() != 1)
genesis              1365         throw runtime_error(
genesis              1366             "backupwallet <destination>\n"
genesis              1367             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
genesis              1368 
genesis              1369     string strDest = params[0].get_str();
genesis              1370     BackupWallet(*pwalletMain, strDest);
genesis              1371 
genesis              1372     return Value::null;
genesis              1373 }
genesis              1374 
genesis              1375 
genesis              1376 Value keypoolrefill(const Array& params, bool fHelp)
genesis              1377 {
genesis              1378     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
genesis              1379         throw runtime_error(
genesis              1380             "keypoolrefill\n"
genesis              1381             "Fills the keypool, requires wallet passphrase to be set.");
genesis              1382     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
genesis              1383         throw runtime_error(
genesis              1384             "keypoolrefill\n"
genesis              1385             "Fills the keypool.");
genesis              1386 
genesis              1387     if (pwalletMain->IsLocked())
genesis              1388         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
genesis              1389 
genesis              1390     pwalletMain->TopUpKeyPool();
genesis              1391 
genesis              1392     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
genesis              1393         throw JSONRPCError(-4, "Error refreshing keypool.");
genesis              1394 
genesis              1395     return Value::null;
genesis              1396 }
genesis              1397 
genesis              1398 
genesis              1399 void ThreadTopUpKeyPool(void* parg)
genesis              1400 {
genesis              1401     pwalletMain->TopUpKeyPool();
genesis              1402 }
genesis              1403 
genesis              1404 void ThreadCleanWalletPassphrase(void* parg)
genesis              1405 {
genesis              1406     int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
genesis              1407 
genesis              1408     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
genesis              1409 
genesis              1410     if (nWalletUnlockTime == 0)
genesis              1411     {
genesis              1412         nWalletUnlockTime = nMyWakeTime;
genesis              1413 
genesis              1414         do
genesis              1415         {
genesis              1416             if (nWalletUnlockTime==0)
genesis              1417                 break;
genesis              1418             int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
genesis              1419             if (nToSleep <= 0)
genesis              1420                 break;
genesis              1421 
genesis              1422             LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
genesis              1423             Sleep(nToSleep);
genesis              1424             ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
genesis              1425 
genesis              1426         } while(1);
genesis              1427 
genesis              1428         if (nWalletUnlockTime)
genesis              1429         {
genesis              1430             nWalletUnlockTime = 0;
genesis              1431             pwalletMain->Lock();
genesis              1432         }
genesis              1433     }
genesis              1434     else
genesis              1435     {
genesis              1436         if (nWalletUnlockTime < nMyWakeTime)
genesis              1437             nWalletUnlockTime = nMyWakeTime;
genesis              1438     }
genesis              1439 
genesis              1440     LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
genesis              1441 
genesis              1442     delete (int64*)parg;
genesis              1443 }
genesis              1444 
genesis              1445 Value walletpassphrase(const Array& params, bool fHelp)
genesis              1446 {
genesis              1447     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
genesis              1448         throw runtime_error(
genesis              1449             "walletpassphrase <passphrase> <timeout>\n"
genesis              1450             "Stores the wallet decryption key in memory for <timeout> seconds.");
genesis              1451     if (fHelp)
genesis              1452         return true;
genesis              1453     if (!pwalletMain->IsCrypted())
genesis              1454         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
genesis              1455 
genesis              1456     if (!pwalletMain->IsLocked())
genesis              1457         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
genesis              1458 
genesis              1459     
genesis              1460     SecureString strWalletPass;
genesis              1461     strWalletPass.reserve(100);
genesis              1462     
genesis              1463     
genesis              1464     strWalletPass = params[0].get_str().c_str();
genesis              1465 
genesis              1466     if (strWalletPass.length() > 0)
genesis              1467     {
genesis              1468         if (!pwalletMain->Unlock(strWalletPass))
genesis              1469             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
genesis              1470     }
genesis              1471     else
genesis              1472         throw runtime_error(
genesis              1473             "walletpassphrase <passphrase> <timeout>\n"
genesis              1474             "Stores the wallet decryption key in memory for <timeout> seconds.");
genesis              1475 
genesis              1476     CreateThread(ThreadTopUpKeyPool, NULL);
genesis              1477     int64* pnSleepTime = new int64(params[1].get_int64());
genesis              1478     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
genesis              1479 
genesis              1480     return Value::null;
genesis              1481 }
genesis              1482 
genesis              1483 
genesis              1484 Value walletpassphrasechange(const Array& params, bool fHelp)
genesis              1485 {
genesis              1486     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
genesis              1487         throw runtime_error(
genesis              1488             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
genesis              1489             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
genesis              1490     if (fHelp)
genesis              1491         return true;
genesis              1492     if (!pwalletMain->IsCrypted())
genesis              1493         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
genesis              1494 
genesis              1495     
genesis              1496     
genesis              1497     SecureString strOldWalletPass;
genesis              1498     strOldWalletPass.reserve(100);
genesis              1499     strOldWalletPass = params[0].get_str().c_str();
genesis              1500 
genesis              1501     SecureString strNewWalletPass;
genesis              1502     strNewWalletPass.reserve(100);
genesis              1503     strNewWalletPass = params[1].get_str().c_str();
genesis              1504 
genesis              1505     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
genesis              1506         throw runtime_error(
genesis              1507             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
genesis              1508             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
genesis              1509 
genesis              1510     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
genesis              1511         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
genesis              1512 
genesis              1513     return Value::null;
genesis              1514 }
genesis              1515 
genesis              1516 
genesis              1517 Value walletlock(const Array& params, bool fHelp)
genesis              1518 {
genesis              1519     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
genesis              1520         throw runtime_error(
genesis              1521             "walletlock\n"
genesis              1522             "Removes the wallet encryption key from memory, locking the wallet.\n"
genesis              1523             "After calling this method, you will need to call walletpassphrase again\n"
genesis              1524             "before being able to call any methods which require the wallet to be unlocked.");
genesis              1525     if (fHelp)
genesis              1526         return true;
genesis              1527     if (!pwalletMain->IsCrypted())
genesis              1528         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
genesis              1529 
genesis              1530     CRITICAL_BLOCK(cs_nWalletUnlockTime)
genesis              1531     {
genesis              1532         pwalletMain->Lock();
genesis              1533         nWalletUnlockTime = 0;
genesis              1534     }
genesis              1535 
genesis              1536     return Value::null;
genesis              1537 }
genesis              1538 
genesis              1539 
genesis              1540 Value encryptwallet(const Array& params, bool fHelp)
genesis              1541 {
genesis              1542     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
genesis              1543         throw runtime_error(
genesis              1544             "encryptwallet <passphrase>\n"
genesis              1545             "Encrypts the wallet with <passphrase>.");
genesis              1546     if (fHelp)
genesis              1547         return true;
genesis              1548     if (pwalletMain->IsCrypted())
genesis              1549         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
genesis              1550 
genesis              1551     
genesis              1552     
genesis              1553     SecureString strWalletPass;
genesis              1554     strWalletPass.reserve(100);
genesis              1555     strWalletPass = params[0].get_str().c_str();
genesis              1556 
genesis              1557     if (strWalletPass.length() < 1)
genesis              1558         throw runtime_error(
genesis              1559             "encryptwallet <passphrase>\n"
genesis              1560             "Encrypts the wallet with <passphrase>.");
genesis              1561 
genesis              1562     if (!pwalletMain->EncryptWallet(strWalletPass))
genesis              1563         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
genesis              1564 
genesis              1565     
genesis              1566     
genesis              1567     
genesis              1568     CreateThread(Shutdown, NULL);
genesis              1569     return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
genesis              1570 }
genesis              1571 
genesis              1572 
genesis              1573 Value validateaddress(const Array& params, bool fHelp)
genesis              1574 {
genesis              1575     if (fHelp || params.size() != 1)
genesis              1576         throw runtime_error(
genesis              1577             "validateaddress <bitcoinaddress>\n"
genesis              1578             "Return information about <bitcoinaddress>.");
genesis              1579 
genesis              1580     CBitcoinAddress address(params[0].get_str());
genesis              1581     bool isValid = address.IsValid();
genesis              1582 
genesis              1583     Object ret;
genesis              1584     ret.push_back(Pair("isvalid", isValid));
genesis              1585     if (isValid)
genesis              1586     {
genesis              1587         
genesis              1588         
genesis              1589         string currentAddress = address.ToString();
genesis              1590         ret.push_back(Pair("address", currentAddress));
genesis              1591         ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
genesis              1592         if (pwalletMain->mapAddressBook.count(address))
genesis              1593             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
genesis              1594     }
genesis              1595     return ret;
genesis              1596 }
genesis              1597 
genesis              1598 
genesis              1599 Value getwork(const Array& params, bool fHelp)
genesis              1600 {
genesis              1601     if (fHelp || params.size() > 1)
genesis              1602         throw runtime_error(
genesis              1603             "getwork [data]\n"
genesis              1604             "If [data] is not specified, returns formatted hash data to work on:\n"
genesis              1605             "  \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" 
genesis              1606             "  \"data\" : block data\n"
genesis              1607             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" 
genesis              1608             "  \"target\" : little endian hash target\n"
genesis              1609             "If [data] is specified, tries to solve the block and returns true if it was successful.");
genesis              1610 
genesis              1611     if (vNodes.empty())
genesis              1612         throw JSONRPCError(-9, "Bitcoin is not connected!");
genesis              1613 
genesis              1614     if (IsInitialBlockDownload())
genesis              1615         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
genesis              1616 
genesis              1617     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
genesis              1618     static mapNewBlock_t mapNewBlock;
genesis              1619     static vector<CBlock*> vNewBlock;
genesis              1620     static CReserveKey reservekey(pwalletMain);
genesis              1621 
genesis              1622     if (params.size() == 0)
genesis              1623     {
genesis              1624         
genesis              1625         static unsigned int nTransactionsUpdatedLast;
genesis              1626         static CBlockIndex* pindexPrev;
genesis              1627         static int64 nStart;
genesis              1628         static CBlock* pblock;
genesis              1629         if (pindexPrev != pindexBest ||
genesis              1630             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
genesis              1631         {
genesis              1632             if (pindexPrev != pindexBest)
genesis              1633             {
genesis              1634                 
genesis              1635                 mapNewBlock.clear();
genesis              1636                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
genesis              1637                     delete pblock;
genesis              1638                 vNewBlock.clear();
genesis              1639             }
genesis              1640             nTransactionsUpdatedLast = nTransactionsUpdated;
genesis              1641             pindexPrev = pindexBest;
genesis              1642             nStart = GetTime();
genesis              1643 
genesis              1644             
genesis              1645             pblock = CreateNewBlock(reservekey);
genesis              1646             if (!pblock)
genesis              1647                 throw JSONRPCError(-7, "Out of memory");
genesis              1648             vNewBlock.push_back(pblock);
genesis              1649         }
genesis              1650 
genesis              1651         
genesis              1652         pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
genesis              1653         pblock->nNonce = 0;
genesis              1654 
genesis              1655         
genesis              1656         static unsigned int nExtraNonce = 0;
genesis              1657         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
genesis              1658 
genesis              1659         
genesis              1660         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
genesis              1661 
genesis              1662         
genesis              1663         char pmidstate[32];
genesis              1664         char pdata[128];
genesis              1665         char phash1[64];
genesis              1666         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
genesis              1667 
genesis              1668         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
genesis              1669 
genesis              1670         Object result;
genesis              1671         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); 
genesis              1672         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
genesis              1673         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); 
genesis              1674         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
genesis              1675         return result;
genesis              1676     }
genesis              1677     else
genesis              1678     {
genesis              1679         
genesis              1680         vector<unsigned char> vchData = ParseHex(params[0].get_str());
genesis              1681         if (vchData.size() != 128)
genesis              1682             throw JSONRPCError(-8, "Invalid parameter");
genesis              1683         CBlock* pdata = (CBlock*)&vchData[0];
genesis              1684 
genesis              1685         
genesis              1686         for (int i = 0; i < 128/4; i++)
genesis              1687             ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
genesis              1688 
genesis              1689         
genesis              1690         if (!mapNewBlock.count(pdata->hashMerkleRoot))
genesis              1691             return false;
genesis              1692         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
genesis              1693 
genesis              1694         pblock->nTime = pdata->nTime;
genesis              1695         pblock->nNonce = pdata->nNonce;
genesis              1696         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
genesis              1697         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
genesis              1698 
genesis              1699         return CheckWork(pblock, *pwalletMain, reservekey);
genesis              1700     }
genesis              1701 }
genesis              1702 
genesis              1703 
genesis              1704 Value getmemorypool(const Array& params, bool fHelp)
genesis              1705 {
genesis              1706     if (fHelp || params.size() > 1)
genesis              1707         throw runtime_error(
genesis              1708             "getmemorypool [data]\n"
genesis              1709             "If [data] is not specified, returns data needed to construct a block to work on:\n"
genesis              1710             "  \"version\" : block version\n"
genesis              1711             "  \"previousblockhash\" : hash of current highest block\n"
genesis              1712             "  \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
genesis              1713             "  \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
genesis              1714             "  \"time\" : timestamp appropriate for next block\n"
genesis              1715             "  \"bits\" : compressed target of next block\n"
genesis              1716             "If [data] is specified, tries to solve the block and returns true if it was successful.");
genesis              1717 
genesis              1718     if (params.size() == 0)
genesis              1719     {
genesis              1720         if (vNodes.empty())
genesis              1721             throw JSONRPCError(-9, "Bitcoin is not connected!");
genesis              1722 
genesis              1723         if (IsInitialBlockDownload())
genesis              1724             throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
genesis              1725 
genesis              1726         static CReserveKey reservekey(pwalletMain);
genesis              1727 
genesis              1728         
genesis              1729         static unsigned int nTransactionsUpdatedLast;
genesis              1730         static CBlockIndex* pindexPrev;
genesis              1731         static int64 nStart;
genesis              1732         static CBlock* pblock;
genesis              1733         if (pindexPrev != pindexBest ||
genesis              1734             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
genesis              1735         {
genesis              1736             nTransactionsUpdatedLast = nTransactionsUpdated;
genesis              1737             pindexPrev = pindexBest;
genesis              1738             nStart = GetTime();
genesis              1739 
genesis              1740             
genesis              1741             if(pblock)
genesis              1742                 delete pblock;
genesis              1743             pblock = CreateNewBlock(reservekey);
genesis              1744             if (!pblock)
genesis              1745                 throw JSONRPCError(-7, "Out of memory");
genesis              1746         }
genesis              1747 
genesis              1748         
genesis              1749         pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
genesis              1750         pblock->nNonce = 0;
genesis              1751 
genesis              1752         Array transactions;
genesis              1753         BOOST_FOREACH(CTransaction tx, pblock->vtx) {
genesis              1754             if(tx.IsCoinBase())
genesis              1755                 continue;
genesis              1756 
genesis              1757             CDataStream ssTx;
genesis              1758             ssTx << tx;
genesis              1759 
genesis              1760             transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
genesis              1761         }
genesis              1762 
genesis              1763         Object result;
genesis              1764         result.push_back(Pair("version", pblock->nVersion));
genesis              1765         result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
genesis              1766         result.push_back(Pair("transactions", transactions));
genesis              1767         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
genesis              1768         result.push_back(Pair("time", (int64_t)pblock->nTime));
genesis              1769 
genesis              1770         union {
genesis              1771             int32_t nBits;
genesis              1772             char cBits[4];
genesis              1773         } uBits;
genesis              1774         uBits.nBits = htonl((int32_t)pblock->nBits);
genesis              1775         result.push_back(Pair("bits", HexStr(BEGIN(uBits.cBits), END(uBits.cBits))));
genesis              1776 
genesis              1777         return result;
genesis              1778     }
genesis              1779     else
genesis              1780     {
genesis              1781         
genesis              1782         CDataStream ssBlock(ParseHex(params[0].get_str()));
genesis              1783         CBlock pblock;
genesis              1784         ssBlock >> pblock;
genesis              1785 
genesis              1786         return ProcessBlock(NULL, &pblock);
genesis              1787     }
genesis              1788 }
genesis              1789 
genesis              1790 
genesis              1791 
genesis              1792 
genesis              1793 
genesis              1794 
genesis              1795 
genesis              1796 
genesis              1797 
genesis              1798 
genesis              1799 
genesis              1800 
genesis              1801 
genesis              1802 
genesis              1803 
genesis              1804 pair<string, rpcfn_type> pCallTable[] =
genesis              1805 {
genesis              1806     make_pair("help",                   &help),
genesis              1807     make_pair("stop",                   &stop),
genesis              1808     make_pair("getblockcount",          &getblockcount),
genesis              1809     make_pair("getblocknumber",         &getblocknumber),
genesis              1810     make_pair("getconnectioncount",     &getconnectioncount),
genesis              1811     make_pair("getdifficulty",          &getdifficulty),
genesis              1812     make_pair("getgenerate",            &getgenerate),
genesis              1813     make_pair("setgenerate",            &setgenerate),
genesis              1814     make_pair("gethashespersec",        &gethashespersec),
genesis              1815     make_pair("getinfo",                &getinfo),
genesis              1816     make_pair("getnewaddress",          &getnewaddress),
genesis              1817     make_pair("getaccountaddress",      &getaccountaddress),
genesis              1818     make_pair("setaccount",             &setaccount),
genesis              1819     make_pair("getaccount",             &getaccount),
genesis              1820     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
genesis              1821     make_pair("sendtoaddress",          &sendtoaddress),
genesis              1822     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
genesis              1823     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
genesis              1824     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
genesis              1825     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
genesis              1826     make_pair("backupwallet",           &backupwallet),
genesis              1827     make_pair("keypoolrefill",          &keypoolrefill),
genesis              1828     make_pair("walletpassphrase",       &walletpassphrase),
genesis              1829     make_pair("walletpassphrasechange", &walletpassphrasechange),
genesis              1830     make_pair("walletlock",             &walletlock),
genesis              1831     make_pair("encryptwallet",          &encryptwallet),
genesis              1832     make_pair("validateaddress",        &validateaddress),
genesis              1833     make_pair("getbalance",             &getbalance),
genesis              1834     make_pair("move",                   &movecmd),
genesis              1835     make_pair("sendfrom",               &sendfrom),
genesis              1836     make_pair("sendmany",               &sendmany),
genesis              1837     make_pair("gettransaction",         &gettransaction),
genesis              1838     make_pair("listtransactions",       &listtransactions),
genesis              1839     make_pair("signmessage",           &signmessage),
genesis              1840     make_pair("verifymessage",         &verifymessage),
genesis              1841     make_pair("getwork",                &getwork),
genesis              1842     make_pair("listaccounts",           &listaccounts),
genesis              1843     make_pair("settxfee",               &settxfee),
genesis              1844     make_pair("getmemorypool",          &getmemorypool),
genesis              1845     make_pair("listsinceblock",        &listsinceblock),
genesis              1846 };
genesis              1847 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
genesis              1848 
genesis              1849 string pAllowInSafeMode[] =
genesis              1850 {
genesis              1851     "help",
genesis              1852     "stop",
genesis              1853     "getblockcount",
genesis              1854     "getblocknumber",  
genesis              1855     "getconnectioncount",
genesis              1856     "getdifficulty",
genesis              1857     "getgenerate",
genesis              1858     "setgenerate",
genesis              1859     "gethashespersec",
genesis              1860     "getinfo",
genesis              1861     "getnewaddress",
genesis              1862     "getaccountaddress",
genesis              1863     "getaccount",
genesis              1864     "getaddressesbyaccount",
genesis              1865     "backupwallet",
genesis              1866     "keypoolrefill",
genesis              1867     "walletpassphrase",
genesis              1868     "walletlock",
genesis              1869     "validateaddress",
genesis              1870     "getwork",
genesis              1871     "getmemorypool",
genesis              1872 };
genesis              1873 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
genesis              1874 
genesis              1875 
genesis              1876 
genesis              1877 
genesis              1878 
genesis              1879 
genesis              1880 
genesis              1881 
genesis              1882 
genesis              1883 
genesis              1884 
genesis              1885 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
genesis              1886 {
genesis              1887     ostringstream s;
genesis              1888     s << "POST / HTTP/1.1\r\n"
genesis              1889       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
genesis              1890       << "Host: 127.0.0.1\r\n"
genesis              1891       << "Content-Type: application/json\r\n"
genesis              1892       << "Content-Length: " << strMsg.size() << "\r\n"
genesis              1893       << "Connection: close\r\n"
genesis              1894       << "Accept: application/json\r\n";
genesis              1895     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
genesis              1896         s << item.first << ": " << item.second << "\r\n";
genesis              1897     s << "\r\n" << strMsg;
genesis              1898 
genesis              1899     return s.str();
genesis              1900 }
genesis              1901 
genesis              1902 string rfc1123Time()
genesis              1903 {
genesis              1904     char buffer[64];
genesis              1905     time_t now;
genesis              1906     time(&now);
genesis              1907     struct tm* now_gmt = gmtime(&now);
genesis              1908     string locale(setlocale(LC_TIME, NULL));
genesis              1909     setlocale(LC_TIME, "C"); 
genesis              1910     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
genesis              1911     setlocale(LC_TIME, locale.c_str());
genesis              1912     return string(buffer);
genesis              1913 }
genesis              1914 
genesis              1915 static string HTTPReply(int nStatus, const string& strMsg)
genesis              1916 {
genesis              1917     if (nStatus == 401)
genesis              1918         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
genesis              1919             "Date: %s\r\n"
genesis              1920             "Server: bitcoin-json-rpc/%s\r\n"
genesis              1921             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
genesis              1922             "Content-Type: text/html\r\n"
genesis              1923             "Content-Length: 296\r\n"
genesis              1924             "\r\n"
genesis              1925             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
genesis              1926             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
genesis              1927             "<HTML>\r\n"
genesis              1928             "<HEAD>\r\n"
genesis              1929             "<TITLE>Error</TITLE>\r\n"
genesis              1930             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
genesis              1931             "</HEAD>\r\n"
genesis              1932             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
genesis              1933             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
genesis              1934     const char *cStatus;
genesis              1935          if (nStatus == 200) cStatus = "OK";
genesis              1936     else if (nStatus == 400) cStatus = "Bad Request";
genesis              1937     else if (nStatus == 403) cStatus = "Forbidden";
genesis              1938     else if (nStatus == 404) cStatus = "Not Found";
genesis              1939     else if (nStatus == 500) cStatus = "Internal Server Error";
genesis              1940     else cStatus = "";
genesis              1941     return strprintf(
genesis              1942             "HTTP/1.1 %d %s\r\n"
genesis              1943             "Date: %s\r\n"
genesis              1944             "Connection: close\r\n"
genesis              1945             "Content-Length: %d\r\n"
genesis              1946             "Content-Type: application/json\r\n"
genesis              1947             "Server: bitcoin-json-rpc/%s\r\n"
genesis              1948             "\r\n"
genesis              1949             "%s",
genesis              1950         nStatus,
genesis              1951         cStatus,
genesis              1952         rfc1123Time().c_str(),
genesis              1953         strMsg.size(),
genesis              1954         FormatFullVersion().c_str(),
genesis              1955         strMsg.c_str());
genesis              1956 }
genesis              1957 
genesis              1958 int ReadHTTPStatus(std::basic_istream<char>& stream)
genesis              1959 {
genesis              1960     string str;
genesis              1961     getline(stream, str);
genesis              1962     vector<string> vWords;
genesis              1963     boost::split(vWords, str, boost::is_any_of(" "));
genesis              1964     if (vWords.size() < 2)
genesis              1965         return 500;
genesis              1966     return atoi(vWords[1].c_str());
genesis              1967 }
genesis              1968 
genesis              1969 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
genesis              1970 {
genesis              1971     int nLen = 0;
genesis              1972     loop
genesis              1973     {
genesis              1974         string str;
genesis              1975         std::getline(stream, str);
genesis              1976         if (str.empty() || str == "\r")
genesis              1977             break;
genesis              1978         string::size_type nColon = str.find(":");
genesis              1979         if (nColon != string::npos)
genesis              1980         {
genesis              1981             string strHeader = str.substr(0, nColon);
genesis              1982             boost::trim(strHeader);
genesis              1983             boost::to_lower(strHeader);
genesis              1984             string strValue = str.substr(nColon+1);
genesis              1985             boost::trim(strValue);
genesis              1986             mapHeadersRet[strHeader] = strValue;
genesis              1987             if (strHeader == "content-length")
genesis              1988                 nLen = atoi(strValue.c_str());
genesis              1989         }
genesis              1990     }
genesis              1991     return nLen;
genesis              1992 }
genesis              1993 
genesis              1994 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
genesis              1995 {
genesis              1996     mapHeadersRet.clear();
genesis              1997     strMessageRet = "";
genesis              1998 
genesis              1999     
genesis              2000     int nStatus = ReadHTTPStatus(stream);
genesis              2001 
genesis              2002     
genesis              2003     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
genesis              2004     if (nLen < 0 || nLen > MAX_SIZE)
genesis              2005         return 500;
genesis              2006 
genesis              2007     
genesis              2008     if (nLen > 0)
genesis              2009     {
genesis              2010         vector<char> vch(nLen);
genesis              2011         stream.read(&vch[0], nLen);
genesis              2012         strMessageRet = string(vch.begin(), vch.end());
genesis              2013     }
genesis              2014 
genesis              2015     return nStatus;
genesis              2016 }
genesis              2017 
genesis              2018 bool HTTPAuthorized(map<string, string>& mapHeaders)
genesis              2019 {
genesis              2020     string strAuth = mapHeaders["authorization"];
genesis              2021     if (strAuth.substr(0,6) != "Basic ")
genesis              2022         return false;
genesis              2023     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
genesis              2024     string strUserPass = DecodeBase64(strUserPass64);
genesis              2025     return strUserPass == strRPCUserColonPass;
genesis              2026 }
genesis              2027 
genesis              2028 
genesis              2029 
genesis              2030 
genesis              2031 
genesis              2032 
genesis              2033 
genesis              2034 
genesis              2035 
genesis              2036 
genesis              2037 
genesis              2038 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
genesis              2039 {
genesis              2040     Object request;
genesis              2041     request.push_back(Pair("method", strMethod));
genesis              2042     request.push_back(Pair("params", params));
genesis              2043     request.push_back(Pair("id", id));
genesis              2044     return write_string(Value(request), false) + "\n";
genesis              2045 }
genesis              2046 
genesis              2047 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
genesis              2048 {
genesis              2049     Object reply;
genesis              2050     if (error.type() != null_type)
genesis              2051         reply.push_back(Pair("result", Value::null));
genesis              2052     else
genesis              2053         reply.push_back(Pair("result", result));
genesis              2054     reply.push_back(Pair("error", error));
genesis              2055     reply.push_back(Pair("id", id));
genesis              2056     return write_string(Value(reply), false) + "\n";
genesis              2057 }
genesis              2058 
genesis              2059 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
genesis              2060 {
genesis              2061     
genesis              2062     int nStatus = 500;
genesis              2063     int code = find_value(objError, "code").get_int();
genesis              2064     if (code == -32600) nStatus = 400;
genesis              2065     else if (code == -32601) nStatus = 404;
genesis              2066     string strReply = JSONRPCReply(Value::null, objError, id);
genesis              2067     stream << HTTPReply(nStatus, strReply) << std::flush;
genesis              2068 }
genesis              2069 
genesis              2070 bool ClientAllowed(const string& strAddress)
genesis              2071 {
genesis              2072     if (strAddress == asio::ip::address_v4::loopback().to_string())
genesis              2073         return true;
genesis              2074     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
genesis              2075     BOOST_FOREACH(string strAllow, vAllow)
genesis              2076         if (WildcardMatch(strAddress, strAllow))
genesis              2077             return true;
genesis              2078     return false;
genesis              2079 }
genesis              2080 
genesis              2081 #ifdef USE_SSL
genesis              2082 
genesis              2083 
genesis              2084 
genesis              2085 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
genesis              2086 public:
genesis              2087     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
genesis              2088     {
genesis              2089         fUseSSL = fUseSSLIn;
genesis              2090         fNeedHandshake = fUseSSLIn;
genesis              2091     }
genesis              2092 
genesis              2093     void handshake(ssl::stream_base::handshake_type role)
genesis              2094     {
genesis              2095         if (!fNeedHandshake) return;
genesis              2096         fNeedHandshake = false;
genesis              2097         stream.handshake(role);
genesis              2098     }
genesis              2099     std::streamsize read(char* s, std::streamsize n)
genesis              2100     {
genesis              2101         handshake(ssl::stream_base::server); 
genesis              2102         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
genesis              2103         return stream.next_layer().read_some(asio::buffer(s, n));
genesis              2104     }
genesis              2105     std::streamsize write(const char* s, std::streamsize n)
genesis              2106     {
genesis              2107         handshake(ssl::stream_base::client); 
genesis              2108         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
genesis              2109         return asio::write(stream.next_layer(), asio::buffer(s, n));
genesis              2110     }
genesis              2111     bool connect(const std::string& server, const std::string& port)
genesis              2112     {
genesis              2113         ip::tcp::resolver resolver(stream.get_io_service());
genesis              2114         ip::tcp::resolver::query query(server.c_str(), port.c_str());
genesis              2115         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
genesis              2116         ip::tcp::resolver::iterator end;
genesis              2117         boost::system::error_code error = asio::error::host_not_found;
genesis              2118         while (error && endpoint_iterator != end)
genesis              2119         {
genesis              2120             stream.lowest_layer().close();
genesis              2121             stream.lowest_layer().connect(*endpoint_iterator++, error);
genesis              2122         }
genesis              2123         if (error)
genesis              2124             return false;
genesis              2125         return true;
genesis              2126     }
genesis              2127 
genesis              2128 private:
genesis              2129     bool fNeedHandshake;
genesis              2130     bool fUseSSL;
genesis              2131     SSLStream& stream;
genesis              2132 };
genesis              2133 #endif
genesis              2134 
genesis              2135 void ThreadRPCServer(void* parg)
genesis              2136 {
genesis              2137     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
genesis              2138     try
genesis              2139     {
genesis              2140         vnThreadsRunning[4]++;
genesis              2141         ThreadRPCServer2(parg);
genesis              2142         vnThreadsRunning[4]--;
genesis              2143     }
genesis              2144     catch (std::exception& e) {
genesis              2145         vnThreadsRunning[4]--;
genesis              2146         PrintException(&e, "ThreadRPCServer()");
genesis              2147     } catch (...) {
genesis              2148         vnThreadsRunning[4]--;
genesis              2149         PrintException(NULL, "ThreadRPCServer()");
genesis              2150     }
genesis              2151     printf("ThreadRPCServer exiting\n");
genesis              2152 }
genesis              2153 
genesis              2154 void ThreadRPCServer2(void* parg)
genesis              2155 {
genesis              2156     printf("ThreadRPCServer started\n");
genesis              2157 
genesis              2158     strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
genesis              2159     if (strRPCUserColonPass == ":")
genesis              2160     {
genesis              2161         unsigned char rand_pwd[32];
genesis              2162         RAND_bytes(rand_pwd, 32);
genesis              2163         string strWhatAmI = "To use bitcoind";
genesis              2164         if (mapArgs.count("-server"))
genesis              2165             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
genesis              2166         else if (mapArgs.count("-daemon"))
genesis              2167             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
genesis              2168         PrintConsole(
genesis              2169             _("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
genesis              2170               "It is recommended you use the following random password:\n"
genesis              2171               "rpcuser=bitcoinrpc\n"
genesis              2172               "rpcpassword=%s\n"
genesis              2173               "(you do not need to remember this password)\n"
genesis              2174               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
genesis              2175                 strWhatAmI.c_str(),
genesis              2176                 GetConfigFile().c_str(),
genesis              2177                 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
genesis              2178         CreateThread(Shutdown, NULL);
genesis              2179         return;
genesis              2180     }
genesis              2181 
genesis              2182     bool fUseSSL = GetBoolArg("-rpcssl");
genesis              2183     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
genesis              2184 
genesis              2185     asio::io_service io_service;
genesis              2186     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
genesis              2187     ip::tcp::acceptor acceptor(io_service, endpoint);
genesis              2188 
genesis              2189     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
genesis              2190 
genesis              2191 #ifdef USE_SSL
genesis              2192     ssl::context context(io_service, ssl::context::sslv23);
genesis              2193     if (fUseSSL)
genesis              2194     {
genesis              2195         context.set_options(ssl::context::no_sslv2);
genesis              2196         filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
genesis              2197         if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
genesis              2198         if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
genesis              2199         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
genesis              2200         filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
genesis              2201         if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
genesis              2202         if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
genesis              2203         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
genesis              2204 
genesis              2205         string ciphers = GetArg("-rpcsslciphers",
genesis              2206                                          "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
genesis              2207         SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
genesis              2208     }
genesis              2209 #else
genesis              2210     if (fUseSSL)
genesis              2211         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
genesis              2212 #endif
genesis              2213 
genesis              2214     loop
genesis              2215     {
genesis              2216         
genesis              2217 #ifdef USE_SSL
genesis              2218         SSLStream sslStream(io_service, context);
genesis              2219         SSLIOStreamDevice d(sslStream, fUseSSL);
genesis              2220         iostreams::stream<SSLIOStreamDevice> stream(d);
genesis              2221 #else
genesis              2222         ip::tcp::iostream stream;
genesis              2223 #endif
genesis              2224 
genesis              2225         ip::tcp::endpoint peer;
genesis              2226         vnThreadsRunning[4]--;
genesis              2227 #ifdef USE_SSL
genesis              2228         acceptor.accept(sslStream.lowest_layer(), peer);
genesis              2229 #else
genesis              2230         acceptor.accept(*stream.rdbuf(), peer);
genesis              2231 #endif
genesis              2232         vnThreadsRunning[4]++;
genesis              2233         if (fShutdown)
genesis              2234             return;
genesis              2235 
genesis              2236         
genesis              2237         if (!ClientAllowed(peer.address().to_string()))
genesis              2238         {
genesis              2239             
genesis              2240             if (!fUseSSL)
genesis              2241                 stream << HTTPReply(403, "") << std::flush;
genesis              2242             continue;
genesis              2243         }
genesis              2244 
genesis              2245         map<string, string> mapHeaders;
genesis              2246         string strRequest;
genesis              2247 
genesis              2248         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
genesis              2249         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
genesis              2250         {   
genesis              2251             acceptor.cancel();
genesis              2252             printf("ThreadRPCServer ReadHTTP timeout\n");
genesis              2253             continue;
genesis              2254         }
genesis              2255 
genesis              2256         
genesis              2257         if (mapHeaders.count("authorization") == 0)
genesis              2258         {
genesis              2259             stream << HTTPReply(401, "") << std::flush;
genesis              2260             continue;
genesis              2261         }
genesis              2262         if (!HTTPAuthorized(mapHeaders))
genesis              2263         {
genesis              2264             printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
genesis              2265             
genesis              2266                If this results in a DOS the user really
genesis              2267                shouldn't have their RPC port exposed.*/
genesis              2268             if (mapArgs["-rpcpassword"].size() < 20)
genesis              2269                 Sleep(250);
genesis              2270 
genesis              2271             stream << HTTPReply(401, "") << std::flush;
genesis              2272             continue;
genesis              2273         }
genesis              2274 
genesis              2275         Value id = Value::null;
genesis              2276         try
genesis              2277         {
genesis              2278             
genesis              2279             Value valRequest;
genesis              2280             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
genesis              2281                 throw JSONRPCError(-32700, "Parse error");
genesis              2282             const Object& request = valRequest.get_obj();
genesis              2283 
genesis              2284             
genesis              2285             id = find_value(request, "id");
genesis              2286 
genesis              2287             
genesis              2288             Value valMethod = find_value(request, "method");
genesis              2289             if (valMethod.type() == null_type)
genesis              2290                 throw JSONRPCError(-32600, "Missing method");
genesis              2291             if (valMethod.type() != str_type)
genesis              2292                 throw JSONRPCError(-32600, "Method must be a string");
genesis              2293             string strMethod = valMethod.get_str();
genesis              2294             if (strMethod != "getwork" && strMethod != "getmemorypool")
genesis              2295                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
genesis              2296 
genesis              2297             
genesis              2298             Value valParams = find_value(request, "params");
genesis              2299             Array params;
genesis              2300             if (valParams.type() == array_type)
genesis              2301                 params = valParams.get_array();
genesis              2302             else if (valParams.type() == null_type)
genesis              2303                 params = Array();
genesis              2304             else
genesis              2305                 throw JSONRPCError(-32600, "Params must be an array");
genesis              2306 
genesis              2307             
genesis              2308             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
genesis              2309             if (mi == mapCallTable.end())
genesis              2310                 throw JSONRPCError(-32601, "Method not found");
genesis              2311 
genesis              2312             
genesis              2313             string strWarning = GetWarnings("rpc");
genesis              2314             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
genesis              2315                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
genesis              2316 
genesis              2317             try
genesis              2318             {
genesis              2319                 
genesis              2320                 Value result;
genesis              2321                 CRITICAL_BLOCK(cs_main)
genesis              2322                 CRITICAL_BLOCK(pwalletMain->cs_wallet)
genesis              2323                     result = (*(*mi).second)(params, false);
genesis              2324 
genesis              2325                 
genesis              2326                 string strReply = JSONRPCReply(result, Value::null, id);
genesis              2327                 stream << HTTPReply(200, strReply) << std::flush;
genesis              2328             }
genesis              2329             catch (std::exception& e)
genesis              2330             {
genesis              2331                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
genesis              2332             }
genesis              2333         }
genesis              2334         catch (Object& objError)
genesis              2335         {
genesis              2336             ErrorReply(stream, objError, id);
genesis              2337         }
genesis              2338         catch (std::exception& e)
genesis              2339         {
genesis              2340             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
genesis              2341         }
genesis              2342     }
genesis              2343 }
genesis              2344 
genesis              2345 
genesis              2346 
genesis              2347 
genesis              2348 Object CallRPC(const string& strMethod, const Array& params)
genesis              2349 {
genesis              2350     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
genesis              2351         throw runtime_error(strprintf(
genesis              2352             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
genesis              2353               "If the file does not exist, create it with owner-readable-only file permissions."),
genesis              2354                 GetConfigFile().c_str()));
genesis              2355 
genesis              2356     
genesis              2357     bool fUseSSL = GetBoolArg("-rpcssl");
genesis              2358 #ifdef USE_SSL
genesis              2359     asio::io_service io_service;
genesis              2360     ssl::context context(io_service, ssl::context::sslv23);
genesis              2361     context.set_options(ssl::context::no_sslv2);
genesis              2362     SSLStream sslStream(io_service, context);
genesis              2363     SSLIOStreamDevice d(sslStream, fUseSSL);
genesis              2364     iostreams::stream<SSLIOStreamDevice> stream(d);
genesis              2365     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
genesis              2366         throw runtime_error("couldn't connect to server");
genesis              2367 #else
genesis              2368     if (fUseSSL)
genesis              2369         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
genesis              2370 
genesis              2371     ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
genesis              2372     if (stream.fail())
genesis              2373         throw runtime_error("couldn't connect to server");
genesis              2374 #endif
genesis              2375 
genesis              2376 
genesis              2377     
genesis              2378     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
genesis              2379     map<string, string> mapRequestHeaders;
genesis              2380     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
genesis              2381 
genesis              2382     
genesis              2383     string strRequest = JSONRPCRequest(strMethod, params, 1);
genesis              2384     string strPost = HTTPPost(strRequest, mapRequestHeaders);
genesis              2385     stream << strPost << std::flush;
genesis              2386 
genesis              2387     
genesis              2388     map<string, string> mapHeaders;
genesis              2389     string strReply;
genesis              2390     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
genesis              2391     if (nStatus == 401)
genesis              2392         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
genesis              2393     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
genesis              2394         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
genesis              2395     else if (strReply.empty())
genesis              2396         throw runtime_error("no response from server");
genesis              2397 
genesis              2398     
genesis              2399     Value valReply;
genesis              2400     if (!read_string(strReply, valReply))
genesis              2401         throw runtime_error("couldn't parse reply from server");
genesis              2402     const Object& reply = valReply.get_obj();
genesis              2403     if (reply.empty())
genesis              2404         throw runtime_error("expected reply to have result, error and id properties");
genesis              2405 
genesis              2406     return reply;
genesis              2407 }
genesis              2408 
genesis              2409 
genesis              2410 
genesis              2411 
genesis              2412 template<typename T>
genesis              2413 void ConvertTo(Value& value)
genesis              2414 {
genesis              2415     if (value.type() == str_type)
genesis              2416     {
genesis              2417         
genesis              2418         Value value2;
genesis              2419         if (!read_string(value.get_str(), value2))
genesis              2420             throw runtime_error("type mismatch");
genesis              2421         value = value2.get_value<T>();
genesis              2422     }
genesis              2423     else
genesis              2424     {
genesis              2425         value = value.get_value<T>();
genesis              2426     }
genesis              2427 }
genesis              2428 
genesis              2429 int CommandLineRPC(int argc, char *argv[])
genesis              2430 {
genesis              2431     string strPrint;
genesis              2432     int nRet = 0;
genesis              2433     try
genesis              2434     {
genesis              2435         
genesis              2436         while (argc > 1 && IsSwitchChar(argv[1][0]))
genesis              2437         {
genesis              2438             argc--;
genesis              2439             argv++;
genesis              2440         }
genesis              2441 
genesis              2442         
genesis              2443         if (argc < 2)
genesis              2444             throw runtime_error("too few parameters");
genesis              2445         string strMethod = argv[1];
genesis              2446 
genesis              2447         
genesis              2448         Array params;
genesis              2449         for (int i = 2; i < argc; i++)
genesis              2450             params.push_back(argv[i]);
genesis              2451         int n = params.size();
genesis              2452 
genesis              2453         
genesis              2454         
genesis              2455         
genesis              2456         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
genesis              2457         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
genesis              2458         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
genesis              2459         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
genesis              2460         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
genesis              2461         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
genesis              2462         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
genesis              2463         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
genesis              2464         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
genesis              2465         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
genesis              2466         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
genesis              2467         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
genesis              2468         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
genesis              2469         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
genesis              2470         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
genesis              2471         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
genesis              2472         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
genesis              2473         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
genesis              2474         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
genesis              2475         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
genesis              2476         if (strMethod == "sendmany"               && n > 1)
genesis              2477         {
genesis              2478             string s = params[1].get_str();
genesis              2479             Value v;
genesis              2480             if (!read_string(s, v) || v.type() != obj_type)
genesis              2481                 throw runtime_error("type mismatch");
genesis              2482             params[1] = v.get_obj();
genesis              2483         }
genesis              2484         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
genesis              2485 
genesis              2486         
genesis              2487         Object reply = CallRPC(strMethod, params);
genesis              2488 
genesis              2489         
genesis              2490         const Value& result = find_value(reply, "result");
genesis              2491         const Value& error  = find_value(reply, "error");
genesis              2492 
genesis              2493         if (error.type() != null_type)
genesis              2494         {
genesis              2495             
genesis              2496             strPrint = "error: " + write_string(error, false);
genesis              2497             int code = find_value(error.get_obj(), "code").get_int();
genesis              2498             nRet = abs(code);
genesis              2499         }
genesis              2500         else
genesis              2501         {
genesis              2502             
genesis              2503             if (result.type() == null_type)
genesis              2504                 strPrint = "";
genesis              2505             else if (result.type() == str_type)
genesis              2506                 strPrint = result.get_str();
genesis              2507             else
genesis              2508                 strPrint = write_string(result, true);
genesis              2509         }
genesis              2510     }
genesis              2511     catch (std::exception& e)
genesis              2512     {
genesis              2513         strPrint = string("error: ") + e.what();
genesis              2514         nRet = 87;
genesis              2515     }
genesis              2516     catch (...)
genesis              2517     {
genesis              2518         PrintException(NULL, "CommandLineRPC()");
genesis              2519     }
genesis              2520 
genesis              2521     if (strPrint != "")
genesis              2522     {
genesis              2523         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
genesis              2524     }
genesis              2525     return nRet;
genesis              2526 }
genesis              2527 
genesis              2528 
genesis              2529 
genesis              2530 
genesis              2531 #ifdef TEST
genesis              2532 int main(int argc, char *argv[])
genesis              2533 {
genesis              2534 #ifdef _MSC_VER
genesis              2535     
genesis              2536     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
genesis              2537     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
genesis              2538 #endif
genesis              2539     setbuf(stdin, NULL);
genesis              2540     setbuf(stdout, NULL);
genesis              2541     setbuf(stderr, NULL);
genesis              2542 
genesis              2543     try
genesis              2544     {
genesis              2545         if (argc >= 2 && string(argv[1]) == "-server")
genesis              2546         {
genesis              2547             printf("server ready\n");
genesis              2548             ThreadRPCServer(NULL);
genesis              2549         }
genesis              2550         else
genesis              2551         {
genesis              2552             return CommandLineRPC(argc, argv);
genesis              2553         }
genesis              2554     }
genesis              2555     catch (std::exception& e) {
genesis              2556         PrintException(&e, "main()");
genesis              2557     } catch (...) {
genesis              2558         PrintException(NULL, "main()");
genesis              2559     }
genesis              2560     return 0;
genesis              2561 }
genesis              2562 #endif