Skip to content

Commit

Permalink
Merge pull request #6134
Browse files Browse the repository at this point in the history
e304432 Pass reference to estimateSmartFee and cleanup whitespace (Suhas Daftuar)
56106a3 Expose RPC calls for estimatesmart functions (Alex Morcos)
e93a236 add estimateSmartFee to the unit test (Alex Morcos)
6303051 EstimateSmart functions consider mempool min fee (Alex Morcos)
f22ac4a Increase success threshold for fee estimation to 95% (Alex Morcos)
4fe2823 Change wallet and GUI code to use new smart fee estimation calls. (Alex Morcos)
22eca7d Add smart fee estimation functions (Alex Morcos)
  • Loading branch information
laanwj committed Nov 27, 2015
2 parents 05d5918 + e304432 commit e92377f
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 66 deletions.
52 changes: 30 additions & 22 deletions qa/rpc-tests/smartfees.py
Expand Up @@ -120,15 +120,26 @@ def check_estimates(node, fees_seen, max_invalid, print_estimates = True):
last_e = e last_e = e
valid_estimate = False valid_estimate = False
invalid_estimates = 0 invalid_estimates = 0
for e in all_estimates: for i,e in enumerate(all_estimates): # estimate is for i+1
if e >= 0: if e >= 0:
valid_estimate = True valid_estimate = True
# estimatesmartfee should return the same result
assert_equal(node.estimatesmartfee(i+1)["feerate"], e)

else: else:
invalid_estimates += 1 invalid_estimates += 1
# Once we're at a high enough confirmation count that we can give an estimate
# We should have estimates for all higher confirmation counts # estimatesmartfee should still be valid
if valid_estimate and e < 0: approx_estimate = node.estimatesmartfee(i+1)["feerate"]
raise AssertionError("Invalid estimate appears at higher confirm count than valid estimate") answer_found = node.estimatesmartfee(i+1)["blocks"]
assert(approx_estimate > 0)
assert(answer_found > i+1)

# Once we're at a high enough confirmation count that we can give an estimate
# We should have estimates for all higher confirmation counts
if valid_estimate:
raise AssertionError("Invalid estimate appears at higher confirm count than valid estimate")

# Check on the expected number of different confirmation counts # Check on the expected number of different confirmation counts
# that we might not have valid estimates for # that we might not have valid estimates for
if invalid_estimates > max_invalid: if invalid_estimates > max_invalid:
Expand Down Expand Up @@ -184,13 +195,13 @@ def setup_network(self):
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes, # NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
# (17k is room enough for 110 or so transactions) # (17k is room enough for 110 or so transactions)
self.nodes.append(start_node(1, self.options.tmpdir, self.nodes.append(start_node(1, self.options.tmpdir,
["-blockprioritysize=1500", "-blockmaxsize=18000", ["-blockprioritysize=1500", "-blockmaxsize=17000",
"-maxorphantx=1000", "-relaypriority=0", "-debug=estimatefee"])) "-maxorphantx=1000", "-relaypriority=0", "-debug=estimatefee"]))
connect_nodes(self.nodes[1], 0) connect_nodes(self.nodes[1], 0)


# Node2 is a stingy miner, that # Node2 is a stingy miner, that
# produces too small blocks (room for only 70 or so transactions) # produces too small blocks (room for only 55 or so transactions)
node2args = ["-blockprioritysize=0", "-blockmaxsize=12000", "-maxorphantx=1000", "-relaypriority=0"] node2args = ["-blockprioritysize=0", "-blockmaxsize=8000", "-maxorphantx=1000", "-relaypriority=0"]


self.nodes.append(start_node(2, self.options.tmpdir, node2args)) self.nodes.append(start_node(2, self.options.tmpdir, node2args))
connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 2)
Expand Down Expand Up @@ -229,22 +240,19 @@ def run_test(self):
self.fees_per_kb = [] self.fees_per_kb = []
self.memutxo = [] self.memutxo = []
self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting
print("Checking estimates for 1/2/3/6/15/25 blocks") print("Will output estimates for 1/2/3/6/15/25 blocks")
print("Creating transactions and mining them with a huge block size")
# Create transactions and mine 20 big blocks with node 0 such that the mempool is always emptied
self.transact_and_mine(30, self.nodes[0])
check_estimates(self.nodes[1], self.fees_per_kb, 1)


