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