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