print("Creating transactions and mining them with a block size that can't keep up") for i in xrange(2):
# Create transactions and mine 30 small blocks with node 2, but create txs faster than we can mine print("Creating transactions and mining them with a block size that can't keep up")
self.transact_and_mine(20, self.nodes[2]) # Create transactions and mine 10 small blocks with node 2, but create txs faster than we can mine
check_estimates(self.nodes[1], self.fees_per_kb, 3) self.transact_and_mine(10, self.nodes[2])
check_estimates(self.nodes[1], self.fees_per_kb, 14)


print("Creating transactions and mining them at a block size that is just big enough") print("Creating transactions and mining them at a block size that is just big enough")
# Generate transactions while mining 40 more blocks, this time with node1 # Generate transactions while mining 10 more blocks, this time with node1
# which mines blocks with capacity just above the rate that transactions are being created # which mines blocks with capacity just above the rate that transactions are being created
self.transact_and_mine(40, self.nodes[1]) self.transact_and_mine(10, self.nodes[1])
check_estimates(self.nodes[1], self.fees_per_kb, 2) check_estimates(self.nodes[1], self.fees_per_kb, 2)


# Finish by mining a normal-sized block: # Finish by mining a normal-sized block:
while len(self.nodes[1].getrawmempool()) > 0: while len(self.nodes[1].getrawmempool()) > 0:
Expand Down
2 changes: 0 additions & 2 deletions src/main.h
Expand Up @@ -56,8 +56,6 @@ static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101;
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25; static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25;
/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */ /** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101; static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */ /** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 72; static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 72;
/** The maximum size of a blk?????.dat file (since 0.8) */ /** The maximum size of a blk?????.dat file (since 0.8) */
Expand Down
52 changes: 52 additions & 0 deletions src/policy/fees.cpp
Expand Up @@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.


#include "policy/fees.h" #include "policy/fees.h"
#include "policy/policy.h"


#include "amount.h" #include "amount.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
Expand Down Expand Up @@ -504,6 +505,33 @@ CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget)
return CFeeRate(median); return CFeeRate(median);
} }


CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool)
{
if (answerFoundAtTarget)
*answerFoundAtTarget = confTarget;
// Return failure if trying to analyze a target we're not tracking
if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms())
return CFeeRate(0);

double median = -1;
while (median < 0 && (unsigned int)confTarget <= feeStats.GetMaxConfirms()) {
median = feeStats.EstimateMedianVal(confTarget++, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
}

if (answerFoundAtTarget)
*answerFoundAtTarget = confTarget - 1;

// If mempool is limiting txs , return at least the min fee from the mempool
CAmount minPoolFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
if (minPoolFee > 0 && minPoolFee > median)
return CFeeRate(minPoolFee);

if (median < 0)
return CFeeRate(0);

return CFeeRate(median);
}

