Merge bitcoin v0.4.0 into ppcoin
[novacoin.git] / src / rpc.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "headers.h"
7 #include "cryptopp/sha.h"
8 #include "db.h"
9 #include "net.h"
10 #include "init.h"
11 #undef printf
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #ifdef USE_SSL
17 #include <boost/asio/ssl.hpp> 
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
21 #endif
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h.  The problem might be when the pch file goes over
28 // a certain size around 145MB.  If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
30
31 using namespace std;
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
35
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
39
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
42
43
44 Object JSONRPCError(int code, const string& message)
45 {
46     Object error;
47     error.push_back(Pair("code", code));
48     error.push_back(Pair("message", message));
49     return error;
50 }
51
52
53 void PrintConsole(const char* format, ...)
54 {
55     char buffer[50000];
56     int limit = sizeof(buffer);
57     va_list arg_ptr;
58     va_start(arg_ptr, format);
59     int ret = _vsnprintf(buffer, limit, format, arg_ptr);
60     va_end(arg_ptr);
61     if (ret < 0 || ret >= limit)
62     {
63         ret = limit - 1;
64         buffer[limit-1] = 0;
65     }
66     printf("%s", buffer);
67 #if defined(__WXMSW__) && defined(GUI)
68     MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
69 #else
70     fprintf(stdout, "%s", buffer);
71 #endif
72 }
73
74
75 int64 AmountFromValue(const Value& value)
76 {
77     double dAmount = value.get_real();
78     if (dAmount <= 0.0 || dAmount > MAX_MONEY)
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.0001\n"
487             "Minimum and default transaction fee is 1 coin");
488
489     // Amount
490     int64 nAmount = MIN_TX_FEE;
491     if (params[0].get_real() != 0.0)                    // rejects 0.0 amounts
492         nAmount = max(nAmount, AmountFromValue(params[0]));
493
494     nTransactionFee = nAmount;
495     return true;
496 }
497
498 Value sendtoaddress(const Array& params, bool fHelp)
499 {
500     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
501         throw runtime_error(
502             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
503             "<amount> is a real and is rounded to the nearest 0.00000001\n"
504             "requires wallet passphrase to be set with walletpassphrase first");
505     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
506         throw runtime_error(
507             "sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
508             "<amount> is a real and is rounded to the nearest 0.00000001");
509
510     CBitcoinAddress address(params[0].get_str());
511     if (!address.IsValid())
512         throw JSONRPCError(-5, "Invalid bitcoin address");
513
514     // Amount
515     int64 nAmount = AmountFromValue(params[1]);
516
517     // Wallet comments
518     CWalletTx wtx;
519     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
520         wtx.mapValue["comment"] = params[2].get_str();
521     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
522         wtx.mapValue["to"]      = params[3].get_str();
523
524     if (pwalletMain->IsLocked())
525         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
526
527     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
528     if (strError != "")
529         throw JSONRPCError(-4, strError);
530
531     return wtx.GetHash().GetHex();
532 }
533
534
535 Value getreceivedbyaddress(const Array& params, bool fHelp)
536 {
537     if (fHelp || params.size() < 1 || params.size() > 2)
538         throw runtime_error(
539             "getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
540             "Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
541
542     // Bitcoin address
543     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
544     CScript scriptPubKey;
545     if (!address.IsValid())
546         throw JSONRPCError(-5, "Invalid bitcoin address");
547     scriptPubKey.SetBitcoinAddress(address);
548     if (!IsMine(*pwalletMain,scriptPubKey))
549         return (double)0.0;
550
551     // Minimum confirmations
552     int nMinDepth = 1;
553     if (params.size() > 1)
554         nMinDepth = params[1].get_int();
555
556     // Tally
557     int64 nAmount = 0;
558     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
559     {
560         const CWalletTx& wtx = (*it).second;
561         if (wtx.IsCoinBase() || !wtx.IsFinal())
562             continue;
563
564         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
565             if (txout.scriptPubKey == scriptPubKey)
566                 if (wtx.GetDepthInMainChain() >= nMinDepth)
567                     nAmount += txout.nValue;
568     }
569
570     return  ValueFromAmount(nAmount);
571 }
572
573
574 void GetAccountAddresses(string strAccount, set<CBitcoinAddress>& setAddress)
575 {
576     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
577     {
578         const CBitcoinAddress& address = item.first;
579         const string& strName = item.second;
580         if (strName == strAccount)
581             setAddress.insert(address);
582     }
583 }
584
585
586 Value getreceivedbyaccount(const Array& params, bool fHelp)
587 {
588     if (fHelp || params.size() < 1 || params.size() > 2)
589         throw runtime_error(
590             "getreceivedbyaccount <account> [minconf=1]\n"
591             "Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.");
592
593     // Minimum confirmations
594     int nMinDepth = 1;
595     if (params.size() > 1)
596         nMinDepth = params[1].get_int();
597
598     // Get the set of pub keys that have the label
599     string strAccount = AccountFromValue(params[0]);
600     set<CBitcoinAddress> setAddress;
601     GetAccountAddresses(strAccount, setAddress);
602
603     // Tally
604     int64 nAmount = 0;
605     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
606     {
607         const CWalletTx& wtx = (*it).second;
608         if (wtx.IsCoinBase() || !wtx.IsFinal())
609             continue;
610
611         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
612         {
613             CBitcoinAddress address;
614             if (ExtractAddress(txout.scriptPubKey, pwalletMain, address) && setAddress.count(address))
615                 if (wtx.GetDepthInMainChain() >= nMinDepth)
616                     nAmount += txout.nValue;
617         }
618     }
619
620     return (double)nAmount / (double)COIN;
621 }
622
623
624 int64 GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth)
625 {
626     int64 nBalance = 0;
627
628     // Tally wallet transactions
629     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
630     {
631         const CWalletTx& wtx = (*it).second;
632         if (!wtx.IsFinal())
633             continue;
634
635         int64 nGenerated, nReceived, nSent, nFee;
636         wtx.GetAccountAmounts(strAccount, nGenerated, nReceived, nSent, nFee);
637
638         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
639             nBalance += nReceived;
640         nBalance += nGenerated - nSent - nFee;
641     }
642
643     // Tally internal accounting entries
644     nBalance += walletdb.GetAccountCreditDebit(strAccount);
645
646     return nBalance;
647 }
648
649 int64 GetAccountBalance(const string& strAccount, int nMinDepth)
650 {
651     CWalletDB walletdb(pwalletMain->strWalletFile);
652     return GetAccountBalance(walletdb, strAccount, nMinDepth);
653 }
654
655
656 Value getbalance(const Array& params, bool fHelp)
657 {
658     if (fHelp || params.size() > 2)
659         throw runtime_error(
660             "getbalance [account] [minconf=1]\n"
661             "If [account] is not specified, returns the server's total available balance.\n"
662             "If [account] is specified, returns the balance in the account.");
663
664     if (params.size() == 0)
665         return  ValueFromAmount(pwalletMain->GetBalance());
666
667     int nMinDepth = 1;
668     if (params.size() > 1)
669         nMinDepth = params[1].get_int();
670
671     if (params[0].get_str() == "*") {
672         // Calculate total balance a different way from GetBalance()
673         // (GetBalance() sums up all unspent TxOuts)
674         // getbalance and getbalance '*' should always return the same number.
675         int64 nBalance = 0;
676         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
677         {
678             const CWalletTx& wtx = (*it).second;
679             if (!wtx.IsFinal())
680                 continue;
681
682             int64 allGeneratedImmature, allGeneratedMature, allFee;
683             allGeneratedImmature = allGeneratedMature = allFee = 0;
684             string strSentAccount;
685             list<pair<CBitcoinAddress, int64> > listReceived;
686             list<pair<CBitcoinAddress, int64> > listSent;
687             wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
688             if (wtx.GetDepthInMainChain() >= nMinDepth)
689                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
690                     nBalance += r.second;
691             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
692                 nBalance -= r.second;
693             nBalance -= allFee;
694             nBalance += allGeneratedMature;
695         }
696         return  ValueFromAmount(nBalance);
697     }
698
699     string strAccount = AccountFromValue(params[0]);
700
701     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
702
703     return ValueFromAmount(nBalance);
704 }
705
706
707 Value movecmd(const Array& params, bool fHelp)
708 {
709     if (fHelp || params.size() < 3 || params.size() > 5)
710         throw runtime_error(
711             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
712             "Move from one account in your wallet to another.");
713
714     string strFrom = AccountFromValue(params[0]);
715     string strTo = AccountFromValue(params[1]);
716     int64 nAmount = AmountFromValue(params[2]);
717     if (params.size() > 3)
718         // unused parameter, used to be nMinDepth, keep type-checking it though
719         (void)params[3].get_int();
720     string strComment;
721     if (params.size() > 4)
722         strComment = params[4].get_str();
723
724     CWalletDB walletdb(pwalletMain->strWalletFile);
725     walletdb.TxnBegin();
726
727     int64 nNow = GetAdjustedTime();
728
729     // Debit
730     CAccountingEntry debit;
731     debit.strAccount = strFrom;
732     debit.nCreditDebit = -nAmount;
733     debit.nTime = nNow;
734     debit.strOtherAccount = strTo;
735     debit.strComment = strComment;
736     walletdb.WriteAccountingEntry(debit);
737
738     // Credit
739     CAccountingEntry credit;
740     credit.strAccount = strTo;
741     credit.nCreditDebit = nAmount;
742     credit.nTime = nNow;
743     credit.strOtherAccount = strFrom;
744     credit.strComment = strComment;
745     walletdb.WriteAccountingEntry(credit);
746
747     walletdb.TxnCommit();
748
749     return true;
750 }
751
752
753 Value sendfrom(const Array& params, bool fHelp)
754 {
755     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
756         throw runtime_error(
757             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
758             "<amount> is a real and is rounded to the nearest 0.00000001\n"
759             "requires wallet passphrase to be set with walletpassphrase first");
760     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
761         throw runtime_error(
762             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
763             "<amount> is a real and is rounded to the nearest 0.00000001");
764
765     string strAccount = AccountFromValue(params[0]);
766     CBitcoinAddress address(params[1].get_str());
767     if (!address.IsValid())
768         throw JSONRPCError(-5, "Invalid bitcoin address");
769     int64 nAmount = AmountFromValue(params[2]);
770     int nMinDepth = 1;
771     if (params.size() > 3)
772         nMinDepth = params[3].get_int();
773
774     CWalletTx wtx;
775     wtx.strFromAccount = strAccount;
776     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
777         wtx.mapValue["comment"] = params[4].get_str();
778     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
779         wtx.mapValue["to"]      = params[5].get_str();
780
781     if (pwalletMain->IsLocked())
782         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
783
784     // Check funds
785     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
786     if (nAmount > nBalance)
787         throw JSONRPCError(-6, "Account has insufficient funds");
788
789     // Send
790     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
791     if (strError != "")
792         throw JSONRPCError(-4, strError);
793
794     return wtx.GetHash().GetHex();
795 }
796
797
798 Value sendmany(const Array& params, bool fHelp)
799 {
800     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
801         throw runtime_error(
802             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
803             "amounts are double-precision floating point numbers\n"
804             "requires wallet passphrase to be set with walletpassphrase first");
805     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
806         throw runtime_error(
807             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
808             "amounts are double-precision floating point numbers");
809
810     string strAccount = AccountFromValue(params[0]);
811     Object sendTo = params[1].get_obj();
812     int nMinDepth = 1;
813     if (params.size() > 2)
814         nMinDepth = params[2].get_int();
815
816     CWalletTx wtx;
817     wtx.strFromAccount = strAccount;
818     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
819         wtx.mapValue["comment"] = params[3].get_str();
820
821     set<CBitcoinAddress> setAddress;
822     vector<pair<CScript, int64> > vecSend;
823
824     int64 totalAmount = 0;
825     BOOST_FOREACH(const Pair& s, sendTo)
826     {
827         CBitcoinAddress address(s.name_);
828         if (!address.IsValid())
829             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
830
831         if (setAddress.count(address))
832             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
833         setAddress.insert(address);
834
835         CScript scriptPubKey;
836         scriptPubKey.SetBitcoinAddress(address);
837         int64 nAmount = AmountFromValue(s.value_); 
838         totalAmount += nAmount;
839
840         vecSend.push_back(make_pair(scriptPubKey, nAmount));
841     }
842
843     if (pwalletMain->IsLocked())
844         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
845
846     // Check funds
847     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
848     if (totalAmount > nBalance)
849         throw JSONRPCError(-6, "Account has insufficient funds");
850
851     // Send
852     CReserveKey keyChange(pwalletMain);
853     int64 nFeeRequired = 0;
854     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
855     if (!fCreated)
856     {
857         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
858             throw JSONRPCError(-6, "Insufficient funds");
859         throw JSONRPCError(-4, "Transaction creation failed");
860     }
861     if (!pwalletMain->CommitTransaction(wtx, keyChange))
862         throw JSONRPCError(-4, "Transaction commit failed");
863
864     return wtx.GetHash().GetHex();
865 }
866
867
868 struct tallyitem
869 {
870     int64 nAmount;
871     int nConf;
872     tallyitem()
873     {
874         nAmount = 0;
875         nConf = INT_MAX;
876     }
877 };
878
879 Value ListReceived(const Array& params, bool fByAccounts)
880 {
881     // Minimum confirmations
882     int nMinDepth = 1;
883     if (params.size() > 0)
884         nMinDepth = params[0].get_int();
885
886     // Whether to include empty accounts
887     bool fIncludeEmpty = false;
888     if (params.size() > 1)
889         fIncludeEmpty = params[1].get_bool();
890
891     // Tally
892     map<CBitcoinAddress, tallyitem> mapTally;
893     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
894     {
895         const CWalletTx& wtx = (*it).second;
896         if (wtx.IsCoinBase() || !wtx.IsFinal())
897             continue;
898
899         int nDepth = wtx.GetDepthInMainChain();
900         if (nDepth < nMinDepth)
901             continue;
902
903         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
904         {
905             CBitcoinAddress address;
906             if (!ExtractAddress(txout.scriptPubKey, pwalletMain, address) || !address.IsValid())
907                 continue;
908
909             tallyitem& item = mapTally[address];
910             item.nAmount += txout.nValue;
911             item.nConf = min(item.nConf, nDepth);
912         }
913     }
914
915     // Reply
916     Array ret;
917     map<string, tallyitem> mapAccountTally;
918     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& item, pwalletMain->mapAddressBook)
919     {
920         const CBitcoinAddress& address = item.first;
921         const string& strAccount = item.second;
922         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
923         if (it == mapTally.end() && !fIncludeEmpty)
924             continue;
925
926         int64 nAmount = 0;
927         int nConf = INT_MAX;
928         if (it != mapTally.end())
929         {
930             nAmount = (*it).second.nAmount;
931             nConf = (*it).second.nConf;
932         }
933
934         if (fByAccounts)
935         {
936             tallyitem& item = mapAccountTally[strAccount];
937             item.nAmount += nAmount;
938             item.nConf = min(item.nConf, nConf);
939         }
940         else
941         {
942             Object obj;
943             obj.push_back(Pair("address",       address.ToString()));
944             obj.push_back(Pair("account",       strAccount));
945             obj.push_back(Pair("label",         strAccount)); // deprecated
946             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
947             obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
948             ret.push_back(obj);
949         }
950     }
951
952     if (fByAccounts)
953     {
954         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
955         {
956             int64 nAmount = (*it).second.nAmount;
957             int nConf = (*it).second.nConf;
958             Object obj;
959             obj.push_back(Pair("account",       (*it).first));
960             obj.push_back(Pair("label",         (*it).first)); // deprecated
961             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
962             obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
963             ret.push_back(obj);
964         }
965     }
966
967     return ret;
968 }
969
970 Value listreceivedbyaddress(const Array& params, bool fHelp)
971 {
972     if (fHelp || params.size() > 2)
973         throw runtime_error(
974             "listreceivedbyaddress [minconf=1] [includeempty=false]\n"
975             "[minconf] is the minimum number of confirmations before payments are included.\n"
976             "[includeempty] whether to include addresses that haven't received any payments.\n"
977             "Returns an array of objects containing:\n"
978             "  \"address\" : receiving address\n"
979             "  \"account\" : the account of the receiving address\n"
980             "  \"amount\" : total amount received by the address\n"
981             "  \"confirmations\" : number of confirmations of the most recent transaction included");
982
983     return ListReceived(params, false);
984 }
985
986 Value listreceivedbyaccount(const Array& params, bool fHelp)
987 {
988     if (fHelp || params.size() > 2)
989         throw runtime_error(
990             "listreceivedbyaccount [minconf=1] [includeempty=false]\n"
991             "[minconf] is the minimum number of confirmations before payments are included.\n"
992             "[includeempty] whether to include accounts that haven't received any payments.\n"
993             "Returns an array of objects containing:\n"
994             "  \"account\" : the account of the receiving addresses\n"
995             "  \"amount\" : total amount received by addresses with this account\n"
996             "  \"confirmations\" : number of confirmations of the most recent transaction included");
997
998     return ListReceived(params, true);
999 }
1000
1001 void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret)
1002 {
1003     int64 nGeneratedImmature, nGeneratedMature, nFee;
1004     string strSentAccount;
1005     list<pair<CBitcoinAddress, int64> > listReceived;
1006     list<pair<CBitcoinAddress, int64> > listSent;
1007     wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1008
1009     bool fAllAccounts = (strAccount == string("*"));
1010
1011     // Generated blocks assigned to account ""
1012     if ((nGeneratedMature+nGeneratedImmature) != 0 && (fAllAccounts || strAccount == ""))
1013     {
1014         Object entry;
1015         entry.push_back(Pair("account", string("")));
1016         if (nGeneratedImmature)
1017         {
1018             entry.push_back(Pair("category", wtx.GetDepthInMainChain() ? "immature" : "orphan"));
1019             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedImmature)));
1020         }
1021         else
1022         {
1023             entry.push_back(Pair("category", "generate"));
1024             entry.push_back(Pair("amount", ValueFromAmount(nGeneratedMature)));
1025         }
1026         if (fLong)
1027             WalletTxToJSON(wtx, entry);
1028         ret.push_back(entry);
1029     }
1030
1031     // Sent
1032     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
1033     {
1034         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1035         {
1036             Object entry;
1037             entry.push_back(Pair("account", strSentAccount));
1038             entry.push_back(Pair("address", s.first.ToString()));
1039             entry.push_back(Pair("category", "send"));
1040             entry.push_back(Pair("amount", ValueFromAmount(-s.second)));
1041             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
1042             if (fLong)
1043                 WalletTxToJSON(wtx, entry);
1044             ret.push_back(entry);
1045         }
1046     }
1047
1048     // Received
1049     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
1050         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1051         {
1052             string account;
1053             if (pwalletMain->mapAddressBook.count(r.first))
1054                 account = pwalletMain->mapAddressBook[r.first];
1055             if (fAllAccounts || (account == strAccount))
1056             {
1057                 Object entry;
1058                 entry.push_back(Pair("account", account));
1059                 entry.push_back(Pair("address", r.first.ToString()));
1060                 entry.push_back(Pair("category", "receive"));
1061                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1062                 if (fLong)
1063                     WalletTxToJSON(wtx, entry);
1064                 ret.push_back(entry);
1065             }
1066         }
1067 }
1068
1069 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1070 {
1071     bool fAllAccounts = (strAccount == string("*"));
1072
1073     if (fAllAccounts || acentry.strAccount == strAccount)
1074     {
1075         Object entry;
1076         entry.push_back(Pair("account", acentry.strAccount));
1077         entry.push_back(Pair("category", "move"));
1078         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1079         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1080         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1081         entry.push_back(Pair("comment", acentry.strComment));
1082         ret.push_back(entry);
1083     }
1084 }
1085
1086 Value listtransactions(const Array& params, bool fHelp)
1087 {
1088     if (fHelp || params.size() > 3)
1089         throw runtime_error(
1090             "listtransactions [account] [count=10] [from=0]\n"
1091             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1092
1093     string strAccount = "*";
1094     if (params.size() > 0)
1095         strAccount = params[0].get_str();
1096     int nCount = 10;
1097     if (params.size() > 1)
1098         nCount = params[1].get_int();
1099     int nFrom = 0;
1100     if (params.size() > 2)
1101         nFrom = params[2].get_int();
1102
1103     Array ret;
1104     CWalletDB walletdb(pwalletMain->strWalletFile);
1105
1106     // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
1107     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1108     typedef multimap<int64, TxPair > TxItems;
1109     TxItems txByTime;
1110
1111     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1112     {
1113         CWalletTx* wtx = &((*it).second);
1114         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1115     }
1116     list<CAccountingEntry> acentries;
1117     walletdb.ListAccountCreditDebit(strAccount, acentries);
1118     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1119     {
1120         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1121     }
1122
1123     // Now: iterate backwards until we have nCount items to return:
1124     TxItems::reverse_iterator it = txByTime.rbegin();
1125     if (txByTime.size() > nFrom) std::advance(it, nFrom);
1126     for (; it != txByTime.rend(); ++it)
1127     {
1128         CWalletTx *const pwtx = (*it).second.first;
1129         if (pwtx != 0)
1130             ListTransactions(*pwtx, strAccount, 0, true, ret);
1131         CAccountingEntry *const pacentry = (*it).second.second;
1132         if (pacentry != 0)
1133             AcentryToJSON(*pacentry, strAccount, ret);
1134
1135         if (ret.size() >= nCount) break;
1136     }
1137     // ret is now newest to oldest
1138     
1139     // Make sure we return only last nCount items (sends-to-self might give us an extra):
1140     if (ret.size() > nCount)
1141     {
1142         Array::iterator last = ret.begin();
1143         std::advance(last, nCount);
1144         ret.erase(last, ret.end());
1145     }
1146     std::reverse(ret.begin(), ret.end()); // oldest to newest
1147
1148     return ret;
1149 }
1150
1151 Value listaccounts(const Array& params, bool fHelp)
1152 {
1153     if (fHelp || params.size() > 1)
1154         throw runtime_error(
1155             "listaccounts [minconf=1]\n"
1156             "Returns Object that has account names as keys, account balances as values.");
1157
1158     int nMinDepth = 1;
1159     if (params.size() > 0)
1160         nMinDepth = params[0].get_int();
1161
1162     map<string, int64> mapAccountBalances;
1163     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1164         if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1165             mapAccountBalances[entry.second] = 0;
1166     }
1167
1168     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1169     {
1170         const CWalletTx& wtx = (*it).second;
1171         int64 nGeneratedImmature, nGeneratedMature, nFee;
1172         string strSentAccount;
1173         list<pair<CBitcoinAddress, int64> > listReceived;
1174         list<pair<CBitcoinAddress, int64> > listSent;
1175         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1176         mapAccountBalances[strSentAccount] -= nFee;
1177         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1178             mapAccountBalances[strSentAccount] -= s.second;
1179         if (wtx.GetDepthInMainChain() >= nMinDepth)
1180         {
1181             mapAccountBalances[""] += nGeneratedMature;
1182             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1183                 if (pwalletMain->mapAddressBook.count(r.first))
1184                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1185                 else
1186                     mapAccountBalances[""] += r.second;
1187         }
1188     }
1189
1190     list<CAccountingEntry> acentries;
1191     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1192     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1193         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1194
1195     Object ret;
1196     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1197         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1198     }
1199     return ret;
1200 }
1201
1202 Value gettransaction(const Array& params, bool fHelp)
1203 {
1204     if (fHelp || params.size() != 1)
1205         throw runtime_error(
1206             "gettransaction <txid>\n"
1207             "Get detailed information about <txid>");
1208
1209     uint256 hash;
1210     hash.SetHex(params[0].get_str());
1211
1212     Object entry;
1213
1214     if (!pwalletMain->mapWallet.count(hash))
1215         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1216     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1217
1218     int64 nCredit = wtx.GetCredit();
1219     int64 nDebit = wtx.GetDebit();
1220     int64 nNet = nCredit - nDebit;
1221     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1222
1223     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1224     if (wtx.IsFromMe())
1225         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1226
1227     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1228
1229     Array details;
1230     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1231     entry.push_back(Pair("details", details));
1232
1233     return entry;
1234 }
1235
1236
1237 Value backupwallet(const Array& params, bool fHelp)
1238 {
1239     if (fHelp || params.size() != 1)
1240         throw runtime_error(
1241             "backupwallet <destination>\n"
1242             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1243
1244     string strDest = params[0].get_str();
1245     BackupWallet(*pwalletMain, strDest);
1246
1247     return Value::null;
1248 }
1249
1250
1251 Value keypoolrefill(const Array& params, bool fHelp)
1252 {
1253     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1254         throw runtime_error(
1255             "keypoolrefill\n"
1256             "Fills the keypool, requires wallet passphrase to be set.");
1257     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1258         throw runtime_error(
1259             "keypoolrefill\n"
1260             "Fills the keypool.");
1261
1262     if (pwalletMain->IsLocked())
1263         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1264
1265     pwalletMain->TopUpKeyPool();
1266
1267     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1268         throw JSONRPCError(-4, "Error refreshing keypool.");
1269
1270     return Value::null;
1271 }
1272
1273
1274 void ThreadTopUpKeyPool(void* parg)
1275 {
1276     pwalletMain->TopUpKeyPool();
1277 }
1278
1279 void ThreadCleanWalletPassphrase(void* parg)
1280 {
1281     int64 nMyWakeTime = GetTime() + *((int*)parg);
1282
1283     if (nWalletUnlockTime == 0)
1284     {
1285         CRITICAL_BLOCK(cs_nWalletUnlockTime)
1286         {
1287             nWalletUnlockTime = nMyWakeTime;
1288         }
1289
1290         while (GetTime() < nWalletUnlockTime)
1291             Sleep(GetTime() - nWalletUnlockTime);
1292
1293         CRITICAL_BLOCK(cs_nWalletUnlockTime)
1294         {
1295             nWalletUnlockTime = 0;
1296         }
1297     }
1298     else
1299     {
1300         CRITICAL_BLOCK(cs_nWalletUnlockTime)
1301         {
1302             if (nWalletUnlockTime < nMyWakeTime)
1303                 nWalletUnlockTime = nMyWakeTime;
1304         }
1305         free(parg);
1306         return;
1307     }
1308
1309     pwalletMain->Lock();
1310
1311     delete (int*)parg;
1312 }
1313
1314 Value walletpassphrase(const Array& params, bool fHelp)
1315 {
1316     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1317         throw runtime_error(
1318             "walletpassphrase <passphrase> <timeout>\n"
1319             "Stores the wallet decryption key in memory for <timeout> seconds.");
1320     if (fHelp)
1321         return true;
1322     if (!pwalletMain->IsCrypted())
1323         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1324
1325     if (!pwalletMain->IsLocked())
1326         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1327
1328     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1329     string strWalletPass;
1330     strWalletPass.reserve(100);
1331     mlock(&strWalletPass[0], strWalletPass.capacity());
1332     strWalletPass = params[0].get_str();
1333
1334     if (strWalletPass.length() > 0)
1335     {
1336         if (!pwalletMain->Unlock(strWalletPass))
1337         {
1338             fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1339             munlock(&strWalletPass[0], strWalletPass.capacity());
1340             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1341         }
1342         fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1343         munlock(&strWalletPass[0], strWalletPass.capacity());
1344     }
1345     else
1346         throw runtime_error(
1347             "walletpassphrase <passphrase> <timeout>\n"
1348             "Stores the wallet decryption key in memory for <timeout> seconds.");
1349
1350     CreateThread(ThreadTopUpKeyPool, NULL);
1351     int* pnSleepTime = new int(params[1].get_int());
1352     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1353
1354     return Value::null;
1355 }
1356
1357
1358 Value walletpassphrasechange(const Array& params, bool fHelp)
1359 {
1360     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1361         throw runtime_error(
1362             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1363             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1364     if (fHelp)
1365         return true;
1366     if (!pwalletMain->IsCrypted())
1367         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1368
1369     string strOldWalletPass;
1370     strOldWalletPass.reserve(100);
1371     mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1372     strOldWalletPass = params[0].get_str();
1373
1374     string strNewWalletPass;
1375     strNewWalletPass.reserve(100);
1376     mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1377     strNewWalletPass = params[1].get_str();
1378
1379     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1380         throw runtime_error(
1381             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1382             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1383
1384     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1385     {
1386         fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1387         fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1388         munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1389         munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1390         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1391     }
1392     fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1393     fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1394     munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1395     munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1396
1397     return Value::null;
1398 }
1399
1400
1401 Value walletlock(const Array& params, bool fHelp)
1402 {
1403     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1404         throw runtime_error(
1405             "walletlock\n"
1406             "Removes the wallet encryption key from memory, locking the wallet.\n"
1407             "After calling this method, you will need to call walletpassphrase again\n"
1408             "before being able to call any methods which require the wallet to be unlocked.");
1409     if (fHelp)
1410         return true;
1411     if (!pwalletMain->IsCrypted())
1412         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1413
1414     pwalletMain->Lock();
1415     CRITICAL_BLOCK(cs_nWalletUnlockTime)
1416     {
1417         nWalletUnlockTime = 0;
1418     }
1419
1420     return Value::null;
1421 }
1422
1423
1424 Value encryptwallet(const Array& params, bool fHelp)
1425 {
1426     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1427         throw runtime_error(
1428             "encryptwallet <passphrase>\n"
1429             "Encrypts the wallet with <passphrase>.");
1430     if (fHelp)
1431         return true;
1432     if (pwalletMain->IsCrypted())
1433         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1434
1435     string strWalletPass;
1436     strWalletPass.reserve(100);
1437     mlock(&strWalletPass[0], strWalletPass.capacity());
1438     strWalletPass = params[0].get_str();
1439
1440     if (strWalletPass.length() < 1)
1441         throw runtime_error(
1442             "encryptwallet <passphrase>\n"
1443             "Encrypts the wallet with <passphrase>.");
1444
1445     if (!pwalletMain->EncryptWallet(strWalletPass))
1446     {
1447         fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1448         munlock(&strWalletPass[0], strWalletPass.capacity());
1449         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1450     }
1451     fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1452     munlock(&strWalletPass[0], strWalletPass.capacity());
1453
1454     return Value::null;
1455 }
1456
1457
1458 Value validateaddress(const Array& params, bool fHelp)
1459 {
1460     if (fHelp || params.size() != 1)
1461         throw runtime_error(
1462             "validateaddress <bitcoinaddress>\n"
1463             "Return information about <bitcoinaddress>.");
1464
1465     CBitcoinAddress address(params[0].get_str());
1466     bool isValid = address.IsValid();
1467
1468     Object ret;
1469     ret.push_back(Pair("isvalid", isValid));
1470     if (isValid)
1471     {
1472         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1473         // version of the address:
1474         string currentAddress = address.ToString();
1475         ret.push_back(Pair("address", currentAddress));
1476         ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1477         if (pwalletMain->mapAddressBook.count(address))
1478             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1479     }
1480     return ret;
1481 }
1482
1483
1484 Value getwork(const Array& params, bool fHelp)
1485 {
1486     if (fHelp || params.size() > 1)
1487         throw runtime_error(
1488             "getwork [data]\n"
1489             "If [data] is not specified, returns formatted hash data to work on:\n"
1490             "  \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1491             "  \"data\" : block data\n"
1492             "  \"hash1\" : formatted hash buffer for second hash\n"
1493             "  \"target\" : little endian hash target\n"
1494             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1495
1496     if (vNodes.empty())
1497         throw JSONRPCError(-9, "Bitcoin is not connected!");
1498
1499     if (IsInitialBlockDownload())
1500         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1501
1502     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1503     static mapNewBlock_t mapNewBlock;
1504     static vector<CBlock*> vNewBlock;
1505     static CReserveKey reservekey(pwalletMain);
1506
1507     if (params.size() == 0)
1508     {
1509         // Update block
1510         static unsigned int nTransactionsUpdatedLast;
1511         static CBlockIndex* pindexPrev;
1512         static int64 nStart;
1513         static CBlock* pblock;
1514         if (pindexPrev != pindexBest ||
1515             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1516         {
1517             if (pindexPrev != pindexBest)
1518             {
1519                 // Deallocate old blocks since they're obsolete now
1520                 mapNewBlock.clear();
1521                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1522                     delete pblock;
1523                 vNewBlock.clear();
1524             }
1525             nTransactionsUpdatedLast = nTransactionsUpdated;
1526             pindexPrev = pindexBest;
1527             nStart = GetTime();
1528
1529             // Create new block
1530             pblock = CreateNewBlock(reservekey);
1531             if (!pblock)
1532                 throw JSONRPCError(-7, "Out of memory");
1533             vNewBlock.push_back(pblock);
1534         }
1535
1536         // Update nTime
1537         pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1538         pblock->nNonce = 0;
1539
1540         // Update nExtraNonce
1541         static unsigned int nExtraNonce = 0;
1542         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1543
1544         // Save
1545         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1546
1547         // Prebuild hash buffers
1548         char pmidstate[32];
1549         char pdata[128];
1550         char phash1[64];
1551         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1552
1553         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1554
1555         Object result;
1556         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1557         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1558         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1))));
1559         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1560         return result;
1561     }
1562     else
1563     {
1564         // Parse parameters
1565         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1566         if (vchData.size() != 128)
1567             throw JSONRPCError(-8, "Invalid parameter");
1568         CBlock* pdata = (CBlock*)&vchData[0];
1569
1570         // Byte reverse
1571         for (int i = 0; i < 128/4; i++)
1572             ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1573
1574         // Get saved block
1575         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1576             return false;
1577         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1578
1579         pblock->nTime = pdata->nTime;
1580         pblock->nNonce = pdata->nNonce;
1581         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
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