Skip to content

Conversation

@ismaelsadeeq
Copy link
Member

@ismaelsadeeq ismaelsadeeq commented Aug 15, 2025

This is a simple PR that updates the block policy estimator’s MIN_BUCKET_FEERATE constant to be identical to the policy DEFAULT_MIN_RELAY_TX_FEE.
It also enables the fee estimator to record transactions with a fee rate up to the DEFAULT_MIN_RELAY_TX_FEE in its stats, which effectively allows the estimator to return sub-1 sat/vB fee rate estimates.

The change is correct because the estimator creates buckets of fee rates from
MIN_BUCKET_FEERATE,
MIN_BUCKET_FEERATE + FEE_SPACING,
MIN_BUCKET_FEERATE + 2 * FEE_SPACING,
… up to MAX_BUCKET_FEERATE.

This means it will record sub-1 sat/vB fee rates in the buckets and may return them as a fee rate estimate when that bucket is the lowest one with sufficient transactions for a given target.

Tying MIN_BUCKET_FEERATE to DEFAULT_MIN_RELAY_TX_FEE also makes it dynamic, so we don’t need to update the fee estimator when the minrelaytxfee default is adjusted in the future.

For the mempool fee rate estimator in #31664, no update is needed since it uses the block assembler and because the node can see sub-1 sat/vB transactions, it can generate block templates with those and therefore return a fee rate estimate accordingly.


While touching this part of the fee estimator code, this PR got rid of the dummy value persisted in the file

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 15, 2025

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

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33199.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK polespinasa
Concept ACK kevkevinpal, musaHaruna

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #34075 (fees: Introduce Mempool Based Fee Estimation to reduce overestimation 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.

Copy link
Member

@polespinasa polespinasa left a comment

Choose a reason for hiding this comment

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

concept ACK

This change makes much sense to me, if the min relay fee is lowered the feerate tracking should also take that into account.

@kevkevinpal
Copy link
Contributor

Concept ACK 413c81b

It makes sense to update MIN_BUCKET_FEERATE with the recent changes to be sub 1 sat/vbyte

I do think the additional test is a bit redundant but I am okay in adding if others think it makes sense

@maflcko
Copy link
Member

maflcko commented Aug 28, 2025

This picks up #13990? If yes, it may be good to explain the differences.

@ismaelsadeeq ismaelsadeeq force-pushed the 08-2025-low-fee-rate-estimate branch 2 times, most recently from 30415b6 to 0eb02ea Compare September 1, 2025 13:13
@ismaelsadeeq
Copy link
Member Author

This picks up #13990? If yes, it may be good to explain the differences.

This is different from #13990 in approach:

It omits the consistency check and avoids extending the fee rate buckets when the min bucket fee rate changes.
Instead, it builds on #29702 by simply bumping the fees file version, which ensures that estimates saved in previous files are not read. As such after a restart, the estimator starts afresh.

@ismaelsadeeq
Copy link
Member Author

Rebased and fixed nits.

Copy link
Member

@polespinasa polespinasa left a comment

Choose a reason for hiding this comment

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

Just some nits and questions :=)

@ismaelsadeeq ismaelsadeeq force-pushed the 08-2025-low-fee-rate-estimate branch from 98be7ef to b767897 Compare November 7, 2025 14:49
@ismaelsadeeq
Copy link
Member Author

Just some nits and questions :=)

I force pushed to address the comment, thanks for review @polespinasa

@musaHaruna
Copy link
Contributor

musaHaruna commented Dec 13, 2025

Concept ACK (code review up to b767897)

I’m new to fee estimation, but I was able to understand this PR because it is fairly straightforward.

The idea is to make DEFAULT_MIN_RELAY_TX_FEE i.e the minimum feerate a node is willing to relay and accept into its mempool by default equal to MIN_BUCKET_FEERATE, which is used by the fee estimator (CBlockPolicyEstimator).

By default, if a transaction’s feerate is below DEFAULT_MIN_RELAY_TX_FEE, the node:
will not relay it, and will not keep it in its mempool.

Nodes are free to choose a different value via the -minrelaytxfee option, but this value (DEFAULT_MIN_RELAY_TX_FEE) defines the default policy.

MIN_BUCKET_FEERATE lives in the fee estimator and defines the lowest feerate bucket that the estimator tracks. Any transaction with a feerate below this value was previously ignored by the estimator. Importantly, MIN_BUCKET_FEERATE does not reject transactions and does not affect relay or mempool policy it only affects what data the fee estimator records.

Before this PR mempool policy accepts transactions down to DEFAULT_MIN_RELAY_TX_FEE = 100 (i.e. 1 sat/vB). while fee estimator (CBlockPolicyEstimator) Starts tracking fees at a higher minimum:
MIN_BUCKET_FEERATE = 1000 (i.e. 10 sat/vB).

As a result, transactions that were perfectly valid, accepted, and relayed by the node were not recorded by the fee estimator. Therefore the estimator could not learn from low-fee traffic.

By making: MIN_BUCKET_FEERATE == DEFAULT_MIN_RELAY_TX_FEE
the fee estimator now tracks all transactions the node is willing to relay, including sub-1 sat/vB transactions (i.e. transactions with feerates below 1 sat/vB, if the relay policy allows them. Not sure if am correct on that), and
can return lower and more accurate fee estimates.

The change is correct because the estimator creates buckets of fee rates from
MIN_BUCKET_FEERATE,
MIN_BUCKET_FEERATE + FEE_SPACING,
MIN_BUCKET_FEERATE + 2 * FEE_SPACING,
… up to MAX_BUCKET_FEERATE.

Confirmed this behaviour by digging into CBlockPolicyEstimator bucket construction logic.

def transact_and_mine(self, numblocks, mining_node):
min_fee = Decimal("0.00001")
min_fee = MINIMUM_RELAY_FEE_RATE
# We will now mine numblocks blocks generating on average 100 transactions between each block
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: feel free to ignore

Suggested change
# We will now mine numblocks blocks generating on average 100 transactions between each block
# We will now mine "numblocks" blocks, generating on average 100 transactions between each block

I think makes it easier to read

Copy link
Member

@polespinasa polespinasa left a comment

Choose a reason for hiding this comment

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

code looks good to me, currently trying to test it on mainnet will ack if positive results :)

a small nit for more clarity on the PR

Copy link
Member

@polespinasa polespinasa left a comment

Choose a reason for hiding this comment

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

cr and tACK b767897

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.

6 participants