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