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