Disable fee estimates for a confirm target of 1 block

Backport of #9239 without GUI changes and fixing conflicts in tests.
This commit is contained in:
Alex Morcos
2016-11-29 12:18:44 -05:00
parent 29435db6a4
commit 3688866880
3 changed files with 30 additions and 9 deletions

View File

@@ -495,7 +495,8 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight,
CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget) CFeeRate CBlockPolicyEstimator::estimateFee(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
if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms()) // It's not possible to get reasonable estimates for confTarget of 1
if (confTarget <= 1 || (unsigned int)confTarget > feeStats.GetMaxConfirms())
return CFeeRate(0); return CFeeRate(0);
double median = feeStats.EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); double median = feeStats.EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);
@@ -514,6 +515,10 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun
if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms()) if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms())
return CFeeRate(0); return CFeeRate(0);
// It's not possible to get reasonable estimates for confTarget of 1
if (confTarget == 1)
confTarget = 2;
double median = -1; double median = -1;
while (median < 0 && (unsigned int)confTarget <= feeStats.GetMaxConfirms()) { while (median < 0 && (unsigned int)confTarget <= feeStats.GetMaxConfirms()) {
median = feeStats.EstimateMedianVal(confTarget++, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); median = feeStats.EstimateMedianVal(confTarget++, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight);

View File

@@ -791,6 +791,8 @@ UniValue estimatefee(const UniValue& params, bool fHelp)
"\n" "\n"
"A negative value is returned if not enough transactions and blocks\n" "A negative value is returned if not enough transactions and blocks\n"
"have been observed to make an estimate.\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" "\nExample:\n"
+ HelpExampleCli("estimatefee", "6") + HelpExampleCli("estimatefee", "6")
); );

View File

@@ -105,19 +105,26 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
// Highest feerate is 10*baseRate and gets in all blocks, // Highest feerate is 10*baseRate and gets in all blocks,
// second highest feerate is 9*baseRate and gets in 9/10 blocks = 90%, // second highest feerate is 9*baseRate and gets in 9/10 blocks = 90%,
// third highest feerate is 8*base rate, and gets in 8/10 blocks = 80%, // third highest feerate is 8*base rate, and gets in 8/10 blocks = 80%,
// so estimateFee(1) should return 10*baseRate. // so estimateFee(1) would return 10*baseRate but is hardcoded to return failure
// Second highest feerate has 100% chance of being included by 2 blocks, // Second highest feerate has 100% chance of being included by 2 blocks,
// so estimateFee(2) should return 9*baseRate etc... // so estimateFee(2) should return 9*baseRate etc...
for (int i = 1; i < 10;i++) { for (int i = 1; i < 10;i++) {
origFeeEst.push_back(mpool.estimateFee(i).GetFeePerK()); origFeeEst.push_back(mpool.estimateFee(i).GetFeePerK());
origPriEst.push_back(mpool.estimatePriority(i)); origPriEst.push_back(mpool.estimatePriority(i));
if (i > 1) { // Fee estimates should be monotonically decreasing if (i > 1) { // Fee estimates should be monotonically decreasing
BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]); if (i > 2) {
BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]);
}
BOOST_CHECK(origPriEst[i-1] <= origPriEst[i-2]); BOOST_CHECK(origPriEst[i-1] <= origPriEst[i-2]);
} }
int mult = 11-i; int mult = 11-i;
BOOST_CHECK(origFeeEst[i-1] < mult*baseRate.GetFeePerK() + deltaFee); if (i > 1) {
BOOST_CHECK(origFeeEst[i-1] > mult*baseRate.GetFeePerK() - deltaFee); BOOST_CHECK(origFeeEst[i-1] < mult*baseRate.GetFeePerK() + deltaFee);
BOOST_CHECK(origFeeEst[i-1] > mult*baseRate.GetFeePerK() - deltaFee);
}
else {
BOOST_CHECK(origFeeEst[i-1] == CFeeRate(0).GetFeePerK());
}
BOOST_CHECK(origPriEst[i-1] < pow(10,mult) * basepri + deltaPri); BOOST_CHECK(origPriEst[i-1] < pow(10,mult) * basepri + deltaPri);
BOOST_CHECK(origPriEst[i-1] > pow(10,mult) * basepri - deltaPri); BOOST_CHECK(origPriEst[i-1] > pow(10,mult) * basepri - deltaPri);
} }
@@ -127,9 +134,12 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
while (blocknum < 250) while (blocknum < 250)
mpool.removeForBlock(block, ++blocknum, dummyConflicted); mpool.removeForBlock(block, ++blocknum, dummyConflicted);
BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0));
for (int i = 1; i < 10;i++) { for (int i = 1; i < 10;i++) {
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee); if (i > 1) {
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee);
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
}
BOOST_CHECK(mpool.estimatePriority(i) < origPriEst[i-1] + deltaPri); BOOST_CHECK(mpool.estimatePriority(i) < origPriEst[i-1] + deltaPri);
BOOST_CHECK(mpool.estimatePriority(i) > origPriEst[i-1] - deltaPri); BOOST_CHECK(mpool.estimatePriority(i) > origPriEst[i-1] - deltaPri);
} }
@@ -169,8 +179,10 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
} }
mpool.removeForBlock(block, 265, dummyConflicted); mpool.removeForBlock(block, 265, dummyConflicted);
block.clear(); block.clear();
BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0));
for (int i = 1; i < 10;i++) { for (int i = 1; i < 10;i++) {
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); if (i > 1)
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
BOOST_CHECK(mpool.estimatePriority(i) > origPriEst[i-1] - deltaPri); BOOST_CHECK(mpool.estimatePriority(i) > origPriEst[i-1] - deltaPri);
} }
@@ -190,8 +202,10 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
mpool.removeForBlock(block, ++blocknum, dummyConflicted); mpool.removeForBlock(block, ++blocknum, dummyConflicted);
block.clear(); block.clear();
} }
BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0));
for (int i = 1; i < 10; i++) { for (int i = 1; i < 10; i++) {
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee); if (i > 1)
BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee);
BOOST_CHECK(mpool.estimatePriority(i) < origPriEst[i-1] - deltaPri); BOOST_CHECK(mpool.estimatePriority(i) < origPriEst[i-1] - deltaPri);
} }