Removed main.h dependency from rpcserver.cpp

Rebased by @laanwj:

- update for RPC methods added since 84d13ee: setmocktime,
  invalidateblock, reconsiderblock. Only the first, setmocktime, required a change,
  the other two are thread safe.
This commit is contained in:
Eric Lombrozo 2014-10-19 04:46:17 -04:00 committed by Wladimir J. van der Laan
parent 6b5f5294bb
commit 4401b2d7c5
11 changed files with 224 additions and 38 deletions

View File

@ -234,6 +234,26 @@ bool static Bind(const CService &addr, unsigned int flags) {
return true; return true;
} }
void OnRPCStopped()
{
cvBlockChange.notify_all();
LogPrint("rpc", "RPC stopped.\n");
}
void OnRPCPreCommand(const CRPCCommand& cmd)
{
#ifdef ENABLE_WALLET
if (cmd.reqWallet && !pwalletMain)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
#endif
// Observe safe mode
string strWarning = GetWarnings("rpc");
if (strWarning != "" && !GetBoolArg("-disablesafemode", false) &&
!cmd.okSafeMode)
throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
}
std::string HelpMessage(HelpMessageMode mode) std::string HelpMessage(HelpMessageMode mode)
{ {
// When adding new options to the categories, please keep and ensure alphabetical ordering. // When adding new options to the categories, please keep and ensure alphabetical ordering.
@ -802,6 +822,8 @@ bool AppInit2(boost::thread_group& threadGroup)
if (fServer) if (fServer)
{ {
uiInterface.InitMessage.connect(SetRPCWarmupStatus); uiInterface.InitMessage.connect(SetRPCWarmupStatus);
RPCServer::OnStopped(&OnRPCStopped);
RPCServer::OnPreCommand(&OnRPCPreCommand);
StartRPCThreads(); StartRPCThreads();
} }

View File

@ -105,6 +105,7 @@ Value getblockcount(const Array& params, bool fHelp)
+ HelpExampleRpc("getblockcount", "") + HelpExampleRpc("getblockcount", "")
); );
LOCK(cs_main);
return chainActive.Height(); return chainActive.Height();
} }
@ -121,6 +122,7 @@ Value getbestblockhash(const Array& params, bool fHelp)
+ HelpExampleRpc("getbestblockhash", "") + HelpExampleRpc("getbestblockhash", "")
); );
LOCK(cs_main);
return chainActive.Tip()->GetBlockHash().GetHex(); return chainActive.Tip()->GetBlockHash().GetHex();
} }
@ -137,6 +139,7 @@ Value getdifficulty(const Array& params, bool fHelp)
+ HelpExampleRpc("getdifficulty", "") + HelpExampleRpc("getdifficulty", "")
); );
LOCK(cs_main);
return GetDifficulty(); return GetDifficulty();
} }
@ -173,6 +176,8 @@ Value getrawmempool(const Array& params, bool fHelp)
+ HelpExampleRpc("getrawmempool", "true") + HelpExampleRpc("getrawmempool", "true")
); );
LOCK(cs_main);
bool fVerbose = false; bool fVerbose = false;
if (params.size() > 0) if (params.size() > 0)
fVerbose = params[0].get_bool(); fVerbose = params[0].get_bool();
@ -233,6 +238,8 @@ Value getblockhash(const Array& params, bool fHelp)
+ HelpExampleRpc("getblockhash", "1000") + HelpExampleRpc("getblockhash", "1000")
); );
LOCK(cs_main);
int nHeight = params[0].get_int(); int nHeight = params[0].get_int();
if (nHeight < 0 || nHeight > chainActive.Height()) if (nHeight < 0 || nHeight > chainActive.Height())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
@ -277,6 +284,8 @@ Value getblock(const Array& params, bool fHelp)
+ HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"")
); );
LOCK(cs_main);
std::string strHash = params[0].get_str(); std::string strHash = params[0].get_str();
uint256 hash(uint256S(strHash)); uint256 hash(uint256S(strHash));
@ -326,6 +335,8 @@ Value gettxoutsetinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("gettxoutsetinfo", "") + HelpExampleRpc("gettxoutsetinfo", "")
); );
LOCK(cs_main);
Object ret; Object ret;
CCoinsStats stats; CCoinsStats stats;
@ -380,6 +391,8 @@ Value gettxout(const Array& params, bool fHelp)
+ HelpExampleRpc("gettxout", "\"txid\", 1") + HelpExampleRpc("gettxout", "\"txid\", 1")
); );
LOCK(cs_main);
Object ret; Object ret;
std::string strHash = params[0].get_str(); std::string strHash = params[0].get_str();
@ -436,6 +449,8 @@ Value verifychain(const Array& params, bool fHelp)
+ HelpExampleRpc("verifychain", "") + HelpExampleRpc("verifychain", "")
); );
LOCK(cs_main);
int nCheckLevel = GetArg("-checklevel", 3); int nCheckLevel = GetArg("-checklevel", 3);
int nCheckDepth = GetArg("-checkblocks", 288); int nCheckDepth = GetArg("-checkblocks", 288);
if (params.size() > 0) if (params.size() > 0)
@ -467,6 +482,8 @@ Value getblockchaininfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getblockchaininfo", "") + HelpExampleRpc("getblockchaininfo", "")
); );
LOCK(cs_main);
Object obj; Object obj;
obj.push_back(Pair("chain", Params().NetworkIDString())); obj.push_back(Pair("chain", Params().NetworkIDString()));
obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("blocks", (int)chainActive.Height()));
@ -526,6 +543,8 @@ Value getchaintips(const Array& params, bool fHelp)
+ HelpExampleRpc("getchaintips", "") + HelpExampleRpc("getchaintips", "")
); );
LOCK(cs_main);
/* Build up a list of chain tips. We start with the list of all /* Build up a list of chain tips. We start with the list of all
known blocks, and successively remove blocks that appear as pprev known blocks, and successively remove blocks that appear as pprev
of another block. */ of another block. */

