Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
651 changes: 325 additions & 326 deletions src/rpc/blockchain.cpp

Large diffs are not rendered by default.

192 changes: 96 additions & 96 deletions src/rpc/fees.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,40 +63,40 @@ static RPCHelpMan estimatesmartfee()
HelpExampleRpc("estimatesmartfee", "6")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});

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;
},
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});

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;
},
};
}

Expand Down Expand Up @@ -154,68 +154,68 @@ static RPCHelpMan estimaterawfee()
HelpExampleCli("estimaterawfee", "6 0.9")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);

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;
},
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);

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;
},
};
}

Expand Down
62 changes: 31 additions & 31 deletions src/rpc/mempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,37 +236,37 @@ static RPCHelpMan testmempoolaccept()
static std::vector<RPCResult> MempoolEntryDescription()
{
return {
RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size. This can be different from actual serialized size for high-sigop transactions."},
RPCResult{RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true,
"transaction fee, denominated in " + CURRENCY_UNIT + " (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", /*optional=*/true,
"transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT +
" (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in " + UNIX_EPOCH_TIME},
RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"},
RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"},
RPCResult{RPCResult::Type::NUM, "descendantsize", "size of in-mempool descendants (including this one)"},
RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", /*optional=*/true,
"transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " +
CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},
RPCResult{RPCResult::Type::NUM, "ancestorsize", "size of in-mempool ancestors (including this one)"},
RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", /*optional=*/true,
"transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " +
CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::OBJ, "fees", "",
{
RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT},
RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
}},
RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",
{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",
{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},
RPCResult{RPCResult::Type::BOOL, "instantsend", "True if this transaction was locked via InstantSend"},
RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"}
RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size. This can be different from actual serialized size for high-sigop transactions."},
RPCResult{RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true,
"transaction fee, denominated in " + CURRENCY_UNIT + " (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", /*optional=*/true,
"transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT +
" (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in " + UNIX_EPOCH_TIME},
RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"},
RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"},
RPCResult{RPCResult::Type::NUM, "descendantsize", "size of in-mempool descendants (including this one)"},
RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", /*optional=*/true,
"transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " +
CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"},
RPCResult{RPCResult::Type::NUM, "ancestorsize", "size of in-mempool ancestors (including this one)"},
RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", /*optional=*/true,
"transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " +
CURRENCY_ATOM + "s (DEPRECATED, returned only if config option -deprecatedrpc=fees is passed)"},
RPCResult{RPCResult::Type::OBJ, "fees", "",
{
RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee, denominated in " + CURRENCY_UNIT},
RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "transaction fees of in-mempool ancestors (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "transaction fees of in-mempool descendants (including this one) with fee deltas used for mining priority, denominated in " + CURRENCY_UNIT},
}},
RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction",
{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",
{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},
RPCResult{RPCResult::Type::BOOL, "instantsend", "True if this transaction was locked via InstantSend"},
RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"}
};
}

Expand Down
Loading
Loading