Skip to content

[ZIP TBD]: comparable-based fee market ZIP#1157

Open
aphelionz wants to merge 11 commits intozcash:mainfrom
ShieldedLabs:aphelionz/dynamic-fees
Open

[ZIP TBD]: comparable-based fee market ZIP#1157
aphelionz wants to merge 11 commits intozcash:mainfrom
ShieldedLabs:aphelionz/dynamic-fees

Conversation

@aphelionz
Copy link
Member

This ZIP proposes the dynamic fee market as described at https://fees.shieldedinfra.net.

The design is still ongoing, and this PR is submitted mainly for inclusion in the upcoming NU7 sentiment poll.

@nuttycom nuttycom changed the title draft: comparable-based fee market ZIP [ZIP TBD]: comparable-based fee market ZIP Jan 23, 2026
aphelionz and others added 2 commits February 4, 2026 16:30
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>

A successful design and implementation is one that:

- Does not leak information that can be used to segment the user base.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Any transaction UX (wallet or other interface) SHOULD offer the user the standard median fee, and a priority fee of median_fee_per_action * priority_multiplier.

This does not satisfy the requirement, since it leaks the user's choice of whether to prioritize the transaction.

Comment on lines +83 to +87
- Provides a clear and consistent user experience:
- Fees are easy to understand and explain
- Fees are kept low and adjust rarely
- Transactions are reliable under uncongested network conditions
- Prioritizes higher value transactions when the network is congested
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

Suggested change
- Provides a clear and consistent user experience:
- Fees are easy to understand and explain
- Fees are kept low and adjust rarely
- Transactions are reliable under uncongested network conditions
- Prioritizes higher value transactions when the network is congested
- Fees are easy to understand and explain.
- Fees adjust rarely.
- Transactions are reliable under uncongested network conditions.
- Prioritizes higher value transactions when the network is congested.

"Clear and consistent user experience" is subjective; if the subitems explain what is meant by this, they are sufficient on their own.

"Fees are kept low" seems at least partly redundant with "Has the fee remain roughly economically stable", and it is not clear what it adds to the latter.

"Fees adjust rarely" does not seem to be satisfied by the proposed mechanism. Is the requirement wrong or is the mechanism wrong?

"Prioritizes higher value transactions when the network is congested" also doesn't seem to be satisfied, since the prioritization is by user choice, not by value.

Comment on lines +91 to +92
- Preventing legitimate transactions requires paying a price higher than
legitimate users are willing to pay
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

This seems impossible. It's always sufficient to pay the same price that users are willing to pay (to displace the same amount of block space), because there's no way to distinguish a competent adversary's transaction from a user transaction, at least if they are shielded.

- Makes griefing expensive:
- Preventing legitimate transactions requires paying a price higher than
legitimate users are willing to pay
- Prevents miners from gaming the protocol by making users pay more
Copy link
Collaborator

Choose a reason for hiding this comment

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

It isn't clear to me that this requirement is met.

- Compatible with current and planned network upgrades i.e. ZIP-235’s NSM
contributions and ZIP-317’s action-based accounting.
- Policy-first, hardened by minimal consensus upgrades later
- Uses a stateless design, with minimal calculations
Copy link
Collaborator

Choose a reason for hiding this comment

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

This presumably means that it doesn't add additional state. The past fees are state.


Let `T` be the set of transactions in the blocks with heights `[chain_tip - reorg_buffer - lookback_window ... chain_tip - reorg_buffer]`.

The new suggested marginal fee is calculated as $\mathsf{median}(T_fee)$. The
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

$\mathsf{T_{fee}}$ is not defined. The intent seems to be that it is the sequence of fees for transactions in $\mathsf{T}$ plus fees for synthetic actions. (Synthetic actions are only mentioned way down on line 156; they have to be introduced much earlier for the algorithm not to be misread, as I originally did.)

Btw, either _ must be escaped as \_, or fee must be written as {fee} if intended as a subscript.

Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

More importantly, this seems wrong for the intent of the algorithm. The marginal fee is incomparable to the past median fee, because you're not taking into account the number of actions. This will not result in stable fee adjustment.

I could be wrong but I don't see that this has an obvious fix. As I stated on the forum:

I believe the fee market proposal mentioned in question 8 has not had time for adequate analysis.

Also see this forum comment.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I had something like dynamic_fee(h) = conventional_fee / (1 - (average_size(blocks[h-20..h]) / max_block_size)) in mind.

<details>
<summary>Rationale</summary>
- A reorg buffer of 5 blocks is chosen to balance the need to mitigate
reorganization risk with the desire to use recent transaction data for fee
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not 10 blocks?

Comment on lines +169 to +170
The following rules can be enforced by relay policy initially, and later
hardened into consensus rules in a future network upgrade.
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

The existing ZIP 317 conventional fee isn't enforced by relay policy; it is enforced by the recommended algorithm for block template construction. (At least that's true for zcashd, and iirc also for zebrad.)

It is unclear whether it is a good idea to have fee policy in consensus; that would have to be separately justified. I suggest expressing it as an "Open question".


- The per-action fee MUST be at least `fee_floor` zats.
- The per-action fee MUST be a power of 10.
- The wallet MUST set `nExpiryHeight` such that `chain_tip + reorg_buffer < nExpiryHeight < chain_tip + lookback_window + reorg_buffer`,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Currently nExpiryHeight is not required to be set. Requiring it is a major behaviour change that would require more thorough justification; it would need be called out in the ZIP Abstract and probably mentioned in the Requirements.