double CBlockPolicyEstimator::estimatePriority(int confTarget) double CBlockPolicyEstimator::estimatePriority(int confTarget)
{ {
// Return failure if trying to analyze a target we're not tracking // Return failure if trying to analyze a target we're not tracking
Expand All @@ -513,6 +541,30 @@ double CBlockPolicyEstimator::estimatePriority(int confTarget)
return priStats.EstimateMedianVal(confTarget, SUFFICIENT_PRITXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); return priStats.EstimateMedianVal(confTarget, SUFFICIENT_PRITXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
} }


double CBlockPolicyEstimator::estimateSmartPriority(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool)
{
if (answerFoundAtTarget)
*answerFoundAtTarget = confTarget;
// Return failure if trying to analyze a target we're not tracking
if (confTarget <= 0 || (unsigned int)confTarget > priStats.GetMaxConfirms())
return -1;

// If mempool is limiting txs, no priority txs are allowed
CAmount minPoolFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
if (minPoolFee > 0)
return INF_PRIORITY;

double median = -1;
while (median < 0 && (unsigned int)confTarget <= priStats.GetMaxConfirms()) {
median = priStats.EstimateMedianVal(confTarget++, SUFFICIENT_PRITXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
}

if (answerFoundAtTarget)
*answerFoundAtTarget = confTarget - 1;

return median;
}

void CBlockPolicyEstimator::Write(CAutoFile& fileout) void CBlockPolicyEstimator::Write(CAutoFile& fileout)
{ {
fileout << nBestSeenHeight; fileout << nBestSeenHeight;
Expand Down
17 changes: 15 additions & 2 deletions src/policy/fees.h
Expand Up @@ -15,6 +15,7 @@
class CAutoFile; class CAutoFile;
class CFeeRate; class CFeeRate;
class CTxMemPoolEntry; class CTxMemPoolEntry;
class CTxMemPool;


/** \class CBlockPolicyEstimator /** \class CBlockPolicyEstimator
* The BlockPolicyEstimator is used for estimating the fee or priority needed * The BlockPolicyEstimator is used for estimating the fee or priority needed
Expand Down Expand Up @@ -182,8 +183,8 @@ static const unsigned int MAX_BLOCK_CONFIRMS = 25;
/** Decay of .998 is a half-life of 346 blocks or about 2.4 days */ /** Decay of .998 is a half-life of 346 blocks or about 2.4 days */
static const double DEFAULT_DECAY = .998; static const double DEFAULT_DECAY = .998;


/** Require greater than 85% of X fee transactions to be confirmed within Y blocks for X to be big enough */ /** Require greater than 95% of X fee transactions to be confirmed within Y blocks for X to be big enough */
static const double MIN_SUCCESS_PCT = .85; static const double MIN_SUCCESS_PCT = .95;
static const double UNLIKELY_PCT = .5; static const double UNLIKELY_PCT = .5;


/** Require an avg of 1 tx in the combined fee bucket per block to have stat significance */ /** Require an avg of 1 tx in the combined fee bucket per block to have stat significance */
Expand Down Expand Up @@ -242,9 +243,21 @@ class CBlockPolicyEstimator
/** Return a fee estimate */ /** Return a fee estimate */
CFeeRate estimateFee(int confTarget); CFeeRate estimateFee(int confTarget);


/** Estimate fee rate needed to get be included in a block within
* confTarget blocks. If no answer can be given at confTarget, return an
* estimate at the lowest target where one can be given.
*/
CFeeRate estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool);

/** Return a priority estimate */ /** Return a priority estimate */
double estimatePriority(int confTarget); double estimatePriority(int confTarget);


/** Estimate priority needed to get be included in a block within
* confTarget blocks. If no answer can be given at confTarget, return an
* estimate at the lowest target where one can be given.
*/
double estimateSmartPriority(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool);

/** Write estimation data to a file */ /** Write estimation data to a file */
void Write(CAutoFile& fileout); void Write(CAutoFile& fileout);


Expand Down
2 changes: 2 additions & 0 deletions src/policy/policy.h
Expand Up @@ -25,6 +25,8 @@ static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
static const unsigned int MAX_P2SH_SIGOPS = 15; static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */ /** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
/** /**
* Standard script verification flags that standard transactions will comply * Standard script verification flags that standard transactions will comply
* with. However scripts violating these flags may still be present in valid * with. However scripts violating these flags may still be present in valid
Expand Down
15 changes: 7 additions & 8 deletions src/qt/coincontroldialog.cpp
Expand Up @@ -538,7 +538,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here


// Priority // Priority
double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget); double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget);
dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority)
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority); sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority);


Expand All @@ -550,10 +550,8 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
// Fee // Fee
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool);


// Allow free? // Allow free? (require at least hard-coded threshold and default to that if no estimate)
double dPriorityNeeded = mempoolEstimatePriority; double dPriorityNeeded = std::max(mempoolEstimatePriority, AllowFreeThreshold());
if (dPriorityNeeded <= 0)
dPriorityNeeded = AllowFreeThreshold(); // not enough data, back to hard-coded
fAllowFree = (dPriority >= dPriorityNeeded); fAllowFree = (dPriority >= dPriorityNeeded);


if (fSendFreeTransactions) if (fSendFreeTransactions)
Expand Down Expand Up @@ -649,8 +647,9 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
double dFeeVary; double dFeeVary;
if (payTxFee.GetFeePerK() > 0) if (payTxFee.GetFeePerK() > 0)
dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000; dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000;
else else {
dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), mempool.estimateFee(nTxConfirmTarget).GetFeePerK()) / 1000; dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), mempool.estimateSmartFee(nTxConfirmTarget).GetFeePerK()) / 1000;
}
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);


l3->setToolTip(toolTip4); l3->setToolTip(toolTip4);
Expand Down Expand Up @@ -686,7 +685,7 @@ void CoinControlDialog::updateView()
QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;


int nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); int nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget); double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget);


std::map<QString, std::vector<COutput> > mapCoins; std::map<QString, std::vector<COutput> > mapCoins;
model->listCoins(mapCoins); model->listCoins(mapCoins);
Expand Down
5 changes: 3 additions & 2 deletions src/qt/sendcoinsdialog.cpp
Expand Up @@ -633,7 +633,8 @@ void SendCoinsDialog::updateSmartFeeLabel()
return; return;


int nBlocksToConfirm = defaultConfirmTarget - ui->sliderSmartFee->value(); int nBlocksToConfirm = defaultConfirmTarget - ui->sliderSmartFee->value();
CFeeRate feeRate = mempool.estimateFee(nBlocksToConfirm); int estimateFoundAtBlocks = nBlocksToConfirm;
CFeeRate feeRate = mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks);
if (feeRate <= CFeeRate(0)) // not enough data => minfee if (feeRate <= CFeeRate(0)) // not enough data => minfee
{ {
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::GetRequiredFee(1000)) + "/kB"); ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::GetRequiredFee(1000)) + "/kB");
Expand All @@ -644,7 +645,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
{ {
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB"); ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB");
ui->labelSmartFee2->hide(); ui->labelSmartFee2->hide();
ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", nBlocksToConfirm)); ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", estimateFoundAtBlocks));
} }


updateFeeMinimizedLabel(); updateFeeMinimizedLabel();
Expand Down
1 change: 1 addition & 0 deletions src/rpcblockchain.cpp
Expand Up @@ -10,6 +10,7 @@
#include "coins.h" #include "coins.h"
#include "consensus/validation.h" #include "consensus/validation.h"
#include "main.h" #include "main.h"
#include "policy/policy.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "rpcserver.h" #include "rpcserver.h"
#include "streams.h" #include "streams.h"
Expand Down
2 changes: 2 additions & 0 deletions src/rpcclient.cpp
Expand Up @@ -96,6 +96,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getrawmempool", 0 }, { "getrawmempool", 0 },
{ "estimatefee", 0 }, { "estimatefee", 0 },
{ "estimatepriority", 0 }, { "estimatepriority", 0 },
{ "estimatesmartfee", 0 },
{ "estimatesmartpriority", 0 },
{ "prioritisetransaction", 1 }, { "prioritisetransaction", 1 },
{ "prioritisetransaction", 2 }, { "prioritisetransaction", 2 },
{ "setban", 2 }, { "setban", 2 },
Expand Down
72 changes: 72 additions & 0 deletions src/rpcmining.cpp
Expand Up @@ -726,3 +726,75 @@ UniValue estimatepriority(const UniValue& params, bool fHelp)


return mempool.estimatePriority(nBlocks); return mempool.estimatePriority(nBlocks);
} }

UniValue estimatesmartfee(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"estimatesmartfee nblocks\n"
"\nWARNING: This interface is unstable and may disappear or change!\n"
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
"confirmation within nblocks blocks if possible and return the number of blocks\n"
"for which the estimate is valid.\n"
"\nArguments:\n"
"1. nblocks (numeric)\n"
"\nResult:\n"
"{\n"
" \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n"
" \"blocks\" : n (numeric) block number where estimate was found\n"
"}\n"
"\n"
"A negative value is returned if not enough transactions and blocks\n"
"have been observed to make an estimate for any number of blocks.\n"
"However it will not return a value below the mempool reject fee.\n"
"\nExample:\n"
+ HelpExampleCli("estimatesmartfee", "6")
);

RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));

int nBlocks = params[0].get_int();

UniValue result(UniValue::VOBJ);
int answerFound;
CFeeRate feeRate = mempool.estimateSmartFee(nBlocks, &answerFound);
result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK())));
result.push_back(Pair("blocks", answerFound));
return result;
}

UniValue estimatesmartpriority(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"estimatesmartpriority nblocks\n"
"\nWARNING: This interface is unstable and may disappear or change!\n"
"\nEstimates the approximate priority a zero-fee transaction needs to begin\n"
"confirmation within nblocks blocks if possible and return the number of blocks\n"
"for which the estimate is valid.\n"
"\nArguments:\n"
"1. nblocks (numeric)\n"
"\nResult:\n"
"{\n"
" \"priority\" : x.x, (numeric) estimated priority\n"
" \"blocks\" : n (numeric) block number where estimate was found\n"
"}\n"
"\n"
"A negative value is returned if not enough transactions and blocks\n"
"have been observed to make an estimate for any number of blocks.\n"
"However if the mempool reject fee is set it will return 1e9 * MAX_MONEY.\n"
"\nExample:\n"
+ HelpExampleCli("estimatesmartpriority", "6")
);

RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));

int nBlocks = params[0].get_int();

UniValue result(UniValue::VOBJ);
int answerFound;
double priority = mempool.estimateSmartPriority(nBlocks, &answerFound);
result.push_back(Pair("priority", priority));
result.push_back(Pair("blocks", answerFound));
return result;
}
2 changes: 2 additions & 0 deletions src/rpcserver.cpp
Expand Up @@ -319,6 +319,8 @@ static const CRPCCommand vRPCCommands[] =
{ "util", "verifymessage", &verifymessage, true }, { "util", "verifymessage", &verifymessage, true },
{ "util", "estimatefee", &estimatefee, true }, { "util", "estimatefee", &estimatefee, true },
{ "util", "estimatepriority", &estimatepriority, true }, { "util", "estimatepriority", &estimatepriority, true },
{ "util", "estimatesmartfee", &estimatesmartfee, true },
{ "util", "estimatesmartpriority", &estimatesmartpriority, true },


/* Not shown in help */ /* Not shown in help */
{ "hidden", "invalidateblock", &invalidateblock, true }, { "hidden", "invalidateblock", &invalidateblock, true },
Expand Down
2 changes: 2 additions & 0 deletions src/rpcserver.h
Expand Up @@ -193,6 +193,8 @@ extern UniValue getblocktemplate(const UniValue& params, bool fHelp);
extern UniValue submitblock(const UniValue& params, bool fHelp); extern UniValue submitblock(const UniValue& params, bool fHelp);
extern UniValue estimatefee(const UniValue& params, bool fHelp); extern UniValue estimatefee(const UniValue& params, bool fHelp);
extern UniValue estimatepriority(const UniValue& params, bool fHelp); extern UniValue estimatepriority(const UniValue& params, bool fHelp);
extern UniValue estimatesmartfee(const UniValue& params, bool fHelp);
extern UniValue estimatesmartpriority(const UniValue& params, bool fHelp);


extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
extern UniValue getaccountaddress(const UniValue& params, bool fHelp); extern UniValue getaccountaddress(const UniValue& params, bool fHelp);
Expand Down

0 comments on commit e92377f

Please sign in to comment.