View File

@ -91,6 +91,8 @@ Value importprivkey(const Array& params, bool fHelp)
+ HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false") + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
string strSecret = params[0].get_str(); string strSecret = params[0].get_str();
@ -158,6 +160,8 @@ Value importaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false") + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
CScript script; CScript script;
CBitcoinAddress address(params[0].get_str()); CBitcoinAddress address(params[0].get_str());
@ -223,6 +227,8 @@ Value importwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("importwallet", "\"test\"") + HelpExampleRpc("importwallet", "\"test\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
ifstream file; ifstream file;
@ -322,6 +328,8 @@ Value dumpprivkey(const Array& params, bool fHelp)
+ HelpExampleRpc("dumpprivkey", "\"myaddress\"") + HelpExampleRpc("dumpprivkey", "\"myaddress\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
string strAddress = params[0].get_str(); string strAddress = params[0].get_str();
@ -351,6 +359,8 @@ Value dumpwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("dumpwallet", "\"test\"") + HelpExampleRpc("dumpwallet", "\"test\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
ofstream file; ofstream file;

View File

@ -88,6 +88,7 @@ Value getnetworkhashps(const Array& params, bool fHelp)
+ HelpExampleRpc("getnetworkhashps", "") + HelpExampleRpc("getnetworkhashps", "")
); );
LOCK(cs_main);
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
} }
@ -107,6 +108,7 @@ Value getgenerate(const Array& params, bool fHelp)
+ HelpExampleRpc("getgenerate", "") + HelpExampleRpc("getgenerate", "")
); );
LOCK(cs_main);
return GetBoolArg("-gen", false); return GetBoolArg("-gen", false);
} }
@ -200,7 +202,6 @@ Value setgenerate(const Array& params, bool fHelp)
return Value::null; return Value::null;
} }
#endif #endif
@ -228,6 +229,9 @@ Value getmininginfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getmininginfo", "") + HelpExampleRpc("getmininginfo", "")
); );
LOCK(cs_main);
Object obj; Object obj;
obj.push_back(Pair("blocks", (int)chainActive.Height())); obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize)); obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
@ -268,8 +272,9 @@ Value prioritisetransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000") + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
); );
uint256 hash = ParseHashStr(params[0].get_str(), "txid"); LOCK(cs_main);
uint256 hash = ParseHashStr(params[0].get_str(), "txid");
CAmount nAmount = params[2].get_int64(); CAmount nAmount = params[2].get_int64();
mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount); mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
@ -358,6 +363,8 @@ Value getblocktemplate(const Array& params, bool fHelp)
+ HelpExampleRpc("getblocktemplate", "") + HelpExampleRpc("getblocktemplate", "")
); );
LOCK(cs_main);
std::string strMode = "template"; std::string strMode = "template";
Value lpval = Value::null; Value lpval = Value::null;
if (params.size() > 0) if (params.size() > 0)

