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