## Wallet Construction

Any transaction UX (wallet or other interface) SHOULD offer the user the standard median fee, and a priority fee of `median_fee_per_action * priority_multiplier`.
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

As stated earlier, this makes transactions distinguishable by the user's choice of priority, which would need to be justified in the Privacy Implications section (and I do not think it is a good idea).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also "standard median fee" is not defined. I think you mean the conventional fee (with the described marginal fee adjustment).

aphelionz and others added 3 commits February 4, 2026 18:08
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
aphelionz and others added 2 commits February 4, 2026 18:10
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
Comment on lines +175 to +176
- The per-action fee MUST be at least `fee_floor` zats.
- The per-action fee MUST be a power of 10.
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

These should explicitly be part of the formula to calculate the marginal fee, rather than being stated as constraints (because the calculation needs to be deterministic in order to not leak information). Also, "marginal fee" is the correct terminology, not "per-action fee".

Comment on lines +71 to +73
The combined effects of an additional bit of user choice (priority vs standard)
and powers of 10 quantization of fees result in an overall reduction of fee
entropy leakage.
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

Line 187 says:

Any transaction UX (wallet or other interface) SHOULD offer the user the standard median fee, and a priority fee of median_fee_per_action * priority_multiplier.

As I read it, the quantization occurs only in the adjusted marginal fee (referred to as median_fee_per_action here). Therefore it has no effect in hiding the user choice. Even if the quantization was applied to the total fee (which is a radical departure from ZIP 317 and would require more analysis), I think it would often not hide the user choice. So this paragraph is misleading in implying that the quantization helps in that regard.


The term "priority multiplier" (or "multiplier") refers to the factor by which a transaction's fee is multiplied if the user opts for priority processing.

The term "comparables" (or "comps") refers to previous transactions used to determine the appropriate fee for a new transaction based on their fees and actions.
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

This term seems not to be used in the body of the ZIP. Relatedly, I don't understand its use in the title.

- Fees are kept low and adjust rarely
- Transactions are reliable under uncongested network conditions
- Prioritizes higher value transactions when the network is congested
- Incentivizes miners to include legitimate transactions in blocks
Copy link
Collaborator

Choose a reason for hiding this comment

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

Without analyzing the dynamic behaviour of the fee adjustment in detail, we can now only say that the fee is at least 10 zatoshis per logical action. Is that high enough to incentivize miners?

- Transactions are reliable under uncongested network conditions
- Prioritizes higher value transactions when the network is congested
- Incentivizes miners to include legitimate transactions in blocks
- Responds quickly to congestion and slowly returns to normal prices
Copy link
Collaborator

Choose a reason for hiding this comment

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

"Quickly" and "slowly" are vague.

Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
Comment on lines +159 to +161
When calculating the median fee, if a block has unused capacity (i.e., fewer
actions than the maximum allowed), we fill the empty space with synthetic
actions, and then perform the median calculation.
Copy link
Collaborator

@daira daira Feb 4, 2026

Choose a reason for hiding this comment

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

"Fill the empty space with synthetic actions" is imprecise. I can guess what it might be intended to mean, but $\mathsf{T}$ is a sequence of transactions, not actions, so you can't directly append actions to it.

The intent seems to be to append fees corresponding to those actions to $\mathsf{T_{fee}}$, but I think this biases the resulting mean more toward fee_floor than intended — because the synthetic actions are each "smaller" than a typical transaction, so there are more of them.

One way to account for this is to count a real transaction with $k$ logical actions and fee $F$ as contributing $k$ copies of $F/k$ to $\mathsf{T_{fee}}$, and calculate $\mathsf{T_{size}}$ as the mean "logical action size" (i.e. tx size divided by $k$ for each action). That way the median would reflect the median marginal fee, which seems to be what is intended. But I shoudn't have to guess. Also this might be "less wrong", but I'm pretty sure it's still not the right thing:

  • using the median means that if more than half the actions are synthetic, then the median will "fall off a cliff" and be exactly fee_floor (and this in practice will happen if blocks are less than half-full, which they currently are);
  • it is unclear that we want to weight transactions with more logical actions higher when calculating whatever average is used.

Note that even if the algorithm is fixed so that it doesn't cause the adjusted marginal fee to go to fee_floor unintentionally, it's also necessary to prevent an adversary (even if they can mine blocks) from being able to do this maliciously, in order to benefit from the low marginal fee to mount a DoS attack on subsequent blocks.


Given the same sequence of transactions `T` as defined above, let synthetic action
`S` be defined as an action with a `S_fee = fee_floor` and a size of
$\mathsf{mean}(T_size)$.
Copy link
Collaborator

Choose a reason for hiding this comment

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

$\mathsf{T}$ might not have enough transactions for $\mathsf{mean}(\mathsf{T_{size}})$ to be representative. For example, if we have a coinbase-only block, $\mathsf{mean}(\mathsf{T_{size}})$ will be equal to the size of that transaction which is likely atypical. And in any case, this gives an adversary a lot of control over $\mathsf{mean}(\mathsf{T_{size}})$, and therefore over the number of synthetic fees in $\mathsf{T_{fee}}$.

aphelionz and others added 2 commits February 5, 2026 15:21
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
Co-authored-by: Daira-Emma Hopwood <daira@jacaranda.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments