Skip to content
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

Merged
merged 10 commits into from Jan 5, 2017
Merged

Improve fee estimation #9138

merged 10 commits into from Jan 5, 2017

Conversation

morcos
Copy link
Member

@morcos morcos commented Nov 11, 2016

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.

return false;
if (chainActive.Height() < pindexBestHeader->nHeight - 1)
return false;
return true;
Copy link
Contributor

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();
Copy link
Contributor

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?

Copy link
Member Author

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.

@morcos
Copy link
Member Author

morcos commented Nov 21, 2016

rebased

@gmaxwell
Copy link
Contributor

Concept ACK.

@jonasschnelli
Copy link
Contributor

Ran this code on top of master on one of my nodes.
Just compared it to the node running master (same network but independent mempool), see below.
The differences for a conf. target of 2 blocks are quite large.

Next step would be to run master and this PR with the same mempool and maybe dump 2,4,8,20 target every ~10mins.

masternode ~/node/bitcoin $ ./src/bitcoin-cli getmempoolinfo
{
  "size": 22022,
  "bytes": 133099706,
  "usage": 252978016,
  "maxmempool": 300000000,
  "mempoolminfee": 0.00001014
}
masternode ~/node/bitcoin $ ./src/bitcoin-cli estimatesmartfee 2
{
  "feerate": 0.00761447,
  "blocks": 2
}
masternode ~/node/bitcoin $ ./src/bitcoin-cli estimatesmartfee 3
{
  "feerate": 0.00069881,
  "blocks": 3
}
masternode ~/node/bitcoin $ ./src/bitcoin-cli estimatesmartfee 8
{
  "feerate": 0.00069881,
  "blocks": 8
}

thisprnode ~/bitcoin/bitcoin $ ./src/bitcoin-cli getmempoolinfo
{
  "size": 24593,
  "bytes": 140534928,
  "usage": 268029424,
  "maxmempool": 300000000,
  "mempoolminfee": 0.00001000
}
thisprnode ~/bitcoin/bitcoin $ ./src/bitcoin-cli estimatesmartfee 2
{
  "feerate": 0.00083575,
  "blocks": 2
}
thisprnode ~/bitcoin/bitcoin $ ./src/bitcoin-cli estimatesmartfee 3
{
  "feerate": 0.00077770,
  "blocks": 3
}
thisprnode ~/bitcoin/bitcoin $ ./src/bitcoin-cli estimatesmartfee 8
{
  "feerate": 0.00069872,
  "blocks": 8
}

@morcos
Copy link
Member Author

morcos commented Nov 25, 2016

@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
Copy link
Member

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 */
Copy link
Member

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)?

@sdaftuar
Copy link
Member

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())) {
Copy link
Member

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.

@morcos
Copy link
Member Author

morcos commented Nov 29, 2016

  • Addressed @sdaftuar's comment requests.
  • Fixed a pre-existing rare edge case which would print errors and make estimates slightly off.
  • Fixed a bug in this PR.

@gmaxwell once you see the BUGFIX commit, I'll squash just that one into the right place in the history.

{
if (IsInitialBlockDownload())
return false;
if (chainActive.Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE))
Copy link
Member

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.

@sdaftuar
Copy link
Member

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.

@morcos morcos force-pushed the refactorFeeEstimation branch 2 times, most recently from ed32b1a to afead86 Compare December 3, 2016 14:02
@morcos
Copy link
Member Author

morcos commented Dec 3, 2016

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...

@morcos
Copy link
Member Author

morcos commented Dec 5, 2016

rebased (and squashed in the bugfix and assert)

@fanquake please milestone for 0.14.0

@maflcko maflcko added this to the 0.14.0 milestone Dec 5, 2016
@sdaftuar
Copy link
Member

sdaftuar commented Dec 9, 2016

re-ACK 98fffcb

@morcos
Copy link
Member Author

morcos commented Dec 10, 2016

Simple rebase due to expected conflict on function signature of CTxMemPool:removeForBlock

@sdaftuar
Copy link
Member

re-ACK 761a9be

Copy link
Member

@sipa sipa left a 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 {
Copy link
Member

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));
Copy link
Member

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.

@morcos
Copy link
Member Author

morcos commented Dec 30, 2016

Rebased to fix a silent merge conflict (the change in wallet.cpp)
Also fixed @sipa's nits, otherwise unchanged from reviewed code.

@gmaxwell
Copy link
Contributor

gmaxwell commented Jan 4, 2017

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.
@morcos
Copy link
Member Author

morcos commented Jan 4, 2017

rebased

@sdaftuar
Copy link
Member

sdaftuar commented Jan 5, 2017

re-ACK 44b64b9

@sipa
Copy link
Member

sipa commented Jan 5, 2017

utACK 44b64b9

@sipa sipa merged commit 44b64b9 into bitcoin:master Jan 5, 2017
sipa added a commit that referenced this pull request Jan 5, 2017
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)
codablock pushed a commit to codablock/dash that referenced this pull request Jan 18, 2018
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)
andvgal pushed a commit to energicryptocurrency/gen2-energi that referenced this pull request Jan 6, 2019
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)
CryptoCentric pushed a commit to absolute-community/absolute that referenced this pull request Feb 26, 2019
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)
CryptoCentric pushed a commit to absolute-community/absolute that referenced this pull request Feb 26, 2019
furszy added a commit to PIVX-Project/PIVX that referenced this pull request Jul 14, 2021
…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
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants