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