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