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