aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/blockchain.cpp157
-rw-r--r--src/rpc/client.cpp7
-rw-r--r--src/rpc/mining.cpp37
-rw-r--r--src/rpc/misc.cpp53
-rw-r--r--src/rpc/net.cpp134
-rw-r--r--src/rpc/protocol.h55
-rw-r--r--src/rpc/rawtransaction.cpp12
-rw-r--r--src/rpc/register.h12
-rw-r--r--src/rpc/server.cpp9
-rw-r--r--src/rpc/server.h1
10 files changed, 310 insertions, 167 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index e3c32d905a..f05f8ff358 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -26,8 +26,20 @@
#include <boost/thread/thread.hpp> // boost::thread::interrupt
+#include <mutex>
+#include <condition_variable>
using namespace std;
+struct CUpdatedBlock
+{
+ uint256 hash;
+ int height;
+};
+
+static std::mutex cs_blockchange;
+static std::condition_variable cond_blockchange;
+static CUpdatedBlock latestblock;
+
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
@@ -168,6 +180,138 @@ UniValue getbestblockhash(const UniValue& params, bool fHelp)
return chainActive.Tip()->GetBlockHash().GetHex();
}
+void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex)
+{
+ if(pindex) {
+ std::lock_guard<std::mutex> lock(cs_blockchange);
+ latestblock.hash = pindex->GetBlockHash();
+ latestblock.height = pindex->nHeight;
+ }
+ cond_blockchange.notify_all();
+}
+
+UniValue waitfornewblock(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() > 1)
+ throw runtime_error(
+ "waitfornewblock\n"
+ "\nWaits for a specific new block and returns useful info about it.\n"
+ "\nReturns the current block on timeout or exit.\n"
+ "\nArguments:\n"
+ "1. timeout (milliseconds) (int, optional, default=false)\n"
+ "\nResult::\n"
+ "{ (json object)\n"
+ " \"hash\" : { (string) The blockhash\n"
+ " \"height\" : { (int) Block height\n"
+ "}\n"
+ "\nExamples\n"
+ + HelpExampleCli("waitfornewblock", "1000")
+ + HelpExampleRpc("waitfornewblock", "1000")
+ );
+ int timeout = 0;
+ if (params.size() > 0)
+ timeout = params[0].get_int();
+
+ CUpdatedBlock block;
+ {
+ std::unique_lock<std::mutex> lock(cs_blockchange);
+ block = latestblock;
+ if(timeout)
+ cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&block]{return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); });
+ else
+ cond_blockchange.wait(lock, [&block]{return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); });
+ block = latestblock;
+ }
+ UniValue ret(UniValue::VOBJ);
+ ret.push_back(Pair("hash", block.hash.GetHex()));
+ ret.push_back(Pair("height", block.height));
+ return ret;
+}
+
+UniValue waitforblock(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 2)
+ throw runtime_error(
+ "waitforblock\n"
+ "\nWaits for a specific new block and returns useful info about it.\n"
+ "\nReturns the current block on timeout or exit.\n"
+ "\nArguments:\n"
+ "1. blockhash to wait for (string)\n"
+ "2. timeout (milliseconds) (int, optional, default=false)\n"
+ "\nResult::\n"
+ "{ (json object)\n"
+ " \"hash\" : { (string) The blockhash\n"
+ " \"height\" : { (int) Block height\n"
+ "}\n"
+ "\nExamples\n"
+ + HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
+ + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
+ );
+ int timeout = 0;
+
+ uint256 hash = uint256S(params[0].get_str());
+
+ if (params.size() > 1)
+ timeout = params[1].get_int();
+
+ CUpdatedBlock block;
+ {
+ std::unique_lock<std::mutex> lock(cs_blockchange);
+ if(timeout)
+ cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&hash]{return latestblock.hash == hash || !IsRPCRunning();});
+ else
+ cond_blockchange.wait(lock, [&hash]{return latestblock.hash == hash || !IsRPCRunning(); });
+ block = latestblock;
+ }
+
+ UniValue ret(UniValue::VOBJ);
+ ret.push_back(Pair("hash", block.hash.GetHex()));
+ ret.push_back(Pair("height", block.height));
+ return ret;
+}
+
+UniValue waitforblockheight(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 2)
+ throw runtime_error(
+ "waitforblock\n"
+ "\nWaits for (at least) block height and returns the height and hash\n"
+ "\nof the current tip.\n"
+ "\nReturns the current block on timeout or exit.\n"
+ "\nArguments:\n"
+ "1. block height to wait for (int)\n"
+ "2. timeout (milliseconds) (int, optional, default=false)\n"
+ "\nResult::\n"
+ "{ (json object)\n"
+ " \"hash\" : { (string) The blockhash\n"
+ " \"height\" : { (int) Block height\n"
+ "}\n"
+ "\nExamples\n"
+ + HelpExampleCli("waitforblockheight", "\"100\", 1000")
+ + HelpExampleRpc("waitforblockheight", "\"100\", 1000")
+ );
+ int timeout = 0;
+
+ int height = params[0].get_int();
+
+ if (params.size() > 1)
+ timeout = params[1].get_int();
+
+ CUpdatedBlock block;
+ {
+ std::unique_lock<std::mutex> lock(cs_blockchange);
+ if(timeout)
+ cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&height]{return latestblock.height >= height || !IsRPCRunning();});
+ else
+ cond_blockchange.wait(lock, [&height]{return latestblock.height >= height || !IsRPCRunning(); });
+ block = latestblock;
+ }
+ UniValue ret(UniValue::VOBJ);
+ ret.push_back(Pair("hash", block.hash.GetHex()));
+ ret.push_back(Pair("height", block.height));
+ return ret;
+}
+
UniValue getdifficulty(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -632,7 +776,7 @@ struct CCoinsStats
//! Calculate statistics about the unspent transaction output set
static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
{
- boost::scoped_ptr<CCoinsViewCursor> pcursor(view->Cursor());
+ std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor());
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
stats.hashBlock = pcursor->GetBestBlock();
@@ -1133,7 +1277,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp)
}
if (state.IsValid()) {
- ActivateBestChain(state, Params());
+ ActivateBestChain(state, Params(), NULL, g_connman.get());
}
if (!state.IsValid()) {
@@ -1171,7 +1315,7 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp)
}
CValidationState state;
- ActivateBestChain(state, Params());
+ ActivateBestChain(state, Params(), NULL, g_connman.get());
if (!state.IsValid()) {
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
@@ -1203,10 +1347,13 @@ static const CRPCCommand commands[] =
/* Not shown in help */
{ "hidden", "invalidateblock", &invalidateblock, true },
{ "hidden", "reconsiderblock", &reconsiderblock, true },
+ { "hidden", "waitfornewblock", &waitfornewblock, true },
+ { "hidden", "waitforblock", &waitforblock, true },
+ { "hidden", "waitforblockheight", &waitforblockheight, true },
};
-void RegisterBlockchainRPCCommands(CRPCTable &tableRPC)
+void RegisterBlockchainRPCCommands(CRPCTable &t)
{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
- tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+ t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index d0675fdb49..c14d9d6747 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -26,7 +26,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{
{ "stop", 0 },
{ "setmocktime", 0 },
- { "getaddednodeinfo", 0 },
{ "generate", 0 },
{ "generate", 1 },
{ "generatetoaddress", 0 },
@@ -47,6 +46,12 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getbalance", 1 },
{ "getbalance", 2 },
{ "getblockhash", 0 },
+ { "waitforblockheight", 0 },
+ { "waitforblockheight", 1 },
+ { "waitforblock", 1 },
+ { "waitforblock", 2 },
+ { "waitfornewblock", 0 },
+ { "waitfornewblock", 1 },
{ "move", 2 },
{ "move", 3 },
{ "sendfrom", 2 },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 92ca4bab6b..7794ac619d 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -131,7 +131,7 @@ UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nG
continue;
}
CValidationState state;
- if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL))
+ if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, g_connman.get()))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
@@ -227,10 +227,11 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
" \"currentblockweight\": nnn, (numeric) The last block weight\n"
" \"currentblocktx\": nnn, (numeric) The last block transaction\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
- " \"errors\": \"...\" (string) Current errors\n"
+ " \"errors\": \"...\" (string) Current errors\n"
+ " \"networkhashps\": nnn, (numeric) The network hashes per second\n"
" \"pooledtx\": n (numeric) The size of the mem pool\n"
" \"testnet\": true|false (boolean) If using testnet or not\n"
- " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
+ " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getmininginfo", "")
@@ -456,7 +457,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
- if (vNodes.empty())
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+
+ if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!");
if (IsInitialBlockDownload())
@@ -546,6 +550,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
UpdateTime(pblock, consensusParams, pindexPrev);
pblock->nNonce = 0;
+ // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
+ const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));
+
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
UniValue transactions(UniValue::VARR);
@@ -574,7 +581,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
int index_in_template = i - 1;
entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
- entry.push_back(Pair("sigops", pblocktemplate->vTxSigOpsCost[index_in_template]));
+ int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
+ if (fPreSegWit) {
+ assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
+ nTxSigOps /= WITNESS_SCALE_FACTOR;
+ }
+ entry.push_back(Pair("sigops", nTxSigOps));
entry.push_back(Pair("weight", GetTransactionWeight(tx)));
transactions.push_back(entry);
@@ -642,7 +654,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
if (nMaxVersionPreVB >= 2) {
// If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
- // Because BIP 34 changed how the generation transaction is serialised, we can only use version/force back to v2 blocks
+ // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks
// This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated
// Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated
aMutable.push_back("version/force");
@@ -657,7 +669,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
- result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST));
+ int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
+ if (fPreSegWit) {
+ assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
+ nSigOpLimit /= WITNESS_SCALE_FACTOR;
+ }
+ result.push_back(Pair("sigoplimit", nSigOpLimit));
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE));
result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT));
result.push_back(Pair("curtime", pblock->GetBlockTime()));
@@ -740,7 +757,7 @@ UniValue submitblock(const UniValue& params, bool fHelp)
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL);
+ bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, g_connman.get());
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{
@@ -905,8 +922,8 @@ static const CRPCCommand commands[] =
{ "util", "estimatesmartpriority", &estimatesmartpriority, true },
};
-void RegisterMiningRPCCommands(CRPCTable &tableRPC)
+void RegisterMiningRPCCommands(CRPCTable &t)
{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
- tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+ t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index a8c5bcd177..5afcf6353c 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -89,7 +89,8 @@ UniValue getinfo(const UniValue& params, bool fHelp)
#endif
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("timeoffset", GetTimeOffset()));
- obj.push_back(Pair("connections", (int)vNodes.size()));
+ if(g_connman)
+ obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
@@ -320,43 +321,6 @@ UniValue createmultisig(const UniValue& params, bool fHelp)
return result;
}
-UniValue createwitnessaddress(const UniValue& params, bool fHelp)
-{
- if (fHelp || params.size() < 1 || params.size() > 1)
- {
- string msg = "createwitnessaddress \"script\"\n"
- "\nCreates a witness address for a particular script.\n"
- "It returns a json object with the address and witness script.\n"
-
- "\nArguments:\n"
- "1. \"script\" (string, required) A hex encoded script\n"
-
- "\nResult:\n"
- "{\n"
- " \"address\":\"multisigaddress\", (string) The value of the new address (P2SH of witness script).\n"
- " \"witnessScript\":\"script\" (string) The string value of the hex-encoded witness script.\n"
- "}\n"
- ;
- throw runtime_error(msg);
- }
-
- if (!IsHex(params[0].get_str())) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Script must be hex-encoded");
- }
-
- std::vector<unsigned char> code = ParseHex(params[0].get_str());
- CScript script(code.begin(), code.end());
- CScript witscript = GetScriptForWitness(script);
- CScriptID witscriptid(witscript);
- CBitcoinAddress address(witscriptid);
-
- UniValue result(UniValue::VOBJ);
- result.push_back(Pair("address", address.ToString()));
- result.push_back(Pair("witnessScript", HexStr(witscript.begin(), witscript.end())));
-
- return result;
-}
-
UniValue verifymessage(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
@@ -471,14 +435,16 @@ UniValue setmocktime(const UniValue& params, bool fHelp)
// atomically with the time change to prevent peers from being
// disconnected because we think we haven't communicated with them
// in a long time.
- LOCK2(cs_main, cs_vNodes);
+ LOCK(cs_main);
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
SetMockTime(params[0].get_int64());
uint64_t t = GetTime();
- BOOST_FOREACH(CNode* pnode, vNodes) {
- pnode->nLastSend = pnode->nLastRecv = t;
+ if(g_connman) {
+ g_connman->ForEachNode([t](CNode* pnode) {
+ pnode->nLastSend = pnode->nLastRecv = t;
+ });
}
return NullUniValue;
@@ -490,7 +456,6 @@ static const CRPCCommand commands[] =
{ "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */
{ "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
{ "util", "createmultisig", &createmultisig, true },
- { "util", "createwitnessaddress", &createwitnessaddress, true },
{ "util", "verifymessage", &verifymessage, true },
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, true },
@@ -498,8 +463,8 @@ static const CRPCCommand commands[] =
{ "hidden", "setmocktime", &setmocktime, true },
};
-void RegisterMiscRPCCommands(CRPCTable &tableRPC)
+void RegisterMiscRPCCommands(CRPCTable &t)
{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
- tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+ t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index b85c7b2e1a..b011029f51 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -36,9 +36,10 @@ UniValue getconnectioncount(const UniValue& params, bool fHelp)
+ HelpExampleRpc("getconnectioncount", "")
);
- LOCK2(cs_main, cs_vNodes);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- return (int)vNodes.size();
+ return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
}
UniValue ping(const UniValue& params, bool fHelp)
@@ -54,29 +55,16 @@ UniValue ping(const UniValue& params, bool fHelp)
+ HelpExampleRpc("ping", "")
);
- // Request that each node send a ping during next message processing pass
- LOCK2(cs_main, cs_vNodes);
-
- BOOST_FOREACH(CNode* pNode, vNodes) {
- pNode->fPingQueued = true;
- }
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ // Request that each node send a ping during next message processing pass
+ g_connman->ForEachNode([](CNode* pnode) {
+ pnode->fPingQueued = true;
+ });
return NullUniValue;
}
-static void CopyNodeStats(std::vector<CNodeStats>& vstats)
-{
- vstats.clear();
-
- LOCK(cs_vNodes);
- vstats.reserve(vNodes.size());
- BOOST_FOREACH(CNode* pnode, vNodes) {
- CNodeStats stats;
- pnode->copyStats(stats);
- vstats.push_back(stats);
- }
-}
-
UniValue getpeerinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -127,10 +115,11 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
+ HelpExampleRpc("getpeerinfo", "")
);
- LOCK(cs_main);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
vector<CNodeStats> vstats;
- CopyNodeStats(vstats);
+ g_connman->GetNodeStats(vstats);
UniValue ret(UniValue::VARR);
@@ -214,32 +203,27 @@ UniValue addnode(const UniValue& params, bool fHelp)
+ HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"")
);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+
string strNode = params[0].get_str();
if (strCommand == "onetry")
{
CAddress addr;
- OpenNetworkConnection(addr, false, NULL, strNode.c_str());
+ g_connman->OpenNetworkConnection(addr, false, NULL, strNode.c_str());
return NullUniValue;
}
- LOCK(cs_vAddedNodes);
- vector<string>::iterator it = vAddedNodes.begin();
- for(; it != vAddedNodes.end(); it++)
- if (strNode == *it)
- break;
-
if (strCommand == "add")
{
- if (it != vAddedNodes.end())
+ if(!g_connman->AddNode(strNode))
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
- vAddedNodes.push_back(strNode);
}
else if(strCommand == "remove")
{
- if (it == vAddedNodes.end())
+ if(!g_connman->RemoveAddedNode(strNode))
throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
- vAddedNodes.erase(it);
}
return NullUniValue;
@@ -258,25 +242,25 @@ UniValue disconnectnode(const UniValue& params, bool fHelp)
+ HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"")
);
- CNode* pNode = FindNode(params[0].get_str());
- if (pNode == NULL)
- throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- pNode->fDisconnect = true;
+ bool ret = g_connman->DisconnectNode(params[0].get_str());
+ if (!ret)
+ throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
return NullUniValue;
}
UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
{
- if (fHelp || params.size() < 1 || params.size() > 2)
+ if (fHelp || params.size() > 1)
throw runtime_error(
- "getaddednodeinfo dummy ( \"node\" )\n"
+ "getaddednodeinfo ( \"node\" )\n"
"\nReturns information about the given added node, or all added nodes\n"
"(note that onetry addnodes are not listed here)\n"
"\nArguments:\n"
- "1. dummy (boolean, required) Kept for historical purposes but ignored\n"
- "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
+ "1. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n"
"\nResult:\n"
"[\n"
" {\n"
@@ -297,12 +281,15 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp)
+ HelpExampleRpc("getaddednodeinfo", "true, \"192.168.0.201\"")
);
- std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- if (params.size() == 2) {
+ std::vector<AddedNodeInfo> vInfo = g_connman->GetAddedNodeInfo();
+
+ if (params.size() == 1) {
bool found = false;
for (const AddedNodeInfo& info : vInfo) {
- if (info.strAddedNode == params[1].get_str()) {
+ if (info.strAddedNode == params[0].get_str()) {
vInfo.assign(1, info);
found = true;
break;
@@ -359,19 +346,21 @@ UniValue getnettotals(const UniValue& params, bool fHelp)
+ HelpExampleCli("getnettotals", "")
+ HelpExampleRpc("getnettotals", "")
);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
- obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
+ obj.push_back(Pair("totalbytesrecv", g_connman->GetTotalBytesRecv()));
+ obj.push_back(Pair("totalbytessent", g_connman->GetTotalBytesSent()));
obj.push_back(Pair("timemillis", GetTimeMillis()));
UniValue outboundLimit(UniValue::VOBJ);
- outboundLimit.push_back(Pair("timeframe", CNode::GetMaxOutboundTimeframe()));
- outboundLimit.push_back(Pair("target", CNode::GetMaxOutboundTarget()));
- outboundLimit.push_back(Pair("target_reached", CNode::OutboundTargetReached(false)));
- outboundLimit.push_back(Pair("serve_historical_blocks", !CNode::OutboundTargetReached(true)));
- outboundLimit.push_back(Pair("bytes_left_in_cycle", CNode::GetOutboundTargetBytesLeft()));
- outboundLimit.push_back(Pair("time_left_in_cycle", CNode::GetMaxOutboundTimeLeftInCycle()));
+ outboundLimit.push_back(Pair("timeframe", g_connman->GetMaxOutboundTimeframe()));
+ outboundLimit.push_back(Pair("target", g_connman->GetMaxOutboundTarget()));
+ outboundLimit.push_back(Pair("target_reached", g_connman->OutboundTargetReached(false)));
+ outboundLimit.push_back(Pair("serve_historical_blocks", !g_connman->OutboundTargetReached(true)));
+ outboundLimit.push_back(Pair("bytes_left_in_cycle", g_connman->GetOutboundTargetBytesLeft()));
+ outboundLimit.push_back(Pair("time_left_in_cycle", g_connman->GetMaxOutboundTimeLeftInCycle()));
obj.push_back(Pair("uploadtarget", outboundLimit));
return obj;
}
@@ -438,15 +427,16 @@ UniValue getnetworkinfo(const UniValue& params, bool fHelp)
);
LOCK(cs_main);
-
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("version", CLIENT_VERSION));
obj.push_back(Pair("subversion", strSubVersion));
obj.push_back(Pair("protocolversion",PROTOCOL_VERSION));
- obj.push_back(Pair("localservices", strprintf("%016x", nLocalServices)));
+ if(g_connman)
+ obj.push_back(Pair("localservices", strprintf("%016x", g_connman->GetLocalServices())));
obj.push_back(Pair("localrelay", fRelayTxes));
obj.push_back(Pair("timeoffset", GetTimeOffset()));
- obj.push_back(Pair("connections", (int)vNodes.size()));
+ if(g_connman)
+ obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
obj.push_back(Pair("networks", GetNetworksInfo()));
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
UniValue localAddresses(UniValue::VARR);
@@ -484,8 +474,10 @@ UniValue setban(const UniValue& params, bool fHelp)
"\nExamples:\n"
+ HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
+ HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
- + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400")
+ + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
CSubNet subNet;
CNetAddr netAddr;
@@ -494,17 +486,20 @@ UniValue setban(const UniValue& params, bool fHelp)
if (params[0].get_str().find("/") != string::npos)
isSubnet = true;
- if (!isSubnet)
- netAddr = CNetAddr(params[0].get_str());
+ if (!isSubnet) {
+ CNetAddr resolved;
+ LookupHost(params[0].get_str().c_str(), resolved, false);
+ netAddr = resolved;
+ }
else
- subNet = CSubNet(params[0].get_str());
+ LookupSubNet(params[0].get_str().c_str(), subNet);
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
if (strCommand == "add")
{
- if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr))
+ if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr))
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
int64_t banTime = 0; //use standard bantime if not specified
@@ -515,11 +510,11 @@ UniValue setban(const UniValue& params, bool fHelp)
if (params.size() == 4 && params[3].isTrue())
absolute = true;
- isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
+ isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
}
else if(strCommand == "remove")
{
- if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
+ if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) ))
throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
}
return NullUniValue;
@@ -536,8 +531,11 @@ UniValue listbanned(const UniValue& params, bool fHelp)
+ HelpExampleRpc("listbanned", "")
);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+
banmap_t banMap;
- CNode::GetBanned(banMap);
+ g_connman->GetBanned(banMap);
UniValue bannedAddresses(UniValue::VARR);
for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
@@ -565,8 +563,10 @@ UniValue clearbanned(const UniValue& params, bool fHelp)
+ HelpExampleCli("clearbanned", "")
+ HelpExampleRpc("clearbanned", "")
);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- CNode::ClearBanned();
+ g_connman->ClearBanned();
return NullUniValue;
}
@@ -587,8 +587,8 @@ static const CRPCCommand commands[] =
{ "network", "clearbanned", &clearbanned, true },
};
-void RegisterNetRPCCommands(CRPCTable &tableRPC)
+void RegisterNetRPCCommands(CRPCTable &t)
{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
- tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+ t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h
index 55d0aac68b..1d2ef0e41e 100644
--- a/src/rpc/protocol.h
+++ b/src/rpc/protocol.h
@@ -38,18 +38,18 @@ enum RPCErrorCode
RPC_PARSE_ERROR = -32700,
//! General application defined errors
- RPC_MISC_ERROR = -1, //! std::exception thrown in command handling
- RPC_FORBIDDEN_BY_SAFE_MODE = -2, //! Server is in safe mode, and command is not allowed in safe mode
- RPC_TYPE_ERROR = -3, //! Unexpected type was passed as parameter
- RPC_INVALID_ADDRESS_OR_KEY = -5, //! Invalid address or key
- RPC_OUT_OF_MEMORY = -7, //! Ran out of memory during operation
- RPC_INVALID_PARAMETER = -8, //! Invalid, missing or duplicate parameter
- RPC_DATABASE_ERROR = -20, //! Database error
- RPC_DESERIALIZATION_ERROR = -22, //! Error parsing or validating structure in raw format
- RPC_VERIFY_ERROR = -25, //! General error during transaction or block submission
- RPC_VERIFY_REJECTED = -26, //! Transaction or block was rejected by network rules
- RPC_VERIFY_ALREADY_IN_CHAIN = -27, //! Transaction already in chain
- RPC_IN_WARMUP = -28, //! Client still warming up
+ RPC_MISC_ERROR = -1, //!< std::exception thrown in command handling
+ RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode
+ RPC_TYPE_ERROR = -3, //!< Unexpected type was passed as parameter
+ RPC_INVALID_ADDRESS_OR_KEY = -5, //!< Invalid address or key
+ RPC_OUT_OF_MEMORY = -7, //!< Ran out of memory during operation
+ RPC_INVALID_PARAMETER = -8, //!< Invalid, missing or duplicate parameter
+ RPC_DATABASE_ERROR = -20, //!< Database error
+ RPC_DESERIALIZATION_ERROR = -22, //!< Error parsing or validating structure in raw format
+ RPC_VERIFY_ERROR = -25, //!< General error during transaction or block submission
+ RPC_VERIFY_REJECTED = -26, //!< Transaction or block was rejected by network rules
+ RPC_VERIFY_ALREADY_IN_CHAIN = -27, //!< Transaction already in chain
+ RPC_IN_WARMUP = -28, //!< Client still warming up
//! Aliases for backward compatibility
RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR,
@@ -57,23 +57,24 @@ enum RPCErrorCode
RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN,
//! P2P client errors
- RPC_CLIENT_NOT_CONNECTED = -9, //! Bitcoin is not connected
- RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //! Still downloading initial blocks
- RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added
- RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before
- RPC_CLIENT_NODE_NOT_CONNECTED = -29, //! Node to disconnect not found in connected nodes
- RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //! Invalid IP/Subnet
+ RPC_CLIENT_NOT_CONNECTED = -9, //!< Bitcoin is not connected
+ RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //!< Still downloading initial blocks
+ RPC_CLIENT_NODE_ALREADY_ADDED = -23, //!< Node is already added
+ RPC_CLIENT_NODE_NOT_ADDED = -24, //!< Node has not been added before
+ RPC_CLIENT_NODE_NOT_CONNECTED = -29, //!< Node to disconnect not found in connected nodes
+ RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //!< Invalid IP/Subnet
+ RPC_CLIENT_P2P_DISABLED = -31, //!< No valid connection manager instance found
//! Wallet errors
- RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.)
- RPC_WALLET_INSUFFICIENT_FUNDS = -6, //! Not enough funds in wallet or account
- RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //! Invalid account name
- RPC_WALLET_KEYPOOL_RAN_OUT = -12, //! Keypool ran out, call keypoolrefill first
- RPC_WALLET_UNLOCK_NEEDED = -13, //! Enter the wallet passphrase with walletpassphrase first
- RPC_WALLET_PASSPHRASE_INCORRECT = -14, //! The wallet passphrase entered was incorrect
- RPC_WALLET_WRONG_ENC_STATE = -15, //! Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.)
- RPC_WALLET_ENCRYPTION_FAILED = -16, //! Failed to encrypt the wallet
- RPC_WALLET_ALREADY_UNLOCKED = -17, //! Wallet is already unlocked
+ RPC_WALLET_ERROR = -4, //!< Unspecified problem with wallet (key not found etc.)
+ RPC_WALLET_INSUFFICIENT_FUNDS = -6, //!< Not enough funds in wallet or account
+ RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //!< Invalid account name
+ RPC_WALLET_KEYPOOL_RAN_OUT = -12, //!< Keypool ran out, call keypoolrefill first
+ RPC_WALLET_UNLOCK_NEEDED = -13, //!< Enter the wallet passphrase with walletpassphrase first
+ RPC_WALLET_PASSPHRASE_INCORRECT = -14, //!< The wallet passphrase entered was incorrect
+ RPC_WALLET_WRONG_ENC_STATE = -15, //!< Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.)
+ RPC_WALLET_ENCRYPTION_FAILED = -16, //!< Failed to encrypt the wallet
+ RPC_WALLET_ALREADY_UNLOCKED = -17, //!< Wallet is already unlocked
};
std::string JSONRPCRequest(const std::string& strMethod, const UniValue& params, const UniValue& id);
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 3270cd384f..d2ad0a52b7 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -891,8 +891,14 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}
- RelayTransaction(tx);
+ if(!g_connman)
+ throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ CInv inv(MSG_TX, hashTx);
+ g_connman->ForEachNode([&inv](CNode* pnode)
+ {
+ pnode->PushInventory(inv);
+ });
return hashTx.GetHex();
}
@@ -910,8 +916,8 @@ static const CRPCCommand commands[] =
{ "blockchain", "verifytxoutproof", &verifytxoutproof, true },
};
-void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC)
+void RegisterRawTransactionRPCCommands(CRPCTable &t)
{
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
- tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+ t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/rpc/register.h b/src/rpc/register.h
index 01aa58a25d..49aee2365f 100644
--- a/src/rpc/register.h
+++ b/src/rpc/register.h
@@ -20,13 +20,13 @@ void RegisterMiningRPCCommands(CRPCTable &tableRPC);
/** Register raw transaction RPC commands */
void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
-static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC)
+static inline void RegisterAllCoreRPCCommands(CRPCTable &t)
{
- RegisterBlockchainRPCCommands(tableRPC);
- RegisterNetRPCCommands(tableRPC);
- RegisterMiscRPCCommands(tableRPC);
- RegisterMiningRPCCommands(tableRPC);
- RegisterRawTransactionRPCCommands(tableRPC);
+ RegisterBlockchainRPCCommands(t);
+ RegisterNetRPCCommands(t);
+ RegisterMiscRPCCommands(t);
+ RegisterMiningRPCCommands(t);
+ RegisterRawTransactionRPCCommands(t);
}
#endif
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 23149baa6d..5fb97f7496 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -25,6 +25,8 @@
#include <boost/thread.hpp>
#include <boost/algorithm/string/case_conv.hpp> // for to_upper()
+#include <memory> // for unique_ptr
+
using namespace RPCServer;
using namespace std;
@@ -34,9 +36,8 @@ static std::string rpcWarmupStatus("RPC server started");
static CCriticalSection cs_rpcWarmup;
/* Timer-creating functions */
static RPCTimerInterface* timerInterface = NULL;
-/* Map of name to timer.
- * @note Can be changed to std::unique_ptr when C++11 */
-static std::map<std::string, boost::shared_ptr<RPCTimerBase> > deadlineTimers;
+/* Map of name to timer. */
+static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers;
static struct CRPCSignals
{
@@ -490,7 +491,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
deadlineTimers.erase(name);
LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
- deadlineTimers.insert(std::make_pair(name, boost::shared_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000))));
+ deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
}
CRPCTable tableRPC;
diff --git a/src/rpc/server.h b/src/rpc/server.h
index b5ccc153d0..4e0aa2c6d6 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -194,5 +194,6 @@ bool StartRPC();
void InterruptRPC();
void StopRPC();
std::string JSONRPCExecBatch(const UniValue& vReq);
+void RPCNotifyBlockChange(bool ibd, const CBlockIndex *);
#endif // BITCOIN_RPCSERVER_H