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