aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/blockchain.cpp256
-rw-r--r--src/rpc/client.cpp3
-rw-r--r--src/rpc/mining.cpp172
-rw-r--r--src/rpc/misc.cpp171
-rw-r--r--src/rpc/net.cpp140
-rw-r--r--src/rpc/protocol.cpp22
-rw-r--r--src/rpc/rawtransaction.cpp39
-rw-r--r--src/rpc/util.cpp68
-rw-r--r--src/rpc/util.h19
9 files changed, 443 insertions, 447 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 346672e45a..189da6ae48 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -88,28 +88,28 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
{
AssertLockHeld(cs_main);
UniValue result(UniValue::VOBJ);
- result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
+ result.pushKV("hash", blockindex->GetBlockHash().GetHex());
int confirmations = -1;
// Only report confirmations if the block is on the main chain
if (chainActive.Contains(blockindex))
confirmations = chainActive.Height() - blockindex->nHeight + 1;
- result.push_back(Pair("confirmations", confirmations));
- result.push_back(Pair("height", blockindex->nHeight));
- result.push_back(Pair("version", blockindex->nVersion));
- result.push_back(Pair("versionHex", strprintf("%08x", blockindex->nVersion)));
- result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
- result.push_back(Pair("time", (int64_t)blockindex->nTime));
- result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
- result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce));
- result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
- result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
- result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
+ result.pushKV("confirmations", confirmations);
+ result.pushKV("height", blockindex->nHeight);
+ result.pushKV("version", blockindex->nVersion);
+ result.pushKV("versionHex", strprintf("%08x", blockindex->nVersion));
+ result.pushKV("merkleroot", blockindex->hashMerkleRoot.GetHex());
+ result.pushKV("time", (int64_t)blockindex->nTime);
+ result.pushKV("mediantime", (int64_t)blockindex->GetMedianTimePast());
+ result.pushKV("nonce", (uint64_t)blockindex->nNonce);
+ result.pushKV("bits", strprintf("%08x", blockindex->nBits));
+ result.pushKV("difficulty", GetDifficulty(blockindex));
+ result.pushKV("chainwork", blockindex->nChainWork.GetHex());
if (blockindex->pprev)
- result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
+ result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex());
CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
- result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
+ result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
return result;
}
@@ -117,19 +117,19 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
{
AssertLockHeld(cs_main);
UniValue result(UniValue::VOBJ);
- result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
+ result.pushKV("hash", blockindex->GetBlockHash().GetHex());
int confirmations = -1;
// Only report confirmations if the block is on the main chain
if (chainActive.Contains(blockindex))
confirmations = chainActive.Height() - blockindex->nHeight + 1;
- result.push_back(Pair("confirmations", confirmations));
- result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)));
- result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
- result.push_back(Pair("weight", (int)::GetBlockWeight(block)));
- result.push_back(Pair("height", blockindex->nHeight));
- result.push_back(Pair("version", block.nVersion));
- result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
- result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
+ result.pushKV("confirmations", confirmations);
+ result.pushKV("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS));
+ result.pushKV("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION));
+ result.pushKV("weight", (int)::GetBlockWeight(block));
+ result.pushKV("height", blockindex->nHeight);
+ result.pushKV("version", block.nVersion);
+ result.pushKV("versionHex", strprintf("%08x", block.nVersion));
+ result.pushKV("merkleroot", block.hashMerkleRoot.GetHex());
UniValue txs(UniValue::VARR);
for(const auto& tx : block.vtx)
{
@@ -142,19 +142,19 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
else
txs.push_back(tx->GetHash().GetHex());
}
- result.push_back(Pair("tx", txs));
- result.push_back(Pair("time", block.GetBlockTime()));
- result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
- result.push_back(Pair("nonce", (uint64_t)block.nNonce));
- result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
- result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
- result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex()));
+ result.pushKV("tx", txs);
+ result.pushKV("time", block.GetBlockTime());
+ result.pushKV("mediantime", (int64_t)blockindex->GetMedianTimePast());
+ result.pushKV("nonce", (uint64_t)block.nNonce);
+ result.pushKV("bits", strprintf("%08x", block.nBits));
+ result.pushKV("difficulty", GetDifficulty(blockindex));
+ result.pushKV("chainwork", blockindex->nChainWork.GetHex());
if (blockindex->pprev)
- result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
+ result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex());
CBlockIndex *pnext = chainActive.Next(blockindex);
if (pnext)
- result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
+ result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
return result;
}
@@ -235,8 +235,8 @@ UniValue waitfornewblock(const JSONRPCRequest& request)
block = latestblock;
}
UniValue ret(UniValue::VOBJ);
- ret.push_back(Pair("hash", block.hash.GetHex()));
- ret.push_back(Pair("height", block.height));
+ ret.pushKV("hash", block.hash.GetHex());
+ ret.pushKV("height", block.height);
return ret;
}
@@ -277,8 +277,8 @@ UniValue waitforblock(const JSONRPCRequest& request)
}
UniValue ret(UniValue::VOBJ);
- ret.push_back(Pair("hash", block.hash.GetHex()));
- ret.push_back(Pair("height", block.height));
+ ret.pushKV("hash", block.hash.GetHex());
+ ret.pushKV("height", block.height);
return ret;
}
@@ -319,8 +319,8 @@ UniValue waitforblockheight(const JSONRPCRequest& request)
block = latestblock;
}
UniValue ret(UniValue::VOBJ);
- ret.push_back(Pair("hash", block.hash.GetHex()));
- ret.push_back(Pair("height", block.height));
+ ret.pushKV("hash", block.hash.GetHex());
+ ret.pushKV("height", block.height);
return ret;
}
@@ -379,18 +379,18 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e)
{
AssertLockHeld(mempool.cs);
- info.push_back(Pair("size", (int)e.GetTxSize()));
- info.push_back(Pair("fee", ValueFromAmount(e.GetFee())));
- info.push_back(Pair("modifiedfee", ValueFromAmount(e.GetModifiedFee())));
- info.push_back(Pair("time", e.GetTime()));
- info.push_back(Pair("height", (int)e.GetHeight()));
- info.push_back(Pair("descendantcount", e.GetCountWithDescendants()));
- info.push_back(Pair("descendantsize", e.GetSizeWithDescendants()));
- info.push_back(Pair("descendantfees", e.GetModFeesWithDescendants()));
- info.push_back(Pair("ancestorcount", e.GetCountWithAncestors()));
- info.push_back(Pair("ancestorsize", e.GetSizeWithAncestors()));
- info.push_back(Pair("ancestorfees", e.GetModFeesWithAncestors()));
- info.push_back(Pair("wtxid", mempool.vTxHashes[e.vTxHashesIdx].first.ToString()));
+ info.pushKV("size", (int)e.GetTxSize());
+ info.pushKV("fee", ValueFromAmount(e.GetFee()));
+ info.pushKV("modifiedfee", ValueFromAmount(e.GetModifiedFee()));
+ info.pushKV("time", e.GetTime());
+ info.pushKV("height", (int)e.GetHeight());
+ info.pushKV("descendantcount", e.GetCountWithDescendants());
+ info.pushKV("descendantsize", e.GetSizeWithDescendants());
+ info.pushKV("descendantfees", e.GetModFeesWithDescendants());
+ info.pushKV("ancestorcount", e.GetCountWithAncestors());
+ info.pushKV("ancestorsize", e.GetSizeWithAncestors());
+ info.pushKV("ancestorfees", e.GetModFeesWithAncestors());
+ info.pushKV("wtxid", mempool.vTxHashes[e.vTxHashesIdx].first.ToString());
const CTransaction& tx = e.GetTx();
std::set<std::string> setDepends;
for (const CTxIn& txin : tx.vin)
@@ -405,7 +405,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e)
depends.push_back(dep);
}
- info.push_back(Pair("depends", depends));
+ info.pushKV("depends", depends);
}
UniValue mempoolToJSON(bool fVerbose)
@@ -419,7 +419,7 @@ UniValue mempoolToJSON(bool fVerbose)
const uint256& hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
entryToJSON(info, e);
- o.push_back(Pair(hash.ToString(), info));
+ o.pushKV(hash.ToString(), info);
}
return o;
}
@@ -526,7 +526,7 @@ UniValue getmempoolancestors(const JSONRPCRequest& request)
const uint256& _hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
entryToJSON(info, e);
- o.push_back(Pair(_hash.ToString(), info));
+ o.pushKV(_hash.ToString(), info);
}
return o;
}
@@ -590,7 +590,7 @@ UniValue getmempooldescendants(const JSONRPCRequest& request)
const uint256& _hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
entryToJSON(info, e);
- o.push_back(Pair(_hash.ToString(), info));
+ o.pushKV(_hash.ToString(), info);
}
return o;
}
@@ -952,14 +952,14 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request)
CCoinsStats stats;
FlushStateToDisk();
if (GetUTXOStats(pcoinsdbview.get(), stats)) {
- ret.push_back(Pair("height", (int64_t)stats.nHeight));
- ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
- ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
- ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
- ret.push_back(Pair("bogosize", (int64_t)stats.nBogoSize));
- ret.push_back(Pair("hash_serialized_2", stats.hashSerialized.GetHex()));
- ret.push_back(Pair("disk_size", stats.nDiskSize));
- ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
+ ret.pushKV("height", (int64_t)stats.nHeight);
+ ret.pushKV("bestblock", stats.hashBlock.GetHex());
+ ret.pushKV("transactions", (int64_t)stats.nTransactions);
+ ret.pushKV("txouts", (int64_t)stats.nTransactionOutputs);
+ ret.pushKV("bogosize", (int64_t)stats.nBogoSize);
+ ret.pushKV("hash_serialized_2", stats.hashSerialized.GetHex());
+ ret.pushKV("disk_size", stats.nDiskSize);
+ ret.pushKV("total_amount", ValueFromAmount(stats.nTotalAmount));
} else {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
}
@@ -1031,17 +1031,17 @@ UniValue gettxout(const JSONRPCRequest& request)
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
CBlockIndex *pindex = it->second;
- ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
+ ret.pushKV("bestblock", pindex->GetBlockHash().GetHex());
if (coin.nHeight == MEMPOOL_HEIGHT) {
- ret.push_back(Pair("confirmations", 0));
+ ret.pushKV("confirmations", 0);
} else {
- ret.push_back(Pair("confirmations", (int64_t)(pindex->nHeight - coin.nHeight + 1)));
+ ret.pushKV("confirmations", (int64_t)(pindex->nHeight - coin.nHeight + 1));
}
- ret.push_back(Pair("value", ValueFromAmount(coin.out.nValue)));
+ ret.pushKV("value", ValueFromAmount(coin.out.nValue));
UniValue o(UniValue::VOBJ);
ScriptPubKeyToUniv(coin.out.scriptPubKey, o, true);
- ret.push_back(Pair("scriptPubKey", o));
- ret.push_back(Pair("coinbase", (bool)coin.fCoinBase));
+ ret.pushKV("scriptPubKey", o);
+ ret.pushKV("coinbase", (bool)coin.fCoinBase);
return ret;
}
@@ -1091,16 +1091,16 @@ static UniValue SoftForkMajorityDesc(int version, CBlockIndex* pindex, const Con
activated = pindex->nHeight >= consensusParams.BIP65Height;
break;
}
- rv.push_back(Pair("status", activated));
+ rv.pushKV("status", activated);
return rv;
}
static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
{
UniValue rv(UniValue::VOBJ);
- rv.push_back(Pair("id", name));
- rv.push_back(Pair("version", version));
- rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams)));
+ rv.pushKV("id", name);
+ rv.pushKV("version", version);
+ rv.pushKV("reject", SoftForkMajorityDesc(version, pindex, consensusParams));
return rv;
}
@@ -1109,29 +1109,29 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse
UniValue rv(UniValue::VOBJ);
const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
switch (thresholdState) {
- case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break;
- case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break;
- case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break;
- case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break;
- case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break;
+ case THRESHOLD_DEFINED: rv.pushKV("status", "defined"); break;
+ case THRESHOLD_STARTED: rv.pushKV("status", "started"); break;
+ case THRESHOLD_LOCKED_IN: rv.pushKV("status", "locked_in"); break;
+ case THRESHOLD_ACTIVE: rv.pushKV("status", "active"); break;
+ case THRESHOLD_FAILED: rv.pushKV("status", "failed"); break;
}
if (THRESHOLD_STARTED == thresholdState)
{
- rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit));
+ rv.pushKV("bit", consensusParams.vDeployments[id].bit);
}
- rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime));
- rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout));
- rv.push_back(Pair("since", VersionBitsTipStateSinceHeight(consensusParams, id)));
+ rv.pushKV("startTime", consensusParams.vDeployments[id].nStartTime);
+ rv.pushKV("timeout", consensusParams.vDeployments[id].nTimeout);
+ rv.pushKV("since", VersionBitsTipStateSinceHeight(consensusParams, id));
if (THRESHOLD_STARTED == thresholdState)
{
UniValue statsUV(UniValue::VOBJ);
BIP9Stats statsStruct = VersionBitsTipStatistics(consensusParams, id);
- statsUV.push_back(Pair("period", statsStruct.period));
- statsUV.push_back(Pair("threshold", statsStruct.threshold));
- statsUV.push_back(Pair("elapsed", statsStruct.elapsed));
- statsUV.push_back(Pair("count", statsStruct.count));
- statsUV.push_back(Pair("possible", statsStruct.possible));
- rv.push_back(Pair("statistics", statsUV));
+ statsUV.pushKV("period", statsStruct.period);
+ statsUV.pushKV("threshold", statsStruct.threshold);
+ statsUV.pushKV("elapsed", statsStruct.elapsed);
+ statsUV.pushKV("count", statsStruct.count);
+ statsUV.pushKV("possible", statsStruct.possible);
+ rv.pushKV("statistics", statsUV);
}
return rv;
}
@@ -1142,7 +1142,7 @@ void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus::Params&
// A timeout value of 0 guarantees a softfork will never be activated.
// This is used when softfork codes are merged without specifying the deployment schedule.
if (consensusParams.vDeployments[id].nTimeout > 0)
- bip9_softforks.push_back(Pair(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id)));
+ bip9_softforks.pushKV(VersionBitsDeploymentInfo[id].name, BIP9SoftForkDesc(consensusParams, id));
}
UniValue getblockchaininfo(const JSONRPCRequest& request)
@@ -1202,17 +1202,17 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("chain", Params().NetworkIDString()));
- obj.push_back(Pair("blocks", (int)chainActive.Height()));
- obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1));
- obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()));
- obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast()));
- obj.push_back(Pair("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip())));
- obj.push_back(Pair("initialblockdownload", IsInitialBlockDownload()));
- obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex()));
- obj.push_back(Pair("size_on_disk", CalculateCurrentUsage()));
- obj.push_back(Pair("pruned", fPruneMode));
+ obj.pushKV("chain", Params().NetworkIDString());
+ obj.pushKV("blocks", (int)chainActive.Height());
+ obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1);
+ obj.pushKV("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex());
+ obj.pushKV("difficulty", (double)GetDifficulty());
+ obj.pushKV("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast());
+ obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip()));
+ obj.pushKV("initialblockdownload", IsInitialBlockDownload());
+ obj.pushKV("chainwork", chainActive.Tip()->nChainWork.GetHex());
+ obj.pushKV("size_on_disk", CalculateCurrentUsage());
+ obj.pushKV("pruned", fPruneMode);
if (fPruneMode) {
CBlockIndex* block = chainActive.Tip();
assert(block);
@@ -1220,13 +1220,13 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
block = block->pprev;
}
- obj.push_back(Pair("pruneheight", block->nHeight));
+ obj.pushKV("pruneheight", block->nHeight);
// if 0, execution bypasses the whole if block.
bool automatic_pruning = (gArgs.GetArg("-prune", 0) != 1);
- obj.push_back(Pair("automatic_pruning", automatic_pruning));
+ obj.pushKV("automatic_pruning", automatic_pruning);
if (automatic_pruning) {
- obj.push_back(Pair("prune_target_size", nPruneTarget));
+ obj.pushKV("prune_target_size", nPruneTarget);
}
}
@@ -1240,10 +1240,10 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
for (int pos = Consensus::DEPLOYMENT_CSV; pos != Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++pos) {
BIP9SoftForkDescPushBack(bip9_softforks, consensusParams, static_cast<Consensus::DeploymentPos>(pos));
}
- obj.push_back(Pair("softforks", softforks));
- obj.push_back(Pair("bip9_softforks", bip9_softforks));
+ obj.pushKV("softforks", softforks);
+ obj.pushKV("bip9_softforks", bip9_softforks);
- obj.push_back(Pair("warnings", GetWarnings("statusbar")));
+ obj.pushKV("warnings", GetWarnings("statusbar"));
return obj;
}
@@ -1331,11 +1331,11 @@ UniValue getchaintips(const JSONRPCRequest& request)
for (const CBlockIndex* block : setTips)
{
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("height", block->nHeight));
- obj.push_back(Pair("hash", block->phashBlock->GetHex()));
+ obj.pushKV("height", block->nHeight);
+ obj.pushKV("hash", block->phashBlock->GetHex());
const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
- obj.push_back(Pair("branchlen", branchLen));
+ obj.pushKV("branchlen", branchLen);
std::string status;
if (chainActive.Contains(block)) {
@@ -1357,7 +1357,7 @@ UniValue getchaintips(const JSONRPCRequest& request)
// No clue.
status = "unknown";
}
- obj.push_back(Pair("status", status));
+ obj.pushKV("status", status);
res.push_back(obj);
}
@@ -1368,13 +1368,13 @@ UniValue getchaintips(const JSONRPCRequest& request)
UniValue mempoolInfoToJSON()
{
UniValue ret(UniValue::VOBJ);
- ret.push_back(Pair("size", (int64_t) mempool.size()));
- ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
- ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
+ ret.pushKV("size", (int64_t) mempool.size());
+ ret.pushKV("bytes", (int64_t) mempool.GetTotalTxSize());
+ ret.pushKV("usage", (int64_t) mempool.DynamicMemoryUsage());
size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
- ret.push_back(Pair("maxmempool", (int64_t) maxmempool));
- ret.push_back(Pair("mempoolminfee", ValueFromAmount(std::max(mempool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK())));
- ret.push_back(Pair("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
+ ret.pushKV("maxmempool", (int64_t) maxmempool);
+ ret.pushKV("mempoolminfee", ValueFromAmount(std::max(mempool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK()));
+ ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
return ret;
}
@@ -1526,12 +1526,13 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
"2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n"
"\nResult:\n"
"{\n"
- " \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n"
- " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
- " \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n"
- " \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n"
- " \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n"
- " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n"
+ " \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n"
+ " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
+ " \"window_final_block_hash\": \"...\", (string) The hash of the final block in the window.\n"
+ " \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n"
+ " \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n"
+ " \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n"
+ " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getchaintxstats", "")
@@ -1580,14 +1581,15 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
int nTxDiff = pindex->nChainTx - pindexPast->nChainTx;
UniValue ret(UniValue::VOBJ);
- ret.push_back(Pair("time", (int64_t)pindex->nTime));
- ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx));
- ret.push_back(Pair("window_block_count", blockcount));
+ ret.pushKV("time", (int64_t)pindex->nTime);
+ ret.pushKV("txcount", (int64_t)pindex->nChainTx);
+ ret.pushKV("window_final_block_hash", pindex->GetBlockHash().GetHex());
+ ret.pushKV("window_block_count", blockcount);
if (blockcount > 0) {
- ret.push_back(Pair("window_tx_count", nTxDiff));
- ret.push_back(Pair("window_interval", nTimeDiff));
+ ret.pushKV("window_tx_count", nTxDiff);
+ ret.pushKV("window_interval", nTimeDiff);
if (nTimeDiff > 0) {
- ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff));
+ ret.pushKV("txrate", ((double)nTxDiff) / nTimeDiff);
}
}
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index f63e970bdd..99c1242d8a 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -114,7 +114,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "pruneblockchain", 0, "height" },
{ "keypoolrefill", 0, "newsize" },
{ "getrawmempool", 0, "verbose" },
- { "estimatefee", 0, "nblocks" },
{ "estimatesmartfee", 0, "conf_target" },
{ "estimaterawfee", 0, "conf_target" },
{ "estimaterawfee", 1, "threshold" },
@@ -213,7 +212,7 @@ UniValue RPCConvertNamedValues(const std::string &strMethod, const std::vector<s
UniValue params(UniValue::VOBJ);
for (const std::string &s: strParams) {
- size_t pos = s.find("=");
+ size_t pos = s.find('=');
if (pos == std::string::npos) {
throw(std::runtime_error("No '=' in named argument '"+s+"', this needs to be present for every argument (even if it is empty)"));
}
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index c22d0ac377..dd74095b62 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -201,7 +201,6 @@ UniValue getmininginfo(const JSONRPCRequest& request)
" \"pooledtx\": n (numeric) The size of the mempool\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
" \"warnings\": \"...\" (string) any network and blockchain warnings\n"
- " \"errors\": \"...\" (string) DEPRECATED. Same as warnings. Only shown when bitcoind is started with -deprecatedrpc=getmininginfo\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getmininginfo", "")
@@ -212,18 +211,14 @@ UniValue getmininginfo(const JSONRPCRequest& request)
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("blocks", (int)chainActive.Height()));
- obj.push_back(Pair("currentblockweight", (uint64_t)nLastBlockWeight));
- obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
- obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("networkhashps", getnetworkhashps(request)));
- obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
- obj.push_back(Pair("chain", Params().NetworkIDString()));
- if (IsDeprecatedRPCEnabled("getmininginfo")) {
- obj.push_back(Pair("errors", GetWarnings("statusbar")));
- } else {
- obj.push_back(Pair("warnings", GetWarnings("statusbar")));
- }
+ obj.pushKV("blocks", (int)chainActive.Height());
+ obj.pushKV("currentblockweight", (uint64_t)nLastBlockWeight);
+ obj.pushKV("currentblocktx", (uint64_t)nLastBlockTx);
+ obj.pushKV("difficulty", (double)GetDifficulty());
+ obj.pushKV("networkhashps", getnetworkhashps(request));
+ obj.pushKV("pooledtx", (uint64_t)mempool.size());
+ obj.pushKV("chain", Params().NetworkIDString());
+ obj.pushKV("warnings", GetWarnings("statusbar"));
return obj;
}
@@ -555,9 +550,9 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
UniValue entry(UniValue::VOBJ);
- entry.push_back(Pair("data", EncodeHexTx(tx)));
- entry.push_back(Pair("txid", txHash.GetHex()));
- entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex()));
+ entry.pushKV("data", EncodeHexTx(tx));
+ entry.pushKV("txid", txHash.GetHex());
+ entry.pushKV("hash", tx.GetWitnessHash().GetHex());
UniValue deps(UniValue::VARR);
for (const CTxIn &in : tx.vin)
@@ -565,23 +560,23 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
if (setTxIndex.count(in.prevout.hash))
deps.push_back(setTxIndex[in.prevout.hash]);
}
- entry.push_back(Pair("depends", deps));
+ entry.pushKV("depends", deps);
int index_in_template = i - 1;
- entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
+ entry.pushKV("fee", pblocktemplate->vTxFees[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)));
+ entry.pushKV("sigops", nTxSigOps);
+ entry.pushKV("weight", GetTransactionWeight(tx));
transactions.push_back(entry);
}
UniValue aux(UniValue::VOBJ);
- aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
+ aux.pushKV("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()));
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
@@ -591,7 +586,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
aMutable.push_back("prevblock");
UniValue result(UniValue::VOBJ);
- result.push_back(Pair("capabilities", aCaps));
+ result.pushKV("capabilities", aCaps);
UniValue aRules(UniValue::VARR);
UniValue vbavailable(UniValue::VOBJ);
@@ -610,7 +605,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
case THRESHOLD_STARTED:
{
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
- vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit));
+ vbavailable.pushKV(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit);
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
if (!vbinfo.gbt_force) {
// If the client doesn't support this, don't indicate it in the [default] version
@@ -635,10 +630,10 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
}
}
}
- result.push_back(Pair("version", pblock->nVersion));
- result.push_back(Pair("rules", aRules));
- result.push_back(Pair("vbavailable", vbavailable));
- result.push_back(Pair("vbrequired", int(0)));
+ result.pushKV("version", pblock->nVersion);
+ result.pushKV("rules", aRules);
+ result.pushKV("vbavailable", vbavailable);
+ result.pushKV("vbrequired", int(0));
if (nMaxVersionPreVB >= 2) {
// If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
@@ -648,15 +643,15 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
aMutable.push_back("version/force");
}
- result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
- result.push_back(Pair("transactions", transactions));
- result.push_back(Pair("coinbaseaux", aux));
- result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue));
- result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
- result.push_back(Pair("target", hashTarget.GetHex()));
- result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
- result.push_back(Pair("mutable", aMutable));
- result.push_back(Pair("noncerange", "00000000ffffffff"));
+ result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
+ result.pushKV("transactions", transactions);
+ result.pushKV("coinbaseaux", aux);
+ result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
+ result.pushKV("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast));
+ result.pushKV("target", hashTarget.GetHex());
+ result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
+ result.pushKV("mutable", aMutable);
+ result.pushKV("noncerange", "00000000ffffffff");
int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE;
if (fPreSegWit) {
@@ -665,17 +660,17 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
assert(nSizeLimit % WITNESS_SCALE_FACTOR == 0);
nSizeLimit /= WITNESS_SCALE_FACTOR;
}
- result.push_back(Pair("sigoplimit", nSigOpLimit));
- result.push_back(Pair("sizelimit", nSizeLimit));
+ result.pushKV("sigoplimit", nSigOpLimit);
+ result.pushKV("sizelimit", nSizeLimit);
if (!fPreSegWit) {
- result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT));
+ result.pushKV("weightlimit", (int64_t)MAX_BLOCK_WEIGHT);
}
- result.push_back(Pair("curtime", pblock->GetBlockTime()));
- result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
- result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
+ result.pushKV("curtime", pblock->GetBlockTime());
+ result.pushKV("bits", strprintf("%08x", pblock->nBits));
+ result.pushKV("height", (int64_t)(pindexPrev->nHeight+1));
if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) {
- result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end())));
+ result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()));
}
return result;
@@ -772,43 +767,8 @@ UniValue submitblock(const JSONRPCRequest& request)
UniValue estimatefee(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
- throw std::runtime_error(
- "estimatefee nblocks\n"
- "\nDEPRECATED. Please use estimatesmartfee for more intelligent estimates."
- "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
- "confirmation within nblocks blocks. Uses virtual transaction size of transaction\n"
- "as defined in BIP 141 (witness data is discounted).\n"
- "\nArguments:\n"
- "1. nblocks (numeric, required)\n"
- "\nResult:\n"
- "n (numeric) estimated fee-per-kilobyte\n"
- "\n"
- "A negative value is returned if not enough transactions and blocks\n"
- "have been observed to make an estimate.\n"
- "-1 is always returned for nblocks == 1 as it is impossible to calculate\n"
- "a fee that is high enough to get reliably included in the next block.\n"
- "\nExample:\n"
- + HelpExampleCli("estimatefee", "6")
- );
-
- if (!IsDeprecatedRPCEnabled("estimatefee")) {
- throw JSONRPCError(RPC_METHOD_DEPRECATED, "estimatefee is deprecated and will be fully removed in v0.17. "
- "To use estimatefee in v0.16, restart bitcoind with -deprecatedrpc=estimatefee.\n"
- "Projects should transition to using estimatesmartfee before upgrading to v0.17");
- }
-
- RPCTypeCheck(request.params, {UniValue::VNUM});
-
- int nBlocks = request.params[0].get_int();
- if (nBlocks < 1)
- nBlocks = 1;
-
- CFeeRate feeRate = ::feeEstimator.estimateFee(nBlocks);
- if (feeRate == CFeeRate(0))
- return -1.0;
-
- return ValueFromAmount(feeRate.GetFeePerK());
+ throw JSONRPCError(RPC_METHOD_DEPRECATED, "estimatefee was removed in v0.17.\n"
+ "Clients should use estimatesmartfee.");
}
UniValue estimatesmartfee(const JSONRPCRequest& request)
@@ -863,12 +823,12 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
FeeCalculation feeCalc;
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(conf_target, &feeCalc, conservative);
if (feeRate != CFeeRate(0)) {
- result.push_back(Pair("feerate", ValueFromAmount(feeRate.GetFeePerK())));
+ result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
} else {
errors.push_back("Insufficient data or no feerate found");
- result.push_back(Pair("errors", errors));
+ result.pushKV("errors", errors);
}
- result.push_back(Pair("blocks", feeCalc.returnedTarget));
+ result.pushKV("blocks", feeCalc.returnedTarget);
return result;
}
@@ -939,37 +899,37 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
UniValue horizon_result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
UniValue passbucket(UniValue::VOBJ);
- passbucket.push_back(Pair("startrange", round(buckets.pass.start)));
- passbucket.push_back(Pair("endrange", round(buckets.pass.end)));
- passbucket.push_back(Pair("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0));
- passbucket.push_back(Pair("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0));
- passbucket.push_back(Pair("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0));
- passbucket.push_back(Pair("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0));
+ passbucket.pushKV("startrange", round(buckets.pass.start));
+ passbucket.pushKV("endrange", round(buckets.pass.end));
+ passbucket.pushKV("withintarget", round(buckets.pass.withinTarget * 100.0) / 100.0);
+ passbucket.pushKV("totalconfirmed", round(buckets.pass.totalConfirmed * 100.0) / 100.0);
+ passbucket.pushKV("inmempool", round(buckets.pass.inMempool * 100.0) / 100.0);
+ passbucket.pushKV("leftmempool", round(buckets.pass.leftMempool * 100.0) / 100.0);
UniValue failbucket(UniValue::VOBJ);
- failbucket.push_back(Pair("startrange", round(buckets.fail.start)));
- failbucket.push_back(Pair("endrange", round(buckets.fail.end)));
- failbucket.push_back(Pair("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0));
- failbucket.push_back(Pair("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0));
- failbucket.push_back(Pair("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0));
- failbucket.push_back(Pair("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0));
+ failbucket.pushKV("startrange", round(buckets.fail.start));
+ failbucket.pushKV("endrange", round(buckets.fail.end));
+ failbucket.pushKV("withintarget", round(buckets.fail.withinTarget * 100.0) / 100.0);
+ failbucket.pushKV("totalconfirmed", round(buckets.fail.totalConfirmed * 100.0) / 100.0);
+ failbucket.pushKV("inmempool", round(buckets.fail.inMempool * 100.0) / 100.0);
+ failbucket.pushKV("leftmempool", round(buckets.fail.leftMempool * 100.0) / 100.0);
// CFeeRate(0) is used to indicate error as a return value from estimateRawFee
if (feeRate != CFeeRate(0)) {
- horizon_result.push_back(Pair("feerate", ValueFromAmount(feeRate.GetFeePerK())));
- horizon_result.push_back(Pair("decay", buckets.decay));
- horizon_result.push_back(Pair("scale", (int)buckets.scale));
- horizon_result.push_back(Pair("pass", passbucket));
+ horizon_result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
+ horizon_result.pushKV("decay", buckets.decay);
+ horizon_result.pushKV("scale", (int)buckets.scale);
+ horizon_result.pushKV("pass", passbucket);
// buckets.fail.start == -1 indicates that all buckets passed, there is no fail bucket to output
- if (buckets.fail.start != -1) horizon_result.push_back(Pair("fail", failbucket));
+ if (buckets.fail.start != -1) horizon_result.pushKV("fail", failbucket);
} else {
// Output only information that is still meaningful in the event of error
- horizon_result.push_back(Pair("decay", buckets.decay));
- horizon_result.push_back(Pair("scale", (int)buckets.scale));
- horizon_result.push_back(Pair("fail", failbucket));
+ horizon_result.pushKV("decay", buckets.decay);
+ horizon_result.pushKV("scale", (int)buckets.scale);
+ horizon_result.pushKV("fail", failbucket);
errors.push_back("Insufficient data or no feerate found which meets threshold");
- horizon_result.push_back(Pair("errors",errors));
+ horizon_result.pushKV("errors",errors);
}
- result.push_back(Pair(StringForFeeEstimateHorizon(horizon), horizon_result));
+ result.pushKV(StringForFeeEstimateHorizon(horizon), horizon_result);
}
return result;
}
@@ -986,7 +946,7 @@ static const CRPCCommand commands[] =
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
- { "util", "estimatefee", &estimatefee, {"nblocks"} },
+ { "hidden", "estimatefee", &estimatefee, {} },
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
{ "hidden", "estimaterawfee", &estimaterawfee, {"conf_target", "threshold"} },
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 3bcad16316..3f89996e61 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -15,6 +15,7 @@
#include <netbase.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
+#include <rpc/util.h>
#include <timedata.h>
#include <util.h>
#include <utilstrencodings.h>
@@ -85,11 +86,11 @@ public:
UniValue operator()(const CKeyID &keyID) const {
UniValue obj(UniValue::VOBJ);
CPubKey vchPubKey;
- obj.push_back(Pair("isscript", false));
- obj.push_back(Pair("iswitness", false));
+ obj.pushKV("isscript", false);
+ obj.pushKV("iswitness", false);
if (pwallet && pwallet->GetPubKey(keyID, vchPubKey)) {
- obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
- obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
+ obj.pushKV("pubkey", HexStr(vchPubKey));
+ obj.pushKV("iscompressed", vchPubKey.IsCompressed());
}
return obj;
}
@@ -97,8 +98,8 @@ public:
UniValue operator()(const CScriptID &scriptID) const {
UniValue obj(UniValue::VOBJ);
CScript subscript;
- obj.push_back(Pair("isscript", true));
- obj.push_back(Pair("iswitness", false));
+ obj.pushKV("isscript", true);
+ obj.pushKV("iswitness", false);
if (pwallet && pwallet->GetCScript(scriptID, subscript)) {
ProcessSubScript(subscript, obj, true);
}
@@ -109,12 +110,12 @@ public:
{
UniValue obj(UniValue::VOBJ);
CPubKey pubkey;
- obj.push_back(Pair("isscript", false));
- obj.push_back(Pair("iswitness", true));
- obj.push_back(Pair("witness_version", 0));
- obj.push_back(Pair("witness_program", HexStr(id.begin(), id.end())));
+ obj.pushKV("isscript", false);
+ obj.pushKV("iswitness", true);
+ obj.pushKV("witness_version", 0);
+ obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
if (pwallet && pwallet->GetPubKey(CKeyID(id), pubkey)) {
- obj.push_back(Pair("pubkey", HexStr(pubkey)));
+ obj.pushKV("pubkey", HexStr(pubkey));
}
return obj;
}
@@ -123,10 +124,10 @@ public:
{
UniValue obj(UniValue::VOBJ);
CScript subscript;
- obj.push_back(Pair("isscript", true));
- obj.push_back(Pair("iswitness", true));
- obj.push_back(Pair("witness_version", 0));
- obj.push_back(Pair("witness_program", HexStr(id.begin(), id.end())));
+ obj.pushKV("isscript", true);
+ obj.pushKV("iswitness", true);
+ obj.pushKV("witness_version", 0);
+ obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
CRIPEMD160 hasher;
uint160 hash;
hasher.Write(id.begin(), 32).Finalize(hash.begin());
@@ -140,9 +141,9 @@ public:
{
UniValue obj(UniValue::VOBJ);
CScript subscript;
- obj.push_back(Pair("iswitness", true));
- obj.push_back(Pair("witness_version", (int)id.version));
- obj.push_back(Pair("witness_program", HexStr(id.program, id.program + id.length)));
+ obj.pushKV("iswitness", true);
+ obj.pushKV("witness_version", (int)id.version);
+ obj.pushKV("witness_program", HexStr(id.program, id.program + id.length));
return obj;
}
};
@@ -205,23 +206,23 @@ UniValue validateaddress(const JSONRPCRequest& request)
bool isValid = IsValidDestination(dest);
UniValue ret(UniValue::VOBJ);
- ret.push_back(Pair("isvalid", isValid));
+ ret.pushKV("isvalid", isValid);
if (isValid)
{
std::string currentAddress = EncodeDestination(dest);
- ret.push_back(Pair("address", currentAddress));
+ ret.pushKV("address", currentAddress);
CScript scriptPubKey = GetScriptForDestination(dest);
- ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
+ ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
#ifdef ENABLE_WALLET
isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO;
- ret.push_back(Pair("ismine", bool(mine & ISMINE_SPENDABLE)));
- ret.push_back(Pair("iswatchonly", bool(mine & ISMINE_WATCH_ONLY)));
+ ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
+ ret.pushKV("iswatchonly", bool(mine & ISMINE_WATCH_ONLY));
UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest);
ret.pushKVs(detail);
if (pwallet && pwallet->mapAddressBook.count(dest)) {
- ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name));
+ ret.pushKV("account", pwallet->mapAddressBook[dest].name);
}
if (pwallet) {
const CKeyMetadata* meta = nullptr;
@@ -239,10 +240,10 @@ UniValue validateaddress(const JSONRPCRequest& request)
}
}
if (meta) {
- ret.push_back(Pair("timestamp", meta->nCreateTime));
+ ret.pushKV("timestamp", meta->nCreateTime);
if (!meta->hdKeypath.empty()) {
- ret.push_back(Pair("hdkeypath", meta->hdKeypath));
- ret.push_back(Pair("hdmasterkeyid", meta->hdMasterKeyID.GetHex()));
+ ret.pushKV("hdkeypath", meta->hdKeypath);
+ ret.pushKV("hdmasterkeyid", meta->hdMasterKeyID.GetHex());
}
}
}
@@ -254,88 +255,18 @@ UniValue validateaddress(const JSONRPCRequest& request)
// Needed even with !ENABLE_WALLET, to pass (ignored) pointers around
class CWallet;
-/**
- * Used by addmultisigaddress / createmultisig:
- */
-CScript _createmultisig_redeemScript(CWallet * const pwallet, const UniValue& params)
-{
- int nRequired = params[0].get_int();
- const UniValue& keys = params[1].get_array();
-
- // Gather public keys
- if (nRequired < 1)
- throw std::runtime_error("a multisignature address must require at least one key to redeem");
- if ((int)keys.size() < nRequired)
- throw std::runtime_error(
- strprintf("not enough keys supplied "
- "(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
- if (keys.size() > 16)
- throw std::runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
- std::vector<CPubKey> pubkeys;
- pubkeys.resize(keys.size());
- for (unsigned int i = 0; i < keys.size(); i++)
- {
- const std::string& ks = keys[i].get_str();
-#ifdef ENABLE_WALLET
- // Case 1: Bitcoin address and we have full public key:
- CTxDestination dest = DecodeDestination(ks);
- if (pwallet && IsValidDestination(dest)) {
- CKeyID key = GetKeyForDestination(*pwallet, dest);
- if (key.IsNull()) {
- throw std::runtime_error(strprintf("%s does not refer to a key", ks));
- }
- CPubKey vchPubKey;
- if (!pwallet->GetPubKey(key, vchPubKey)) {
- throw std::runtime_error(strprintf("no full public key for address %s", ks));
- }
- if (!vchPubKey.IsFullyValid())
- throw std::runtime_error(" Invalid public key: "+ks);
- pubkeys[i] = vchPubKey;
- }
-
- // Case 2: hex public key
- else
-#endif
- if (IsHex(ks))
- {
- CPubKey vchPubKey(ParseHex(ks));
- if (!vchPubKey.IsFullyValid())
- throw std::runtime_error(" Invalid public key: "+ks);
- pubkeys[i] = vchPubKey;
- }
- else
- {
- throw std::runtime_error(" Invalid public key: "+ks);
- }
- }
- CScript result = GetScriptForMultisig(nRequired, pubkeys);
-
- if (result.size() > MAX_SCRIPT_ELEMENT_SIZE)
- throw std::runtime_error(
- strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE));
-
- return result;
-}
-
UniValue createmultisig(const JSONRPCRequest& request)
{
-#ifdef ENABLE_WALLET
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
-#else
- CWallet * const pwallet = nullptr;
-#endif
-
if (request.fHelp || request.params.size() < 2 || request.params.size() > 2)
{
std::string msg = "createmultisig nrequired [\"key\",...]\n"
"\nCreates a multi-signature address with n signature of m keys required.\n"
"It returns a json object with the address and redeemScript.\n"
-
"\nArguments:\n"
- "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
- "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
+ "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
+ "2. \"keys\" (string, required) A json array of hex-encoded public keys\n"
" [\n"
- " \"key\" (string) bitcoin address or hex-encoded public key\n"
+ " \"key\" (string) The hex-encoded public key\n"
" ,...\n"
" ]\n"
@@ -346,21 +277,35 @@ UniValue createmultisig(const JSONRPCRequest& request)
"}\n"
"\nExamples:\n"
- "\nCreate a multisig address from 2 addresses\n"
- + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
+ "\nCreate a multisig address from 2 public keys\n"
+ + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
"\nAs a json rpc call\n"
- + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
+ + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"")
;
throw std::runtime_error(msg);
}
+ int required = request.params[0].get_int();
+
+ // Get the public keys
+ const UniValue& keys = request.params[1].get_array();
+ std::vector<CPubKey> pubkeys;
+ for (unsigned int i = 0; i < keys.size(); ++i) {
+ if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) {
+ pubkeys.push_back(HexToPubKey(keys[i].get_str()));
+ } else {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\nNote that from v0.16, createmultisig no longer accepts addresses."
+ " Users must use addmultisigaddress to create multisig addresses with addresses known to the wallet.", keys[i].get_str()));
+ }
+ }
+
// Construct using pay-to-script-hash:
- CScript inner = _createmultisig_redeemScript(pwallet, request.params);
+ CScript inner = CreateMultisigRedeemscript(required, pubkeys);
CScriptID innerID(inner);
UniValue result(UniValue::VOBJ);
- result.push_back(Pair("address", EncodeDestination(innerID)));
- result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
+ result.pushKV("address", EncodeDestination(innerID));
+ result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
return result;
}
@@ -494,12 +439,12 @@ static UniValue RPCLockedMemoryInfo()
{
LockedPool::Stats stats = LockedPoolManager::Instance().stats();
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("used", uint64_t(stats.used)));
- obj.push_back(Pair("free", uint64_t(stats.free)));
- obj.push_back(Pair("total", uint64_t(stats.total)));
- obj.push_back(Pair("locked", uint64_t(stats.locked)));
- obj.push_back(Pair("chunks_used", uint64_t(stats.chunks_used)));
- obj.push_back(Pair("chunks_free", uint64_t(stats.chunks_free)));
+ obj.pushKV("used", uint64_t(stats.used));
+ obj.pushKV("free", uint64_t(stats.free));
+ obj.pushKV("total", uint64_t(stats.total));
+ obj.pushKV("locked", uint64_t(stats.locked));
+ obj.pushKV("chunks_used", uint64_t(stats.chunks_used));
+ obj.pushKV("chunks_free", uint64_t(stats.chunks_free));
return obj;
}
@@ -556,7 +501,7 @@ UniValue getmemoryinfo(const JSONRPCRequest& request)
std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str();
if (mode == "stats") {
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("locked", RPCLockedMemoryInfo()));
+ obj.pushKV("locked", RPCLockedMemoryInfo());
return obj;
} else if (mode == "mallocinfo") {
#ifdef HAVE_MALLOC_INFO
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index a81b651981..7a0225ff0d 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -130,59 +130,59 @@ UniValue getpeerinfo(const JSONRPCRequest& request)
UniValue obj(UniValue::VOBJ);
CNodeStateStats statestats;
bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
- obj.push_back(Pair("id", stats.nodeid));
- obj.push_back(Pair("addr", stats.addrName));
+ obj.pushKV("id", stats.nodeid);
+ obj.pushKV("addr", stats.addrName);
if (!(stats.addrLocal.empty()))
- obj.push_back(Pair("addrlocal", stats.addrLocal));
+ obj.pushKV("addrlocal", stats.addrLocal);
if (stats.addrBind.IsValid())
- obj.push_back(Pair("addrbind", stats.addrBind.ToString()));
- obj.push_back(Pair("services", strprintf("%016x", stats.nServices)));
- obj.push_back(Pair("relaytxes", stats.fRelayTxes));
- obj.push_back(Pair("lastsend", stats.nLastSend));
- obj.push_back(Pair("lastrecv", stats.nLastRecv));
- obj.push_back(Pair("bytessent", stats.nSendBytes));
- obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
- obj.push_back(Pair("conntime", stats.nTimeConnected));
- obj.push_back(Pair("timeoffset", stats.nTimeOffset));
+ obj.pushKV("addrbind", stats.addrBind.ToString());
+ obj.pushKV("services", strprintf("%016x", stats.nServices));
+ obj.pushKV("relaytxes", stats.fRelayTxes);
+ obj.pushKV("lastsend", stats.nLastSend);
+ obj.pushKV("lastrecv", stats.nLastRecv);
+ obj.pushKV("bytessent", stats.nSendBytes);
+ obj.pushKV("bytesrecv", stats.nRecvBytes);
+ obj.pushKV("conntime", stats.nTimeConnected);
+ obj.pushKV("timeoffset", stats.nTimeOffset);
if (stats.dPingTime > 0.0)
- obj.push_back(Pair("pingtime", stats.dPingTime));
+ obj.pushKV("pingtime", stats.dPingTime);
if (stats.dMinPing < static_cast<double>(std::numeric_limits<int64_t>::max())/1e6)
- obj.push_back(Pair("minping", stats.dMinPing));
+ obj.pushKV("minping", stats.dMinPing);
if (stats.dPingWait > 0.0)
- obj.push_back(Pair("pingwait", stats.dPingWait));
- obj.push_back(Pair("version", stats.nVersion));
+ obj.pushKV("pingwait", stats.dPingWait);
+ obj.pushKV("version", stats.nVersion);
// Use the sanitized form of subver here, to avoid tricksy remote peers from
// corrupting or modifying the JSON output by putting special characters in
// their ver message.
- obj.push_back(Pair("subver", stats.cleanSubVer));
- obj.push_back(Pair("inbound", stats.fInbound));
- obj.push_back(Pair("addnode", stats.m_manual_connection));
- obj.push_back(Pair("startingheight", stats.nStartingHeight));
+ obj.pushKV("subver", stats.cleanSubVer);
+ obj.pushKV("inbound", stats.fInbound);
+ obj.pushKV("addnode", stats.m_manual_connection);
+ obj.pushKV("startingheight", stats.nStartingHeight);
if (fStateStats) {
- obj.push_back(Pair("banscore", statestats.nMisbehavior));
- obj.push_back(Pair("synced_headers", statestats.nSyncHeight));
- obj.push_back(Pair("synced_blocks", statestats.nCommonHeight));
+ obj.pushKV("banscore", statestats.nMisbehavior);
+ obj.pushKV("synced_headers", statestats.nSyncHeight);
+ obj.pushKV("synced_blocks", statestats.nCommonHeight);
UniValue heights(UniValue::VARR);
for (int height : statestats.vHeightInFlight) {
heights.push_back(height);
}
- obj.push_back(Pair("inflight", heights));
+ obj.pushKV("inflight", heights);
}
- obj.push_back(Pair("whitelisted", stats.fWhitelisted));
+ obj.pushKV("whitelisted", stats.fWhitelisted);
UniValue sendPerMsgCmd(UniValue::VOBJ);
for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) {
if (i.second > 0)
- sendPerMsgCmd.push_back(Pair(i.first, i.second));
+ sendPerMsgCmd.pushKV(i.first, i.second);
}
- obj.push_back(Pair("bytessent_per_msg", sendPerMsgCmd));
+ obj.pushKV("bytessent_per_msg", sendPerMsgCmd);
UniValue recvPerMsgCmd(UniValue::VOBJ);
for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) {
if (i.second > 0)
- recvPerMsgCmd.push_back(Pair(i.first, i.second));
+ recvPerMsgCmd.pushKV(i.first, i.second);
}
- obj.push_back(Pair("bytesrecv_per_msg", recvPerMsgCmd));
+ obj.pushKV("bytesrecv_per_msg", recvPerMsgCmd);
ret.push_back(obj);
}
@@ -331,16 +331,16 @@ UniValue getaddednodeinfo(const JSONRPCRequest& request)
for (const AddedNodeInfo& info : vInfo) {
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("addednode", info.strAddedNode));
- obj.push_back(Pair("connected", info.fConnected));
+ obj.pushKV("addednode", info.strAddedNode);
+ obj.pushKV("connected", info.fConnected);
UniValue addresses(UniValue::VARR);
if (info.fConnected) {
UniValue address(UniValue::VOBJ);
- address.push_back(Pair("address", info.resolvedAddress.ToString()));
- address.push_back(Pair("connected", info.fInbound ? "inbound" : "outbound"));
+ address.pushKV("address", info.resolvedAddress.ToString());
+ address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
addresses.push_back(address);
}
- obj.push_back(Pair("addresses", addresses));
+ obj.pushKV("addresses", addresses);
ret.push_back(obj);
}
@@ -377,18 +377,18 @@ UniValue getnettotals(const JSONRPCRequest& request)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
UniValue obj(UniValue::VOBJ);
- obj.push_back(Pair("totalbytesrecv", g_connman->GetTotalBytesRecv()));
- obj.push_back(Pair("totalbytessent", g_connman->GetTotalBytesSent()));
- obj.push_back(Pair("timemillis", GetTimeMillis()));
+ obj.pushKV("totalbytesrecv", g_connman->GetTotalBytesRecv());
+ obj.pushKV("totalbytessent", g_connman->GetTotalBytesSent());
+ obj.pushKV("timemillis", GetTimeMillis());
UniValue outboundLimit(UniValue::VOBJ);
- 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));
+ outboundLimit.pushKV("timeframe", g_connman->GetMaxOutboundTimeframe());
+ outboundLimit.pushKV("target", g_connman->GetMaxOutboundTarget());
+ outboundLimit.pushKV("target_reached", g_connman->OutboundTargetReached(false));
+ outboundLimit.pushKV("serve_historical_blocks", !g_connman->OutboundTargetReached(true));
+ outboundLimit.pushKV("bytes_left_in_cycle", g_connman->GetOutboundTargetBytesLeft());
+ outboundLimit.pushKV("time_left_in_cycle", g_connman->GetMaxOutboundTimeLeftInCycle());
+ obj.pushKV("uploadtarget", outboundLimit);
return obj;
}
@@ -403,11 +403,11 @@ static UniValue GetNetworksInfo()
proxyType proxy;
UniValue obj(UniValue::VOBJ);
GetProxy(network, proxy);
- obj.push_back(Pair("name", GetNetworkName(network)));
- obj.push_back(Pair("limited", IsLimited(network)));
- obj.push_back(Pair("reachable", IsReachable(network)));
- obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string()));
- obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
+ obj.pushKV("name", GetNetworkName(network));
+ obj.pushKV("limited", IsLimited(network));
+ obj.pushKV("reachable", IsReachable(network));
+ obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
+ obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
networks.push_back(obj);
}
return networks;
@@ -458,34 +458,34 @@ UniValue getnetworkinfo(const JSONRPCRequest& request)
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.pushKV("version", CLIENT_VERSION);
+ obj.pushKV("subversion", strSubVersion);
+ obj.pushKV("protocolversion",PROTOCOL_VERSION);
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.pushKV("localservices", strprintf("%016x", g_connman->GetLocalServices()));
+ obj.pushKV("localrelay", fRelayTxes);
+ obj.pushKV("timeoffset", GetTimeOffset());
if (g_connman) {
- obj.push_back(Pair("networkactive", g_connman->GetNetworkActive()));
- obj.push_back(Pair("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL)));
+ obj.pushKV("networkactive", g_connman->GetNetworkActive());
+ obj.pushKV("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
}
- obj.push_back(Pair("networks", GetNetworksInfo()));
- obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
- obj.push_back(Pair("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK())));
+ obj.pushKV("networks", GetNetworksInfo());
+ obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
+ obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
UniValue localAddresses(UniValue::VARR);
{
LOCK(cs_mapLocalHost);
for (const std::pair<CNetAddr, LocalServiceInfo> &item : mapLocalHost)
{
UniValue rec(UniValue::VOBJ);
- rec.push_back(Pair("address", item.first.ToString()));
- rec.push_back(Pair("port", item.second.nPort));
- rec.push_back(Pair("score", item.second.nScore));
+ rec.pushKV("address", item.first.ToString());
+ rec.pushKV("port", item.second.nPort);
+ rec.pushKV("score", item.second.nScore);
localAddresses.push_back(rec);
}
}
- obj.push_back(Pair("localaddresses", localAddresses));
- obj.push_back(Pair("warnings", GetWarnings("statusbar")));
+ obj.pushKV("localaddresses", localAddresses);
+ obj.pushKV("warnings", GetWarnings("statusbar"));
return obj;
}
@@ -516,7 +516,7 @@ UniValue setban(const JSONRPCRequest& request)
CNetAddr netAddr;
bool isSubnet = false;
- if (request.params[0].get_str().find("/") != std::string::npos)
+ if (request.params[0].get_str().find('/') != std::string::npos)
isSubnet = true;
if (!isSubnet) {
@@ -575,10 +575,10 @@ UniValue listbanned(const JSONRPCRequest& request)
{
const CBanEntry& banEntry = entry.second;
UniValue rec(UniValue::VOBJ);
- rec.push_back(Pair("address", entry.first.ToString()));
- rec.push_back(Pair("banned_until", banEntry.nBanUntil));
- rec.push_back(Pair("ban_created", banEntry.nCreateTime));
- rec.push_back(Pair("ban_reason", banEntry.banReasonToString()));
+ rec.pushKV("address", entry.first.ToString());
+ rec.pushKV("banned_until", banEntry.nBanUntil);
+ rec.pushKV("ban_created", banEntry.nCreateTime);
+ rec.pushKV("ban_reason", banEntry.banReasonToString());
bannedAddresses.push_back(rec);
}
diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp
index ddc1bb6232..0635b757c6 100644
--- a/src/rpc/protocol.cpp
+++ b/src/rpc/protocol.cpp
@@ -26,9 +26,9 @@
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id)
{
UniValue request(UniValue::VOBJ);
- request.push_back(Pair("method", strMethod));
- request.push_back(Pair("params", params));
- request.push_back(Pair("id", id));
+ request.pushKV("method", strMethod);
+ request.pushKV("params", params);
+ request.pushKV("id", id);
return request;
}
@@ -36,11 +36,11 @@ UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const Un
{
UniValue reply(UniValue::VOBJ);
if (!error.isNull())
- reply.push_back(Pair("result", NullUniValue));
+ reply.pushKV("result", NullUniValue);
else
- reply.push_back(Pair("result", result));
- reply.push_back(Pair("error", error));
- reply.push_back(Pair("id", id));
+ reply.pushKV("result", result);
+ reply.pushKV("error", error);
+ reply.pushKV("id", id);
return reply;
}
@@ -53,8 +53,8 @@ std::string JSONRPCReply(const UniValue& result, const UniValue& error, const Un
UniValue JSONRPCError(int code, const std::string& message)
{
UniValue error(UniValue::VOBJ);
- error.push_back(Pair("code", code));
- error.push_back(Pair("message", message));
+ error.pushKV("code", code);
+ error.pushKV("message", message);
return error;
}
@@ -72,9 +72,7 @@ static fs::path GetAuthCookieFile(bool temp=false)
if (temp) {
arg += ".tmp";
}
- fs::path path(arg);
- if (!path.is_complete()) path = GetDataDir() / path;
- return path;
+ return AbsPathForConfigVal(fs::path(arg));
}
bool GenerateAuthCookie(std::string *cookie_out)
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 82399e1567..24f2431efc 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -47,17 +47,17 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
TxToUniv(tx, uint256(), entry, true, RPCSerializationFlags());
if (!hashBlock.IsNull()) {
- entry.push_back(Pair("blockhash", hashBlock.GetHex()));
+ entry.pushKV("blockhash", hashBlock.GetHex());
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi != mapBlockIndex.end() && (*mi).second) {
CBlockIndex* pindex = (*mi).second;
if (chainActive.Contains(pindex)) {
- entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
- entry.push_back(Pair("time", pindex->GetBlockTime()));
- entry.push_back(Pair("blocktime", pindex->GetBlockTime()));
+ entry.pushKV("confirmations", 1 + chainActive.Height() - pindex->nHeight);
+ entry.pushKV("time", pindex->GetBlockTime());
+ entry.pushKV("blocktime", pindex->GetBlockTime());
}
else
- entry.push_back(Pair("confirmations", 0));
+ entry.pushKV("confirmations", 0);
}
}
}
@@ -147,6 +147,11 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
uint256 hash = ParseHashV(request.params[0], "parameter 1");
CBlockIndex* blockindex = nullptr;
+ if (hash == Params().GenesisBlock().hashMerkleRoot) {
+ // Special exception for the genesis block coinbase transaction
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "The genesis block coinbase is not considered an ordinary transaction and cannot be retrieved");
+ }
+
// Accept either a bool (true) or a num (>=1) to indicate verbose output.
bool fVerbose = false;
if (!request.params[1].isNull()) {
@@ -185,7 +190,7 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
}
UniValue result(UniValue::VOBJ);
- if (blockindex) result.push_back(Pair("in_active_chain", in_active_chain));
+ if (blockindex) result.pushKV("in_active_chain", in_active_chain);
TxToJSON(*tx, hash_block, result);
return result;
}
@@ -557,7 +562,7 @@ UniValue decodescript(const JSONRPCRequest& request)
if (type.isStr() && type.get_str() != "scripthash") {
// P2SH cannot be wrapped in a P2SH. If this script is already a P2SH,
// don't return the address for a P2SH of the P2SH.
- r.push_back(Pair("p2sh", EncodeDestination(CScriptID(script))));
+ r.pushKV("p2sh", EncodeDestination(CScriptID(script)));
}
return r;
@@ -567,16 +572,16 @@ UniValue decodescript(const JSONRPCRequest& request)
static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
{
UniValue entry(UniValue::VOBJ);
- entry.push_back(Pair("txid", txin.prevout.hash.ToString()));
- entry.push_back(Pair("vout", (uint64_t)txin.prevout.n));
+ entry.pushKV("txid", txin.prevout.hash.ToString());
+ entry.pushKV("vout", (uint64_t)txin.prevout.n);
UniValue witness(UniValue::VARR);
for (unsigned int i = 0; i < txin.scriptWitness.stack.size(); i++) {
witness.push_back(HexStr(txin.scriptWitness.stack[i].begin(), txin.scriptWitness.stack[i].end()));
}
- entry.push_back(Pair("witness", witness));
- entry.push_back(Pair("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
- entry.push_back(Pair("sequence", (uint64_t)txin.nSequence));
- entry.push_back(Pair("error", strMessage));
+ entry.pushKV("witness", witness);
+ entry.pushKV("scriptSig", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
+ entry.pushKV("sequence", (uint64_t)txin.nSequence);
+ entry.pushKV("error", strMessage);
vErrorsRet.push_back(entry);
}
@@ -687,7 +692,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
"\nArguments:\n"
"1. \"hexstring\" (string, required) The transaction hex string\n"
- "2. \"prevtxs\" (string, optional) An json array of previous dependent transaction outputs\n"
+ "2. \"prevtxs\" (string, optional) A json array of previous dependent transaction outputs\n"
" [ (json array of json objects, or 'null' if none provided)\n"
" {\n"
" \"txid\":\"id\", (string, required) The transaction id\n"
@@ -911,10 +916,10 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
bool fComplete = vErrors.empty();
UniValue result(UniValue::VOBJ);
- result.push_back(Pair("hex", EncodeHexTx(mtx)));
- result.push_back(Pair("complete", fComplete));
+ result.pushKV("hex", EncodeHexTx(mtx));
+ result.pushKV("complete", fComplete);
if (!vErrors.empty()) {
- result.push_back(Pair("errors", vErrors));
+ result.pushKV("errors", vErrors);
}
return result;
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
new file mode 100644
index 0000000000..09ded4e46e
--- /dev/null
+++ b/src/rpc/util.cpp
@@ -0,0 +1,68 @@
+// Copyright (c) 2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <base58.h>
+#include <keystore.h>
+#include <pubkey.h>
+#include <rpc/protocol.h>
+#include <rpc/util.h>
+#include <tinyformat.h>
+#include <utilstrencodings.h>
+
+// Converts a hex string to a public key if possible
+CPubKey HexToPubKey(const std::string& hex_in)
+{
+ if (!IsHex(hex_in)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
+ }
+ CPubKey vchPubKey(ParseHex(hex_in));
+ if (!vchPubKey.IsFullyValid()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
+ }
+ return vchPubKey;
+}
+
+// Retrieves a public key for an address from the given CKeyStore
+CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in)
+{
+ CTxDestination dest = DecodeDestination(addr_in);
+ if (!IsValidDestination(dest)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in);
+ }
+ CKeyID key = GetKeyForDestination(*keystore, dest);
+ if (key.IsNull()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in));
+ }
+ CPubKey vchPubKey;
+ if (!keystore->GetPubKey(key, vchPubKey)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in));
+ }
+ if (!vchPubKey.IsFullyValid()) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet contains an invalid public key");
+ }
+ return vchPubKey;
+}
+
+// Creates a multisig redeemscript from a given list of public keys and number required.
+CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys)
+{
+ // Gather public keys
+ if (required < 1) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "a multisignature address must require at least one key to redeem");
+ }
+ if ((int)pubkeys.size() < required) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("not enough keys supplied (got %u keys, but need at least %d to redeem)", pubkeys.size(), required));
+ }
+ if (pubkeys.size() > 16) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Number of keys involved in the multisignature address creation > 16\nReduce the number");
+ }
+
+ CScript result = GetScriptForMultisig(required, pubkeys);
+
+ if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, (strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)));
+ }
+
+ return result;
+}
diff --git a/src/rpc/util.h b/src/rpc/util.h
new file mode 100644
index 0000000000..568a4260ba
--- /dev/null
+++ b/src/rpc/util.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_RPC_UTIL_H
+#define BITCOIN_RPC_UTIL_H
+
+#include <string>
+#include <vector>
+
+class CKeyStore;
+class CPubKey;
+class CScript;
+
+CPubKey HexToPubKey(const std::string& hex_in);
+CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
+CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
+
+#endif // BITCOIN_RPC_UTIL_H