New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve fee estimation #9138
Improve fee estimation #9138
Conversation
return false; | ||
if (chainActive.Height() < pindexBestHeader->nHeight - 1) | ||
return false; | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - usually a blank line before this line (but probably not a standard)
} | ||
|
||
// How many blocks did it take for miners to include this transaction? | ||
// blocksToConfirm is 1-based, so a transaction included in the earliest | ||
// possible block has confirmation count of 1 | ||
int blocksToConfirm = nBlockHeight - entry.GetHeight(); | ||
int blocksToConfirm = nBlockHeight - entry->GetHeight(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what did this fix please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see commit message "Pass pointers to existing CTxMemPoolEntries to fee estimation"
The idea is this would save unnecessary copying.
989a2c4
to
2ea74cf
Compare
2ea74cf
to
6b8681b
Compare
rebased |
Concept ACK. |
Ran this code on top of master on one of my nodes. Next step would be to run master and this PR with the same mempool and maybe dump 2,4,8,20 target every ~10mins.
|
@jonasschnelli I simulated this PR's code against master and the differences were very slight. If your testing setups were identical (started with the same fee estimates and started the nodes at the same time), then the way you might see substantial differences is if your testing nodes have to catch up a little bit when you start them, then this code will decay your old estimates and the old code wouldn't. So this code will more quickly reflect current conditions instead of still having a heavy weight for old fee estimates. Furthermore if you started this code after being down for more than a few weeks, you might even start seeing messages about fee estimates need to warm up as the historical data will have decayed so much. |
@@ -392,6 +382,9 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight, | |||
for (unsigned int i = 0; i < entries.size(); i++) | |||
processBlockTx(nBlockHeight, entries[i]); | |||
|
|||
// Update best seen height after removals so they find the right mempool txs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify this comment? I have been staring at this for a while and can't figure out what you meant.
@@ -128,6 +128,8 @@ static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000; | |||
static const unsigned int DEFAULT_LIMITFREERELAY = 0; | |||
static const bool DEFAULT_RELAYPRIORITY = true; | |||
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; | |||
/** Maximum age of our tip for us to be considered current for fee estimation */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Can you update the comment to include the unit (ie seconds)?
Code review ACK. Will test. |
// This transaction depended on other transactions in the mempool to | ||
// be included in a block before it was able to be included, so | ||
// we shouldn't include it in our calculations | ||
if (!removeTx(entry.GetTx().GetHash())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does calling this here result in one extra call to removeTx()
for each in-mempool, in-block transaction? It looks like we also will call this in CTxMempool::removeUnchecked
, which I guess is harmless, but worth commenting.
{ | ||
if (IsInitialBlockDownload()) | ||
return false; | ||
if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think we should AssertLockHeld(cs_main)
here.
Tested this code in simulation on 10 days in July, comparing the transactions tracked and the fee estimates returned before and after this PR. ACK apart from the AssertLockHeld nit above. |
ed32b1a
to
afead86
Compare
dancing again on the grave of main.cpp This was a clean rebase and I added @sdaftuar's AssertLockHeld. In a couple days I'll squash the last two commits... |
afead86
to
98fffcb
Compare
rebased (and squashed in the bugfix and assert) @fanquake please milestone for 0.14.0 |
re-ACK 98fffcb |
98fffcb
to
761a9be
Compare
Simple rebase due to expected conflict on function signature of |
re-ACK 761a9be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK. I don't understand the fee estimation code enough to judge the changes to the semantics.
mapMemPoolTxs.erase(hash); | ||
return true; | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coding style nit: else
on the same line.
for (const auto& tx : vtx) | ||
{ | ||
uint256 hash = tx->GetHash(); | ||
|
||
indexed_transaction_set::iterator i = mapTx.find(hash); | ||
if (i != mapTx.end()) | ||
entries.push_back(*i); | ||
entries.push_back(&(*i)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parentheses aren't needed here.
761a9be
to
d6b2ff7
Compare
Rebased to fix a silent merge conflict (the change in wallet.cpp) |
reviewed and tested this before it got conflicted ACK. needs rebase. |
Once priority estimation was removed, not all transactions in the mempool are tracked in the fee estimation mempool tracking. So there is no error if a transaction is not found for removal.
This was an oversight, where blocks and mempool tracking were ignored during IBD, but transactions that arrived during IBD but were included in blocks after IBD were not ignored.
Fee estimation can just check its own mapMemPoolTxs to determine the same information. Note that now fee estimation for block processing must happen before those transactions are removed, but this shoudl be a speedup.
All decisions about whether the transactions are valid data points are made at the time the transaction arrives. Updating on blocks all the time will now cause stale fee estimates to decay quickly when we restart a node.
Make a more conservative notion of whether the node is caught up to the rest of the network and only count transactions as fee estimation data points if the node is caught up.
d6b2ff7
to
44b64b9
Compare
rebased |
re-ACK 44b64b9 |
utACK 44b64b9 |
44b64b9 Fix edge case with stale fee estimates (Alex Morcos) 78ae62d Add clarifying comments to fee estimation (Alex Morcos) 5fe0f47 Add extra logging to processBlock in fee estimation. (Alex Morcos) dc008c4 Add IsCurrentForFeeEstimatation (Alex Morcos) ebafdca Pass pointers to existing CTxMemPoolEntries to fee estimation (Alex Morcos) d825838 Always update fee estimates on new blocks. (Alex Morcos) 6f06b26 rename bool to validFeeEstimate (Alex Morcos) 84f7ab0 Remove member variable hadNoDependencies from CTxMemPoolEntry (Alex Morcos) 60ac00d Don't track transactions at all during IBD. (Alex Morcos) 4df4479 Remove extraneous LogPrint from fee estimation (Alex Morcos)
44b64b9 Fix edge case with stale fee estimates (Alex Morcos) 78ae62d Add clarifying comments to fee estimation (Alex Morcos) 5fe0f47 Add extra logging to processBlock in fee estimation. (Alex Morcos) dc008c4 Add IsCurrentForFeeEstimatation (Alex Morcos) ebafdca Pass pointers to existing CTxMemPoolEntries to fee estimation (Alex Morcos) d825838 Always update fee estimates on new blocks. (Alex Morcos) 6f06b26 rename bool to validFeeEstimate (Alex Morcos) 84f7ab0 Remove member variable hadNoDependencies from CTxMemPoolEntry (Alex Morcos) 60ac00d Don't track transactions at all during IBD. (Alex Morcos) 4df4479 Remove extraneous LogPrint from fee estimation (Alex Morcos)
44b64b9 Fix edge case with stale fee estimates (Alex Morcos) 78ae62d Add clarifying comments to fee estimation (Alex Morcos) 5fe0f47 Add extra logging to processBlock in fee estimation. (Alex Morcos) dc008c4 Add IsCurrentForFeeEstimatation (Alex Morcos) ebafdca Pass pointers to existing CTxMemPoolEntries to fee estimation (Alex Morcos) d825838 Always update fee estimates on new blocks. (Alex Morcos) 6f06b26 rename bool to validFeeEstimate (Alex Morcos) 84f7ab0 Remove member variable hadNoDependencies from CTxMemPoolEntry (Alex Morcos) 60ac00d Don't track transactions at all during IBD. (Alex Morcos) 4df4479 Remove extraneous LogPrint from fee estimation (Alex Morcos)
44b64b9 Fix edge case with stale fee estimates (Alex Morcos) 78ae62d Add clarifying comments to fee estimation (Alex Morcos) 5fe0f47 Add extra logging to processBlock in fee estimation. (Alex Morcos) dc008c4 Add IsCurrentForFeeEstimatation (Alex Morcos) ebafdca Pass pointers to existing CTxMemPoolEntries to fee estimation (Alex Morcos) d825838 Always update fee estimates on new blocks. (Alex Morcos) 6f06b26 rename bool to validFeeEstimate (Alex Morcos) 84f7ab0 Remove member variable hadNoDependencies from CTxMemPoolEntry (Alex Morcos) 60ac00d Don't track transactions at all during IBD. (Alex Morcos) 4df4479 Remove extraneous LogPrint from fee estimation (Alex Morcos)
…priority removal f5b2e54 Fix comparisons for integer expressions of different signedness (random-zebra) 784d8b4 [Doc] Add Mempool priority changes to release notes (random-zebra) 6163d4b Remove -blockminsize option (Suhas Daftuar) b304fb9 Allow setting minrelaytxfee to 0 (Alex Morcos) 006136e Make boost::multi_index comparators const (Suhas Daftuar) 5858fb5 [Tests] Remove priority check for sapling txes (random-zebra) e267d02 [Cleanup] Remove coin age priority completely (random-zebra) 4298938 [RPC] Remove priorityDelta from prioritisetransaction (random-zebra) cd1535a [rpc] Remove priority information from mempool RPC calls (Alex Morcos) 3b4d207 [Refactor][RPC] entryToJSON/EntryDescriptionString out of mempoolToJSON (random-zebra) 142415e Fix edge case with stale fee estimates (Alex Morcos) 9f47b0f Add clarifying comments to fee estimation (Alex Morcos) 57b7922 Add extra logging to processBlock in fee estimation. (Alex Morcos) 59486ef Add IsCurrentForFeeEstimatation (Alex Morcos) d23ebfd Pass pointers to existing CTxMemPoolEntries to fee estimation (Alex Morcos) be5982e Always update fee estimates on new blocks. (Alex Morcos) aa97809 rename bool to validFeeEstimate (Alex Morcos) 82aba64 Remove member variable hadNoDependencies from CTxMemPoolEntry (random-zebra) c3758e1 Don't track transactions at all during IBD. (Alex Morcos) 9ca59ae [rpc] rawtx: Prepare fLimitFree to make it an option (MarcoFalke) f682e75 [wallet] Set fLimitFree = true (MarcoFalke) 0221d5a [QA] Fix random failure in wallet_abandonconflict.py (random-zebra) 33c9aa1 [Trivial] Pass hash by const ref to CBlockPolicyEstimator::removeTx (random-zebra) 7be33e0 Remove extraneous LogPrint from fee estimation (Alex Morcos) 7b6e8a3 [test] Remove priority from tests (Alex Morcos) c2ecf27 No longer allow "free" transactions (Alex Morcos) 5c577c5 [Cleanup] Remove feature_nulldummy.py unused functional test (random-zebra) 3097847 [cleanup] Remove estimatePriority and estimateSmartPriority (random-zebra) f283e8a [debug] Change -printpriority option (Alex Morcos) dcddcaf [Cleanup] Remove unused (always false) fAllowFree arg in GetMinRelayFee (random-zebra) 03d2ee9 [mining] Remove -blockprioritysize. (Alex Morcos) cfaeb97 [BUG] Don't add priority txes (random-zebra) 01882da Add unit tests for ancestor feerate mining (Suhas Daftuar) 49b1a9b [Policy] Limit total SHIELD size and check spork 20 in addPackageTxs (random-zebra) cc473ed Use ancestor-feerate based transaction selection for mining (random-zebra) dfaf4e7 [Wallet] Remove sendfree (random-zebra) Pull request description: This PR implements CPFP transaction selection mechanism, which is the simplest "fee bumping technique" (we might want to consider implementing RBF too later on). The algorithm in `CreateNewBlock` now selects transactions based on their feerate, inclusive of unconfirmed ancestor transactions. This means that a low-fee transaction can become more likely to be selected if a high-fee transaction that spends its outputs is relayed: the fee burned in the "child" transaction, actually pays for the parent tx too (hence the name). This PR also removes completely the (already deprecated) notion of coinage-based priority and "free transactions area". Changes backported / adapted from: - bitcoin#7600 [Suhas Daftuar] - bitcoin#8287 [MarcoFalke] - bitcoin#8295 [Suhas Daftuar] - bitcoin#9138 [Alex Morcos] - bitcoin#9602 [Alex Morcos] - bitcoin#11847 [Suhas Daftuar] ACKs for top commit: Fuzzbawls: utACK f5b2e54 furszy: re-ACK f5b2e54 after rebase and last commit. Tree-SHA512: aef64628008699c81735660fcbe51789b7dc9d2a670d0c695399a2821f01f5d72e46d72b5f57d7b28c0e0028b60b4d6294ee101b8038ea46d237c7b8729a79da
This PR is partly a refactor, partly bug fix, and partly improved robustness in edge cases. Outside of the edge cases (when your node is behind) the results are unchanged.
Explanations of the changes in the individual commits.