// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
#include "db.h"
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
extern map<string, rpcfn_type> mapCallTable;
+static std::string strRPCUserColonPass;
+
static int64 nWalletUnlockTime;
static CCriticalSection cs_nWalletUnlockTime;
// We already filter duplicates, but these deprecated screw up the sort order
if (strMethod == "getamountreceived" ||
strMethod == "getallreceived" ||
+ strMethod == "getblocknumber" || // deprecated
(strMethod.find("label") != string::npos))
continue;
if (strCommand != "" && strMethod != strCommand)
// Help text is returned in an exception
string strHelp = string(e.what());
if (strCommand == "")
- if (strHelp.find('\n') != -1)
+ if (strHelp.find('\n') != string::npos)
strHelp = strHelp.substr(0, strHelp.find('\n'));
strRet += strHelp + "\n";
}
}
+// deprecated
Value getblocknumber(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getblocknumber\n"
- "Returns the block number of the latest block in the longest block chain.");
+ "Deprecated. Use getblockcount.");
return nBestHeight;
}
list<pair<CBitcoinAddress, int64> > listSent;
wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
if (wtx.GetDepthInMainChain() >= nMinDepth)
+ {
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
nBalance += r.second;
+ }
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent)
nBalance -= r.second;
nBalance -= allFee;
strComment = params[4].get_str();
CWalletDB walletdb(pwalletMain->strWalletFile);
- walletdb.TxnBegin();
+ if (!walletdb.TxnBegin())
+ throw JSONRPCError(-20, "database error");
int64 nNow = GetAdjustedTime();
credit.strComment = strComment;
walletdb.WriteAccountingEntry(credit);
- walletdb.TxnCommit();
+ if (!walletdb.TxnCommit())
+ throw JSONRPCError(-20, "database error");
return true;
}
// Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+ {
BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived)
{
string account;
ret.push_back(entry);
}
}
+ }
}
void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
if (params.size() > 2)
nFrom = params[2].get_int();
+ if (nCount < 0)
+ throw JSONRPCError(-8, "Negative count");
+ if (nFrom < 0)
+ throw JSONRPCError(-8, "Negative from");
+
Array ret;
CWalletDB walletdb(pwalletMain->strWalletFile);
- // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap:
+ // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap.
typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
typedef multimap<int64, TxPair > TxItems;
TxItems txByTime;
+ // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
+ // would make this much faster for applications that do this a lot.
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
CWalletTx* wtx = &((*it).second);
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
}
- // Now: iterate backwards until we have nCount items to return:
- TxItems::reverse_iterator it = txByTime.rbegin();
- if (txByTime.size() > nFrom) std::advance(it, nFrom);
- for (; it != txByTime.rend(); ++it)
+ // iterate backwards until we have nCount items to return:
+ for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
{
CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0)
if (pacentry != 0)
AcentryToJSON(*pacentry, strAccount, ret);
- if (ret.size() >= nCount) break;
+ if (ret.size() >= (nCount+nFrom)) break;
}
- // ret is now newest to oldest
+ // ret is newest to oldest
- // Make sure we return only last nCount items (sends-to-self might give us an extra):
- if (ret.size() > nCount)
- {
- Array::iterator last = ret.begin();
- std::advance(last, nCount);
- ret.erase(last, ret.end());
- }
- std::reverse(ret.begin(), ret.end()); // oldest to newest
+ if (nFrom > ret.size()) nFrom = ret.size();
+ if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
+ Array::iterator first = ret.begin();
+ std::advance(first, nFrom);
+ Array::iterator last = ret.begin();
+ std::advance(last, nFrom+nCount);
+
+ if (last != ret.end()) ret.erase(last, ret.end());
+ if (first != ret.begin()) ret.erase(ret.begin(), first);
+
+ std::reverse(ret.begin(), ret.end()); // Return oldest to newest
return ret;
}
{
if (fHelp)
throw runtime_error(
- "listsinceblock [blockid] [target-confirmations]\n"
- "Get all transactions in blocks since block [blockid], or all transactions if omitted");
+ "listsinceblock [blockhash] [target-confirmations]\n"
+ "Get all transactions in blocks since block [blockhash], or all transactions if omitted");
CBlockIndex *pindex = NULL;
int target_confirms = 1;
if (target_confirms == 1)
{
- printf("oops!\n");
lastblock = hashBestChain;
}
else
"help",
"stop",
"getblockcount",
- "getblocknumber",
+ "getblocknumber", // deprecated
"getconnectioncount",
"getdifficulty",
"getgenerate",
return false;
string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
string strUserPass = DecodeBase64(strUserPass64);
- string::size_type nColon = strUserPass.find(":");
- if (nColon == string::npos)
- return false;
- string strUser = strUserPass.substr(0, nColon);
- string strPassword = strUserPass.substr(nColon+1);
- return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
+ return strUserPass == strRPCUserColonPass;
}
//
printf("ThreadRPCServer exiting\n");
}
+#ifdef QT_GUI
+extern bool HACK_SHUTDOWN;
+#endif
+
void ThreadRPCServer2(void* parg)
{
printf("ThreadRPCServer started\n");
- if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
+ strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
+ if (strRPCUserColonPass == ":")
{
unsigned char rand_pwd[32];
RAND_bytes(rand_pwd, 32);
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
else if (mapArgs.count("-daemon"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
- PrintConsole(
+ ThreadSafeMessageBox(strprintf(
_("Error: %s, you must set a rpcpassword in the configuration file:\n %s\n"
"It is recommended you use the following random password:\n"
"rpcuser=bitcoinrpc\n"
"If the file does not exist, create it with owner-readable-only file permissions.\n"),
strWhatAmI.c_str(),
GetConfigFile().c_str(),
- EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
+ EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
+ _("Error"), wxOK | wxMODAL);
#ifndef QT_GUI
CreateThread(Shutdown, NULL);
#endif
asio::io_service io_service;
ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
+#ifndef QT_GUI
ip::tcp::acceptor acceptor(io_service, endpoint);
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+#else
+ ip::tcp::acceptor acceptor(io_service);
+ try
+ {
+ acceptor.open(endpoint.protocol());
+ acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor.bind(endpoint);
+ acceptor.listen(socket_base::max_connections);
+ }
+ catch(boost::system::system_error &e)
+ {
+ HACK_SHUTDOWN = true;
+ ThreadSafeMessageBox(strprintf(_("An error occured while setting up the RPC port %i for listening: %s"), endpoint.port(), e.what()),
+ _("Error"), wxOK | wxMODAL);
+ return;
+ }
+#endif
#ifdef USE_SSL
ssl::context context(io_service, ssl::context::sslv23);