aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/mining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc/mining.cpp')
-rw-r--r--src/rpc/mining.cpp338
1 files changed, 49 insertions, 289 deletions
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 1d1ae92c58..1ad704a490 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -7,6 +7,7 @@
#include <chainparams.h>
#include <consensus/amount.h>
#include <consensus/consensus.h>
+#include <consensus/merkle.h>
#include <consensus/params.h>
#include <consensus/validation.h>
#include <core_io.h>
@@ -16,7 +17,6 @@
#include <net.h>
#include <node/context.h>
#include <node/miner.h>
-#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
#include <rpc/mining.h>
@@ -27,9 +27,9 @@
#include <script/script.h>
#include <script/signingprovider.h>
#include <shutdown.h>
+#include <timedata.h>
#include <txmempool.h>
#include <univalue.h>
-#include <util/fees.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/system.h>
@@ -43,7 +43,6 @@
using node::BlockAssembler;
using node::CBlockTemplate;
-using node::IncrementExtraNonce;
using node::NodeContext;
using node::RegenerateCommitments;
using node::UpdateTime;
@@ -111,23 +110,17 @@ static RPCHelpMan getnetworkhashps()
{
ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
- return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1, chainman.ActiveChain());
+ return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].getInt<int>() : 120, !request.params[1].isNull() ? request.params[1].getInt<int>() : -1, chainman.ActiveChain());
},
};
}
-static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, unsigned int& extra_nonce, uint256& block_hash)
+static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, uint256& block_hash)
{
block_hash.SetNull();
+ block.hashMerkleRoot = BlockMerkleRoot(block);
- {
- LOCK(cs_main);
- IncrementExtraNonce(&block, chainman.ActiveChain().Tip(), extra_nonce);
- }
-
- CChainParams chainparams(Params());
-
- while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus()) && !ShutdownRequested()) {
+ while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainman.GetConsensus()) && !ShutdownRequested()) {
++block.nNonce;
--max_tries;
}
@@ -139,7 +132,7 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
}
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
- if (!chainman.ProcessNewBlock(chainparams, shared_pblock, true, nullptr)) {
+ if (!chainman.ProcessNewBlock(shared_pblock, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
}
@@ -149,30 +142,20 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& mempool, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
{
- int nHeightEnd = 0;
- int nHeight = 0;
-
- { // Don't keep cs_main locked
- LOCK(cs_main);
- nHeight = chainman.ActiveChain().Height();
- nHeightEnd = nHeight+nGenerate;
- }
- unsigned int nExtraNonce = 0;
UniValue blockHashes(UniValue::VARR);
- while (nHeight < nHeightEnd && !ShutdownRequested())
- {
- std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(chainman.ActiveChainstate(), mempool, Params()).CreateNewBlock(coinbase_script));
+ while (nGenerate > 0 && !ShutdownRequested()) {
+ std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler{chainman.ActiveChainstate(), &mempool}.CreateNewBlock(coinbase_script));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
uint256 block_hash;
- if (!GenerateBlock(chainman, *pblock, nMaxTries, nExtraNonce, block_hash)) {
+ if (!GenerateBlock(chainman, *pblock, nMaxTries, block_hash)) {
break;
}
if (!block_hash.IsNull()) {
- ++nHeight;
+ --nGenerate;
blockHashes.push_back(block_hash.GetHex());
}
}
@@ -233,8 +216,8 @@ static RPCHelpMan generatetodescriptor()
"\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- const int num_blocks{request.params[0].get_int()};
- const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].get_int()};
+ const int num_blocks{request.params[0].getInt<int>()};
+ const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].getInt<int>()};
CScript coinbase_script;
std::string error;
@@ -280,8 +263,8 @@ static RPCHelpMan generatetoaddress()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- const int num_blocks{request.params[0].get_int()};
- const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].get_int()};
+ const int num_blocks{request.params[0].getInt<int>()};
+ const uint64_t max_tries{request.params[2].isNull() ? DEFAULT_MAX_TRIES : request.params[2].getInt<int>()};
CTxDestination destination = DecodeDestination(request.params[1].get_str());
if (!IsValidDestination(destination)) {
@@ -365,15 +348,13 @@ static RPCHelpMan generateblock()
}
}
- CChainParams chainparams(Params());
CBlock block;
ChainstateManager& chainman = EnsureChainman(node);
{
LOCK(cs_main);
- CTxMemPool empty_mempool;
- std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(chainman.ActiveChainstate(), empty_mempool, chainparams).CreateNewBlock(coinbase_script));
+ std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler{chainman.ActiveChainstate(), nullptr}.CreateNewBlock(coinbase_script));
if (!blocktemplate) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
}
@@ -390,16 +371,15 @@ static RPCHelpMan generateblock()
LOCK(cs_main);
BlockValidationState state;
- if (!TestBlockValidity(state, chainparams, chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), false, false)) {
+ if (!TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), GetAdjustedTime, false, false)) {
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
}
}
uint256 block_hash;
uint64_t max_tries{DEFAULT_MAX_TRIES};
- unsigned int extra_nonce{0};
- if (!GenerateBlock(chainman, block, max_tries, extra_nonce, block_hash) || block_hash.IsNull()) {
+ if (!GenerateBlock(chainman, block, max_tries, block_hash) || block_hash.IsNull()) {
throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
}
@@ -446,7 +426,7 @@ static RPCHelpMan getmininginfo()
obj.pushKV("difficulty", (double)GetDifficulty(active_chain.Tip()));
obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request));
obj.pushKV("pooledtx", (uint64_t)mempool.size());
- obj.pushKV("chain", Params().NetworkIDString());
+ obj.pushKV("chain", chainman.GetParams().NetworkIDString());
obj.pushKV("warnings", GetWarnings(false).original);
return obj;
},
@@ -479,7 +459,7 @@ static RPCHelpMan prioritisetransaction()
LOCK(cs_main);
uint256 hash(ParseHashV(request.params[0], "txid"));
- CAmount nAmount = request.params[2].get_int64();
+ CAmount nAmount = request.params[2].getInt<int64_t>();
if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.");
@@ -496,7 +476,7 @@ static RPCHelpMan prioritisetransaction()
static UniValue BIP22ValidationResult(const BlockValidationState& state)
{
if (state.IsValid())
- return NullUniValue;
+ return UniValue::VNULL;
if (state.IsError())
throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
@@ -618,7 +598,6 @@ static RPCHelpMan getblocktemplate()
std::string strMode = "template";
UniValue lpval = NullUniValue;
std::set<std::string> setClientRules;
- int64_t nMaxVersionPreVB = -1;
CChainState& active_chainstate = chainman.ActiveChainstate();
CChain& active_chain = active_chainstate.m_chain;
if (!request.params[0].isNull())
@@ -660,7 +639,7 @@ static RPCHelpMan getblocktemplate()
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return "inconclusive-not-best-prevblk";
BlockValidationState state;
- TestBlockValidity(state, Params(), active_chainstate, block, pindexPrev, false, true);
+ TestBlockValidity(state, chainman.GetParams(), active_chainstate, block, pindexPrev, GetAdjustedTime, false, true);
return BIP22ValidationResult(state);
}
@@ -670,19 +649,13 @@ static RPCHelpMan getblocktemplate()
const UniValue& v = aClientRules[i];
setClientRules.insert(v.get_str());
}
- } else {
- // NOTE: It is important that this NOT be read if versionbits is supported
- const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
- if (uvMaxVersion.isNum()) {
- nMaxVersionPreVB = uvMaxVersion.get_int64();
- }
}
}
if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
- if (!Params().IsTestChain()) {
+ if (!chainman.GetParams().IsTestChain()) {
const CConnman& connman = EnsureConnman(node);
if (connman.GetNodeCount(ConnectionDirection::Both) == 0) {
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
@@ -706,7 +679,7 @@ static RPCHelpMan getblocktemplate()
if (lpval.isStr())
{
// Format: <hashBestChain><nTransactionsUpdatedLast>
- std::string lpstr = lpval.get_str();
+ const std::string& lpstr = lpval.get_str();
hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
nTransactionsUpdatedLastLP = LocaleIndependentAtoi<int64_t>(lpstr.substr(64));
@@ -743,7 +716,7 @@ static RPCHelpMan getblocktemplate()
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
}
- const Consensus::Params& consensusParams = Params().GetConsensus();
+ const Consensus::Params& consensusParams = chainman.GetParams().GetConsensus();
// GBT must be called with 'signet' set in the rules for signet chains
if (consensusParams.signet_blocks && setClientRules.count("signet") != 1) {
@@ -772,7 +745,7 @@ static RPCHelpMan getblocktemplate()
// Create new block
CScript scriptDummy = CScript() << OP_TRUE;
- pblocktemplate = BlockAssembler(active_chainstate, mempool, Params()).CreateNewBlock(scriptDummy);
+ pblocktemplate = BlockAssembler{active_chainstate, &mempool}.CreateNewBlock(scriptDummy);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
@@ -787,7 +760,7 @@ static RPCHelpMan getblocktemplate()
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 = !DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT);
+ const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT);
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
@@ -853,7 +826,7 @@ static RPCHelpMan getblocktemplate()
UniValue vbavailable(UniValue::VOBJ);
for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
Consensus::DeploymentPos pos = Consensus::DeploymentPos(j);
- ThresholdState state = g_versionbitscache.State(pindexPrev, consensusParams, pos);
+ ThresholdState state = chainman.m_versionbitscache.State(pindexPrev, consensusParams, pos);
switch (state) {
case ThresholdState::DEFINED:
case ThresholdState::FAILED:
@@ -861,7 +834,7 @@ static RPCHelpMan getblocktemplate()
break;
case ThresholdState::LOCKED_IN:
// Ensure bit is set in block version
- pblock->nVersion |= g_versionbitscache.Mask(consensusParams, pos);
+ pblock->nVersion |= chainman.m_versionbitscache.Mask(consensusParams, pos);
[[fallthrough]];
case ThresholdState::STARTED:
{
@@ -870,7 +843,7 @@ static RPCHelpMan getblocktemplate()
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
- pblock->nVersion &= ~g_versionbitscache.Mask(consensusParams, pos);
+ pblock->nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos);
}
}
break;
@@ -883,7 +856,6 @@ static RPCHelpMan getblocktemplate()
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
// Not supported by the client; make sure it's safe to proceed
if (!vbinfo.gbt_force) {
- // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
}
}
@@ -896,14 +868,6 @@ static RPCHelpMan getblocktemplate()
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
- // 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");
- }
-
result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
result.pushKV("transactions", transactions);
result.pushKV("coinbaseaux", aux);
@@ -947,10 +911,10 @@ class submitblock_StateCatcher final : public CValidationInterface
{
public:
uint256 hash;
- bool found;
+ bool found{false};
BlockValidationState state;
- explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {}
+ explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), state() {}
protected:
void BlockChecked(const CBlock& block, const BlockValidationState& stateIn) override {
@@ -1010,14 +974,14 @@ static RPCHelpMan submitblock()
LOCK(cs_main);
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock);
if (pindex) {
- UpdateUncommittedBlockStructures(block, pindex, Params().GetConsensus());
+ chainman.UpdateUncommittedBlockStructures(block, pindex);
}
}
bool new_block;
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
RegisterSharedValidationInterface(sc);
- bool accepted = chainman.ProcessNewBlock(Params(), blockptr, /*force_processing=*/true, /*new_block=*/&new_block);
+ bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
UnregisterSharedValidationInterface(sc);
if (!new_block && accepted) {
return "duplicate";
@@ -1059,8 +1023,8 @@ static RPCHelpMan submitheader()
}
BlockValidationState state;
- chainman.ProcessNewBlockHeaders({h}, state, Params());
- if (state.IsValid()) return NullUniValue;
+ chainman.ProcessNewBlockHeaders({h}, /*min_pow_checked=*/true, state);
+ if (state.IsValid()) return UniValue::VNULL;
if (state.IsError()) {
throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
}
@@ -1069,225 +1033,21 @@ static RPCHelpMan submitheader()
};
}
-static RPCHelpMan estimatesmartfee()
-{
- return RPCHelpMan{"estimatesmartfee",
- "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
- "confirmation within conf_target blocks if possible and return the number of blocks\n"
- "for which the estimate is valid. Uses virtual transaction size as defined\n"
- "in BIP 141 (witness data is discounted).\n",
- {
- {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
- {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"conservative"}, "The fee estimate mode.\n"
- " Whether to return a more conservative estimate which also satisfies\n"
- " a longer history. A conservative estimate potentially returns a\n"
- " higher feerate and is more likely to be sufficient for the desired\n"
- " target, but is not as responsive to short term drops in the\n"
- " prevailing fee market. Must be one of (case insensitive):\n"
- "\"" + FeeModes("\"\n\"") + "\""},
- },
- RPCResult{
- RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::NUM, "feerate", /*optional=*/true, "estimate fee rate in " + CURRENCY_UNIT + "/kvB (only present if no errors were encountered)"},
- {RPCResult::Type::ARR, "errors", /*optional=*/true, "Errors encountered during processing (if there are any)",
- {
- {RPCResult::Type::STR, "", "error"},
- }},
- {RPCResult::Type::NUM, "blocks", "block number where estimate was found\n"
- "The request target will be clamped between 2 and the highest target\n"
- "fee estimation is able to return based on how long it has been running.\n"
- "An error is returned if not enough transactions and blocks\n"
- "have been observed to make an estimate for any number of blocks."},
- }},
- RPCExamples{
- HelpExampleCli("estimatesmartfee", "6") +
- HelpExampleRpc("estimatesmartfee", "6")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
-{
- RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
- RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
-
- CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
- const NodeContext& node = EnsureAnyNodeContext(request.context);
- const CTxMemPool& mempool = EnsureMemPool(node);
-
- unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
- unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
- bool conservative = true;
- if (!request.params[1].isNull()) {
- FeeEstimateMode fee_mode;
- if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage());
- }
- if (fee_mode == FeeEstimateMode::ECONOMICAL) conservative = false;
- }
-
- UniValue result(UniValue::VOBJ);
- UniValue errors(UniValue::VARR);
- FeeCalculation feeCalc;
- CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)};
- if (feeRate != CFeeRate(0)) {
- CFeeRate min_mempool_feerate{mempool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000)};
- CFeeRate min_relay_feerate{::minRelayTxFee};
- feeRate = std::max({feeRate, min_mempool_feerate, min_relay_feerate});
- result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
- } else {
- errors.push_back("Insufficient data or no feerate found");
- result.pushKV("errors", errors);
- }
- result.pushKV("blocks", feeCalc.returnedTarget);
- return result;
-},
- };
-}
-
-static RPCHelpMan estimaterawfee()
-{
- return RPCHelpMan{"estimaterawfee",
- "\nWARNING: This interface is unstable and may disappear or change!\n"
- "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n"
- " implementation of fee estimation. The parameters it can be called with\n"
- " and the results it returns will change if the internal implementation changes.\n"
- "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
- "confirmation within conf_target blocks if possible. Uses virtual transaction size as\n"
- "defined in BIP 141 (witness data is discounted).\n",
- {
- {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
- {"threshold", RPCArg::Type::NUM, RPCArg::Default{0.95}, "The proportion of transactions in a given feerate range that must have been\n"
- " confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n"
- " lower buckets."},
- },
- RPCResult{
- RPCResult::Type::OBJ, "", "Results are returned for any horizon which tracks blocks up to the confirmation target",
- {
- {RPCResult::Type::OBJ, "short", /*optional=*/true, "estimate for short time horizon",
- {
- {RPCResult::Type::NUM, "feerate", /*optional=*/true, "estimate fee rate in " + CURRENCY_UNIT + "/kvB"},
- {RPCResult::Type::NUM, "decay", "exponential decay (per block) for historical moving average of confirmation data"},
- {RPCResult::Type::NUM, "scale", "The resolution of confirmation targets at this time horizon"},
- {RPCResult::Type::OBJ, "pass", /*optional=*/true, "information about the lowest range of feerates to succeed in meeting the threshold",
- {
- {RPCResult::Type::NUM, "startrange", "start of feerate range"},
- {RPCResult::Type::NUM, "endrange", "end of feerate range"},
- {RPCResult::Type::NUM, "withintarget", "number of txs over history horizon in the feerate range that were confirmed within target"},
- {RPCResult::Type::NUM, "totalconfirmed", "number of txs over history horizon in the feerate range that were confirmed at any point"},
- {RPCResult::Type::NUM, "inmempool", "current number of txs in mempool in the feerate range unconfirmed for at least target blocks"},
- {RPCResult::Type::NUM, "leftmempool", "number of txs over history horizon in the feerate range that left mempool unconfirmed after target"},
- }},
- {RPCResult::Type::OBJ, "fail", /*optional=*/true, "information about the highest range of feerates to fail to meet the threshold",
- {
- {RPCResult::Type::ELISION, "", ""},
- }},
- {RPCResult::Type::ARR, "errors", /*optional=*/true, "Errors encountered during processing (if there are any)",
- {
- {RPCResult::Type::STR, "error", ""},
- }},
- }},
- {RPCResult::Type::OBJ, "medium", /*optional=*/true, "estimate for medium time horizon",
- {
- {RPCResult::Type::ELISION, "", ""},
- }},
- {RPCResult::Type::OBJ, "long", /*optional=*/true, "estimate for long time horizon",
- {
- {RPCResult::Type::ELISION, "", ""},
- }},
- }},
- RPCExamples{
- HelpExampleCli("estimaterawfee", "6 0.9")
- },
- [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+void RegisterMiningRPCCommands(CRPCTable& t)
{
- RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
- RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
-
- CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
-
- unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
- unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
- double threshold = 0.95;
- if (!request.params[1].isNull()) {
- threshold = request.params[1].get_real();
- }
- if (threshold < 0 || threshold > 1) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid threshold");
- }
-
- UniValue result(UniValue::VOBJ);
-
- for (const FeeEstimateHorizon horizon : ALL_FEE_ESTIMATE_HORIZONS) {
- CFeeRate feeRate;
- EstimationResult buckets;
-
- // Only output results for horizons which track the target
- if (conf_target > fee_estimator.HighestTargetTracked(horizon)) continue;
-
- feeRate = fee_estimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
- UniValue horizon_result(UniValue::VOBJ);
- UniValue errors(UniValue::VARR);
- UniValue passbucket(UniValue::VOBJ);
- 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.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.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.pushKV("fail", failbucket);
- } else {
- // Output only information that is still meaningful in the event of error
- 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.pushKV("errors",errors);
- }
- result.pushKV(StringForFeeEstimateHorizon(horizon), horizon_result);
- }
- return result;
-},
+ static const CRPCCommand commands[]{
+ {"mining", &getnetworkhashps},
+ {"mining", &getmininginfo},
+ {"mining", &prioritisetransaction},
+ {"mining", &getblocktemplate},
+ {"mining", &submitblock},
+ {"mining", &submitheader},
+
+ {"hidden", &generatetoaddress},
+ {"hidden", &generatetodescriptor},
+ {"hidden", &generateblock},
+ {"hidden", &generate},
};
-}
-
-void RegisterMiningRPCCommands(CRPCTable &t)
-{
-// clang-format off
-static const CRPCCommand commands[] =
-{ // category actor (function)
- // --------------------- -----------------------
- { "mining", &getnetworkhashps, },
- { "mining", &getmininginfo, },
- { "mining", &prioritisetransaction, },
- { "mining", &getblocktemplate, },
- { "mining", &submitblock, },
- { "mining", &submitheader, },
-
-
- { "hidden", &generatetoaddress, },
- { "hidden", &generatetodescriptor, },
- { "hidden", &generateblock, },
-
- { "util", &estimatesmartfee, },
-
- { "hidden", &estimaterawfee, },
- { "hidden", &generate, },
-};
-// clang-format on
for (const auto& c : commands) {
t.appendCommand(c.name, &c);
}