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