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