Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d04633d
Merge #10707: Better API for estimatesmartfee RPC
sipa Jul 17, 2017
b8c1d66
Merge #10795: No longer ever reuse keypool indexes
laanwj Jul 18, 2017
11e41b9
internal -> fInternal
PastaPastaPasta Sep 16, 2019
75e8e0a
add a zero to the GenerateNewKey call
PastaPastaPasta Sep 16, 2019
0631cd9
Merge #10789: Punctuation/grammer fixes in rpcwallet.cpp
laanwj Jul 25, 2017
dbd4993
Merge #10758: Fix some chainstate-init-order bugs.
laanwj Aug 1, 2017
714438a
remove rewinding blocks
PastaPastaPasta Sep 16, 2019
cd5a12f
Merge #10862: Remove unused variable int64_t nEnd. Fix typo: "condito…
laanwj Jul 20, 2017
05ad6d2
change nEnd to index (might break the progress bar on wallet creation…
PastaPastaPasta Sep 18, 2019
9f71ab0
remove chainparams from method call (10758)
PastaPastaPasta Sep 18, 2019
1f06ecd
add gargs
PastaPastaPasta Sep 18, 2019
d5fdf62
Merge #10919: Fix more init bugs.
laanwj Aug 7, 2017
c438c93
Merge #11022: Basic keypool topup
laanwj Aug 14, 2017
2d922f5
fix
PastaPastaPasta Sep 18, 2019
e941c9b
Merge #11028: Avoid masking of difficulty adjustment errors by checkp…
laanwj Aug 14, 2017
3d44562
remove `LogPrintf("Initializing databases...\n");`
PastaPastaPasta Sep 19, 2019
ac07bf6
revert unintentional change, 10758
PastaPastaPasta Sep 19, 2019
02328ae
Merge #11044: [wallet] Keypool topup cleanups
laanwj Aug 18, 2017
4b579c7
Fix remaining issues
UdjinM6 Sep 20, 2019
64dde0f
add back the todo
PastaPastaPasta Sep 22, 2019
f7a9b0d
move `deterministicMNManager->UpgradeDBIfNeeded();` to be after LoadC…
PastaPastaPasta Sep 22, 2019
a72fc7c
resolve NIT, remove extra line
PastaPastaPasta Sep 22, 2019
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
4 changes: 1 addition & 3 deletions src/dashd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,7 @@ bool AppInit(int argc, char* argv[])
if (!fRet)
{
Interrupt(threadGroup);
// threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
// the startup-failure cases to make sure they don't result in a hang due to some
// thread-blocking-waiting-for-another-thread-during-startup case
threadGroup.join_all();
} else {
WaitForShutdown(&threadGroup);
}
Expand Down
110 changes: 70 additions & 40 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,9 @@ void PrepareShutdown()
}

// FlushStateToDisk generates a SetBestChain callback, which we should avoid missing
FlushStateToDisk();
if (pcoinsTip != nullptr) {
FlushStateToDisk();
}

// After there are no more peers/RPC left to give us new data which may generate
// CValidationInterface callbacks, flush them...
Expand Down Expand Up @@ -782,7 +784,7 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
fReindex = false;
LogPrintf("Reindexing finished\n");
// To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
InitBlockIndex(chainparams);
LoadGenesisBlock(chainparams);
}

// hardcoded $DATADIR/bootstrap.dat
Expand Down Expand Up @@ -1749,27 +1751,25 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
delete deterministicMNManager;
delete evoDb;

evoDb = new CEvoDB(nEvoDbCache, false, fReindex || fReindexChainState);
evoDb = new CEvoDB(nEvoDbCache, false, fReset || fReindexChainState);
deterministicMNManager = new CDeterministicMNManager(*evoDb);
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex || fReindexChainState);
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
llmq::InitLLMQSystem(*evoDb, &scheduler, false, fReindex || fReindexChainState);
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReset);
llmq::InitLLMQSystem(*evoDb, &scheduler, false, fReset || fReindexChainState);

if (fReindex) {
if (fReset) {
pblocktree->WriteReindexing(true);
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
if (fPruneMode)
CleanupBlockRevFiles();
} else {
// If necessary, upgrade from older database format.
if (!pcoinsdbview->Upgrade()) {
strLoadError = _("Error upgrading chainstate database");
break;
}
}

if (fRequestShutdown) break;

// LoadBlockIndex will load fTxIndex from the db, or set it if
// we're reindexing. It will also load fHavePruned if we've
// ever removed a block file from disk.
// Note that it also sets fReindex based on the disk flag!
// From here on out fReindex and fReset mean something different!
if (!LoadBlockIndex(chainparams)) {
strLoadError = _("Error loading block database");
break;
Expand All @@ -1783,12 +1783,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!chainparams.GetConsensus().hashDevnetGenesisBlock.IsNull() && !mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashDevnetGenesisBlock) == 0)
return InitError(_("Incorrect or no devnet genesis block found. Wrong datadir for devnet specified?"));

