From 4401b2d7c52e0f3841225369fb0d10767c51aaa2 Mon Sep 17 00:00:00 2001 From: Eric Lombrozo Date: Sun, 19 Oct 2014 04:46:17 -0400 Subject: [PATCH] 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. --- src/init.cpp | 22 ++++++++++++ src/rpcblockchain.cpp | 19 +++++++++++ src/rpcdump.cpp | 10 ++++++ src/rpcmining.cpp | 11 ++++-- src/rpcmisc.cpp | 16 +++++++++ src/rpcnet.cpp | 10 ++++-- src/rpcrawtransaction.cpp | 14 +++++++- src/rpcserver.cpp | 70 ++++++++++++++++++++++----------------- src/rpcserver.h | 10 ++++++ src/rpcwallet.cpp | 69 ++++++++++++++++++++++++++++++++++++-- src/sync.h | 11 ++++++ 11 files changed, 224 insertions(+), 38 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index aaa5f06c7..7054264c0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -234,6 +234,26 @@ bool static Bind(const CService &addr, unsigned int flags) { 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) { // 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) { uiInterface.InitMessage.connect(SetRPCWarmupStatus); + RPCServer::OnStopped(&OnRPCStopped); + RPCServer::OnPreCommand(&OnRPCPreCommand); StartRPCThreads(); } diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index cfc559d19..293d6d561 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -105,6 +105,7 @@ Value getblockcount(const Array& params, bool fHelp) + HelpExampleRpc("getblockcount", "") ); + LOCK(cs_main); return chainActive.Height(); } @@ -121,6 +122,7 @@ Value getbestblockhash(const Array& params, bool fHelp) + HelpExampleRpc("getbestblockhash", "") ); + LOCK(cs_main); return chainActive.Tip()->GetBlockHash().GetHex(); } @@ -137,6 +139,7 @@ Value getdifficulty(const Array& params, bool fHelp) + HelpExampleRpc("getdifficulty", "") ); + LOCK(cs_main); return GetDifficulty(); } @@ -173,6 +176,8 @@ Value getrawmempool(const Array& params, bool fHelp) + HelpExampleRpc("getrawmempool", "true") ); + LOCK(cs_main); + bool fVerbose = false; if (params.size() > 0) fVerbose = params[0].get_bool(); @@ -233,6 +238,8 @@ Value getblockhash(const Array& params, bool fHelp) + HelpExampleRpc("getblockhash", "1000") ); + LOCK(cs_main); + int nHeight = params[0].get_int(); if (nHeight < 0 || nHeight > chainActive.Height()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); @@ -277,6 +284,8 @@ Value getblock(const Array& params, bool fHelp) + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") ); + LOCK(cs_main); + std::string strHash = params[0].get_str(); uint256 hash(uint256S(strHash)); @@ -326,6 +335,8 @@ Value gettxoutsetinfo(const Array& params, bool fHelp) + HelpExampleRpc("gettxoutsetinfo", "") ); + LOCK(cs_main); + Object ret; CCoinsStats stats; @@ -380,6 +391,8 @@ Value gettxout(const Array& params, bool fHelp) + HelpExampleRpc("gettxout", "\"txid\", 1") ); + LOCK(cs_main); + Object ret; std::string strHash = params[0].get_str(); @@ -436,6 +449,8 @@ Value verifychain(const Array& params, bool fHelp) + HelpExampleRpc("verifychain", "") ); + LOCK(cs_main); + int nCheckLevel = GetArg("-checklevel", 3); int nCheckDepth = GetArg("-checkblocks", 288); if (params.size() > 0) @@ -467,6 +482,8 @@ Value getblockchaininfo(const Array& params, bool fHelp) + HelpExampleRpc("getblockchaininfo", "") ); + LOCK(cs_main); + Object obj; obj.push_back(Pair("chain", Params().NetworkIDString())); obj.push_back(Pair("blocks", (int)chainActive.Height())); @@ -526,6 +543,8 @@ Value getchaintips(const Array& params, bool fHelp) + HelpExampleRpc("getchaintips", "") ); + LOCK(cs_main); + /* Build up a list of chain tips. We start with the list of all known blocks, and successively remove blocks that appear as pprev of another block. */ diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 8666779cc..b9c92a06c 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -91,6 +91,8 @@ Value importprivkey(const Array& params, bool fHelp) + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + EnsureWalletIsUnlocked(); string strSecret = params[0].get_str(); @@ -158,6 +160,8 @@ Value importaddress(const Array& params, bool fHelp) + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + CScript script; CBitcoinAddress address(params[0].get_str()); @@ -223,6 +227,8 @@ Value importwallet(const Array& params, bool fHelp) + HelpExampleRpc("importwallet", "\"test\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + EnsureWalletIsUnlocked(); ifstream file; @@ -322,6 +328,8 @@ Value dumpprivkey(const Array& params, bool fHelp) + HelpExampleRpc("dumpprivkey", "\"myaddress\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + EnsureWalletIsUnlocked(); string strAddress = params[0].get_str(); @@ -351,6 +359,8 @@ Value dumpwallet(const Array& params, bool fHelp) + HelpExampleRpc("dumpwallet", "\"test\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + EnsureWalletIsUnlocked(); ofstream file; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 5df5de66d..369b3fb4d 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -88,6 +88,7 @@ Value getnetworkhashps(const Array& params, bool fHelp) + HelpExampleRpc("getnetworkhashps", "") ); + LOCK(cs_main); 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", "") ); + LOCK(cs_main); return GetBoolArg("-gen", false); } @@ -200,7 +202,6 @@ Value setgenerate(const Array& params, bool fHelp) return Value::null; } - #endif @@ -228,6 +229,9 @@ Value getmininginfo(const Array& params, bool fHelp) + HelpExampleRpc("getmininginfo", "") ); + + LOCK(cs_main); + Object obj; obj.push_back(Pair("blocks", (int)chainActive.Height())); 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") ); - 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(); 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", "") ); + LOCK(cs_main); + std::string strMode = "template"; Value lpval = Value::null; if (params.size() > 0) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 3d647a0d2..8d260b1cc 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -69,6 +69,12 @@ Value getinfo(const Array& params, bool fHelp) + HelpExampleRpc("getinfo", "") ); +#ifdef ENABLE_WALLET + LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL); +#else + LOCK(cs_main); +#endif + proxyType proxy; GetProxy(NET_IPV4, proxy); @@ -172,6 +178,12 @@ Value validateaddress(const Array& params, bool fHelp) + 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()); bool isValid = address.IsValid(); @@ -329,6 +341,8 @@ Value verifymessage(const Array& params, bool fHelp) + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"") ); + LOCK(cs_main); + string strAddress = params[0].get_str(); string strSign = params[1].get_str(); string strMessage = params[2].get_str(); @@ -372,6 +386,8 @@ Value setmocktime(const Array& params, bool fHelp) if (!Params().MineBlocksOnDemand()) throw runtime_error("setmocktime for regression testing (-regtest mode) only"); + LOCK(cs_main); + RPCTypeCheck(params, boost::assign::list_of(int_type)); SetMockTime(params[0].get_int64()); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index f0fadb598..6306fd440 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -34,7 +34,8 @@ Value getconnectioncount(const Array& params, bool fHelp) + HelpExampleRpc("getconnectioncount", "") ); - LOCK(cs_vNodes); + LOCK2(cs_main, cs_vNodes); + 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 - LOCK(cs_vNodes); + LOCK2(cs_main, cs_vNodes); + BOOST_FOREACH(CNode* pNode, vNodes) { pNode->fPingQueued = true; } @@ -113,6 +115,8 @@ Value getpeerinfo(const Array& params, bool fHelp) + HelpExampleRpc("getpeerinfo", "") ); + LOCK(cs_main); + vector vstats; CopyNodeStats(vstats); @@ -411,6 +415,8 @@ Value getnetworkinfo(const Array& params, bool fHelp) + HelpExampleRpc("getnetworkinfo", "") ); + LOCK(cs_main); + Object obj; obj.push_back(Pair("version", CLIENT_VERSION)); obj.push_back(Pair("subversion", diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 2b108bf58..0859c0e61 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -169,6 +169,8 @@ Value getrawtransaction(const Array& params, bool fHelp) + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1") ); + LOCK(cs_main); + uint256 hash = ParseHashV(params[0], "parameter 1"); bool fVerbose = false; @@ -256,6 +258,7 @@ Value listunspent(const Array& params, bool fHelp) Array results; vector vecOutputs; assert(pwalletMain != NULL); + LOCK2(cs_main, pwalletMain->cs_wallet); pwalletMain->AvailableCoins(vecOutputs, false); BOOST_FOREACH(const COutput& out, vecOutputs) { 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}\"") ); + LOCK(cs_main); RPCTypeCheck(params, boost::assign::list_of(array_type)(obj_type)); Array inputs = params[0].get_array(); @@ -428,6 +432,7 @@ Value decoderawtransaction(const Array& params, bool fHelp) + HelpExampleRpc("decoderawtransaction", "\"hexstring\"") ); + LOCK(cs_main); RPCTypeCheck(params, boost::assign::list_of(str_type)); CTransaction tx; @@ -466,6 +471,7 @@ Value decodescript(const Array& params, bool fHelp) + HelpExampleRpc("decodescript", "\"hexstring\"") ); + LOCK(cs_main); RPCTypeCheck(params, boost::assign::list_of(str_type)); Object r; @@ -532,6 +538,11 @@ Value signrawtransaction(const Array& params, bool fHelp) + 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); vector txData(ParseHexV(params[0], "argument 1")); @@ -591,7 +602,7 @@ Value signrawtransaction(const Array& params, bool fHelp) } } #ifdef ENABLE_WALLET - else + else if (pwalletMain) EnsureWalletIsUnlocked(); #endif @@ -722,6 +733,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) + HelpExampleRpc("sendrawtransaction", "\"signedhex\"") ); + LOCK(cs_main); RPCTypeCheck(params, boost::assign::list_of(str_type)(bool_type)); // parse hex string from parameter diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index e4f23d56d..f5f8bb22a 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -7,9 +7,11 @@ #include "base58.h" #include "init.h" -#include "main.h" +#include "random.h" +#include "sync.h" #include "ui_interface.h" #include "util.h" +#include "utilstrencodings.h" #ifdef ENABLE_WALLET #include "wallet.h" #endif @@ -23,11 +25,13 @@ #include #include #include +#include #include #include "json/json_spirit_writer_template.h" using namespace boost::asio; using namespace json_spirit; +using namespace RPCServer; using namespace std; static std::string strRPCUserColonPass; @@ -46,6 +50,34 @@ static boost::asio::io_service::work *rpc_dummy_work = NULL; static std::vector rpc_allow_subnets; //!< List of subnets to allow RPC connections from static std::vector< boost::shared_ptr > rpc_acceptors; +static struct CRPCSignals +{ + boost::signals2::signal Started; + boost::signals2::signal Stopped; + boost::signals2::signal PreCommand; + boost::signals2::signal PostCommand; +} g_rpcSignals; + +void RPCServer::OnStarted(boost::function slot) +{ + g_rpcSignals.Started.connect(slot); +} + +void RPCServer::OnStopped(boost::function slot) +{ + g_rpcSignals.Stopped.connect(slot); +} + +void RPCServer::OnPreCommand(boost::function slot) +{ + g_rpcSignals.PreCommand.connect(boost::bind(slot, _1)); +} + +void RPCServer::OnPostCommand(boost::function slot) +{ + g_rpcSignals.PostCommand.connect(boost::bind(slot, _1)); +} + void RPCTypeCheck(const Array& params, const list& typesExpected, bool fAllowNull) @@ -693,6 +725,7 @@ void StartRPCThreads() for (int i = 0; i < GetArg("-rpcthreads", 4); i++) rpc_worker_group->create_thread(boost::bind(&boost::asio::io_service::run, rpc_io_service)); fRPCRunning = true; + g_rpcSignals.Started(); } void StartDummyRPCThread() @@ -735,7 +768,7 @@ void StopRPCThreads() deadlineTimers.clear(); rpc_io_service->stop(); - cvBlockChange.notify_all(); + g_rpcSignals.Stopped(); if (rpc_worker_group != NULL) rpc_worker_group->join_all(); 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]; if (!pcmd) 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 - string strWarning = GetWarnings("rpc"); - if (strWarning != "" && !GetBoolArg("-disablesafemode", false) && - !pcmd->okSafeMode) - throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning); + g_rpcSignals.PreCommand(*pcmd); try { // Execute - Value result; - { - 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; + return pcmd->actor(params, false); } catch (const std::exception& e) { throw JSONRPCError(RPC_MISC_ERROR, e.what()); } + + g_rpcSignals.PostCommand(*pcmd); } std::string HelpExampleCli(string methodname, string args){ diff --git a/src/rpcserver.h b/src/rpcserver.h index 1b94b758f..41cd9da16 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -19,6 +19,16 @@ #include "json/json_spirit_utils.h" #include "json/json_spirit_writer_template.h" +class CRPCCommand; + +namespace RPCServer +{ + void OnStarted(boost::function slot); + void OnStopped(boost::function slot); + void OnPreCommand(boost::function slot); + void OnPostCommand(boost::function slot); +} + class CBlockIndex; class CNetAddr; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 6ad3ee54d..338b64850 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -90,6 +90,8 @@ Value getnewaddress(const Array& params, bool fHelp) + HelpExampleRpc("getnewaddress", "") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + // Parse the account first so we don't generate a key if there's an error string strAccount; if (params.size() > 0) @@ -164,13 +166,14 @@ Value getaccountaddress(const Array& params, bool fHelp) + 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 string strAccount = AccountFromValue(params[0]); Value ret; ret = GetAccountAddress(strAccount).ToString(); - return ret; } @@ -189,6 +192,8 @@ Value getrawchangeaddress(const Array& params, bool fHelp) + HelpExampleRpc("getrawchangeaddress", "") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + if (!pwalletMain->IsLocked()) pwalletMain->TopUpKeyPool(); @@ -219,11 +224,12 @@ Value setaccount(const Array& params, bool fHelp) + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - string strAccount; if (params.size() > 1) strAccount = AccountFromValue(params[1]); @@ -262,6 +268,8 @@ Value getaccount(const Array& params, bool fHelp) + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); @@ -292,6 +300,8 @@ Value getaddressesbyaccount(const Array& params, bool fHelp) + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + string strAccount = AccountFromValue(params[0]); // 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\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); @@ -409,6 +421,8 @@ Value listaddressgroupings(const Array& params, bool fHelp) + HelpExampleRpc("listaddressgroupings", "") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + Array jsonGroupings; map balances = pwalletMain->GetAddressBalances(); BOOST_FOREACH(set grouping, pwalletMain->GetAddressGroupings()) @@ -454,6 +468,8 @@ Value signmessage(const Array& params, bool fHelp) + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + EnsureWalletIsUnlocked(); string strAddress = params[0].get_str(); @@ -504,6 +520,8 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + // Bitcoin address CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); if (!address.IsValid()) @@ -557,6 +575,8 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + // Minimum confirmations int nMinDepth = 1; if (params.size() > 1) @@ -643,6 +663,8 @@ Value getbalance(const Array& params, bool fHelp) + HelpExampleRpc("getbalance", "\"*\", 6") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + if (params.size() == 0) return ValueFromAmount(pwalletMain->GetBalance()); @@ -695,6 +717,9 @@ Value getunconfirmedbalance(const Array ¶ms, bool fHelp) throw runtime_error( "getunconfirmedbalance\n" "Returns the server's total unconfirmed balance\n"); + + LOCK2(cs_main, pwalletMain->cs_wallet); + return ValueFromAmount(pwalletMain->GetUnconfirmedBalance()); } @@ -721,6 +746,8 @@ Value movecmd(const Array& params, bool fHelp) + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + string strFrom = AccountFromValue(params[0]); string strTo = AccountFromValue(params[1]); 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\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + string strAccount = AccountFromValue(params[0]); CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) @@ -850,6 +879,8 @@ Value sendmany(const Array& params, bool fHelp) + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + string strAccount = AccountFromValue(params[0]); Object sendTo = params[1].get_obj(); int nMinDepth = 1; @@ -935,6 +966,8 @@ Value addmultisigaddress(const Array& params, bool fHelp) throw runtime_error(msg); } + LOCK2(cs_main, pwalletMain->cs_wallet); + string strAccount; if (params.size() > 2) strAccount = AccountFromValue(params[2]); @@ -1110,6 +1143,8 @@ Value listreceivedbyaddress(const Array& params, bool fHelp) + HelpExampleRpc("listreceivedbyaddress", "6, true, true") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + return ListReceived(params, false); } @@ -1141,6 +1176,8 @@ Value listreceivedbyaccount(const Array& params, bool fHelp) + HelpExampleRpc("listreceivedbyaccount", "6, true, true") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + return ListReceived(params, true); } @@ -1292,6 +1329,8 @@ Value listtransactions(const Array& params, bool fHelp) + HelpExampleRpc("listtransactions", "\"*\", 20, 100") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + string strAccount = "*"; if (params.size() > 0) strAccount = params[0].get_str(); @@ -1372,6 +1411,8 @@ Value listaccounts(const Array& params, bool fHelp) + HelpExampleRpc("listaccounts", "6") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + int nMinDepth = 1; if (params.size() > 0) nMinDepth = params[0].get_int(); @@ -1460,6 +1501,8 @@ Value listsinceblock(const Array& params, bool fHelp) + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + CBlockIndex *pindex = NULL; int target_confirms = 1; isminefilter filter = ISMINE_SPENDABLE; @@ -1546,6 +1589,8 @@ Value gettransaction(const Array& params, bool fHelp) + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + uint256 hash; hash.SetHex(params[0].get_str()); @@ -1594,6 +1639,8 @@ Value backupwallet(const Array& params, bool fHelp) + HelpExampleRpc("backupwallet", "\"backup.dat\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + string strDest = params[0].get_str(); if (!BackupWallet(*pwalletMain, strDest)) throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!"); @@ -1616,6 +1663,8 @@ Value keypoolrefill(const Array& params, bool fHelp) + HelpExampleRpc("keypoolrefill", "") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool unsigned int kpSize = 0; if (params.size() > 0) { @@ -1663,6 +1712,8 @@ Value walletpassphrase(const Array& params, bool fHelp) + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + if (fHelp) return true; if (!pwalletMain->IsCrypted()) @@ -1710,6 +1761,8 @@ Value walletpassphrasechange(const Array& params, bool fHelp) + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + if (fHelp) return true; if (!pwalletMain->IsCrypted()) @@ -1756,6 +1809,8 @@ Value walletlock(const Array& params, bool fHelp) + HelpExampleRpc("walletlock", "") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + if (fHelp) return true; if (!pwalletMain->IsCrypted()) @@ -1797,6 +1852,8 @@ Value encryptwallet(const Array& params, bool fHelp) + HelpExampleRpc("encryptwallet", "\"my pass phrase\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + if (fHelp) return true; if (pwalletMain->IsCrypted()) @@ -1861,6 +1918,8 @@ Value lockunspent(const Array& params, bool fHelp) + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + if (params.size() == 1) RPCTypeCheck(params, boost::assign::list_of(bool_type)); else @@ -1930,6 +1989,8 @@ Value listlockunspent(const Array& params, bool fHelp) + HelpExampleRpc("listlockunspent", "") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + vector vOutpts; pwalletMain->ListLockedCoins(vOutpts); @@ -1961,6 +2022,8 @@ Value settxfee(const Array& params, bool fHelp) + HelpExampleRpc("settxfee", "0.00001") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + // Amount CAmount nAmount = 0; if (params[0].get_real() != 0.0) @@ -1992,6 +2055,8 @@ Value getwalletinfo(const Array& params, bool fHelp) + HelpExampleRpc("getwalletinfo", "") ); + LOCK2(cs_main, pwalletMain->cs_wallet); + Object obj; obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); diff --git a/src/sync.h b/src/sync.h index 7891e4156..27e80e813 100644 --- a/src/sync.h +++ b/src/sync.h @@ -142,6 +142,17 @@ public: 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(*pmutexIn, boost::defer_lock); + if (fTry) + TryEnter(pszName, pszFile, nLine); + else + Enter(pszName, pszFile, nLine); + } + ~CMutexLock() { if (lock.owns_lock())