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