// Initialize the block index (no-op if non-empty database was already loaded)
if (!InitBlockIndex(chainparams)) {
strLoadError = _("Error initializing block database");
break;
}

// Check for changed -txindex state
if (fTxIndex != gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
strLoadError = _("You need to rebuild the database using -reindex-chainstate to change -txindex");
Expand All @@ -1802,37 +1796,73 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
break;
}

// At this point blocktree args are consistent with what's on disk.
// If we're not mid-reindex (based on disk + args), add a genesis block on disk
// (otherwise we use the one already on disk).
// This is called again in ThreadImport after the reindex completes.
if (!fReindex && !LoadGenesisBlock(chainparams)) {
strLoadError = _("Error initializing block database");
break;
}

// At this point we're either in reindex or we've loaded a useful
// block tree into mapBlockIndex!

pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState);
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);

// If necessary, upgrade from older database format.
// This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
if (!pcoinsdbview->Upgrade()) {
strLoadError = _("Error upgrading chainstate database");
break;
}

// ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
if (!ReplayBlocks(chainparams, pcoinsdbview)) {
strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.");
break;
}

// The on-disk coinsdb is now in a good state, create the cache
pcoinsTip = new CCoinsViewCache(pcoinscatcher);
LoadChainTip(chainparams);

bool is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull();
if (!is_coinsview_empty) {
// LoadChainTip sets chainActive based on pcoinsTip's best block
if (!LoadChainTip(chainparams)) {
strLoadError = _("Error initializing block database");
break;
}
assert(chainActive.Tip() != NULL);
}

deterministicMNManager->UpgradeDBIfNeeded();

uiInterface.InitMessage(_("Verifying blocks..."));
if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks",
MIN_BLOCKS_TO_KEEP);
}
if (!is_coinsview_empty) {
uiInterface.InitMessage(_("Verifying blocks..."));
if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks",
MIN_BLOCKS_TO_KEEP);
}

{
LOCK(cs_main);
CBlockIndex* tip = chainActive.Tip();
RPCNotifyBlockChange(true, tip);
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
strLoadError = _("The block database contains a block which appears to be from the future. "
"This may be due to your computer's date and time being set incorrectly. "
"Only rebuild the block database if you are sure that your computer's date and time are correct");
break;
{
LOCK(cs_main);
CBlockIndex* tip = chainActive.Tip();
RPCNotifyBlockChange(true, tip);
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
strLoadError = _("The block database contains a block which appears to be from the future. "
"This may be due to your computer's date and time being set incorrectly. "
"Only rebuild the block database if you are sure that your computer's date and time are correct");
break;
}
}
}

if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
strLoadError = _("Corrupted block database detected");
break;
if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
strLoadError = _("Corrupted block database detected");
break;
}
}
} catch (const std::exception& e) {
LogPrintf("%s\n", e.what());
Expand Down
19 changes: 8 additions & 11 deletions src/policy/fees.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,20 +837,20 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
EstimationResult tempResult;

// Return failure if trying to analyze a target we're not tracking
if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms())
return CFeeRate(0);
if (confTarget <= 0 || (unsigned int)confTarget > longStats->GetMaxConfirms()) {
return CFeeRate(0); // error condition
}

// It's not possible to get reasonable estimates for confTarget of 1
if (confTarget == 1)
confTarget = 2;
if (confTarget == 1) confTarget = 2;

unsigned int maxUsableEstimate = MaxUsableEstimate();
if (maxUsableEstimate <= 1)
return CFeeRate(0);

if ((unsigned int)confTarget > maxUsableEstimate) {
confTarget = maxUsableEstimate;
}
if (feeCalc) feeCalc->returnedTarget = confTarget;

if (confTarget <= 1) return CFeeRate(0); // error condition