View File

@ -69,6 +69,12 @@ Value getinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getinfo", "") + HelpExampleRpc("getinfo", "")
); );
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
proxyType proxy; proxyType proxy;
GetProxy(NET_IPV4, proxy); GetProxy(NET_IPV4, proxy);
@ -172,6 +178,12 @@ Value validateaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
); );
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
CBitcoinAddress address(params[0].get_str()); CBitcoinAddress address(params[0].get_str());
bool isValid = address.IsValid(); bool isValid = address.IsValid();
@ -329,6 +341,8 @@ Value verifymessage(const Array& params, bool fHelp)
+ HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"") + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
); );
LOCK(cs_main);
string strAddress = params[0].get_str(); string strAddress = params[0].get_str();
string strSign = params[1].get_str(); string strSign = params[1].get_str();
string strMessage = params[2].get_str(); string strMessage = params[2].get_str();
@ -372,6 +386,8 @@ Value setmocktime(const Array& params, bool fHelp)
if (!Params().MineBlocksOnDemand()) if (!Params().MineBlocksOnDemand())
throw runtime_error("setmocktime for regression testing (-regtest mode) only"); throw runtime_error("setmocktime for regression testing (-regtest mode) only");
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(int_type)); RPCTypeCheck(params, boost::assign::list_of(int_type));
SetMockTime(params[0].get_int64()); SetMockTime(params[0].get_int64());

View File

@ -34,7 +34,8 @@ Value getconnectioncount(const Array& params, bool fHelp)
+ HelpExampleRpc("getconnectioncount", "") + HelpExampleRpc("getconnectioncount", "")
); );
LOCK(cs_vNodes); LOCK2(cs_main, cs_vNodes);
return (int)vNodes.size(); return (int)vNodes.size();
} }
@ -52,7 +53,8 @@ Value ping(const Array& params, bool fHelp)
); );
// Request that each node send a ping during next message processing pass // Request that each node send a ping during next message processing pass
LOCK(cs_vNodes); LOCK2(cs_main, cs_vNodes);
BOOST_FOREACH(CNode* pNode, vNodes) { BOOST_FOREACH(CNode* pNode, vNodes) {
pNode->fPingQueued = true; pNode->fPingQueued = true;
} }
@ -113,6 +115,8 @@ Value getpeerinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getpeerinfo", "") + HelpExampleRpc("getpeerinfo", "")
); );
LOCK(cs_main);
vector<CNodeStats> vstats; vector<CNodeStats> vstats;
CopyNodeStats(vstats); CopyNodeStats(vstats);
@ -411,6 +415,8 @@ Value getnetworkinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getnetworkinfo", "") + HelpExampleRpc("getnetworkinfo", "")
); );
LOCK(cs_main);
Object obj; Object obj;
obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("subversion", obj.push_back(Pair("subversion",

View File

@ -169,6 +169,8 @@ Value getrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("getrawtransaction", "\"mytxid\", 1") + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1")
); );
LOCK(cs_main);
uint256 hash = ParseHashV(params[0], "parameter 1"); uint256 hash = ParseHashV(params[0], "parameter 1");
bool fVerbose = false; bool fVerbose = false;
@ -256,6 +258,7 @@ Value listunspent(const Array& params, bool fHelp)
Array results; Array results;
vector<COutput> vecOutputs; vector<COutput> vecOutputs;
assert(pwalletMain != NULL); assert(pwalletMain != NULL);
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->AvailableCoins(vecOutputs, false); pwalletMain->AvailableCoins(vecOutputs, false);
BOOST_FOREACH(const COutput& out, vecOutputs) { BOOST_FOREACH(const COutput& out, vecOutputs) {
if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth)
@ -334,6 +337,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"") + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"address\\\":0.01}\"")
); );
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type)); RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type));
Array inputs = params[0].get_array(); Array inputs = params[0].get_array();
@ -428,6 +432,7 @@ Value decoderawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("decoderawtransaction", "\"hexstring\"") + HelpExampleRpc("decoderawtransaction", "\"hexstring\"")
); );
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type)); RPCTypeCheck(params, boost::assign::list_of(str_type));
CTransaction tx; CTransaction tx;
@ -466,6 +471,7 @@ Value decodescript(const Array& params, bool fHelp)
+ HelpExampleRpc("decodescript", "\"hexstring\"") + HelpExampleRpc("decodescript", "\"hexstring\"")
); );
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type)); RPCTypeCheck(params, boost::assign::list_of(str_type));
Object r; Object r;
@ -532,6 +538,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("signrawtransaction", "\"myhex\"") + HelpExampleRpc("signrawtransaction", "\"myhex\"")
); );
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
RPCTypeCheck(params, boost::assign::list_of(str_type)(array_type)(array_type)(str_type), true); RPCTypeCheck(params, boost::assign::list_of(str_type)(array_type)(array_type)(str_type), true);
vector<unsigned char> txData(ParseHexV(params[0], "argument 1")); vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
@ -591,7 +602,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
} }
} }
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
else else if (pwalletMain)
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
#endif #endif
@ -722,6 +733,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("sendrawtransaction", "\"signedhex\"") + HelpExampleRpc("sendrawtransaction", "\"signedhex\"")
); );
LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type)); RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type));
// parse hex string from parameter // parse hex string from parameter

