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