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