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