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