assert(confTarget > 0); //estimateCombinedFee and estimateConservativeFee take unsigned ints
/** true is passed to estimateCombined fee for target/2 and target so
Expand Down Expand Up @@ -897,10 +897,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
}
}

if (feeCalc) feeCalc->returnedTarget = confTarget;

if (median < 0)
return CFeeRate(0);
if (median < 0) return CFeeRate(0); // error condition

return CFeeRate(median);
}
Expand Down
1 change: 0 additions & 1 deletion src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getrawmempool", 0, "verbose" },
{ "estimatefee", 0, "nblocks" },
{ "estimatesmartfee", 0, "nblocks" },
{ "estimatesmartfee", 1, "conservative" },
{ "estimaterawfee", 0, "nblocks" },
{ "estimaterawfee", 1, "threshold" },
{ "prioritisetransaction", 1, "fee_delta" },
Expand Down
72 changes: 43 additions & 29 deletions src/rpc/mining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -833,41 +833,58 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
"estimatesmartfee nblocks (conservative)\n"
"estimatesmartfee conf_target (\"estimate_mode\")\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"
"confirmation within conf_target blocks if possible and return the number of blocks\n"
"for which the estimate is valid.\n"
"\nArguments:\n"
"1. nblocks (numeric)\n"
"2. conservative (bool, optional, default=true) Whether to return a more conservative estimate which\n"
" also satisfies a longer history. A conservative estimate potentially returns a higher\n"
" feerate and is more likely to be sufficient for the desired target, but is not as\n"
" responsive to short term drops in the prevailing fee market\n"
"1. conf_target (numeric) Confirmation target in blocks (1 - 1008)\n"
"2. \"estimate_mode\" (string, optional, 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:\n"
" \"UNSET\" (defaults to CONSERVATIVE)\n"
" \"ECONOMICAL\"\n"
" \"CONSERVATIVE\"\n"
"\nResult:\n"
"{\n"
" \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in " + CURRENCY_UNIT + ")\n"
" \"feerate\" : x.x, (numeric, optional) estimate fee-per-kilobyte (in " + CURRENCY_UNIT + ")\n"
" \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\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"
"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.\n"
"\nExample:\n"
+ HelpExampleCli("estimatesmartfee", "6")
);

RPCTypeCheck(request.params, {UniValue::VNUM});

int nBlocks = request.params[0].get_int();
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
unsigned int conf_target = ParseConfirmTarget(request.params[0]);
bool conservative = true;
if (request.params.size() > 1 && !request.params[1].isNull()) {
RPCTypeCheckArgument(request.params[1], UniValue::VBOOL);
conservative = request.params[1].get_bool();
FeeEstimateMode fee_mode;
if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
}
if (fee_mode == FeeEstimateMode::ECONOMICAL) conservative = false;
}

UniValue result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
FeeCalculation feeCalc;
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &feeCalc, conservative);
result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK())));
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(conf_target, &feeCalc, conservative);
if (feeRate != CFeeRate(0)) {
result.push_back(Pair("feerate", ValueFromAmount(feeRate.GetFeePerK())));
} else {
errors.push_back("Insufficient data or no feerate found");
result.push_back(Pair("errors", errors));
}
result.push_back(Pair("blocks", feeCalc.returnedTarget));
return result;
}
Expand All @@ -876,17 +893,17 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
"estimaterawfee nblocks (threshold)\n"
"estimaterawfee conf_target (threshold)\n"
"\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 nblocks blocks if possible.\n"
"confirmation within conf_target blocks if possible.\n"
"\nArguments:\n"
"1. nblocks (numeric) Confirmation target in blocks (1 - 1008)\n"
"1. conf_target (numeric) Confirmation target in blocks (1 - 1008)\n"
"2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n"
" confirmed within nblocks in order to consider those feerates as high enough and proceed to check\n"
" confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n"
" lower buckets. Default: 0.95\n"
"\nResult:\n"
"{\n"
Expand Down Expand Up @@ -914,12 +931,9 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
+ HelpExampleCli("estimaterawfee", "6 0.9")
);

RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true);
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
int nBlocks = request.params[0].get_int();
if (nBlocks < 1 || (unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid nblocks");
}
unsigned int conf_target = ParseConfirmTarget(request.params[0]);
double threshold = 0.95;
if (!request.params[1].isNull()) {
threshold = request.params[1].get_real();
Expand All @@ -935,9 +949,9 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
EstimationResult buckets;

// Only output results for horizons which track the target
if ((unsigned int)nBlocks > ::feeEstimator.HighestTargetTracked(horizon)) continue;
if (conf_target > ::feeEstimator.HighestTargetTracked(horizon)) continue;

feeRate = ::feeEstimator.estimateRawFee(nBlocks, threshold, horizon, &buckets);
feeRate = ::feeEstimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
UniValue horizon_result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
UniValue passbucket(UniValue::VOBJ);
Expand Down Expand Up @@ -989,9 +1003,9 @@ static const CRPCCommand commands[] =
{ "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} },
#endif // ENABLE_MINER
{ "util", "estimatefee", &estimatefee, true, {"nblocks"} },
{ "util", "estimatesmartfee", &estimatesmartfee, true, {"nblocks", "conservative"} },
{ "util", "estimatesmartfee", &estimatesmartfee, true, {"conf_target", "estimate_mode"} },

{ "hidden", "estimaterawfee", &estimaterawfee, true, {"nblocks", "threshold"} },
{ "hidden", "estimaterawfee", &estimaterawfee, true, {"conf_target", "threshold"} },
};

void RegisterMiningRPCCommands(CRPCTable &t)
Expand Down
Loading