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