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