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