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