View File

@ -7,9 +7,11 @@
#include "base58.h" #include "base58.h"
#include "init.h" #include "init.h"
#include "main.h" #include "random.h"
#include "sync.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "util.h" #include "util.h"
#include "utilstrencodings.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include "wallet.h" #include "wallet.h"
#endif #endif
@ -23,11 +25,13 @@
#include <boost/iostreams/concepts.hpp> #include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp> #include <boost/iostreams/stream.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include "json/json_spirit_writer_template.h" #include "json/json_spirit_writer_template.h"
using namespace boost::asio; using namespace boost::asio;
using namespace json_spirit; using namespace json_spirit;
using namespace RPCServer;
using namespace std; using namespace std;
static std::string strRPCUserColonPass; static std::string strRPCUserColonPass;
@ -46,6 +50,34 @@ static boost::asio::io_service::work *rpc_dummy_work = NULL;
static std::vector<CSubNet> rpc_allow_subnets; //!< List of subnets to allow RPC connections from static std::vector<CSubNet> rpc_allow_subnets; //!< List of subnets to allow RPC connections from
static std::vector< boost::shared_ptr<ip::tcp::acceptor> > rpc_acceptors; static std::vector< boost::shared_ptr<ip::tcp::acceptor> > rpc_acceptors;
static struct CRPCSignals
{
boost::signals2::signal<void ()> Started;
boost::signals2::signal<void ()> Stopped;
boost::signals2::signal<void (const CRPCCommand&)> PreCommand;
boost::signals2::signal<void (const CRPCCommand&)> PostCommand;
} g_rpcSignals;
void RPCServer::OnStarted(boost::function<void ()> slot)
{
g_rpcSignals.Started.connect(slot);
}
void RPCServer::OnStopped(boost::function<void ()> slot)
{
g_rpcSignals.Stopped.connect(slot);
}
void RPCServer::OnPreCommand(boost::function<void (const CRPCCommand&)> slot)
{
g_rpcSignals.PreCommand.connect(boost::bind(slot, _1));
}
void RPCServer::OnPostCommand(boost::function<void (const CRPCCommand&)> slot)
{
g_rpcSignals.PostCommand.connect(boost::bind(slot, _1));
}
void RPCTypeCheck(const Array& params, void RPCTypeCheck(const Array& params,
const list<Value_type>& typesExpected, const list<Value_type>& typesExpected,
bool fAllowNull) bool fAllowNull)
@ -693,6 +725,7 @@ void StartRPCThreads()
for (int i = 0; i < GetArg("-rpcthreads", 4); i++) for (int i = 0; i < GetArg("-rpcthreads", 4); i++)
rpc_worker_group->create_thread(boost::bind(&boost::asio::io_service::run, rpc_io_service)); rpc_worker_group->create_thread(boost::bind(&boost::asio::io_service::run, rpc_io_service));
fRPCRunning = true; fRPCRunning = true;
g_rpcSignals.Started();
} }
void StartDummyRPCThread() void StartDummyRPCThread()
@ -735,7 +768,7 @@ void StopRPCThreads()
deadlineTimers.clear(); deadlineTimers.clear();
rpc_io_service->stop(); rpc_io_service->stop();
cvBlockChange.notify_all(); g_rpcSignals.Stopped();
if (rpc_worker_group != NULL) if (rpc_worker_group != NULL)
rpc_worker_group->join_all(); rpc_worker_group->join_all();
delete rpc_dummy_work; rpc_dummy_work = NULL; delete rpc_dummy_work; rpc_dummy_work = NULL;
@ -978,45 +1011,20 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
const CRPCCommand *pcmd = tableRPC[strMethod]; const CRPCCommand *pcmd = tableRPC[strMethod];
if (!pcmd) if (!pcmd)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
#ifdef ENABLE_WALLET
if (pcmd->reqWallet && !pwalletMain)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
#endif
// Observe safe mode g_rpcSignals.PreCommand(*pcmd);
string strWarning = GetWarnings("rpc");
if (strWarning != "" && !GetBoolArg("-disablesafemode", false) &&
!pcmd->okSafeMode)
throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning);
try try
{ {
// Execute // Execute
Value result; return pcmd->actor(params, false);
{
if (pcmd->threadSafe)
result = pcmd->actor(params, false);
#ifdef ENABLE_WALLET
else if (!pwalletMain) {
LOCK(cs_main);
result = pcmd->actor(params, false);
} else {
LOCK2(cs_main, pwalletMain->cs_wallet);
result = pcmd->actor(params, false);
}
#else // ENABLE_WALLET
else {
LOCK(cs_main);
result = pcmd->actor(params, false);
}
#endif // !ENABLE_WALLET
}
return result;
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
throw JSONRPCError(RPC_MISC_ERROR, e.what()); throw JSONRPCError(RPC_MISC_ERROR, e.what());
} }
g_rpcSignals.PostCommand(*pcmd);
} }
std::string HelpExampleCli(string methodname, string args){ std::string HelpExampleCli(string methodname, string args){

View File

@ -19,6 +19,16 @@
#include "json/json_spirit_utils.h" #include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h" #include "json/json_spirit_writer_template.h"
class CRPCCommand;
namespace RPCServer
{
void OnStarted(boost::function<void ()> slot);
void OnStopped(boost::function<void ()> slot);
void OnPreCommand(boost::function<void (const CRPCCommand&)> slot);
void OnPostCommand(boost::function<void (const CRPCCommand&)> slot);
}
class CBlockIndex; class CBlockIndex;
class CNetAddr; class CNetAddr;

View File

@ -90,6 +90,8 @@ Value getnewaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("getnewaddress", "") + HelpExampleRpc("getnewaddress", "")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
// Parse the account first so we don't generate a key if there's an error // Parse the account first so we don't generate a key if there's an error
string strAccount; string strAccount;
if (params.size() > 0) if (params.size() > 0)
@ -164,13 +166,14 @@ Value getaccountaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("getaccountaddress", "\"myaccount\"") + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
// Parse the account first so we don't generate a key if there's an error // Parse the account first so we don't generate a key if there's an error
string strAccount = AccountFromValue(params[0]); string strAccount = AccountFromValue(params[0]);
Value ret; Value ret;
ret = GetAccountAddress(strAccount).ToString(); ret = GetAccountAddress(strAccount).ToString();
return ret; return ret;
} }
@ -189,6 +192,8 @@ Value getrawchangeaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("getrawchangeaddress", "") + HelpExampleRpc("getrawchangeaddress", "")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
if (!pwalletMain->IsLocked()) if (!pwalletMain->IsLocked())
pwalletMain->TopUpKeyPool(); pwalletMain->TopUpKeyPool();
@ -219,11 +224,12 @@ Value setaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"") + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
CBitcoinAddress address(params[0].get_str()); CBitcoinAddress address(params[0].get_str());
if (!address.IsValid()) if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
string strAccount; string strAccount;
if (params.size() > 1) if (params.size() > 1)
strAccount = AccountFromValue(params[1]); strAccount = AccountFromValue(params[1]);
@ -262,6 +268,8 @@ Value getaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
CBitcoinAddress address(params[0].get_str()); CBitcoinAddress address(params[0].get_str());
if (!address.IsValid()) if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
@ -292,6 +300,8 @@ Value getaddressesbyaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("getaddressesbyaccount", "\"tabby\"") + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = AccountFromValue(params[0]); string strAccount = AccountFromValue(params[0]);
// Find all addresses that have the given account // Find all addresses that have the given account
@ -363,6 +373,8 @@ Value sendtoaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"") + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
CBitcoinAddress address(params[0].get_str()); CBitcoinAddress address(params[0].get_str());
if (!address.IsValid()) if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
@ -409,6 +421,8 @@ Value listaddressgroupings(const Array& params, bool fHelp)
+ HelpExampleRpc("listaddressgroupings", "") + HelpExampleRpc("listaddressgroupings", "")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
Array jsonGroupings; Array jsonGroupings;
map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances(); map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings()) BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
@ -454,6 +468,8 @@ Value signmessage(const Array& params, bool fHelp)
+ HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"") + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
string strAddress = params[0].get_str(); string strAddress = params[0].get_str();
@ -504,6 +520,8 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6") + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
// Bitcoin address // Bitcoin address
CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
if (!address.IsValid()) if (!address.IsValid())
@ -557,6 +575,8 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6") + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
// Minimum confirmations // Minimum confirmations
int nMinDepth = 1; int nMinDepth = 1;
if (params.size() > 1) if (params.size() > 1)
@ -643,6 +663,8 @@ Value getbalance(const Array& params, bool fHelp)
+ HelpExampleRpc("getbalance", "\"*\", 6") + HelpExampleRpc("getbalance", "\"*\", 6")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
if (params.size() == 0) if (params.size() == 0)
return ValueFromAmount(pwalletMain->GetBalance()); return ValueFromAmount(pwalletMain->GetBalance());
@ -695,6 +717,9 @@ Value getunconfirmedbalance(const Array &params, bool fHelp)
throw runtime_error( throw runtime_error(
"getunconfirmedbalance\n" "getunconfirmedbalance\n"
"Returns the server's total unconfirmed balance\n"); "Returns the server's total unconfirmed balance\n");
LOCK2(cs_main, pwalletMain->cs_wallet);
return ValueFromAmount(pwalletMain->GetUnconfirmedBalance()); return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
} }
@ -721,6 +746,8 @@ Value movecmd(const Array& params, bool fHelp)
+ HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"") + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
string strFrom = AccountFromValue(params[0]); string strFrom = AccountFromValue(params[0]);
string strTo = AccountFromValue(params[1]); string strTo = AccountFromValue(params[1]);
CAmount nAmount = AmountFromValue(params[2]); CAmount nAmount = AmountFromValue(params[2]);
@ -793,6 +820,8 @@ Value sendfrom(const Array& params, bool fHelp)
+ HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"") + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = AccountFromValue(params[0]); string strAccount = AccountFromValue(params[0]);
CBitcoinAddress address(params[1].get_str()); CBitcoinAddress address(params[1].get_str());
if (!address.IsValid()) if (!address.IsValid())
@ -850,6 +879,8 @@ Value sendmany(const Array& params, bool fHelp)
+ HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"") + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = AccountFromValue(params[0]); string strAccount = AccountFromValue(params[0]);
Object sendTo = params[1].get_obj(); Object sendTo = params[1].get_obj();
int nMinDepth = 1; int nMinDepth = 1;
@ -935,6 +966,8 @@ Value addmultisigaddress(const Array& params, bool fHelp)
throw runtime_error(msg); throw runtime_error(msg);
} }
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount; string strAccount;
if (params.size() > 2) if (params.size() > 2)
strAccount = AccountFromValue(params[2]); strAccount = AccountFromValue(params[2]);
@ -1110,6 +1143,8 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
+ HelpExampleRpc("listreceivedbyaddress", "6, true, true") + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
return ListReceived(params, false); return ListReceived(params, false);
} }
@ -1141,6 +1176,8 @@ Value listreceivedbyaccount(const Array& params, bool fHelp)
+ HelpExampleRpc("listreceivedbyaccount", "6, true, true") + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
return ListReceived(params, true); return ListReceived(params, true);
} }
@ -1292,6 +1329,8 @@ Value listtransactions(const Array& params, bool fHelp)
+ HelpExampleRpc("listtransactions", "\"*\", 20, 100") + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
string strAccount = "*"; string strAccount = "*";
if (params.size() > 0) if (params.size() > 0)
strAccount = params[0].get_str(); strAccount = params[0].get_str();
@ -1372,6 +1411,8 @@ Value listaccounts(const Array& params, bool fHelp)
+ HelpExampleRpc("listaccounts", "6") + HelpExampleRpc("listaccounts", "6")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
int nMinDepth = 1; int nMinDepth = 1;
if (params.size() > 0) if (params.size() > 0)
nMinDepth = params[0].get_int(); nMinDepth = params[0].get_int();
@ -1460,6 +1501,8 @@ Value listsinceblock(const Array& params, bool fHelp)
+ HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6") + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
CBlockIndex *pindex = NULL; CBlockIndex *pindex = NULL;
int target_confirms = 1; int target_confirms = 1;
isminefilter filter = ISMINE_SPENDABLE; isminefilter filter = ISMINE_SPENDABLE;
@ -1546,6 +1589,8 @@ Value gettransaction(const Array& params, bool fHelp)
+ HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
uint256 hash; uint256 hash;
hash.SetHex(params[0].get_str()); hash.SetHex(params[0].get_str());
@ -1594,6 +1639,8 @@ Value backupwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("backupwallet", "\"backup.dat\"") + HelpExampleRpc("backupwallet", "\"backup.dat\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
string strDest = params[0].get_str(); string strDest = params[0].get_str();
if (!BackupWallet(*pwalletMain, strDest)) if (!BackupWallet(*pwalletMain, strDest))
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!"); throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
@ -1616,6 +1663,8 @@ Value keypoolrefill(const Array& params, bool fHelp)
+ HelpExampleRpc("keypoolrefill", "") + HelpExampleRpc("keypoolrefill", "")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
// 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
unsigned int kpSize = 0; unsigned int kpSize = 0;
if (params.size() > 0) { if (params.size() > 0) {
@ -1663,6 +1712,8 @@ Value walletpassphrase(const Array& params, bool fHelp)
+ HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60") + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
if (fHelp) if (fHelp)
return true; return true;
if (!pwalletMain->IsCrypted()) if (!pwalletMain->IsCrypted())
@ -1710,6 +1761,8 @@ Value walletpassphrasechange(const Array& params, bool fHelp)
+ HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"") + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
if (fHelp) if (fHelp)
return true; return true;
if (!pwalletMain->IsCrypted()) if (!pwalletMain->IsCrypted())
@ -1756,6 +1809,8 @@ Value walletlock(const Array& params, bool fHelp)
+ HelpExampleRpc("walletlock", "") + HelpExampleRpc("walletlock", "")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
if (fHelp) if (fHelp)
return true; return true;
if (!pwalletMain->IsCrypted()) if (!pwalletMain->IsCrypted())
@ -1797,6 +1852,8 @@ Value encryptwallet(const Array& params, bool fHelp)
+ HelpExampleRpc("encryptwallet", "\"my pass phrase\"") + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
if (fHelp) if (fHelp)
return true; return true;
if (pwalletMain->IsCrypted()) if (pwalletMain->IsCrypted())
@ -1861,6 +1918,8 @@ Value lockunspent(const Array& params, bool fHelp)
+ HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
if (params.size() == 1) if (params.size() == 1)
RPCTypeCheck(params, boost::assign::list_of(bool_type)); RPCTypeCheck(params, boost::assign::list_of(bool_type));
else else
@ -1930,6 +1989,8 @@ Value listlockunspent(const Array& params, bool fHelp)
+ HelpExampleRpc("listlockunspent", "") + HelpExampleRpc("listlockunspent", "")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
vector<COutPoint> vOutpts; vector<COutPoint> vOutpts;
pwalletMain->ListLockedCoins(vOutpts); pwalletMain->ListLockedCoins(vOutpts);
@ -1961,6 +2022,8 @@ Value settxfee(const Array& params, bool fHelp)
+ HelpExampleRpc("settxfee", "0.00001") + HelpExampleRpc("settxfee", "0.00001")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
// Amount // Amount
CAmount nAmount = 0; CAmount nAmount = 0;
if (params[0].get_real() != 0.0) if (params[0].get_real() != 0.0)
@ -1992,6 +2055,8 @@ Value getwalletinfo(const Array& params, bool fHelp)
+ HelpExampleRpc("getwalletinfo", "") + HelpExampleRpc("getwalletinfo", "")
); );
LOCK2(cs_main, pwalletMain->cs_wallet);
Object obj; Object obj;
obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));

View File

@ -142,6 +142,17 @@ public:
Enter(pszName, pszFile, nLine); Enter(pszName, pszFile, nLine);
} }
CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false)
{
if (!pmutexIn) return;
lock = boost::unique_lock<Mutex>(*pmutexIn, boost::defer_lock);
if (fTry)
TryEnter(pszName, pszFile, nLine);
else
Enter(pszName, pszFile, nLine);
}
~CMutexLock() ~CMutexLock()
{ {
if (lock.owns_lock()) if (lock.owns_lock())