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