Merge branch 'master' of https://github.com/bitcoin/bitcoin
[novacoin.git] / src / bitcoinrpc.cpp
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "headers.h"
7 #include "cryptopp/sha.h"
8 #include "db.h"
9 #include "net.h"
10 #include "init.h"
11 #undef printf
12 #include <boost/asio.hpp>
13 #include <boost/iostreams/concepts.hpp>
14 #include <boost/iostreams/stream.hpp>
15 #include <boost/algorithm/string.hpp>
16 #ifdef USE_SSL
17 #include <boost/asio/ssl.hpp> 
18 #include <boost/filesystem.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
21 #endif
22 #include "json/json_spirit_reader_template.h"
23 #include "json/json_spirit_writer_template.h"
24 #include "json/json_spirit_utils.h"
25 #define printf OutputDebugStringF
26 // MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
27 // precompiled in headers.h.  The problem might be when the pch file goes over
28 // a certain size around 145MB.  If we need access to json_spirit outside this
29 // file, we could use the compiled json_spirit option.
30
31 using namespace std;
32 using namespace boost;
33 using namespace boost::asio;
34 using namespace json_spirit;
35
36 void ThreadRPCServer2(void* parg);
37 typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
38 extern map<string, rpcfn_type> mapCallTable;
39
40 static int64 nWalletUnlockTime;
41 static CCriticalSection cs_nWalletUnlockTime;
42
43
44 Object JSONRPCError(int code, const string& message)
45 {
46     Object error;
47     error.push_back(Pair("code", code));
48     error.push_back(Pair("message", message));
49     return error;
50 }
51
52
53 void PrintConsole(const std::string &format, ...)
54 {
55     char buffer[50000];
56     int limit = sizeof(buffer);
57     va_list arg_ptr;
58     va_start(arg_ptr, format);
59     int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
60     va_end(arg_ptr);
61     if (ret < 0 || ret >= limit)
62     {
63         ret = limit - 1;
64         buffer[limit-1] = 0;
65     }
66     printf("%s", buffer);
67 #if defined(__WXMSW__) && defined(GUI)
68     MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
69 #else
70     fprintf(stdout, "%s", buffer);
71 #endif
72 }
73
74
75 int64 AmountFromValue(const Value& value)
76 {
77     double dAmount = value.get_real();
78     if (dAmount <= 0.0 || dAmount > 21000000.0)
79         throw JSONRPCError(-3, "Invalid amount");
80     int64 nAmount = roundint64(dAmount * COIN);
81     if (!MoneyRange(nAmount))
82         throw JSONRPCError(-3, "Invalid amount");
83     return nAmount;
84 }
85
86 Value ValueFromAmount(int64 amount)
87 {
88     return (double)amount / (double)COIN;
89 }
90
91 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
92 {
93     entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
94     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
95     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
96     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
97         entry.push_back(Pair(item.first, item.second));
98 }
99
100 string AccountFromValue(const Value& value)
101 {
102     string strAccount = value.get_str();
103     if (strAccount == "*")
104         throw JSONRPCError(-11, "Invalid account name");
105     return strAccount;
106 }
107
108
109
110 ///
111 /// Note: This interface may still be subject to change.
112 ///
113
114
115 Value help(const Array& params, bool fHelp)
116 {
117     if (fHelp || params.size() > 1)
118         throw runtime_error(
119             "help [command]\n"
120             "List commands, or get help for a command.");
121
122     string strCommand;
123     if (params.size() > 0)
124         strCommand = params[0].get_str();
125
126     string strRet;
127     set<rpcfn_type> setDone;
128     for (map<string, rpcfn_type>::iterator mi = mapCallTable.begin(); mi != mapCallTable.end(); ++mi)
129     {
130         string strMethod = (*mi).first;
131         // We already filter duplicates, but these deprecated screw up the sort order
132         if (strMethod == "getamountreceived" ||
133             strMethod == "getallreceived" ||
134             (strMethod.find("label") != string::npos))
135             continue;
136         if (strCommand != "" && strMethod != strCommand)
137             continue;
138         try
139         {
140             Array params;
141             rpcfn_type pfn = (*mi).second;
142             if (setDone.insert(pfn).second)
143                 (*pfn)(params, true);
144         }
145         catch (std::exception& e)
146         {
147             // Help text is returned in an exception
148             string strHelp = string(e.what());
149             if (strCommand == "")
150                 if (strHelp.find('\n') != -1)
151                     strHelp = strHelp.substr(0, strHelp.find('\n'));
152             strRet += strHelp + "\n";
153         }
154     }
155     if (strRet == "")
156         strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
157     strRet = strRet.substr(0,strRet.size()-1);
158     return strRet;
159 }
160
161
162 Value stop(const Array& params, bool fHelp)
163 {
164     if (fHelp || params.size() != 0)
165         throw runtime_error(
166             "stop\n"
167             "Stop bitcoin server.");
168
169     // Shutdown will take long enough that the response should get back
170     CreateThread(Shutdown, NULL);
171     return "bitcoin server stopping";
172 }
173
174
175 Value getblockcount(const Array& params, bool fHelp)
176 {
177     if (fHelp || params.size() != 0)
178         throw runtime_error(
179             "getblockcount\n"
180             "Returns the number of blocks in the longest block chain.");
181
182     return nBestHeight;
183 }
184
185
186 Value getblocknumber(const Array& params, bool fHelp)
187 {
188     if (fHelp || params.size() != 0)
189         throw runtime_error(
190             "getblocknumber\n"
191             "Returns the block number of the latest block in the longest block chain.");
192
193     return nBestHeight;
194 }
195
196
197 Value getconnectioncount(const Array& params, bool fHelp)
198 {
199     if (fHelp || params.size() != 0)
200         throw runtime_error(
201             "getconnectioncount\n"
202             "Returns the number of connections to other nodes.");
203
204     return (int)vNodes.size();
205 }
206
207
208 double GetDifficulty()
209 {
210     // Floating point number that is a multiple of the minimum difficulty,
211     // minimum difficulty = 1.0.
212
213     if (pindexBest == NULL)
214         return 1.0;
215     int nShift = (pindexBest->nBits >> 24) & 0xff;
216
217     double dDiff =
218         (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
219
220     while (nShift < 29)
221     {
222         dDiff *= 256.0;
223         nShift++;
224     }
225     while (nShift > 29)
226     {
227         dDiff /= 256.0;
228         nShift--;
229     }
230
231     return dDiff;
232 }
233
234 Value getdifficulty(const Array& params, bool fHelp)
235 {
236     if (fHelp || params.size() != 0)
237         throw runtime_error(
238             "getdifficulty\n"
239             "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
240
241     return GetDifficulty();
242 }
243
244
245 Value getgenerate(const Array& params, bool fHelp)
246 {
247     if (fHelp || params.size() != 0)
248         throw runtime_error(
249             "getgenerate\n"
250             "Returns true or false.");
251
252     return (bool)fGenerateBitcoins;
253 }
254
255
256 Value setgenerate(const Array& params, bool fHelp)
257 {
258     if (fHelp || params.size() < 1 || params.size() > 2)
259         throw runtime_error(
260             "setgenerate <generate> [genproclimit]\n"
261             "<generate> is true or false to turn generation on or off.\n"
262             "Generation is limited to [genproclimit] processors, -1 is unlimited.");
263
264     bool fGenerate = true;
265     if (params.size() > 0)
266         fGenerate = params[0].get_bool();
267
268     if (params.size() > 1)
269     {
270         int nGenProcLimit = params[1].get_int();
271         fLimitProcessors = (nGenProcLimit != -1);
272         WriteSetting("fLimitProcessors", fLimitProcessors);
273         if (nGenProcLimit != -1)
274             WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
275         if (nGenProcLimit == 0)
276             fGenerate = false;
277     }
278
279     GenerateBitcoins(fGenerate, pwalletMain);
280     return Value::null;
281 }
282
283
284 Value gethashespersec(const Array& params, bool fHelp)
285 {
286     if (fHelp || params.size() != 0)
287         throw runtime_error(
288             "gethashespersec\n"
289             "Returns a recent hashes per second performance measurement while generating.");
290
291     if (GetTimeMillis() - nHPSTimerStart > 8000)
292         return (boost::int64_t)0;
293     return (boost::int64_t)dHashesPerSec;
294 }
295
296
297 Value getinfo(const Array& params, bool fHelp)
298 {
299     if (fHelp || params.size() != 0)
300         throw runtime_error(
301             "getinfo\n"
302             "Returns an object containing various state info.");
303
304     Object obj;
305     obj.push_back(Pair("version",       (int)VERSION));
306     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
307     obj.push_back(Pair("blocks",        (int)nBestHeight));
308     obj.push_back(Pair("connections",   (int)vNodes.size()));
309     obj.push_back(Pair("proxy",         (fUseProxy ? addrProxy.ToStringIPPort() : string())));
310     obj.push_back(Pair("generate",      (bool)fGenerateBitcoins));
311     obj.push_back(Pair("genproclimit",  (int)(fLimitProcessors ? nLimitProcessors : -1)));
312     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
313     obj.push_back(Pair("hashespersec",  gethashespersec(params, false)));
314     obj.push_back(Pair("testnet",       fTestNet));
315     obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
316     obj.push_back(Pair("keypoolsize",   pwalletMain->GetKeyPoolSize()));
317     obj.push_back(Pair("paytxfee",      ValueFromAmount(nTransactionFee)));
318     if (pwalletMain->IsCrypted())
319         obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
320     obj.push_back(Pair("errors",        GetWarnings("statusbar")));
321     return obj;
322 }
323
324
325 Value getnewaddress(const Array& params, bool fHelp)
326 {
327     if (fHelp || params.size() > 1)
328         throw runtime_error(
329             "getnewaddress [account]\n"
330             "Returns a new bitcoin address for receiving payments.  "
331             "If [account] is specified (recommended), it is added to the address book "
332             "so payments received with the address will be credited to [account].");
333
334     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(-14, "Error: The wallet passphrase entered was incorrect.");
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(-14, "Error: The wallet passphrase entered was incorrect.");
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(-14, "Error: The wallet passphrase entered was incorrect.");
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         if (txByTime.size() > nFrom) std::advance(it, nFrom);
1192         for (; it != txByTime.rend(); ++it)
1193         {
1194             CWalletTx *const pwtx = (*it).second.first;
1195             if (pwtx != 0)
1196                 ListTransactions(*pwtx, strAccount, 0, true, ret);
1197             CAccountingEntry *const pacentry = (*it).second.second;
1198             if (pacentry != 0)
1199                 AcentryToJSON(*pacentry, strAccount, ret);
1200
1201             if (ret.size() >= nCount) break;
1202         }
1203         // ret is now newest to oldest
1204     }
1205     
1206     // Make sure we return only last nCount items (sends-to-self might give us an extra):
1207     if (ret.size() > nCount)
1208     {
1209         Array::iterator last = ret.begin();
1210         std::advance(last, nCount);
1211         ret.erase(last, ret.end());
1212     }
1213     std::reverse(ret.begin(), ret.end()); // oldest to newest
1214
1215     return ret;
1216 }
1217
1218 Value listaccounts(const Array& params, bool fHelp)
1219 {
1220     if (fHelp || params.size() > 1)
1221         throw runtime_error(
1222             "listaccounts [minconf=1]\n"
1223             "Returns Object that has account names as keys, account balances as values.");
1224
1225     int nMinDepth = 1;
1226     if (params.size() > 0)
1227         nMinDepth = params[0].get_int();
1228
1229     map<string, int64> mapAccountBalances;
1230     CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1231     CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1232     {
1233         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1234             if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1235                 mapAccountBalances[entry.second] = 0;
1236         }
1237
1238         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1239         {
1240             const CWalletTx& wtx = (*it).second;
1241             int64 nGeneratedImmature, nGeneratedMature, nFee;
1242             string strSentAccount;
1243             list<pair<CBitcoinAddress, int64> > listReceived;
1244             list<pair<CBitcoinAddress, int64> > listSent;
1245             wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1246             mapAccountBalances[strSentAccount] -= nFee;
1247             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1248                 mapAccountBalances[strSentAccount] -= s.second;
1249             if (wtx.GetDepthInMainChain() >= nMinDepth)
1250             {
1251                 mapAccountBalances[""] += nGeneratedMature;
1252                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1253                     if (pwalletMain->mapAddressBook.count(r.first))
1254                         mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1255                     else
1256                         mapAccountBalances[""] += r.second;
1257             }
1258         }
1259     }
1260
1261     list<CAccountingEntry> acentries;
1262     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1263     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1264         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1265
1266     Object ret;
1267     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1268         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1269     }
1270     return ret;
1271 }
1272
1273 Value gettransaction(const Array& params, bool fHelp)
1274 {
1275     if (fHelp || params.size() != 1)
1276         throw runtime_error(
1277             "gettransaction <txid>\n"
1278             "Get detailed information about <txid>");
1279
1280     uint256 hash;
1281     hash.SetHex(params[0].get_str());
1282
1283     Object entry;
1284     CRITICAL_BLOCK(pwalletMain->cs_mapWallet)
1285     {
1286         if (!pwalletMain->mapWallet.count(hash))
1287             throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1288         const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1289
1290         int64 nCredit = wtx.GetCredit();
1291         int64 nDebit = wtx.GetDebit();
1292         int64 nNet = nCredit - nDebit;
1293         int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1294
1295         entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1296         if (wtx.IsFromMe())
1297             entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1298
1299         WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1300
1301         Array details;
1302         ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1303         entry.push_back(Pair("details", details));
1304     }
1305
1306     return entry;
1307 }
1308
1309
1310 Value backupwallet(const Array& params, bool fHelp)
1311 {
1312     if (fHelp || params.size() != 1)
1313         throw runtime_error(
1314             "backupwallet <destination>\n"
1315             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1316
1317     string strDest = params[0].get_str();
1318     BackupWallet(*pwalletMain, strDest);
1319
1320     return Value::null;
1321 }
1322
1323
1324 Value keypoolrefill(const Array& params, bool fHelp)
1325 {
1326     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1327         throw runtime_error(
1328             "keypoolrefill\n"
1329             "Fills the keypool, requires wallet passphrase to be set.");
1330     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1331         throw runtime_error(
1332             "keypoolrefill\n"
1333             "Fills the keypool.");
1334
1335     CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1336     {
1337         if (pwalletMain->IsLocked())
1338             throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1339
1340         pwalletMain->TopUpKeyPool();
1341     }
1342
1343     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1344         throw JSONRPCError(-4, "Error refreshing keypool.");
1345
1346     return Value::null;
1347 }
1348
1349
1350 void ThreadTopUpKeyPool(void* parg)
1351 {
1352     pwalletMain->TopUpKeyPool();
1353 }
1354
1355 void ThreadCleanWalletPassphrase(void* parg)
1356 {
1357     int64 nMyWakeTime = GetTime() + *((int*)parg);
1358
1359     if (nWalletUnlockTime == 0)
1360     {
1361         CRITICAL_BLOCK(cs_nWalletUnlockTime)
1362         {
1363             nWalletUnlockTime = nMyWakeTime;
1364         }
1365
1366         while (GetTime() < nWalletUnlockTime)
1367             Sleep(GetTime() - nWalletUnlockTime);
1368
1369         CRITICAL_BLOCK(cs_nWalletUnlockTime)
1370         {
1371             nWalletUnlockTime = 0;
1372         }
1373     }
1374     else
1375     {
1376         CRITICAL_BLOCK(cs_nWalletUnlockTime)
1377         {
1378             if (nWalletUnlockTime < nMyWakeTime)
1379                 nWalletUnlockTime = nMyWakeTime;
1380         }
1381         free(parg);
1382         return;
1383     }
1384
1385     pwalletMain->Lock();
1386
1387     delete (int*)parg;
1388 }
1389
1390 Value walletpassphrase(const Array& params, bool fHelp)
1391 {
1392     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1393         throw runtime_error(
1394             "walletpassphrase <passphrase> <timeout>\n"
1395             "Stores the wallet decryption key in memory for <timeout> seconds.");
1396     if (fHelp)
1397         return true;
1398     if (!pwalletMain->IsCrypted())
1399         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1400
1401     if (!pwalletMain->IsLocked())
1402         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1403
1404     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1405     string strWalletPass;
1406     strWalletPass.reserve(100);
1407     mlock(&strWalletPass[0], strWalletPass.capacity());
1408     strWalletPass = params[0].get_str();
1409
1410     CRITICAL_BLOCK(pwalletMain->cs_vMasterKey)
1411     {
1412         if (strWalletPass.length() > 0)
1413         {
1414             if (!pwalletMain->Unlock(strWalletPass))
1415             {
1416                 fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1417                 munlock(&strWalletPass[0], strWalletPass.capacity());
1418                 throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1419             }
1420             fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1421             munlock(&strWalletPass[0], strWalletPass.capacity());
1422         }
1423         else
1424             throw runtime_error(
1425                 "walletpassphrase <passphrase> <timeout>\n"
1426                 "Stores the wallet decryption key in memory for <timeout> seconds.");
1427     }
1428
1429     CreateThread(ThreadTopUpKeyPool, NULL);
1430     int* pnSleepTime = new int(params[1].get_int());
1431     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1432
1433     return Value::null;
1434 }
1435
1436
1437 Value walletpassphrasechange(const Array& params, bool fHelp)
1438 {
1439     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1440         throw runtime_error(
1441             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1442             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1443     if (fHelp)
1444         return true;
1445     if (!pwalletMain->IsCrypted())
1446         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1447
1448     string strOldWalletPass;
1449     strOldWalletPass.reserve(100);
1450     mlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1451     strOldWalletPass = params[0].get_str();
1452
1453     string strNewWalletPass;
1454     strNewWalletPass.reserve(100);
1455     mlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1456     strNewWalletPass = params[1].get_str();
1457
1458     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1459         throw runtime_error(
1460             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1461             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1462
1463     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1464     {
1465         fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1466         fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1467         munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1468         munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1469         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1470     }
1471     fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0');
1472     fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0');
1473     munlock(&strOldWalletPass[0], strOldWalletPass.capacity());
1474     munlock(&strNewWalletPass[0], strNewWalletPass.capacity());
1475
1476     return Value::null;
1477 }
1478
1479
1480 Value walletlock(const Array& params, bool fHelp)
1481 {
1482     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1483         throw runtime_error(
1484             "walletlock\n"
1485             "Removes the wallet encryption key from memory, locking the wallet.\n"
1486             "After calling this method, you will need to call walletpassphrase again\n"
1487             "before being able to call any methods which require the wallet to be unlocked.");
1488     if (fHelp)
1489         return true;
1490     if (!pwalletMain->IsCrypted())
1491         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1492
1493     pwalletMain->Lock();
1494     CRITICAL_BLOCK(cs_nWalletUnlockTime)
1495     {
1496         nWalletUnlockTime = 0;
1497     }
1498
1499     return Value::null;
1500 }
1501
1502
1503 Value encryptwallet(const Array& params, bool fHelp)
1504 {
1505     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1506         throw runtime_error(
1507             "encryptwallet <passphrase>\n"
1508             "Encrypts the wallet with <passphrase>.");
1509     if (fHelp)
1510         return true;
1511     if (pwalletMain->IsCrypted())
1512         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1513
1514     string strWalletPass;
1515     strWalletPass.reserve(100);
1516     mlock(&strWalletPass[0], strWalletPass.capacity());
1517     strWalletPass = params[0].get_str();
1518
1519     if (strWalletPass.length() < 1)
1520         throw runtime_error(
1521             "encryptwallet <passphrase>\n"
1522             "Encrypts the wallet with <passphrase>.");
1523
1524     if (!pwalletMain->EncryptWallet(strWalletPass))
1525     {
1526         fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1527         munlock(&strWalletPass[0], strWalletPass.capacity());
1528         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1529     }
1530     fill(strWalletPass.begin(), strWalletPass.end(), '\0');
1531     munlock(&strWalletPass[0], strWalletPass.capacity());
1532
1533     return Value::null;
1534 }
1535
1536
1537 Value validateaddress(const Array& params, bool fHelp)
1538 {
1539     if (fHelp || params.size() != 1)
1540         throw runtime_error(
1541             "validateaddress <bitcoinaddress>\n"
1542             "Return information about <bitcoinaddress>.");
1543
1544     CBitcoinAddress address(params[0].get_str());
1545     bool isValid = address.IsValid();
1546
1547     Object ret;
1548     ret.push_back(Pair("isvalid", isValid));
1549     if (isValid)
1550     {
1551         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1552         // version of the address:
1553         string currentAddress = address.ToString();
1554         ret.push_back(Pair("address", currentAddress));
1555         ret.push_back(Pair("ismine", (pwalletMain->HaveKey(address) > 0)));
1556         CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook)
1557         {
1558             if (pwalletMain->mapAddressBook.count(address))
1559                 ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1560         }
1561     }
1562     return ret;
1563 }
1564
1565
1566 Value getwork(const Array& params, bool fHelp)
1567 {
1568     if (fHelp || params.size() > 1)
1569         throw runtime_error(
1570             "getwork [data]\n"
1571             "If [data] is not specified, returns formatted hash data to work on:\n"
1572             "  \"midstate\" : precomputed hash state after hashing the first half of the data\n"
1573             "  \"data\" : block data\n"
1574             "  \"hash1\" : formatted hash buffer for second hash\n"
1575             "  \"target\" : little endian hash target\n"
1576             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1577
1578     if (vNodes.empty())
1579         throw JSONRPCError(-9, "Bitcoin is not connected!");
1580
1581     if (IsInitialBlockDownload())
1582         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1583
1584     static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
1585     static vector<CBlock*> vNewBlock;
1586     static CReserveKey reservekey(pwalletMain);
1587
1588     if (params.size() == 0)
1589     {
1590         // Update block
1591         static unsigned int nTransactionsUpdatedLast;
1592         static CBlockIndex* pindexPrev;
1593         static int64 nStart;
1594         static CBlock* pblock;
1595         if (pindexPrev != pindexBest ||
1596             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1597         {
1598             if (pindexPrev != pindexBest)
1599             {
1600                 // Deallocate old blocks since they're obsolete now
1601                 mapNewBlock.clear();
1602                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1603                     delete pblock;
1604                 vNewBlock.clear();
1605             }
1606             nTransactionsUpdatedLast = nTransactionsUpdated;
1607             pindexPrev = pindexBest;
1608             nStart = GetTime();
1609
1610             // Create new block
1611             pblock = CreateNewBlock(reservekey);
1612             if (!pblock)
1613                 throw JSONRPCError(-7, "Out of memory");
1614             vNewBlock.push_back(pblock);
1615         }
1616
1617         // Update nTime
1618         pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
1619         pblock->nNonce = 0;
1620
1621         // Update nExtraNonce
1622         static unsigned int nExtraNonce = 0;
1623         static int64 nPrevTime = 0;
1624         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, nPrevTime);
1625
1626         // Save
1627         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
1628
1629         // Prebuild hash buffers
1630         char pmidstate[32];
1631         char pdata[128];
1632         char phash1[64];
1633         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1634
1635         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1636
1637         Object result;
1638         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
1639         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1640         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1))));
1641         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1642         return result;
1643     }
1644     else
1645     {
1646         // Parse parameters
1647         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1648         if (vchData.size() != 128)
1649             throw JSONRPCError(-8, "Invalid parameter");
1650         CBlock* pdata = (CBlock*)&vchData[0];
1651
1652         // Byte reverse
1653         for (int i = 0; i < 128/4; i++)
1654             ((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
1655
1656         // Get saved block
1657         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1658             return false;
1659         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1660         unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
1661
1662         pblock->nTime = pdata->nTime;
1663         pblock->nNonce = pdata->nNonce;
1664         pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
1665         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1666
1667         return CheckWork(pblock, *pwalletMain, reservekey);
1668     }
1669 }
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681 //
1682 // Call Table
1683 //
1684
1685 pair<string, rpcfn_type> pCallTable[] =
1686 {
1687     make_pair("help",                   &help),
1688     make_pair("stop",                   &stop),
1689     make_pair("getblockcount",          &getblockcount),
1690     make_pair("getblocknumber",         &getblocknumber),
1691     make_pair("getconnectioncount",     &getconnectioncount),
1692     make_pair("getdifficulty",          &getdifficulty),
1693     make_pair("getgenerate",            &getgenerate),
1694     make_pair("setgenerate",            &setgenerate),
1695     make_pair("gethashespersec",        &gethashespersec),
1696     make_pair("getinfo",                &getinfo),
1697     make_pair("getnewaddress",          &getnewaddress),
1698     make_pair("getaccountaddress",      &getaccountaddress),
1699     make_pair("setaccount",             &setaccount),
1700     make_pair("setlabel",               &setaccount), // deprecated
1701     make_pair("getaccount",             &getaccount),
1702     make_pair("getlabel",               &getaccount), // deprecated
1703     make_pair("getaddressesbyaccount",  &getaddressesbyaccount),
1704     make_pair("getaddressesbylabel",    &getaddressesbyaccount), // deprecated
1705     make_pair("sendtoaddress",          &sendtoaddress),
1706     make_pair("getamountreceived",      &getreceivedbyaddress), // deprecated, renamed to getreceivedbyaddress
1707     make_pair("getallreceived",         &listreceivedbyaddress), // deprecated, renamed to listreceivedbyaddress
1708     make_pair("getreceivedbyaddress",   &getreceivedbyaddress),
1709     make_pair("getreceivedbyaccount",   &getreceivedbyaccount),
1710     make_pair("getreceivedbylabel",     &getreceivedbyaccount), // deprecated
1711     make_pair("listreceivedbyaddress",  &listreceivedbyaddress),
1712     make_pair("listreceivedbyaccount",  &listreceivedbyaccount),
1713     make_pair("listreceivedbylabel",    &listreceivedbyaccount), // deprecated
1714     make_pair("backupwallet",           &backupwallet),
1715     make_pair("keypoolrefill",          &keypoolrefill),
1716     make_pair("walletpassphrase",       &walletpassphrase),
1717     make_pair("walletpassphrasechange", &walletpassphrasechange),
1718     make_pair("walletlock",             &walletlock),
1719     make_pair("encryptwallet",          &encryptwallet),
1720     make_pair("validateaddress",        &validateaddress),
1721     make_pair("getbalance",             &getbalance),
1722     make_pair("move",                   &movecmd),
1723     make_pair("sendfrom",               &sendfrom),
1724     make_pair("sendmany",               &sendmany),
1725     make_pair("gettransaction",         &gettransaction),
1726     make_pair("listtransactions",       &listtransactions),
1727     make_pair("getwork",                &getwork),
1728     make_pair("listaccounts",           &listaccounts),
1729     make_pair("settxfee",               &settxfee),
1730 };
1731 map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
1732
1733 string pAllowInSafeMode[] =
1734 {
1735     "help",
1736     "stop",
1737     "getblockcount",
1738     "getblocknumber",
1739     "getconnectioncount",
1740     "getdifficulty",
1741     "getgenerate",
1742     "setgenerate",
1743     "gethashespersec",
1744     "getinfo",
1745     "getnewaddress",
1746     "getaccountaddress",
1747     "setlabel", // deprecated
1748     "getaccount",
1749     "getlabel", // deprecated
1750     "getaddressesbyaccount",
1751     "getaddressesbylabel", // deprecated
1752     "backupwallet",
1753     "keypoolrefill",
1754     "walletpassphrase",
1755     "walletlock",
1756     "validateaddress",
1757     "getwork",
1758 };
1759 set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
1760
1761
1762
1763
1764 //
1765 // HTTP protocol
1766 //
1767 // This ain't Apache.  We're just using HTTP header for the length field
1768 // and to be compatible with other JSON-RPC implementations.
1769 //
1770
1771 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
1772 {
1773     ostringstream s;
1774     s << "POST / HTTP/1.1\r\n"
1775       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
1776       << "Host: 127.0.0.1\r\n"
1777       << "Content-Type: application/json\r\n"
1778       << "Content-Length: " << strMsg.size() << "\r\n"
1779       << "Accept: application/json\r\n";
1780     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
1781         s << item.first << ": " << item.second << "\r\n";
1782     s << "\r\n" << strMsg;
1783
1784     return s.str();
1785 }
1786
1787 string rfc1123Time()
1788 {
1789     char buffer[64];
1790     time_t now;
1791     time(&now);
1792     struct tm* now_gmt = gmtime(&now);
1793     string locale(setlocale(LC_TIME, NULL));
1794     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
1795     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
1796     setlocale(LC_TIME, locale.c_str());
1797     return string(buffer);
1798 }
1799
1800 static string HTTPReply(int nStatus, const string& strMsg)
1801 {
1802     if (nStatus == 401)
1803         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
1804             "Date: %s\r\n"
1805             "Server: bitcoin-json-rpc/%s\r\n"
1806             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
1807             "Content-Type: text/html\r\n"
1808             "Content-Length: 296\r\n"
1809             "\r\n"
1810             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
1811             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
1812             "<HTML>\r\n"
1813             "<HEAD>\r\n"
1814             "<TITLE>Error</TITLE>\r\n"
1815             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
1816             "</HEAD>\r\n"
1817             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
1818             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
1819     string strStatus;
1820          if (nStatus == 200) strStatus = "OK";
1821     else if (nStatus == 400) strStatus = "Bad Request";
1822     else if (nStatus == 403) strStatus = "Forbidden";
1823     else if (nStatus == 404) strStatus = "Not Found";
1824     else if (nStatus == 500) strStatus = "Internal Server Error";
1825     return strprintf(
1826             "HTTP/1.1 %d %s\r\n"
1827             "Date: %s\r\n"
1828             "Connection: close\r\n"
1829             "Content-Length: %d\r\n"
1830             "Content-Type: application/json\r\n"
1831             "Server: bitcoin-json-rpc/%s\r\n"
1832             "\r\n"
1833             "%s",
1834         nStatus,
1835         strStatus.c_str(),
1836         rfc1123Time().c_str(),
1837         strMsg.size(),
1838         FormatFullVersion().c_str(),
1839         strMsg.c_str());
1840 }
1841
1842 int ReadHTTPStatus(std::basic_istream<char>& stream)
1843 {
1844     string str;
1845     getline(stream, str);
1846     vector<string> vWords;
1847     boost::split(vWords, str, boost::is_any_of(" "));
1848     if (vWords.size() < 2)
1849         return 500;
1850     return atoi(vWords[1].c_str());
1851 }
1852
1853 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
1854 {
1855     int nLen = 0;
1856     loop
1857     {
1858         string str;
1859         std::getline(stream, str);
1860         if (str.empty() || str == "\r")
1861             break;
1862         string::size_type nColon = str.find(":");
1863         if (nColon != string::npos)
1864         {
1865             string strHeader = str.substr(0, nColon);
1866             boost::trim(strHeader);
1867             boost::to_lower(strHeader);
1868             string strValue = str.substr(nColon+1);
1869             boost::trim(strValue);
1870             mapHeadersRet[strHeader] = strValue;
1871             if (strHeader == "content-length")
1872                 nLen = atoi(strValue.c_str());
1873         }
1874     }
1875     return nLen;
1876 }
1877
1878 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
1879 {
1880     mapHeadersRet.clear();
1881     strMessageRet = "";
1882
1883     // Read status
1884     int nStatus = ReadHTTPStatus(stream);
1885
1886     // Read header
1887     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
1888     if (nLen < 0 || nLen > MAX_SIZE)
1889         return 500;
1890
1891     // Read message
1892     if (nLen > 0)
1893     {
1894         vector<char> vch(nLen);
1895         stream.read(&vch[0], nLen);
1896         strMessageRet = string(vch.begin(), vch.end());
1897     }
1898
1899     return nStatus;
1900 }
1901
1902 string EncodeBase64(string s)
1903 {
1904     BIO *b64, *bmem;
1905     BUF_MEM *bptr;
1906
1907     b64 = BIO_new(BIO_f_base64());
1908     BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1909     bmem = BIO_new(BIO_s_mem());
1910     b64 = BIO_push(b64, bmem);
1911     BIO_write(b64, s.c_str(), s.size());
1912     BIO_flush(b64);
1913     BIO_get_mem_ptr(b64, &bptr);
1914
1915     string result(bptr->data, bptr->length);
1916     BIO_free_all(b64);
1917
1918     return result;
1919 }
1920
1921 string DecodeBase64(string s)
1922 {
1923     BIO *b64, *bmem;
1924
1925     char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
1926
1927     b64 = BIO_new(BIO_f_base64());
1928     BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
1929     bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
1930     bmem = BIO_push(b64, bmem);
1931     BIO_read(bmem, buffer, s.size());
1932     BIO_free_all(bmem);
1933
1934     string result(buffer);
1935     free(buffer);
1936     return result;
1937 }
1938
1939 bool HTTPAuthorized(map<string, string>& mapHeaders)
1940 {
1941     string strAuth = mapHeaders["authorization"];
1942     if (strAuth.substr(0,6) != "Basic ")
1943         return false;
1944     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
1945     string strUserPass = DecodeBase64(strUserPass64);
1946     string::size_type nColon = strUserPass.find(":");
1947     if (nColon == string::npos)
1948         return false;
1949     string strUser = strUserPass.substr(0, nColon);
1950     string strPassword = strUserPass.substr(nColon+1);
1951     return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
1952 }
1953
1954 //
1955 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
1956 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
1957 // unspecified (HTTP errors and contents of 'error').
1958 //
1959 // 1.0 spec: http://json-rpc.org/wiki/specification
1960 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
1961 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
1962 //
1963
1964 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
1965 {
1966     Object request;
1967     request.push_back(Pair("method", strMethod));
1968     request.push_back(Pair("params", params));
1969     request.push_back(Pair("id", id));
1970     return write_string(Value(request), false) + "\n";
1971 }
1972
1973 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
1974 {
1975     Object reply;
1976     if (error.type() != null_type)
1977         reply.push_back(Pair("result", Value::null));
1978     else
1979         reply.push_back(Pair("result", result));
1980     reply.push_back(Pair("error", error));
1981     reply.push_back(Pair("id", id));
1982     return write_string(Value(reply), false) + "\n";
1983 }
1984
1985 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
1986 {
1987     // Send error reply from json-rpc error object
1988     int nStatus = 500;
1989     int code = find_value(objError, "code").get_int();
1990     if (code == -32600) nStatus = 400;
1991     else if (code == -32601) nStatus = 404;
1992     string strReply = JSONRPCReply(Value::null, objError, id);
1993     stream << HTTPReply(nStatus, strReply) << std::flush;
1994 }
1995
1996 bool ClientAllowed(const string& strAddress)
1997 {
1998     if (strAddress == asio::ip::address_v4::loopback().to_string())
1999         return true;
2000     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2001     BOOST_FOREACH(string strAllow, vAllow)
2002         if (WildcardMatch(strAddress, strAllow))
2003             return true;
2004     return false;
2005 }
2006
2007 #ifdef USE_SSL
2008 //
2009 // IOStream device that speaks SSL but can also speak non-SSL
2010 //
2011 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2012 public:
2013     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2014     {
2015         fUseSSL = fUseSSLIn;
2016         fNeedHandshake = fUseSSLIn;
2017     }
2018
2019     void handshake(ssl::stream_base::handshake_type role)
2020     {
2021         if (!fNeedHandshake) return;
2022         fNeedHandshake = false;
2023         stream.handshake(role);
2024     }
2025     std::streamsize read(char* s, std::streamsize n)
2026     {
2027         handshake(ssl::stream_base::server); // HTTPS servers read first
2028         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2029         return stream.next_layer().read_some(asio::buffer(s, n));
2030     }
2031     std::streamsize write(const char* s, std::streamsize n)
2032     {
2033         handshake(ssl::stream_base::client); // HTTPS clients write first
2034         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2035         return asio::write(stream.next_layer(), asio::buffer(s, n));
2036     }
2037     bool connect(const std::string& server, const std::string& port)
2038     {
2039         ip::tcp::resolver resolver(stream.get_io_service());
2040         ip::tcp::resolver::query query(server.c_str(), port.c_str());
2041         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2042         ip::tcp::resolver::iterator end;
2043         boost::system::error_code error = asio::error::host_not_found;
2044         while (error && endpoint_iterator != end)
2045         {
2046             stream.lowest_layer().close();
2047             stream.lowest_layer().connect(*endpoint_iterator++, error);
2048         }
2049         if (error)
2050             return false;
2051         return true;
2052     }
2053
2054 private:
2055     bool fNeedHandshake;
2056     bool fUseSSL;
2057     SSLStream& stream;
2058 };
2059 #endif
2060
2061 void ThreadRPCServer(void* parg)
2062 {
2063     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2064     try
2065     {
2066         vnThreadsRunning[4]++;
2067         ThreadRPCServer2(parg);
2068         vnThreadsRunning[4]--;
2069     }
2070     catch (std::exception& e) {
2071         vnThreadsRunning[4]--;
2072         PrintException(&e, "ThreadRPCServer()");
2073     } catch (...) {
2074         vnThreadsRunning[4]--;
2075         PrintException(NULL, "ThreadRPCServer()");
2076     }
2077     printf("ThreadRPCServer exiting\n");
2078 }
2079
2080 void ThreadRPCServer2(void* parg)
2081 {
2082     printf("ThreadRPCServer started\n");
2083
2084     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2085     {
2086         string strWhatAmI = "To use bitcoind";
2087         if (mapArgs.count("-server"))
2088             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2089         else if (mapArgs.count("-daemon"))
2090             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2091         PrintConsole(
2092             _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
2093               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2094                 strWhatAmI.c_str(),
2095                 GetConfigFile().c_str());
2096         CreateThread(Shutdown, NULL);
2097         return;
2098     }
2099
2100     bool fUseSSL = GetBoolArg("-rpcssl");
2101     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2102
2103     asio::io_service io_service;
2104     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2105     ip::tcp::acceptor acceptor(io_service, endpoint);
2106
2107     acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2108
2109 #ifdef USE_SSL
2110     ssl::context context(io_service, ssl::context::sslv23);
2111     if (fUseSSL)
2112     {
2113         context.set_options(ssl::context::no_sslv2);
2114         filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
2115         if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
2116         if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
2117         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
2118         filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
2119         if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
2120         if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
2121         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
2122
2123         string ciphers = GetArg("-rpcsslciphers",
2124                                          "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2125         SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
2126     }
2127 #else
2128     if (fUseSSL)
2129         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2130 #endif
2131
2132     loop
2133     {
2134         // Accept connection
2135 #ifdef USE_SSL
2136         SSLStream sslStream(io_service, context);
2137         SSLIOStreamDevice d(sslStream, fUseSSL);
2138         iostreams::stream<SSLIOStreamDevice> stream(d);
2139 #else
2140         ip::tcp::iostream stream;
2141 #endif
2142
2143         ip::tcp::endpoint peer;
2144         vnThreadsRunning[4]--;
2145 #ifdef USE_SSL
2146         acceptor.accept(sslStream.lowest_layer(), peer);
2147 #else
2148         acceptor.accept(*stream.rdbuf(), peer);
2149 #endif
2150         vnThreadsRunning[4]++;
2151         if (fShutdown)
2152             return;
2153
2154         // Restrict callers by IP
2155         if (!ClientAllowed(peer.address().to_string()))
2156         {
2157             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2158             if (!fUseSSL)
2159                 stream << HTTPReply(403, "") << std::flush;
2160             continue;
2161         }
2162
2163         map<string, string> mapHeaders;
2164         string strRequest;
2165
2166         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2167         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2168         {   // Timed out:
2169             acceptor.cancel();
2170             printf("ThreadRPCServer ReadHTTP timeout\n");
2171             continue;
2172         }
2173
2174         // Check authorization
2175         if (mapHeaders.count("authorization") == 0)
2176         {
2177             stream << HTTPReply(401, "") << std::flush;
2178             continue;
2179         }
2180         if (!HTTPAuthorized(mapHeaders))
2181         {
2182             // Deter brute-forcing short passwords
2183             if (mapArgs["-rpcpassword"].size() < 15)
2184                 Sleep(50);
2185
2186             stream << HTTPReply(401, "") << std::flush;
2187             printf("ThreadRPCServer incorrect password attempt\n");
2188             continue;
2189         }
2190
2191         Value id = Value::null;
2192         try
2193         {
2194             // Parse request
2195             Value valRequest;
2196             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2197                 throw JSONRPCError(-32700, "Parse error");
2198             const Object& request = valRequest.get_obj();
2199
2200             // Parse id now so errors from here on will have the id
2201             id = find_value(request, "id");
2202
2203             // Parse method
2204             Value valMethod = find_value(request, "method");
2205             if (valMethod.type() == null_type)
2206                 throw JSONRPCError(-32600, "Missing method");
2207             if (valMethod.type() != str_type)
2208                 throw JSONRPCError(-32600, "Method must be a string");
2209             string strMethod = valMethod.get_str();
2210             if (strMethod != "getwork")
2211                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2212
2213             // Parse params
2214             Value valParams = find_value(request, "params");
2215             Array params;
2216             if (valParams.type() == array_type)
2217                 params = valParams.get_array();
2218             else if (valParams.type() == null_type)
2219                 params = Array();
2220             else
2221                 throw JSONRPCError(-32600, "Params must be an array");
2222
2223             // Find method
2224             map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
2225             if (mi == mapCallTable.end())
2226                 throw JSONRPCError(-32601, "Method not found");
2227
2228             // Observe safe mode
2229             string strWarning = GetWarnings("rpc");
2230             if (strWarning != "" && !GetBoolArg("-disablesafemode") && !setAllowInSafeMode.count(strMethod))
2231                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2232
2233             try
2234             {
2235                 // Execute
2236                 Value result = (*(*mi).second)(params, false);
2237
2238                 // Send reply
2239                 string strReply = JSONRPCReply(result, Value::null, id);
2240                 stream << HTTPReply(200, strReply) << std::flush;
2241             }
2242             catch (std::exception& e)
2243             {
2244                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2245             }
2246         }
2247         catch (Object& objError)
2248         {
2249             ErrorReply(stream, objError, id);
2250         }
2251         catch (std::exception& e)
2252         {
2253             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2254         }
2255     }
2256 }
2257
2258
2259
2260
2261 Object CallRPC(const string& strMethod, const Array& params)
2262 {
2263     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2264         throw runtime_error(strprintf(
2265             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2266               "If the file does not exist, create it with owner-readable-only file permissions."),
2267                 GetConfigFile().c_str()));
2268
2269     // Connect to localhost
2270     bool fUseSSL = GetBoolArg("-rpcssl");
2271 #ifdef USE_SSL
2272     asio::io_service io_service;
2273     ssl::context context(io_service, ssl::context::sslv23);
2274     context.set_options(ssl::context::no_sslv2);
2275     SSLStream sslStream(io_service, context);
2276     SSLIOStreamDevice d(sslStream, fUseSSL);
2277     iostreams::stream<SSLIOStreamDevice> stream(d);
2278     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2279         throw runtime_error("couldn't connect to server");
2280 #else
2281     if (fUseSSL)
2282         throw runtime_error("-rpcssl=1, but bitcoin compiled without full openssl libraries.");
2283
2284     ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
2285     if (stream.fail())
2286         throw runtime_error("couldn't connect to server");
2287 #endif
2288
2289
2290     // HTTP basic authentication
2291     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2292     map<string, string> mapRequestHeaders;
2293     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2294
2295     // Send request
2296     string strRequest = JSONRPCRequest(strMethod, params, 1);
2297     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2298     stream << strPost << std::flush;
2299
2300     // Receive reply
2301     map<string, string> mapHeaders;
2302     string strReply;
2303     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2304     if (nStatus == 401)
2305         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2306     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2307         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2308     else if (strReply.empty())
2309         throw runtime_error("no response from server");
2310
2311     // Parse reply
2312     Value valReply;
2313     if (!read_string(strReply, valReply))
2314         throw runtime_error("couldn't parse reply from server");
2315     const Object& reply = valReply.get_obj();
2316     if (reply.empty())
2317         throw runtime_error("expected reply to have result, error and id properties");
2318
2319     return reply;
2320 }
2321
2322
2323
2324
2325 template<typename T>
2326 void ConvertTo(Value& value)
2327 {
2328     if (value.type() == str_type)
2329     {
2330         // reinterpret string as unquoted json value
2331         Value value2;
2332         if (!read_string(value.get_str(), value2))
2333             throw runtime_error("type mismatch");
2334         value = value2.get_value<T>();
2335     }
2336     else
2337     {
2338         value = value.get_value<T>();
2339     }
2340 }
2341
2342 int CommandLineRPC(int argc, char *argv[])
2343 {
2344     string strPrint;
2345     int nRet = 0;
2346     try
2347     {
2348         // Skip switches
2349         while (argc > 1 && IsSwitchChar(argv[1][0]))
2350         {
2351             argc--;
2352             argv++;
2353         }
2354
2355         // Method
2356         if (argc < 2)
2357             throw runtime_error("too few parameters");
2358         string strMethod = argv[1];
2359
2360         // Parameters default to strings
2361         Array params;
2362         for (int i = 2; i < argc; i++)
2363             params.push_back(argv[i]);
2364         int n = params.size();
2365
2366         //
2367         // Special case non-string parameter types
2368         //
2369         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2370         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2371         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2372         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2373         if (strMethod == "getamountreceived"      && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2374         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2375         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2376         if (strMethod == "getreceivedbylabel"     && n > 1) ConvertTo<boost::int64_t>(params[1]); // deprecated
2377         if (strMethod == "getallreceived"         && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2378         if (strMethod == "getallreceived"         && n > 1) ConvertTo<bool>(params[1]); // deprecated
2379         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2380         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2381         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2382         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2383         if (strMethod == "listreceivedbylabel"    && n > 0) ConvertTo<boost::int64_t>(params[0]); // deprecated
2384         if (strMethod == "listreceivedbylabel"    && n > 1) ConvertTo<bool>(params[1]); // deprecated
2385         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2386         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2387         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2388         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2389         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2390         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2391         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2392         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2393         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2394         if (strMethod == "sendmany"               && n > 1)
2395         {
2396             string s = params[1].get_str();
2397             Value v;
2398             if (!read_string(s, v) || v.type() != obj_type)
2399                 throw runtime_error("type mismatch");
2400             params[1] = v.get_obj();
2401         }
2402         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2403
2404         // Execute
2405         Object reply = CallRPC(strMethod, params);
2406
2407         // Parse reply
2408         const Value& result = find_value(reply, "result");
2409         const Value& error  = find_value(reply, "error");
2410
2411         if (error.type() != null_type)
2412         {
2413             // Error
2414             strPrint = "error: " + write_string(error, false);
2415             int code = find_value(error.get_obj(), "code").get_int();
2416             nRet = abs(code);
2417         }
2418         else
2419         {
2420             // Result
2421             if (result.type() == null_type)
2422                 strPrint = "";
2423             else if (result.type() == str_type)
2424                 strPrint = result.get_str();
2425             else
2426                 strPrint = write_string(result, true);
2427         }
2428     }
2429     catch (std::exception& e)
2430     {
2431         strPrint = string("error: ") + e.what();
2432         nRet = 87;
2433     }
2434     catch (...)
2435     {
2436         PrintException(NULL, "CommandLineRPC()");
2437     }
2438
2439     if (strPrint != "")
2440     {
2441 #if defined(__WXMSW__) && defined(GUI)
2442         // Windows GUI apps can't print to command line,
2443         // so settle for a message box yuck
2444         MyMessageBox(strPrint, "Bitcoin", wxOK);
2445 #else
2446         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2447 #endif
2448     }
2449     return nRet;
2450 }
2451
2452
2453
2454
2455 #ifdef TEST
2456 int main(int argc, char *argv[])
2457 {
2458 #ifdef _MSC_VER
2459     // Turn off microsoft heap dump noise
2460     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2461     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2462 #endif
2463     setbuf(stdin, NULL);
2464     setbuf(stdout, NULL);
2465     setbuf(stderr, NULL);
2466
2467     try
2468     {
2469         if (argc >= 2 && string(argv[1]) == "-server")
2470         {
2471             printf("server ready\n");
2472             ThreadRPCServer(NULL);
2473         }
2474         else
2475         {
2476             return CommandLineRPC(argc, argv);
2477         }
2478     }
2479     catch (std::exception& e) {
2480         PrintException(&e, "main()");
2481     } catch (...) {
2482         PrintException(NULL, "main()");
2483     }
2484     return 0;
2485 }
2486 #endif