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