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