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