206347faf87c4a63ccda55f9dcbcc4c188dc7eb6
[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 "main.h"
7 #include "wallet.h"
8 #include "db.h"
9 #include "walletdb.h"
10 #include "net.h"
11 #include "init.h"
12 #include "ui_interface.h"
13 #include "bitcoinrpc.h"
14
15 #undef printf
16 #include <boost/asio.hpp>
17 #include <boost/filesystem.hpp>
18 #include <boost/iostreams/concepts.hpp>
19 #include <boost/iostreams/stream.hpp>
20 #include <boost/algorithm/string.hpp>
21 #include <boost/lexical_cast.hpp>
22 #include <boost/asio/ssl.hpp> 
23 #include <boost/filesystem/fstream.hpp>
24 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
25
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
39 static std::string strRPCUserColonPass;
40
41 static int64 nWalletUnlockTime;
42 static CCriticalSection cs_nWalletUnlockTime;
43
44 extern Value dumpprivkey(const Array& params, bool fHelp);
45 extern Value importprivkey(const Array& params, bool fHelp);
46
47 Object JSONRPCError(int code, const string& message)
48 {
49     Object error;
50     error.push_back(Pair("code", code));
51     error.push_back(Pair("message", message));
52     return error;
53 }
54
55 double GetDifficulty(const CBlockIndex* blockindex = NULL)
56 {
57     // Floating point number that is a multiple of the minimum difficulty,
58     // minimum difficulty = 1.0.
59     if (blockindex == NULL)
60     {
61         if (pindexBest == NULL)
62             return 1.0;
63         else
64             blockindex = pindexBest;
65     }
66
67     int nShift = (blockindex->nBits >> 24) & 0xff;
68
69     double dDiff =
70         (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);
71
72     while (nShift < 29)
73     {
74         dDiff *= 256.0;
75         nShift++;
76     }
77     while (nShift > 29)
78     {
79         dDiff /= 256.0;
80         nShift--;
81     }
82
83     return dDiff;
84 }
85
86
87 int64 AmountFromValue(const Value& value)
88 {
89     double dAmount = value.get_real();
90     if (dAmount <= 0.0 || dAmount > 21000000.0)
91         throw JSONRPCError(-3, "Invalid amount");
92     int64 nAmount = roundint64(dAmount * COIN);
93     if (!MoneyRange(nAmount))
94         throw JSONRPCError(-3, "Invalid amount");
95     return nAmount;
96 }
97
98 Value ValueFromAmount(int64 amount)
99 {
100     return (double)amount / (double)COIN;
101 }
102
103 std::string
104 HexBits(unsigned int nBits)
105 {
106     union {
107         int32_t nBits;
108         char cBits[4];
109     } uBits;
110     uBits.nBits = htonl((int32_t)nBits);
111     return HexStr(BEGIN(uBits.cBits), END(uBits.cBits));
112 }
113
114 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
115 {
116     int confirms = wtx.GetDepthInMainChain();
117     entry.push_back(Pair("confirmations", confirms));
118     if (confirms)
119     {
120         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
121         entry.push_back(Pair("blockindex", wtx.nIndex));
122     }
123     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
124     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
125     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
126         entry.push_back(Pair(item.first, item.second));
127 }
128
129 string AccountFromValue(const Value& value)
130 {
131     string strAccount = value.get_str();
132     if (strAccount == "*")
133         throw JSONRPCError(-11, "Invalid account name");
134     return strAccount;
135 }
136
137 Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
138 {
139     Object result;
140     result.push_back(Pair("hash", block.GetHash().GetHex()));
141     result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
142     result.push_back(Pair("height", blockindex->nHeight));
143     result.push_back(Pair("version", block.nVersion));
144     result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
145     result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
146     result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
147     result.push_back(Pair("bits", HexBits(block.nBits)));
148     result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
149     Array txhashes;
150     BOOST_FOREACH (const CTransaction&tx, block.vtx)
151         txhashes.push_back(tx.GetHash().GetHex());
152     result.push_back(Pair("tx", txhashes));
153
154     if (blockindex->pprev)
155         result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
156     if (blockindex->pnext)
157         result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));
158     return result;
159 }
160
161
162
163 ///
164 /// Note: This interface may still be subject to change.
165 ///
166
167 string CRPCTable::help(string strCommand) const
168 {
169     string strRet;
170     set<rpcfn_type> setDone;
171     for (map<string, const CRPCCommand*>::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi)
172     {
173         const CRPCCommand *pcmd = mi->second;
174         string strMethod = mi->first;
175         // We already filter duplicates, but these deprecated screw up the sort order
176         if (strMethod == "getamountreceived" ||
177             strMethod == "getallreceived" ||
178             strMethod == "getblocknumber" || // deprecated
179             (strMethod.find("label") != string::npos))
180             continue;
181         if (strCommand != "" && strMethod != strCommand)
182             continue;
183         try
184         {
185             Array params;
186             rpcfn_type pfn = pcmd->actor;
187             if (setDone.insert(pfn).second)
188                 (*pfn)(params, true);
189         }
190         catch (std::exception& e)
191         {
192             // Help text is returned in an exception
193             string strHelp = string(e.what());
194             if (strCommand == "")
195                 if (strHelp.find('\n') != string::npos)
196                     strHelp = strHelp.substr(0, strHelp.find('\n'));
197             strRet += strHelp + "\n";
198         }
199     }
200     if (strRet == "")
201         strRet = strprintf("help: unknown command: %s\n", strCommand.c_str());
202     strRet = strRet.substr(0,strRet.size()-1);
203     return strRet;
204 }
205
206 Value help(const Array& params, bool fHelp)
207 {
208     if (fHelp || params.size() > 1)
209         throw runtime_error(
210             "help [command]\n"
211             "List commands, or get help for a command.");
212
213     string strCommand;
214     if (params.size() > 0)
215         strCommand = params[0].get_str();
216
217     return tableRPC.help(strCommand);
218 }
219
220
221 Value stop(const Array& params, bool fHelp)
222 {
223     if (fHelp || params.size() != 0)
224         throw runtime_error(
225             "stop\n"
226             "Stop bitcoin server.");
227     // Shutdown will take long enough that the response should get back
228     QueueShutdown();
229     return "bitcoin server stopping";
230 }
231
232
233 Value getblockcount(const Array& params, bool fHelp)
234 {
235     if (fHelp || params.size() != 0)
236         throw runtime_error(
237             "getblockcount\n"
238             "Returns the number of blocks in the longest block chain.");
239
240     return nBestHeight;
241 }
242
243
244 // deprecated
245 Value getblocknumber(const Array& params, bool fHelp)
246 {
247     if (fHelp || params.size() != 0)
248         throw runtime_error(
249             "getblocknumber\n"
250             "Deprecated.  Use getblockcount.");
251
252     return nBestHeight;
253 }
254
255
256 Value getconnectioncount(const Array& params, bool fHelp)
257 {
258     if (fHelp || params.size() != 0)
259         throw runtime_error(
260             "getconnectioncount\n"
261             "Returns the number of connections to other nodes.");
262
263     return (int)vNodes.size();
264 }
265
266
267 Value getdifficulty(const Array& params, bool fHelp)
268 {
269     if (fHelp || params.size() != 0)
270         throw runtime_error(
271             "getdifficulty\n"
272             "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
273
274     return GetDifficulty();
275 }
276
277
278 Value getgenerate(const Array& params, bool fHelp)
279 {
280     if (fHelp || params.size() != 0)
281         throw runtime_error(
282             "getgenerate\n"
283             "Returns true or false.");
284
285     return GetBoolArg("-gen");
286 }
287
288
289 Value setgenerate(const Array& params, bool fHelp)
290 {
291     if (fHelp || params.size() < 1 || params.size() > 2)
292         throw runtime_error(
293             "setgenerate <generate> [genproclimit]\n"
294             "<generate> is true or false to turn generation on or off.\n"
295             "Generation is limited to [genproclimit] processors, -1 is unlimited.");
296
297     bool fGenerate = true;
298     if (params.size() > 0)
299         fGenerate = params[0].get_bool();
300
301     if (params.size() > 1)
302     {
303         int nGenProcLimit = params[1].get_int();
304         mapArgs["-genproclimit"] = itostr(nGenProcLimit);
305         if (nGenProcLimit == 0)
306             fGenerate = false;
307     }
308     mapArgs["-gen"] = (fGenerate ? "1" : "0");
309
310     GenerateBitcoins(fGenerate, pwalletMain);
311     return Value::null;
312 }
313
314
315 Value gethashespersec(const Array& params, bool fHelp)
316 {
317     if (fHelp || params.size() != 0)
318         throw runtime_error(
319             "gethashespersec\n"
320             "Returns a recent hashes per second performance measurement while generating.");
321
322     if (GetTimeMillis() - nHPSTimerStart > 8000)
323         return (boost::int64_t)0;
324     return (boost::int64_t)dHashesPerSec;
325 }
326
327
328 Value getinfo(const Array& params, bool fHelp)
329 {
330     if (fHelp || params.size() != 0)
331         throw runtime_error(
332             "getinfo\n"
333             "Returns an object containing various state info.");
334
335     Object obj;
336     obj.push_back(Pair("version",       (int)CLIENT_VERSION));
337     obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
338     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
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)mempool.size()));
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, 0);
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, 0);
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             {
805                 BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
806                     nBalance += r.second;
807             }
808             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
809                 nBalance -= r.second;
810             nBalance -= allFee;
811             nBalance += allGeneratedMature;
812         }
813         return  ValueFromAmount(nBalance);
814     }
815
816     string strAccount = AccountFromValue(params[0]);
817
818     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
819
820     return ValueFromAmount(nBalance);
821 }
822
823
824 Value movecmd(const Array& params, bool fHelp)
825 {
826     if (fHelp || params.size() < 3 || params.size() > 5)
827         throw runtime_error(
828             "move <fromaccount> <toaccount> <amount> [minconf=1] [comment]\n"
829             "Move from one account in your wallet to another.");
830
831     string strFrom = AccountFromValue(params[0]);
832     string strTo = AccountFromValue(params[1]);
833     int64 nAmount = AmountFromValue(params[2]);
834     if (params.size() > 3)
835         // unused parameter, used to be nMinDepth, keep type-checking it though
836         (void)params[3].get_int();
837     string strComment;
838     if (params.size() > 4)
839         strComment = params[4].get_str();
840
841     CWalletDB walletdb(pwalletMain->strWalletFile);
842     walletdb.TxnBegin();
843
844     int64 nNow = GetAdjustedTime();
845
846     // Debit
847     CAccountingEntry debit;
848     debit.strAccount = strFrom;
849     debit.nCreditDebit = -nAmount;
850     debit.nTime = nNow;
851     debit.strOtherAccount = strTo;
852     debit.strComment = strComment;
853     walletdb.WriteAccountingEntry(debit);
854
855     // Credit
856     CAccountingEntry credit;
857     credit.strAccount = strTo;
858     credit.nCreditDebit = nAmount;
859     credit.nTime = nNow;
860     credit.strOtherAccount = strFrom;
861     credit.strComment = strComment;
862     walletdb.WriteAccountingEntry(credit);
863
864     walletdb.TxnCommit();
865
866     return true;
867 }
868
869
870 Value sendfrom(const Array& params, bool fHelp)
871 {
872     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
873         throw runtime_error(
874             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
875             "<amount> is a real and is rounded to the nearest 0.00000001\n"
876             "requires wallet passphrase to be set with walletpassphrase first");
877     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 3 || params.size() > 6))
878         throw runtime_error(
879             "sendfrom <fromaccount> <tobitcoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
880             "<amount> is a real and is rounded to the nearest 0.00000001");
881
882     string strAccount = AccountFromValue(params[0]);
883     CBitcoinAddress address(params[1].get_str());
884     if (!address.IsValid())
885         throw JSONRPCError(-5, "Invalid bitcoin address");
886     int64 nAmount = AmountFromValue(params[2]);
887     int nMinDepth = 1;
888     if (params.size() > 3)
889         nMinDepth = params[3].get_int();
890
891     CWalletTx wtx;
892     wtx.strFromAccount = strAccount;
893     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
894         wtx.mapValue["comment"] = params[4].get_str();
895     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
896         wtx.mapValue["to"]      = params[5].get_str();
897
898     if (pwalletMain->IsLocked())
899         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
900
901     // Check funds
902     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
903     if (nAmount > nBalance)
904         throw JSONRPCError(-6, "Account has insufficient funds");
905
906     // Send
907     string strError = pwalletMain->SendMoneyToBitcoinAddress(address, nAmount, wtx);
908     if (strError != "")
909         throw JSONRPCError(-4, strError);
910
911     return wtx.GetHash().GetHex();
912 }
913
914
915 Value sendmany(const Array& params, bool fHelp)
916 {
917     if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
918         throw runtime_error(
919             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
920             "amounts are double-precision floating point numbers\n"
921             "requires wallet passphrase to be set with walletpassphrase first");
922     if (!pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 4))
923         throw runtime_error(
924             "sendmany <fromaccount> {address:amount,...} [minconf=1] [comment]\n"
925             "amounts are double-precision floating point numbers");
926
927     string strAccount = AccountFromValue(params[0]);
928     Object sendTo = params[1].get_obj();
929     int nMinDepth = 1;
930     if (params.size() > 2)
931         nMinDepth = params[2].get_int();
932
933     CWalletTx wtx;
934     wtx.strFromAccount = strAccount;
935     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
936         wtx.mapValue["comment"] = params[3].get_str();
937
938     set<CBitcoinAddress> setAddress;
939     vector<pair<CScript, int64> > vecSend;
940
941     int64 totalAmount = 0;
942     BOOST_FOREACH(const Pair& s, sendTo)
943     {
944         CBitcoinAddress address(s.name_);
945         if (!address.IsValid())
946             throw JSONRPCError(-5, string("Invalid bitcoin address:")+s.name_);
947
948         if (setAddress.count(address))
949             throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_);
950         setAddress.insert(address);
951
952         CScript scriptPubKey;
953         scriptPubKey.SetBitcoinAddress(address);
954         int64 nAmount = AmountFromValue(s.value_); 
955         totalAmount += nAmount;
956
957         vecSend.push_back(make_pair(scriptPubKey, nAmount));
958     }
959
960     if (pwalletMain->IsLocked())
961         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
962
963     // Check funds
964     int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
965     if (totalAmount > nBalance)
966         throw JSONRPCError(-6, "Account has insufficient funds");
967
968     // Send
969     CReserveKey keyChange(pwalletMain);
970     int64 nFeeRequired = 0;
971     bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
972     if (!fCreated)
973     {
974         if (totalAmount + nFeeRequired > pwalletMain->GetBalance())
975             throw JSONRPCError(-6, "Insufficient funds");
976         throw JSONRPCError(-4, "Transaction creation failed");
977     }
978     if (!pwalletMain->CommitTransaction(wtx, keyChange))
979         throw JSONRPCError(-4, "Transaction commit failed");
980
981     return wtx.GetHash().GetHex();
982 }
983
984 Value addmultisigaddress(const Array& params, bool fHelp)
985 {
986     if (fHelp || params.size() < 2 || params.size() > 3)
987     {
988         string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
989             "Add a nrequired-to-sign multisignature address to the wallet\"\n"
990             "each key is a bitcoin address or hex-encoded public key\n"
991             "If [account] is specified, assign address to [account].";
992         throw runtime_error(msg);
993     }
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 (unsigned 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     {
1239         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1240         {
1241             string account;
1242             if (pwalletMain->mapAddressBook.count(r.first))
1243                 account = pwalletMain->mapAddressBook[r.first];
1244             if (fAllAccounts || (account == strAccount))
1245             {
1246                 Object entry;
1247                 entry.push_back(Pair("account", account));
1248                 entry.push_back(Pair("address", r.first.ToString()));
1249                 entry.push_back(Pair("category", "receive"));
1250                 entry.push_back(Pair("amount", ValueFromAmount(r.second)));
1251                 if (fLong)
1252                     WalletTxToJSON(wtx, entry);
1253                 ret.push_back(entry);
1254             }
1255         }
1256     }
1257 }
1258
1259 void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
1260 {
1261     bool fAllAccounts = (strAccount == string("*"));
1262
1263     if (fAllAccounts || acentry.strAccount == strAccount)
1264     {
1265         Object entry;
1266         entry.push_back(Pair("account", acentry.strAccount));
1267         entry.push_back(Pair("category", "move"));
1268         entry.push_back(Pair("time", (boost::int64_t)acentry.nTime));
1269         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
1270         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
1271         entry.push_back(Pair("comment", acentry.strComment));
1272         ret.push_back(entry);
1273     }
1274 }
1275
1276 Value listtransactions(const Array& params, bool fHelp)
1277 {
1278     if (fHelp || params.size() > 3)
1279         throw runtime_error(
1280             "listtransactions [account] [count=10] [from=0]\n"
1281             "Returns up to [count] most recent transactions skipping the first [from] transactions for account [account].");
1282
1283     string strAccount = "*";
1284     if (params.size() > 0)
1285         strAccount = params[0].get_str();
1286     int nCount = 10;
1287     if (params.size() > 1)
1288         nCount = params[1].get_int();
1289     int nFrom = 0;
1290     if (params.size() > 2)
1291         nFrom = params[2].get_int();
1292
1293     if (nCount < 0)
1294         throw JSONRPCError(-8, "Negative count");
1295     if (nFrom < 0)
1296         throw JSONRPCError(-8, "Negative from");
1297
1298     Array ret;
1299     CWalletDB walletdb(pwalletMain->strWalletFile);
1300
1301     // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
1302     typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
1303     typedef multimap<int64, TxPair > TxItems;
1304     TxItems txByTime;
1305
1306     // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
1307     // would make this much faster for applications that do this a lot.
1308     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1309     {
1310         CWalletTx* wtx = &((*it).second);
1311         txByTime.insert(make_pair(wtx->GetTxTime(), TxPair(wtx, (CAccountingEntry*)0)));
1312     }
1313     list<CAccountingEntry> acentries;
1314     walletdb.ListAccountCreditDebit(strAccount, acentries);
1315     BOOST_FOREACH(CAccountingEntry& entry, acentries)
1316     {
1317         txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
1318     }
1319
1320     // iterate backwards until we have nCount items to return:
1321     for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
1322     {
1323         CWalletTx *const pwtx = (*it).second.first;
1324         if (pwtx != 0)
1325             ListTransactions(*pwtx, strAccount, 0, true, ret);
1326         CAccountingEntry *const pacentry = (*it).second.second;
1327         if (pacentry != 0)
1328             AcentryToJSON(*pacentry, strAccount, ret);
1329
1330         if (ret.size() >= (nCount+nFrom)) break;
1331     }
1332     // ret is newest to oldest
1333     
1334     if (nFrom > ret.size()) nFrom = ret.size();
1335     if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
1336     Array::iterator first = ret.begin();
1337     std::advance(first, nFrom);
1338     Array::iterator last = ret.begin();
1339     std::advance(last, nFrom+nCount);
1340
1341     if (last != ret.end()) ret.erase(last, ret.end());
1342     if (first != ret.begin()) ret.erase(ret.begin(), first);
1343
1344     std::reverse(ret.begin(), ret.end()); // Return oldest to newest
1345
1346     return ret;
1347 }
1348
1349 Value listaccounts(const Array& params, bool fHelp)
1350 {
1351     if (fHelp || params.size() > 1)
1352         throw runtime_error(
1353             "listaccounts [minconf=1]\n"
1354             "Returns Object that has account names as keys, account balances as values.");
1355
1356     int nMinDepth = 1;
1357     if (params.size() > 0)
1358         nMinDepth = params[0].get_int();
1359
1360     map<string, int64> mapAccountBalances;
1361     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, string)& entry, pwalletMain->mapAddressBook) {
1362         if (pwalletMain->HaveKey(entry.first)) // This address belongs to me
1363             mapAccountBalances[entry.second] = 0;
1364     }
1365
1366     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
1367     {
1368         const CWalletTx& wtx = (*it).second;
1369         int64 nGeneratedImmature, nGeneratedMature, nFee;
1370         string strSentAccount;
1371         list<pair<CBitcoinAddress, int64> > listReceived;
1372         list<pair<CBitcoinAddress, int64> > listSent;
1373         wtx.GetAmounts(nGeneratedImmature, nGeneratedMature, listReceived, listSent, nFee, strSentAccount);
1374         mapAccountBalances[strSentAccount] -= nFee;
1375         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& s, listSent)
1376             mapAccountBalances[strSentAccount] -= s.second;
1377         if (wtx.GetDepthInMainChain() >= nMinDepth)
1378         {
1379             mapAccountBalances[""] += nGeneratedMature;
1380             BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
1381                 if (pwalletMain->mapAddressBook.count(r.first))
1382                     mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second;
1383                 else
1384                     mapAccountBalances[""] += r.second;
1385         }
1386     }
1387
1388     list<CAccountingEntry> acentries;
1389     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
1390     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
1391         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
1392
1393     Object ret;
1394     BOOST_FOREACH(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) {
1395         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
1396     }
1397     return ret;
1398 }
1399
1400 Value listsinceblock(const Array& params, bool fHelp)
1401 {
1402     if (fHelp)
1403         throw runtime_error(
1404             "listsinceblock [blockid] [target-confirmations]\n"
1405             "Get all transactions in blocks since block [blockid], or all transactions if omitted");
1406
1407     CBlockIndex *pindex = NULL;
1408     int target_confirms = 1;
1409
1410     if (params.size() > 0)
1411     {
1412         uint256 blockId = 0;
1413
1414         blockId.SetHex(params[0].get_str());
1415         pindex = CBlockLocator(blockId).GetBlockIndex();
1416     }
1417
1418     if (params.size() > 1)
1419     {
1420         target_confirms = params[1].get_int();
1421
1422         if (target_confirms < 1)
1423             throw JSONRPCError(-8, "Invalid parameter");
1424     }
1425
1426     int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
1427
1428     Array transactions;
1429
1430     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
1431     {
1432         CWalletTx tx = (*it).second;
1433
1434         if (depth == -1 || tx.GetDepthInMainChain() < depth)
1435             ListTransactions(tx, "*", 0, true, transactions);
1436     }
1437
1438     uint256 lastblock;
1439
1440     if (target_confirms == 1)
1441     {
1442         printf("oops!\n");
1443         lastblock = hashBestChain;
1444     }
1445     else
1446     {
1447         int target_height = pindexBest->nHeight + 1 - target_confirms;
1448
1449         CBlockIndex *block;
1450         for (block = pindexBest;
1451              block && block->nHeight > target_height;
1452              block = block->pprev)  { }
1453
1454         lastblock = block ? block->GetBlockHash() : 0;
1455     }
1456
1457     Object ret;
1458     ret.push_back(Pair("transactions", transactions));
1459     ret.push_back(Pair("lastblock", lastblock.GetHex()));
1460
1461     return ret;
1462 }
1463
1464 Value gettransaction(const Array& params, bool fHelp)
1465 {
1466     if (fHelp || params.size() != 1)
1467         throw runtime_error(
1468             "gettransaction <txid>\n"
1469             "Get detailed information about <txid>");
1470
1471     uint256 hash;
1472     hash.SetHex(params[0].get_str());
1473
1474     Object entry;
1475
1476     if (!pwalletMain->mapWallet.count(hash))
1477         throw JSONRPCError(-5, "Invalid or non-wallet transaction id");
1478     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
1479
1480     int64 nCredit = wtx.GetCredit();
1481     int64 nDebit = wtx.GetDebit();
1482     int64 nNet = nCredit - nDebit;
1483     int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0);
1484
1485     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
1486     if (wtx.IsFromMe())
1487         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
1488
1489     WalletTxToJSON(pwalletMain->mapWallet[hash], entry);
1490
1491     Array details;
1492     ListTransactions(pwalletMain->mapWallet[hash], "*", 0, false, details);
1493     entry.push_back(Pair("details", details));
1494
1495     return entry;
1496 }
1497
1498
1499 Value backupwallet(const Array& params, bool fHelp)
1500 {
1501     if (fHelp || params.size() != 1)
1502         throw runtime_error(
1503             "backupwallet <destination>\n"
1504             "Safely copies wallet.dat to destination, which can be a directory or a path with filename.");
1505
1506     string strDest = params[0].get_str();
1507     BackupWallet(*pwalletMain, strDest);
1508
1509     return Value::null;
1510 }
1511
1512
1513 Value keypoolrefill(const Array& params, bool fHelp)
1514 {
1515     if (pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1516         throw runtime_error(
1517             "keypoolrefill\n"
1518             "Fills the keypool, requires wallet passphrase to be set.");
1519     if (!pwalletMain->IsCrypted() && (fHelp || params.size() > 0))
1520         throw runtime_error(
1521             "keypoolrefill\n"
1522             "Fills the keypool.");
1523
1524     if (pwalletMain->IsLocked())
1525         throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
1526
1527     pwalletMain->TopUpKeyPool();
1528
1529     if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100))
1530         throw JSONRPCError(-4, "Error refreshing keypool.");
1531
1532     return Value::null;
1533 }
1534
1535
1536 void ThreadTopUpKeyPool(void* parg)
1537 {
1538     pwalletMain->TopUpKeyPool();
1539 }
1540
1541 void ThreadCleanWalletPassphrase(void* parg)
1542 {
1543     int64 nMyWakeTime = GetTimeMillis() + *((int64*)parg) * 1000;
1544
1545     ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1546
1547     if (nWalletUnlockTime == 0)
1548     {
1549         nWalletUnlockTime = nMyWakeTime;
1550
1551         do
1552         {
1553             if (nWalletUnlockTime==0)
1554                 break;
1555             int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
1556             if (nToSleep <= 0)
1557                 break;
1558
1559             LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1560             Sleep(nToSleep);
1561             ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
1562
1563         } while(1);
1564
1565         if (nWalletUnlockTime)
1566         {
1567             nWalletUnlockTime = 0;
1568             pwalletMain->Lock();
1569         }
1570     }
1571     else
1572     {
1573         if (nWalletUnlockTime < nMyWakeTime)
1574             nWalletUnlockTime = nMyWakeTime;
1575     }
1576
1577     LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
1578
1579     delete (int64*)parg;
1580 }
1581
1582 Value walletpassphrase(const Array& params, bool fHelp)
1583 {
1584     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1585         throw runtime_error(
1586             "walletpassphrase <passphrase> <timeout>\n"
1587             "Stores the wallet decryption key in memory for <timeout> seconds.");
1588     if (fHelp)
1589         return true;
1590     if (!pwalletMain->IsCrypted())
1591         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
1592
1593     if (!pwalletMain->IsLocked())
1594         throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
1595
1596     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
1597     SecureString strWalletPass;
1598     strWalletPass.reserve(100);
1599     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1600     // Alternately, find a way to make params[0] mlock()'d to begin with.
1601     strWalletPass = params[0].get_str().c_str();
1602
1603     if (strWalletPass.length() > 0)
1604     {
1605         if (!pwalletMain->Unlock(strWalletPass))
1606             throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1607     }
1608     else
1609         throw runtime_error(
1610             "walletpassphrase <passphrase> <timeout>\n"
1611             "Stores the wallet decryption key in memory for <timeout> seconds.");
1612
1613     CreateThread(ThreadTopUpKeyPool, NULL);
1614     int64* pnSleepTime = new int64(params[1].get_int64());
1615     CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
1616
1617     return Value::null;
1618 }
1619
1620
1621 Value walletpassphrasechange(const Array& params, bool fHelp)
1622 {
1623     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
1624         throw runtime_error(
1625             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1626             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1627     if (fHelp)
1628         return true;
1629     if (!pwalletMain->IsCrypted())
1630         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
1631
1632     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
1633     // Alternately, find a way to make params[0] mlock()'d to begin with.
1634     SecureString strOldWalletPass;
1635     strOldWalletPass.reserve(100);
1636     strOldWalletPass = params[0].get_str().c_str();
1637
1638     SecureString strNewWalletPass;
1639     strNewWalletPass.reserve(100);
1640     strNewWalletPass = params[1].get_str().c_str();
1641
1642     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
1643         throw runtime_error(
1644             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
1645             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
1646
1647     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
1648         throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect.");
1649
1650     return Value::null;
1651 }
1652
1653
1654 Value walletlock(const Array& params, bool fHelp)
1655 {
1656     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
1657         throw runtime_error(
1658             "walletlock\n"
1659             "Removes the wallet encryption key from memory, locking the wallet.\n"
1660             "After calling this method, you will need to call walletpassphrase again\n"
1661             "before being able to call any methods which require the wallet to be unlocked.");
1662     if (fHelp)
1663         return true;
1664     if (!pwalletMain->IsCrypted())
1665         throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
1666
1667     {
1668         LOCK(cs_nWalletUnlockTime);
1669         pwalletMain->Lock();
1670         nWalletUnlockTime = 0;
1671     }
1672
1673     return Value::null;
1674 }
1675
1676
1677 Value encryptwallet(const Array& params, bool fHelp)
1678 {
1679     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
1680         throw runtime_error(
1681             "encryptwallet <passphrase>\n"
1682             "Encrypts the wallet with <passphrase>.");
1683     if (fHelp)
1684         return true;
1685     if (pwalletMain->IsCrypted())
1686         throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
1687
1688     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
1689     // Alternately, find a way to make params[0] mlock()'d to begin with.
1690     SecureString strWalletPass;
1691     strWalletPass.reserve(100);
1692     strWalletPass = params[0].get_str().c_str();
1693
1694     if (strWalletPass.length() < 1)
1695         throw runtime_error(
1696             "encryptwallet <passphrase>\n"
1697             "Encrypts the wallet with <passphrase>.");
1698
1699     if (!pwalletMain->EncryptWallet(strWalletPass))
1700         throw JSONRPCError(-16, "Error: Failed to encrypt the wallet.");
1701
1702     // BDB seems to have a bad habit of writing old data into
1703     // slack space in .dat files; that is bad if the old data is
1704     // unencrypted private keys.  So:
1705     QueueShutdown();
1706     return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
1707 }
1708
1709
1710 Value validateaddress(const Array& params, bool fHelp)
1711 {
1712     if (fHelp || params.size() != 1)
1713         throw runtime_error(
1714             "validateaddress <bitcoinaddress>\n"
1715             "Return information about <bitcoinaddress>.");
1716
1717     CBitcoinAddress address(params[0].get_str());
1718     bool isValid = address.IsValid();
1719
1720     Object ret;
1721     ret.push_back(Pair("isvalid", isValid));
1722     if (isValid)
1723     {
1724         // Call Hash160ToAddress() so we always return current ADDRESSVERSION
1725         // version of the address:
1726         string currentAddress = address.ToString();
1727         ret.push_back(Pair("address", currentAddress));
1728         if (pwalletMain->HaveKey(address))
1729         {
1730             ret.push_back(Pair("ismine", true));
1731             std::vector<unsigned char> vchPubKey;
1732             pwalletMain->GetPubKey(address, vchPubKey);
1733             ret.push_back(Pair("pubkey", HexStr(vchPubKey)));
1734             CKey key;
1735             key.SetPubKey(vchPubKey);
1736             ret.push_back(Pair("iscompressed", key.IsCompressed()));
1737         }
1738         else if (pwalletMain->HaveCScript(address.GetHash160()))
1739         {
1740             ret.push_back(Pair("isscript", true));
1741             CScript subscript;
1742             pwalletMain->GetCScript(address.GetHash160(), subscript);
1743             ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
1744             std::vector<CBitcoinAddress> addresses;
1745             txnouttype whichType;
1746             int nRequired;
1747             ExtractAddresses(subscript, whichType, addresses, nRequired);
1748             ret.push_back(Pair("script", GetTxnOutputType(whichType)));
1749             Array a;
1750             BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
1751                 a.push_back(addr.ToString());
1752             ret.push_back(Pair("addresses", a));
1753             if (whichType == TX_MULTISIG)
1754                 ret.push_back(Pair("sigsrequired", nRequired));
1755         }
1756         else
1757             ret.push_back(Pair("ismine", false));
1758         if (pwalletMain->mapAddressBook.count(address))
1759             ret.push_back(Pair("account", pwalletMain->mapAddressBook[address]));
1760     }
1761     return ret;
1762 }
1763
1764 Value getwork(const Array& params, bool fHelp)
1765 {
1766     if (fHelp || params.size() > 1)
1767         throw runtime_error(
1768             "getwork [data]\n"
1769             "If [data] is not specified, returns formatted hash data to work on:\n"
1770             "  \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
1771             "  \"data\" : block data\n"
1772             "  \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
1773             "  \"target\" : little endian hash target\n"
1774             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1775
1776     if (vNodes.empty())
1777         throw JSONRPCError(-9, "Bitcoin is not connected!");
1778
1779     if (IsInitialBlockDownload())
1780         throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1781
1782     typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
1783     static mapNewBlock_t mapNewBlock;
1784     static vector<CBlock*> vNewBlock;
1785     static CReserveKey reservekey(pwalletMain);
1786
1787     if (params.size() == 0)
1788     {
1789         // Update block
1790         static unsigned int nTransactionsUpdatedLast;
1791         static CBlockIndex* pindexPrev;
1792         static int64 nStart;
1793         static CBlock* pblock;
1794         if (pindexPrev != pindexBest ||
1795             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
1796         {
1797             if (pindexPrev != pindexBest)
1798             {
1799                 // Deallocate old blocks since they're obsolete now
1800                 mapNewBlock.clear();
1801                 BOOST_FOREACH(CBlock* pblock, vNewBlock)
1802                     delete pblock;
1803                 vNewBlock.clear();
1804             }
1805             nTransactionsUpdatedLast = nTransactionsUpdated;
1806             pindexPrev = pindexBest;
1807             nStart = GetTime();
1808
1809             // Create new block
1810             pblock = CreateNewBlock(reservekey);
1811             if (!pblock)
1812                 throw JSONRPCError(-7, "Out of memory");
1813             vNewBlock.push_back(pblock);
1814         }
1815
1816         // Update nTime
1817         pblock->UpdateTime(pindexPrev);
1818         pblock->nNonce = 0;
1819
1820         // Update nExtraNonce
1821         static unsigned int nExtraNonce = 0;
1822         IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1823
1824         // Save
1825         mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig);
1826
1827         // Prebuild hash buffers
1828         char pmidstate[32];
1829         char pdata[128];
1830         char phash1[64];
1831         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
1832
1833         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
1834
1835         Object result;
1836         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
1837         result.push_back(Pair("data",     HexStr(BEGIN(pdata), END(pdata))));
1838         result.push_back(Pair("hash1",    HexStr(BEGIN(phash1), END(phash1)))); // deprecated
1839         result.push_back(Pair("target",   HexStr(BEGIN(hashTarget), END(hashTarget))));
1840         return result;
1841     }
1842     else
1843     {
1844         // Parse parameters
1845         vector<unsigned char> vchData = ParseHex(params[0].get_str());
1846         if (vchData.size() != 128)
1847             throw JSONRPCError(-8, "Invalid parameter");
1848         CBlock* pdata = (CBlock*)&vchData[0];
1849
1850         // Byte reverse
1851         for (int i = 0; i < 128/4; i++)
1852             ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]);
1853
1854         // Get saved block
1855         if (!mapNewBlock.count(pdata->hashMerkleRoot))
1856             return false;
1857         CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
1858
1859         pblock->nTime = pdata->nTime;
1860         pblock->nNonce = pdata->nNonce;
1861         pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
1862         pblock->hashMerkleRoot = pblock->BuildMerkleTree();
1863
1864         return CheckWork(pblock, *pwalletMain, reservekey);
1865     }
1866 }
1867
1868
1869 Value getmemorypool(const Array& params, bool fHelp)
1870 {
1871     if (fHelp || params.size() > 1)
1872         throw runtime_error(
1873             "getmemorypool [data]\n"
1874             "If [data] is not specified, returns data needed to construct a block to work on:\n"
1875             "  \"version\" : block version\n"
1876             "  \"previousblockhash\" : hash of current highest block\n"
1877             "  \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
1878             "  \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
1879             "  \"coinbaseflags\" : data that should be included in coinbase so support for new features can be judged\n"
1880             "  \"time\" : timestamp appropriate for next block\n"
1881             "  \"mintime\" : minimum timestamp appropriate for next block\n"
1882             "  \"curtime\" : current timestamp\n"
1883             "  \"bits\" : compressed target of next block\n"
1884             "If [data] is specified, tries to solve the block and returns true if it was successful.");
1885
1886     if (params.size() == 0)
1887     {
1888         if (vNodes.empty())
1889             throw JSONRPCError(-9, "Bitcoin is not connected!");
1890
1891         if (IsInitialBlockDownload())
1892             throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
1893
1894         static CReserveKey reservekey(pwalletMain);
1895
1896         // Update block
1897         static unsigned int nTransactionsUpdatedLast;
1898         static CBlockIndex* pindexPrev;
1899         static int64 nStart;
1900         static CBlock* pblock;
1901         if (pindexPrev != pindexBest ||
1902             (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
1903         {
1904             nTransactionsUpdatedLast = nTransactionsUpdated;
1905             pindexPrev = pindexBest;
1906             nStart = GetTime();
1907
1908             // Create new block
1909             if(pblock)
1910                 delete pblock;
1911             pblock = CreateNewBlock(reservekey);
1912             if (!pblock)
1913                 throw JSONRPCError(-7, "Out of memory");
1914         }
1915
1916         // Update nTime
1917         pblock->UpdateTime(pindexPrev);
1918         pblock->nNonce = 0;
1919
1920         Array transactions;
1921         BOOST_FOREACH(CTransaction tx, pblock->vtx) {
1922             if(tx.IsCoinBase())
1923                 continue;
1924
1925             CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
1926             ssTx << tx;
1927
1928             transactions.push_back(HexStr(ssTx.begin(), ssTx.end()));
1929         }
1930
1931         Object result;
1932         result.push_back(Pair("version", pblock->nVersion));
1933         result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
1934         result.push_back(Pair("transactions", transactions));
1935         result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
1936         result.push_back(Pair("coinbaseflags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
1937         result.push_back(Pair("time", (int64_t)pblock->nTime));
1938         result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
1939         result.push_back(Pair("curtime", (int64_t)GetAdjustedTime()));
1940         result.push_back(Pair("bits", HexBits(pblock->nBits)));
1941
1942         return result;
1943     }
1944     else
1945     {
1946         // Parse parameters
1947         CDataStream ssBlock(ParseHex(params[0].get_str()), SER_NETWORK, PROTOCOL_VERSION);
1948         CBlock pblock;
1949         ssBlock >> pblock;
1950
1951         return ProcessBlock(NULL, &pblock);
1952     }
1953 }
1954
1955 Value getblockhash(const Array& params, bool fHelp)
1956 {
1957     if (fHelp || params.size() != 1)
1958         throw runtime_error(
1959             "getblockhash <index>\n"
1960             "Returns hash of block in best-block-chain at <index>.");
1961
1962     int nHeight = params[0].get_int();
1963     if (nHeight < 0 || nHeight > nBestHeight)
1964         throw runtime_error("Block number out of range.");
1965
1966     CBlock block;
1967     CBlockIndex* pblockindex = mapBlockIndex[hashBestChain];
1968     while (pblockindex->nHeight > nHeight)
1969         pblockindex = pblockindex->pprev;
1970     return pblockindex->phashBlock->GetHex();
1971 }
1972
1973 Value getblock(const Array& params, bool fHelp)
1974 {
1975     if (fHelp || params.size() != 1)
1976         throw runtime_error(
1977             "getblock <hash>\n"
1978             "Returns details of a block with given block-hash.");
1979
1980     std::string strHash = params[0].get_str();
1981     uint256 hash(strHash);
1982
1983     if (mapBlockIndex.count(hash) == 0)
1984         throw JSONRPCError(-5, "Block not found");
1985
1986     CBlock block;
1987     CBlockIndex* pblockindex = mapBlockIndex[hash];
1988     block.ReadFromDisk(pblockindex, true);
1989
1990     return blockToJSON(block, pblockindex);
1991 }
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003 //
2004 // Call Table
2005 //
2006
2007
2008 static const CRPCCommand vRPCCommands[] =
2009 { //  name                      function                 safe mode?
2010   //  ------------------------  -----------------------  ----------
2011     { "help",                   &help,                   true },
2012     { "stop",                   &stop,                   true },
2013     { "getblockcount",          &getblockcount,          true },
2014     { "getblocknumber",         &getblocknumber,         true },
2015     { "getconnectioncount",     &getconnectioncount,     true },
2016     { "getdifficulty",          &getdifficulty,          true },
2017     { "getgenerate",            &getgenerate,            true },
2018     { "setgenerate",            &setgenerate,            true },
2019     { "gethashespersec",        &gethashespersec,        true },
2020     { "getinfo",                &getinfo,                true },
2021     { "getmininginfo",          &getmininginfo,          true },
2022     { "getnewaddress",          &getnewaddress,          true },
2023     { "getaccountaddress",      &getaccountaddress,      true },
2024     { "setaccount",             &setaccount,             true },
2025     { "getaccount",             &getaccount,             false },
2026     { "getaddressesbyaccount",  &getaddressesbyaccount,  true },
2027     { "sendtoaddress",          &sendtoaddress,          false },
2028     { "getreceivedbyaddress",   &getreceivedbyaddress,   false },
2029     { "getreceivedbyaccount",   &getreceivedbyaccount,   false },
2030     { "listreceivedbyaddress",  &listreceivedbyaddress,  false },
2031     { "listreceivedbyaccount",  &listreceivedbyaccount,  false },
2032     { "backupwallet",           &backupwallet,           true },
2033     { "keypoolrefill",          &keypoolrefill,          true },
2034     { "walletpassphrase",       &walletpassphrase,       true },
2035     { "walletpassphrasechange", &walletpassphrasechange, false },
2036     { "walletlock",             &walletlock,             true },
2037     { "encryptwallet",          &encryptwallet,          false },
2038     { "validateaddress",        &validateaddress,        true },
2039     { "getbalance",             &getbalance,             false },
2040     { "move",                   &movecmd,                false },
2041     { "sendfrom",               &sendfrom,               false },
2042     { "sendmany",               &sendmany,               false },
2043     { "addmultisigaddress",     &addmultisigaddress,     false },
2044     { "getblock",               &getblock,               false },
2045     { "getblockhash",           &getblockhash,           false },
2046     { "gettransaction",         &gettransaction,         false },
2047     { "listtransactions",       &listtransactions,       false },
2048     { "signmessage",            &signmessage,            false },
2049     { "verifymessage",          &verifymessage,          false },
2050     { "getwork",                &getwork,                true },
2051     { "listaccounts",           &listaccounts,           false },
2052     { "settxfee",               &settxfee,               false },
2053     { "getmemorypool",          &getmemorypool,          true },
2054     { "listsinceblock",         &listsinceblock,         false },
2055     { "dumpprivkey",            &dumpprivkey,            false },
2056     { "importprivkey",          &importprivkey,          false },
2057 };
2058
2059 CRPCTable::CRPCTable()
2060 {
2061     unsigned int vcidx;
2062     for (vcidx = 0; vcidx < (sizeof(vRPCCommands) / sizeof(vRPCCommands[0])); vcidx++)
2063     {
2064         const CRPCCommand *pcmd;
2065
2066         pcmd = &vRPCCommands[vcidx];
2067         mapCommands[pcmd->name] = pcmd;
2068     }
2069 }
2070
2071 const CRPCCommand *CRPCTable::operator[](string name) const
2072 {
2073     map<string, const CRPCCommand*>::const_iterator it = mapCommands.find(name);
2074     if (it == mapCommands.end())
2075         return NULL;
2076     return (*it).second;
2077 }
2078
2079 //
2080 // HTTP protocol
2081 //
2082 // This ain't Apache.  We're just using HTTP header for the length field
2083 // and to be compatible with other JSON-RPC implementations.
2084 //
2085
2086 string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
2087 {
2088     ostringstream s;
2089     s << "POST / HTTP/1.1\r\n"
2090       << "User-Agent: bitcoin-json-rpc/" << FormatFullVersion() << "\r\n"
2091       << "Host: 127.0.0.1\r\n"
2092       << "Content-Type: application/json\r\n"
2093       << "Content-Length: " << strMsg.size() << "\r\n"
2094       << "Connection: close\r\n"
2095       << "Accept: application/json\r\n";
2096     BOOST_FOREACH(const PAIRTYPE(string, string)& item, mapRequestHeaders)
2097         s << item.first << ": " << item.second << "\r\n";
2098     s << "\r\n" << strMsg;
2099
2100     return s.str();
2101 }
2102
2103 string rfc1123Time()
2104 {
2105     char buffer[64];
2106     time_t now;
2107     time(&now);
2108     struct tm* now_gmt = gmtime(&now);
2109     string locale(setlocale(LC_TIME, NULL));
2110     setlocale(LC_TIME, "C"); // we want posix (aka "C") weekday/month strings
2111     strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S +0000", now_gmt);
2112     setlocale(LC_TIME, locale.c_str());
2113     return string(buffer);
2114 }
2115
2116 static string HTTPReply(int nStatus, const string& strMsg)
2117 {
2118     if (nStatus == 401)
2119         return strprintf("HTTP/1.0 401 Authorization Required\r\n"
2120             "Date: %s\r\n"
2121             "Server: bitcoin-json-rpc/%s\r\n"
2122             "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
2123             "Content-Type: text/html\r\n"
2124             "Content-Length: 296\r\n"
2125             "\r\n"
2126             "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
2127             "\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
2128             "<HTML>\r\n"
2129             "<HEAD>\r\n"
2130             "<TITLE>Error</TITLE>\r\n"
2131             "<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
2132             "</HEAD>\r\n"
2133             "<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
2134             "</HTML>\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str());
2135     const char *cStatus;
2136          if (nStatus == 200) cStatus = "OK";
2137     else if (nStatus == 400) cStatus = "Bad Request";
2138     else if (nStatus == 403) cStatus = "Forbidden";
2139     else if (nStatus == 404) cStatus = "Not Found";
2140     else if (nStatus == 500) cStatus = "Internal Server Error";
2141     else cStatus = "";
2142     return strprintf(
2143             "HTTP/1.1 %d %s\r\n"
2144             "Date: %s\r\n"
2145             "Connection: close\r\n"
2146             "Content-Length: %d\r\n"
2147             "Content-Type: application/json\r\n"
2148             "Server: bitcoin-json-rpc/%s\r\n"
2149             "\r\n"
2150             "%s",
2151         nStatus,
2152         cStatus,
2153         rfc1123Time().c_str(),
2154         strMsg.size(),
2155         FormatFullVersion().c_str(),
2156         strMsg.c_str());
2157 }
2158
2159 int ReadHTTPStatus(std::basic_istream<char>& stream)
2160 {
2161     string str;
2162     getline(stream, str);
2163     vector<string> vWords;
2164     boost::split(vWords, str, boost::is_any_of(" "));
2165     if (vWords.size() < 2)
2166         return 500;
2167     return atoi(vWords[1].c_str());
2168 }
2169
2170 int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
2171 {
2172     int nLen = 0;
2173     loop
2174     {
2175         string str;
2176         std::getline(stream, str);
2177         if (str.empty() || str == "\r")
2178             break;
2179         string::size_type nColon = str.find(":");
2180         if (nColon != string::npos)
2181         {
2182             string strHeader = str.substr(0, nColon);
2183             boost::trim(strHeader);
2184             boost::to_lower(strHeader);
2185             string strValue = str.substr(nColon+1);
2186             boost::trim(strValue);
2187             mapHeadersRet[strHeader] = strValue;
2188             if (strHeader == "content-length")
2189                 nLen = atoi(strValue.c_str());
2190         }
2191     }
2192     return nLen;
2193 }
2194
2195 int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
2196 {
2197     mapHeadersRet.clear();
2198     strMessageRet = "";
2199
2200     // Read status
2201     int nStatus = ReadHTTPStatus(stream);
2202
2203     // Read header
2204     int nLen = ReadHTTPHeader(stream, mapHeadersRet);
2205     if (nLen < 0 || nLen > MAX_SIZE)
2206         return 500;
2207
2208     // Read message
2209     if (nLen > 0)
2210     {
2211         vector<char> vch(nLen);
2212         stream.read(&vch[0], nLen);
2213         strMessageRet = string(vch.begin(), vch.end());
2214     }
2215
2216     return nStatus;
2217 }
2218
2219 bool HTTPAuthorized(map<string, string>& mapHeaders)
2220 {
2221     string strAuth = mapHeaders["authorization"];
2222     if (strAuth.substr(0,6) != "Basic ")
2223         return false;
2224     string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
2225     string strUserPass = DecodeBase64(strUserPass64);
2226     return strUserPass == strRPCUserColonPass;
2227 }
2228
2229 //
2230 // JSON-RPC protocol.  Bitcoin speaks version 1.0 for maximum compatibility,
2231 // but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
2232 // unspecified (HTTP errors and contents of 'error').
2233 //
2234 // 1.0 spec: http://json-rpc.org/wiki/specification
2235 // 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
2236 // http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
2237 //
2238
2239 string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
2240 {
2241     Object request;
2242     request.push_back(Pair("method", strMethod));
2243     request.push_back(Pair("params", params));
2244     request.push_back(Pair("id", id));
2245     return write_string(Value(request), false) + "\n";
2246 }
2247
2248 string JSONRPCReply(const Value& result, const Value& error, const Value& id)
2249 {
2250     Object reply;
2251     if (error.type() != null_type)
2252         reply.push_back(Pair("result", Value::null));
2253     else
2254         reply.push_back(Pair("result", result));
2255     reply.push_back(Pair("error", error));
2256     reply.push_back(Pair("id", id));
2257     return write_string(Value(reply), false) + "\n";
2258 }
2259
2260 void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2261 {
2262     // Send error reply from json-rpc error object
2263     int nStatus = 500;
2264     int code = find_value(objError, "code").get_int();
2265     if (code == -32600) nStatus = 400;
2266     else if (code == -32601) nStatus = 404;
2267     string strReply = JSONRPCReply(Value::null, objError, id);
2268     stream << HTTPReply(nStatus, strReply) << std::flush;
2269 }
2270
2271 bool ClientAllowed(const string& strAddress)
2272 {
2273     if (strAddress == asio::ip::address_v4::loopback().to_string())
2274         return true;
2275     const vector<string>& vAllow = mapMultiArgs["-rpcallowip"];
2276     BOOST_FOREACH(string strAllow, vAllow)
2277         if (WildcardMatch(strAddress, strAllow))
2278             return true;
2279     return false;
2280 }
2281
2282 //
2283 // IOStream device that speaks SSL but can also speak non-SSL
2284 //
2285 class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
2286 public:
2287     SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
2288     {
2289         fUseSSL = fUseSSLIn;
2290         fNeedHandshake = fUseSSLIn;
2291     }
2292
2293     void handshake(ssl::stream_base::handshake_type role)
2294     {
2295         if (!fNeedHandshake) return;
2296         fNeedHandshake = false;
2297         stream.handshake(role);
2298     }
2299     std::streamsize read(char* s, std::streamsize n)
2300     {
2301         handshake(ssl::stream_base::server); // HTTPS servers read first
2302         if (fUseSSL) return stream.read_some(asio::buffer(s, n));
2303         return stream.next_layer().read_some(asio::buffer(s, n));
2304     }
2305     std::streamsize write(const char* s, std::streamsize n)
2306     {
2307         handshake(ssl::stream_base::client); // HTTPS clients write first
2308         if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
2309         return asio::write(stream.next_layer(), asio::buffer(s, n));
2310     }
2311     bool connect(const std::string& server, const std::string& port)
2312     {
2313         ip::tcp::resolver resolver(stream.get_io_service());
2314         ip::tcp::resolver::query query(server.c_str(), port.c_str());
2315         ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
2316         ip::tcp::resolver::iterator end;
2317         boost::system::error_code error = asio::error::host_not_found;
2318         while (error && endpoint_iterator != end)
2319         {
2320             stream.lowest_layer().close();
2321             stream.lowest_layer().connect(*endpoint_iterator++, error);
2322         }
2323         if (error)
2324             return false;
2325         return true;
2326     }
2327
2328 private:
2329     bool fNeedHandshake;
2330     bool fUseSSL;
2331     SSLStream& stream;
2332 };
2333
2334 void ThreadRPCServer(void* parg)
2335 {
2336     IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
2337     try
2338     {
2339         vnThreadsRunning[THREAD_RPCSERVER]++;
2340         ThreadRPCServer2(parg);
2341         vnThreadsRunning[THREAD_RPCSERVER]--;
2342     }
2343     catch (std::exception& e) {
2344         vnThreadsRunning[THREAD_RPCSERVER]--;
2345         PrintException(&e, "ThreadRPCServer()");
2346     } catch (...) {
2347         vnThreadsRunning[THREAD_RPCSERVER]--;
2348         PrintException(NULL, "ThreadRPCServer()");
2349     }
2350     printf("ThreadRPCServer exiting\n");
2351 }
2352
2353 void ThreadRPCServer2(void* parg)
2354 {
2355     printf("ThreadRPCServer started\n");
2356
2357     strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
2358     if (mapArgs["-rpcpassword"] == "")
2359     {
2360         unsigned char rand_pwd[32];
2361         RAND_bytes(rand_pwd, 32);
2362         string strWhatAmI = "To use bitcoind";
2363         if (mapArgs.count("-server"))
2364             strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
2365         else if (mapArgs.count("-daemon"))
2366             strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
2367         ThreadSafeMessageBox(strprintf(
2368             _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
2369               "It is recommended you use the following random password:\n"
2370               "rpcuser=bitcoinrpc\n"
2371               "rpcpassword=%s\n"
2372               "(you do not need to remember this password)\n"
2373               "If the file does not exist, create it with owner-readable-only file permissions.\n"),
2374                 strWhatAmI.c_str(),
2375                 GetConfigFile().string().c_str(),
2376                 EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
2377             _("Error"), wxOK | wxMODAL);
2378         QueueShutdown();
2379         return;
2380     }
2381
2382     bool fUseSSL = GetBoolArg("-rpcssl");
2383     asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
2384
2385     asio::io_service io_service;
2386     ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
2387     ip::tcp::acceptor acceptor(io_service);
2388     try
2389     {
2390         acceptor.open(endpoint.protocol());
2391         acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
2392         acceptor.bind(endpoint);
2393         acceptor.listen(socket_base::max_connections);
2394     }
2395     catch(boost::system::system_error &e)
2396     {
2397         ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
2398                              _("Error"), wxOK | wxMODAL);
2399         QueueShutdown();
2400         return;
2401     }
2402
2403     ssl::context context(io_service, ssl::context::sslv23);
2404     if (fUseSSL)
2405     {
2406         context.set_options(ssl::context::no_sslv2);
2407
2408         filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
2409         if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
2410         if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
2411         else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
2412
2413         filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
2414         if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
2415         if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
2416         else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
2417
2418         string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
2419         SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
2420     }
2421
2422     loop
2423     {
2424         // Accept connection
2425         SSLStream sslStream(io_service, context);
2426         SSLIOStreamDevice d(sslStream, fUseSSL);
2427         iostreams::stream<SSLIOStreamDevice> stream(d);
2428
2429         ip::tcp::endpoint peer;
2430         vnThreadsRunning[THREAD_RPCSERVER]--;
2431         acceptor.accept(sslStream.lowest_layer(), peer);
2432         vnThreadsRunning[4]++;
2433         if (fShutdown)
2434             return;
2435
2436         // Restrict callers by IP
2437         if (!ClientAllowed(peer.address().to_string()))
2438         {
2439             // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2440             if (!fUseSSL)
2441                 stream << HTTPReply(403, "") << std::flush;
2442             continue;
2443         }
2444
2445         map<string, string> mapHeaders;
2446         string strRequest;
2447
2448         boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
2449         if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
2450         {   // Timed out:
2451             acceptor.cancel();
2452             printf("ThreadRPCServer ReadHTTP timeout\n");
2453             continue;
2454         }
2455
2456         // Check authorization
2457         if (mapHeaders.count("authorization") == 0)
2458         {
2459             stream << HTTPReply(401, "") << std::flush;
2460             continue;
2461         }
2462         if (!HTTPAuthorized(mapHeaders))
2463         {
2464             printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
2465             /* Deter brute-forcing short passwords.
2466                If this results in a DOS the user really
2467                shouldn't have their RPC port exposed.*/
2468             if (mapArgs["-rpcpassword"].size() < 20)
2469                 Sleep(250);
2470
2471             stream << HTTPReply(401, "") << std::flush;
2472             continue;
2473         }
2474
2475         Value id = Value::null;
2476         try
2477         {
2478             // Parse request
2479             Value valRequest;
2480             if (!read_string(strRequest, valRequest) || valRequest.type() != obj_type)
2481                 throw JSONRPCError(-32700, "Parse error");
2482             const Object& request = valRequest.get_obj();
2483
2484             // Parse id now so errors from here on will have the id
2485             id = find_value(request, "id");
2486
2487             // Parse method
2488             Value valMethod = find_value(request, "method");
2489             if (valMethod.type() == null_type)
2490                 throw JSONRPCError(-32600, "Missing method");
2491             if (valMethod.type() != str_type)
2492                 throw JSONRPCError(-32600, "Method must be a string");
2493             string strMethod = valMethod.get_str();
2494             if (strMethod != "getwork" && strMethod != "getmemorypool")
2495                 printf("ThreadRPCServer method=%s\n", strMethod.c_str());
2496
2497             // Parse params
2498             Value valParams = find_value(request, "params");
2499             Array params;
2500             if (valParams.type() == array_type)
2501                 params = valParams.get_array();
2502             else if (valParams.type() == null_type)
2503                 params = Array();
2504             else
2505                 throw JSONRPCError(-32600, "Params must be an array");
2506
2507             // Find method
2508             const CRPCCommand *pcmd = tableRPC[strMethod];
2509             if (!pcmd)
2510                 throw JSONRPCError(-32601, "Method not found");
2511
2512             // Observe safe mode
2513             string strWarning = GetWarnings("rpc");
2514             if (strWarning != "" && !GetBoolArg("-disablesafemode") &&
2515                 !pcmd->okSafeMode)
2516                 throw JSONRPCError(-2, string("Safe mode: ") + strWarning);
2517
2518             try
2519             {
2520                 // Execute
2521                 Value result;
2522                 {
2523                     LOCK2(cs_main, pwalletMain->cs_wallet);
2524                     result = pcmd->actor(params, false);
2525                 }
2526
2527                 // Send reply
2528                 string strReply = JSONRPCReply(result, Value::null, id);
2529                 stream << HTTPReply(200, strReply) << std::flush;
2530             }
2531             catch (std::exception& e)
2532             {
2533                 ErrorReply(stream, JSONRPCError(-1, e.what()), id);
2534             }
2535         }
2536         catch (Object& objError)
2537         {
2538             ErrorReply(stream, objError, id);
2539         }
2540         catch (std::exception& e)
2541         {
2542             ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
2543         }
2544     }
2545 }
2546
2547
2548
2549
2550 Object CallRPC(const string& strMethod, const Array& params)
2551 {
2552     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
2553         throw runtime_error(strprintf(
2554             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
2555               "If the file does not exist, create it with owner-readable-only file permissions."),
2556                 GetConfigFile().string().c_str()));
2557
2558     // Connect to localhost
2559     bool fUseSSL = GetBoolArg("-rpcssl");
2560     asio::io_service io_service;
2561     ssl::context context(io_service, ssl::context::sslv23);
2562     context.set_options(ssl::context::no_sslv2);
2563     SSLStream sslStream(io_service, context);
2564     SSLIOStreamDevice d(sslStream, fUseSSL);
2565     iostreams::stream<SSLIOStreamDevice> stream(d);
2566     if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
2567         throw runtime_error("couldn't connect to server");
2568
2569     // HTTP basic authentication
2570     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
2571     map<string, string> mapRequestHeaders;
2572     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
2573
2574     // Send request
2575     string strRequest = JSONRPCRequest(strMethod, params, 1);
2576     string strPost = HTTPPost(strRequest, mapRequestHeaders);
2577     stream << strPost << std::flush;
2578
2579     // Receive reply
2580     map<string, string> mapHeaders;
2581     string strReply;
2582     int nStatus = ReadHTTP(stream, mapHeaders, strReply);
2583     if (nStatus == 401)
2584         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
2585     else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500)
2586         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
2587     else if (strReply.empty())
2588         throw runtime_error("no response from server");
2589
2590     // Parse reply
2591     Value valReply;
2592     if (!read_string(strReply, valReply))
2593         throw runtime_error("couldn't parse reply from server");
2594     const Object& reply = valReply.get_obj();
2595     if (reply.empty())
2596         throw runtime_error("expected reply to have result, error and id properties");
2597
2598     return reply;
2599 }
2600
2601
2602
2603
2604 template<typename T>
2605 void ConvertTo(Value& value)
2606 {
2607     if (value.type() == str_type)
2608     {
2609         // reinterpret string as unquoted json value
2610         Value value2;
2611         if (!read_string(value.get_str(), value2))
2612             throw runtime_error("type mismatch");
2613         value = value2.get_value<T>();
2614     }
2615     else
2616     {
2617         value = value.get_value<T>();
2618     }
2619 }
2620
2621 int CommandLineRPC(int argc, char *argv[])
2622 {
2623     string strPrint;
2624     int nRet = 0;
2625     try
2626     {
2627         // Skip switches
2628         while (argc > 1 && IsSwitchChar(argv[1][0]))
2629         {
2630             argc--;
2631             argv++;
2632         }
2633
2634         // Method
2635         if (argc < 2)
2636             throw runtime_error("too few parameters");
2637         string strMethod = argv[1];
2638
2639         // Parameters default to strings
2640         Array params;
2641         for (int i = 2; i < argc; i++)
2642             params.push_back(argv[i]);
2643         int n = params.size();
2644
2645         //
2646         // Special case non-string parameter types
2647         //
2648         if (strMethod == "setgenerate"            && n > 0) ConvertTo<bool>(params[0]);
2649         if (strMethod == "setgenerate"            && n > 1) ConvertTo<boost::int64_t>(params[1]);
2650         if (strMethod == "sendtoaddress"          && n > 1) ConvertTo<double>(params[1]);
2651         if (strMethod == "settxfee"               && n > 0) ConvertTo<double>(params[0]);
2652         if (strMethod == "getreceivedbyaddress"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2653         if (strMethod == "getreceivedbyaccount"   && n > 1) ConvertTo<boost::int64_t>(params[1]);
2654         if (strMethod == "listreceivedbyaddress"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2655         if (strMethod == "listreceivedbyaddress"  && n > 1) ConvertTo<bool>(params[1]);
2656         if (strMethod == "listreceivedbyaccount"  && n > 0) ConvertTo<boost::int64_t>(params[0]);
2657         if (strMethod == "listreceivedbyaccount"  && n > 1) ConvertTo<bool>(params[1]);
2658         if (strMethod == "getbalance"             && n > 1) ConvertTo<boost::int64_t>(params[1]);
2659         if (strMethod == "getblockhash"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2660         if (strMethod == "move"                   && n > 2) ConvertTo<double>(params[2]);
2661         if (strMethod == "move"                   && n > 3) ConvertTo<boost::int64_t>(params[3]);
2662         if (strMethod == "sendfrom"               && n > 2) ConvertTo<double>(params[2]);
2663         if (strMethod == "sendfrom"               && n > 3) ConvertTo<boost::int64_t>(params[3]);
2664         if (strMethod == "listtransactions"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2665         if (strMethod == "listtransactions"       && n > 2) ConvertTo<boost::int64_t>(params[2]);
2666         if (strMethod == "listaccounts"           && n > 0) ConvertTo<boost::int64_t>(params[0]);
2667         if (strMethod == "walletpassphrase"       && n > 1) ConvertTo<boost::int64_t>(params[1]);
2668         if (strMethod == "listsinceblock"         && n > 1) ConvertTo<boost::int64_t>(params[1]);
2669         if (strMethod == "sendmany"               && n > 1)
2670         {
2671             string s = params[1].get_str();
2672             Value v;
2673             if (!read_string(s, v) || v.type() != obj_type)
2674                 throw runtime_error("type mismatch");
2675             params[1] = v.get_obj();
2676         }
2677         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
2678         if (strMethod == "addmultisigaddress"      && n > 0) ConvertTo<boost::int64_t>(params[0]);
2679         if (strMethod == "addmultisigaddress"      && n > 1)
2680         {
2681             string s = params[1].get_str();
2682             Value v;
2683             if (!read_string(s, v) || v.type() != array_type)
2684                 throw runtime_error("type mismatch "+s);
2685             params[1] = v.get_array();
2686         }
2687
2688         // Execute
2689         Object reply = CallRPC(strMethod, params);
2690
2691         // Parse reply
2692         const Value& result = find_value(reply, "result");
2693         const Value& error  = find_value(reply, "error");
2694
2695         if (error.type() != null_type)
2696         {
2697             // Error
2698             strPrint = "error: " + write_string(error, false);
2699             int code = find_value(error.get_obj(), "code").get_int();
2700             nRet = abs(code);
2701         }
2702         else
2703         {
2704             // Result
2705             if (result.type() == null_type)
2706                 strPrint = "";
2707             else if (result.type() == str_type)
2708                 strPrint = result.get_str();
2709             else
2710                 strPrint = write_string(result, true);
2711         }
2712     }
2713     catch (std::exception& e)
2714     {
2715         strPrint = string("error: ") + e.what();
2716         nRet = 87;
2717     }
2718     catch (...)
2719     {
2720         PrintException(NULL, "CommandLineRPC()");
2721     }
2722
2723     if (strPrint != "")
2724     {
2725         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
2726     }
2727     return nRet;
2728 }
2729
2730
2731
2732
2733 #ifdef TEST
2734 int main(int argc, char *argv[])
2735 {
2736 #ifdef _MSC_VER
2737     // Turn off microsoft heap dump noise
2738     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2739     _CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
2740 #endif
2741     setbuf(stdin, NULL);
2742     setbuf(stdout, NULL);
2743     setbuf(stderr, NULL);
2744
2745     try
2746     {
2747         if (argc >= 2 && string(argv[1]) == "-server")
2748         {
2749             printf("server ready\n");
2750             ThreadRPCServer(NULL);
2751         }
2752         else
2753         {
2754             return CommandLineRPC(argc, argv);
2755         }
2756     }
2757     catch (std::exception& e) {
2758         PrintException(&e, "main()");
2759     } catch (...) {
2760         PrintException(NULL, "main()");
2761     }
2762     return 0;
2763 }
2764 #endif
2765
2766 const CRPCTable tableRPC;