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

Fee Estimation: Ignore all transactions that are CPFP'd #30079

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

ismaelsadeeq
Copy link
Member

@ismaelsadeeq ismaelsadeeq commented May 10, 2024

Another attempt at #25380 with an alternate approach

This PR updates CBlockPolicyEstimator to ignore all transactions that are CPFP'd by some child when a new block is received.
This fixes the assumption that all transactions are confirmed solely because of their fee rate.
As some transactions are confirmed due to a CPFP by some child.

This approach linearize all transactions removed from the mempool because of the new block, and only ignore transactions whose mining score is not the same with their the fee rate.

All transaction with in-mempool parent are already not tracked for fee estimation, so the child that CPFP'd the parent is also ignored.

Upon implementing the cluster mempool, we will just track chunks and make the fee estimator package aware.

@DrahtBot
Copy link
Contributor

DrahtBot commented May 10, 2024

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK instagibbs, josibake
Stale ACK rkrux

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #30157 (Fee Estimation via Fee rate Forecasters by ismaelsadeeq)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@glozow
Copy link
Member

glozow commented May 10, 2024

cc @josibake @instagibbs @naumenkogs @darosior @murchandamus since you reviewed the last time

@instagibbs
Copy link
Member

concept ACK

strikes me as the right idea, keep it simple for now, focusing on correctness. Do we have charts anywhere tracking % of transactions that are in a cluster size of 1?

@ismaelsadeeq
Copy link
Member Author

Do we have charts anywhere tracking % of transactions that are in a cluster size of 1?

I will analyze the percentage of cluster size 1 transactions mined in previous blocks.

@josibake
Copy link
Member

Concept ACK

Copy link

@rkrux rkrux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK c12a677

Make successful, all functional tests successful.
Mentioned few nits and asked few questions for my clarity.

The downside of this approach is that transactions that are not CPFP’d will aslo be ignored.

Related to this^, one specific case I can think of that will be affected is of layered transactions that are meant to be confirmed together, example: fanout transactions to increase the utxo count in the wallet and make the utxo value distribution more even, but Idk how frequently these transactions happen.

test/functional/feature_fee_estimation.py Outdated Show resolved Hide resolved
test/functional/feature_fee_estimation.py Outdated Show resolved Hide resolved
test/functional/feature_fee_estimation.py Outdated Show resolved Hide resolved
test/functional/feature_fee_estimation.py Show resolved Hide resolved
test/functional/feature_fee_estimation.py Show resolved Hide resolved
test/functional/feature_fee_estimation.py Show resolved Hide resolved
src/policy/fees.cpp Outdated Show resolved Hide resolved
src/policy/fees.cpp Outdated Show resolved Hide resolved
test/functional/feature_fee_estimation.py Show resolved Hide resolved
test/functional/feature_fee_estimation.py Show resolved Hide resolved
@ismaelsadeeq ismaelsadeeq force-pushed the 05-2023-ignore-transactions-with-parents branch from c12a677 to 2563305 Compare May 14, 2024 17:03
@ismaelsadeeq
Copy link
Member Author

Do we have charts anywhere tracking % of transactions that are in a cluster size of 1?

I will analyze the percentage of cluster size 1 transactions mined in previous blocks.

I tracked recent 1000 blocks from block 842457 to 843457

~61% of transactions in the last 1000 blocks were confirmed in a cluster size > 1.
~38% of transactions in the last 1000 blocks were confirmed in a cluster size 1

Transactions: 3974143
Cluster size 1 transactions: 1516505
Approximate percentage of Cluster size 1 transactions: ~38
Transactions in a cluster size > 1 transactions: 2457638
Approximate percentage of transactions in a cluster size > 1: ~61

The data is available here here https://docs.google.com/spreadsheets/d/1QTE2EQeQlamA123pIn0SY4F-9jtnzS7e7CV1etT6ytM/edit?usp=sharing

I used this script to collect the data https://gist.github.com/ismaelsadeeq/e2767040b720f65986976b3f8c6b7b20

@ismaelsadeeq
Copy link
Member Author

Thanks for review @rkrux

Copy link

@rkrux rkrux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reACK 2563305

Thanks for the quick turnaround on this @ismaelsadeeq!

@@ -383,6 +401,79 @@ def test_acceptstalefeeestimates_option(self):
assert_equal(self.nodes[0].estimatesmartfee(1)["feerate"], fee_rate)


def send_and_mine_child_tx(self, broadcaster, miner, parent_tx, feerate):
u = {"txid": parent_tx["txid"], "vout": 0, "value": Decimal(parent_tx["tx"].vout[0].nValue) / COIN}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decimal(parent_tx["tx"].vout[0].nValue) / COIN

Is there not a satToBtc() already? WDYT about introducing one? I've noticed this conversion in this diff thrice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to modify if there is need to retouch, else this is a good idea for a follow-up @rkrux

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, would recommend this be a separate PR, since there are likely multiple instances in other tests where we could replace the satToBtc conversion with a utility function in the test framework.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I can pick this up in a separate PR.

Copy link
Member

@josibake josibake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, although unclear to me why we don't also remove the child transaction from fee estimation to avoid overestimating. Would recommend also removing the children, or at least documenting why it doesn't matter in a comment.

@@ -662,6 +662,22 @@ bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const Remo
return true;
}

void CBlockPolicyEstimator::removeParentTxs(const std::vector<RemovedMempoolTransactionInfo>& txs_removed_for_block)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a6e8133 ("ignore all transaction with in block child"):

Shouldn't we also remove the child? Otherwise we will overestimate fees, unless I'm missing something? Example:

  • Parent pays 1 sat/vb
  • 10 sat/vb per tx is required to be competitive for the next block
  • Child pays 20 sat/vb to try and get them + parent to 10 sat/vb
  • Now in fee estimation, we see 20 sat/vb for a child that could have only paid 10 sat/vb

Copy link
Member

@glozow glozow May 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although unclear to me why we don't also remove the child transaction from fee estimation to avoid overestimating

A child is already ignored, new mempool txns with unconfirmed parents are never added

bitcoin/src/validation.cpp

Lines 1274 to 1279 in dd42a5d

const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
ws.m_vsize, ws.m_entry->GetHeight(),
args.m_bypass_limits, args.m_package_submission,
IsCurrentForFeeEstimation(m_active_chainstate),
m_pool.HasNoInputsOf(tx));
m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());

bitcoin/src/policy/fees.cpp

Lines 610 to 615 in dd42a5d

// This transaction should only count for fee estimation if:
// - it's not being re-added during a reorg which bypasses typical mempool fee limits
// - the node is not behind
// - the transaction is not dependent on any other transactions in the mempool
// - it's not part of a package.
const bool validForFeeEstimation = !tx.m_mempool_limit_bypassed && !tx.m_submitted_in_package && tx.m_chainstate_is_current && tx.m_has_no_mempool_parents;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your review, Josie. I think you are missing something.

When the child arrives, it will have a mempool parent, and we currently do not consider all transactions with mempool parent for fee estimation.

So when processing a transaction in processBlockTx all transactions with mempool parent, will be missing and , and we will skip them.

Child transactions whose parents aren't in our mempool will also be missing, and we will skip them because orphan transactions aren't added to the mempool and hence won't be tracked.
They are skipped here:

if (!_removeTx(tx.info.m_tx->GetHash(), true)) {

See the discussion with @rkrux:
#30079 (comment)

I recently made a delving on how fix this limitation and track chunks post cluster mempool.
Package-aware fee estimator post

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, my bad. I had even read that comment that @glozow linked to earlier but it didn't click for me that by the time we get to the block we've already processed transactions and excluded the child transaction. I think a comment explaining what you just explained here would help a lot, maybe at the call site of removeParentTxs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the comment, thanks.

src/policy/fees.h Outdated Show resolved Hide resolved
@@ -383,6 +401,79 @@ def test_acceptstalefeeestimates_option(self):
assert_equal(self.nodes[0].estimatesmartfee(1)["feerate"], fee_rate)


def send_and_mine_child_tx(self, broadcaster, miner, parent_tx, feerate):
u = {"txid": parent_tx["txid"], "vout": 0, "value": Decimal(parent_tx["tx"].vout[0].nValue) / COIN}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, would recommend this be a separate PR, since there are likely multiple instances in other tests where we could replace the satToBtc conversion with a utility function in the test framework.

@DrahtBot DrahtBot requested a review from josibake May 16, 2024 10:02
@laanwj laanwj added the Mempool label May 16, 2024
@bitcoin bitcoin deleted a comment from laib200 Jun 3, 2024
@ismaelsadeeq ismaelsadeeq force-pushed the 05-2023-ignore-transactions-with-parents branch from 2563305 to 57556e5 Compare June 3, 2024 12:55
@ismaelsadeeq ismaelsadeeq changed the title Fee Estimation: Ignore all transactions with an in-block child Fee Estimation: Ignore all transactions that are CPFP'd Jun 3, 2024
@ismaelsadeeq
Copy link
Member Author

ismaelsadeeq commented Jun 3, 2024

Do we have charts anywhere tracking % of transactions that are in a cluster size of 1?

I will analyze the percentage of cluster size 1 transactions mined in previous blocks.

I tracked recent 1000 blocks from block 842457 to 843457

~61% of transactions in the last 1000 blocks were confirmed in a cluster size > 1. ~38% of transactions in the last 1000 blocks were confirmed in a cluster size 1

Transactions: 3974143 Cluster size 1 transactions: 1516505 Approximate percentage of Cluster size 1 transactions: ~38 Transactions in a cluster size > 1 transactions: 2457638 Approximate percentage of transactions in a cluster size > 1: ~61

The data is available here here https://docs.google.com/spreadsheets/d/1QTE2EQeQlamA123pIn0SY4F-9jtnzS7e7CV1etT6ytM/edit?usp=sharing

I used this script to collect the data https://gist.github.com/ismaelsadeeq/e2767040b720f65986976b3f8c6b7b20

This data shows that most transactions are in cluster size > 1.

So I switched to ignoring transaction that are CPFP'd only.

Thanks for your reviews @rkrux @josibake

@ismaelsadeeq ismaelsadeeq force-pushed the 05-2023-ignore-transactions-with-parents branch from 57556e5 to 55d615c Compare June 3, 2024 14:57
@DrahtBot
Copy link
Contributor

DrahtBot commented Jun 3, 2024

🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the
documentation.

Possibly this is due to a silent merge conflict (the changes in this pull request being
incompatible with the current code in the target branch). If so, make sure to rebase on the latest
commit of the target branch.

Leave a comment here, if you need help tracking down a confusing failure.

Debug: https://github.com/bitcoin/bitcoin/runs/25734218532

ismaelsadeeq and others added 6 commits June 3, 2024 16:02
- GetTxAncestorsAndDescendants takes the vector of transactions removed from the mempool
  after a block is connected. The function assumed that the order the transactions were
  included in the block was maintained; that is, all transaction parents was be added
  into the vector first before descendants.

- GetTxAncestorsAndDescendants computes all the ancestors and descendants of the transactions.
  The transaction is also included as a descendant and ancestor of itself.

Co-authored-by: willcl-ark <will@256k1.dev>
Co-authored-by: Antoine Poinsot <darosior@protonmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants