-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Comprehensive compute fees #20531
Comprehensive compute fees #20531
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
--- | ||
title: Comprehensive Compute Fees | ||
--- | ||
|
||
## Motivation | ||
|
||
The current fee structure lacks a comprehensive account of the work required by | ||
a validator to process a transaction. The fee structure is only based on the | ||
number of signatures in a transaction but is meant to account for the work that | ||
the validator must perform to validate each transaction. The validator performs | ||
a lot more user-defined work than just signature verification. Processing a | ||
transaction typically includes signature verifications, account locking, account | ||
loading, and instruction processing. | ||
|
||
## Proposed Solution | ||
|
||
The following solution does not specify what native token costs are to be | ||
associated with the new fee structure. Instead, it sets the criteria and | ||
provides the knobs that a cost model can use to determine those costs. | ||
|
||
### Fee | ||
|
||
The goal of the fees is to cover the computation cost of processing a | ||
transaction. Each of the fee categories below will be represented as a compute | ||
unit cost that, when added together, encompasses the entire cost of processing | ||
the transaction. By calculating the total cost of the transaction, the runtime | ||
can charge a more representative fee and make better transaction scheduling | ||
decisions. | ||
|
||
A fee will be calculated based on: | ||
|
||
1. Number of signatures | ||
- Fixed rate per signature | ||
2. Number of write locks | ||
- Fixed rate per writable account | ||
3. Data byte cost | ||
- Fixed rate per byte of the sum of the length all a transactions instruction | ||
datas | ||
Comment on lines
+36
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh, nice, this prose sounds to me that it's already generalized enough, including the upcoming extended (larger-than-MTU) ones. :) ref: #20691 |
||
4. Account sizes | ||
- Account sizes can't be known up-front but can account for a considerable | ||
amount of the load the transaction incurs on the network. The payer will | ||
be charged for a maximum account size (10m) upfront and refunded the | ||
difference after the actual account sizes are known. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the refund mechanism There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calc the fee based on the account size estimate (or overestimate) and verify that the payer has sufficient balance to cover it. Then after processing the transaction and the final measured cost is known deduct the final cost which may be lower than the original estimate. The same thing as planned for the compute budget, verify the payer's balance based on what they asked for (or default) and then deduct the actual amount used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, I was under impression that before processing, the asked/estimated fund in payer's account will be deducted, or locked somehow, to make sure the fund will be there to cover expense. Then after processing, the remaining balance will be credited back to payer's account. Thought that is a lot of labor and chances for errors; what you described is easier. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fee is currently deducted from the payer account before processing any instructions. We can credit some of that back after processing depending on the difference between the requested and the actual. |
||
5. Compute budget | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (please allow late comment) I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. example: vote transactions and dexes order books. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This is a good use case; but could discounting frequently accessed accounts potentially make DoS attacks easier/cheaper? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, maybe not likely? i thought the main theme of this revamped compute fees is to reflect the actual computing resource consumed to execute a particular tx. this means we closely model the performance characteristics of any modern machine to be metered as a single unit of amount called fees, right? Then, any frequently accessed data should be in some kind of cache. so, I thought txes touching the frequently accessed accounts should be cheaper. Another context i heard is that 1 SOL/day for validators is too much pain. So, I want to avoid voting txes to be higher than now (source: @mvines ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
to be specific, those data will be in AccountDb's AccountCache and/or linux kernel's page cache, etc... |
||
- Each transaction will be given a default transaction-wide compute budget of | ||
200k units with the option of requesting a larger budget via a compute | ||
budget instruction up to a maximum of 1m units. This budget is used to | ||
limit the time it takes to process a transaction. The compute budget | ||
portion of the fee will be charged up-front based on the default or | ||
requested amount. After processing, the actual number of units consumed | ||
will be known, and the payer will be refunded the difference, so the payer | ||
only pays for what they used. Builtin programs will have a fixed cost | ||
while BPF program's cost will be measured at runtime. | ||
6. Precompiled programs | ||
- Precompiled programs are performing compute-intensive operations. The work | ||
incurred by a precompiled program is predictable based on the instruction's | ||
data array. Therefore a cost will be assigned per precompiled program | ||
based on the parsing of instruction data. Because precompiled programs are | ||
processed outside of the bank, their compute cost will not be reflected in | ||
the compute budget and will not be used in transaction scheduling | ||
decisions. The methods used to determine the fixed cost of the components | ||
above are described in | ||
[#19627](https://github.com/solana-labs/solana/issues/19627) | ||
|
||
### Cost model | ||
|
||
The cost model is used to assess what load a transaction will incur during | ||
in-slot processing and then make decisions on how to best schedule transaction | ||
into batches. | ||
|
||
The cost model's criteria are identical to the fee's criteria except for | ||
signatures and precompiled programs. These two costs are incurred before a | ||
transaction is scheduled and therefore do not affect how long a transaction | ||
takes within a slot to process. | ||
|
||
### Cache account sizes and use them instead of the max | ||
|
||
https://github.com/solana-labs/solana/issues/20511 | ||
|
||
### Transaction-wide compute caps | ||
|
||
The current compute budget caps are independently applied to each instruction | ||
within a transaction. This means the overall transaction cap varies depending on | ||
how many instructions are in the transaction. To more accurately schedule a | ||
transaction, the compute budget will be applied transaction-wide. One challenge | ||
of the transaction-wide cap is that each instruction (program) can no longer | ||
expect to be given an equal amount of compute units. Each instruction will be | ||
given the remaining units left over after processing earlier instructions. This | ||
will provide some additional tuning and composability challenges for developers. | ||
|
||
### Requestable compute budget caps and heap sizes | ||
|
||
The precompiled | ||
[ComputeBudget](https://github.com/solana-labs/solana/blob/00929f836348d76cb3503d0ba5f76f0d275bcc66/sdk/src/compute_budget.rs#L34) | ||
program can be used to request higher transaction-wide compute budget caps and | ||
program heap sizes. The requested increases will be reflected in the | ||
transaction's fee. | ||
|
||
### Fees for precompiled program failures | ||
|
||
https://github.com/solana-labs/solana/issues/20481 | ||
|
||
### Rate governing | ||
|
||
Current rate governing needs to be re-assessed. Current fees are being rate | ||
governed down to their minimums because the number of signatures in each slot is | ||
far lower than the "target" signatures per slot. | ||
|
||
Instead of using the number of signatures to rate govern, the cost model will | ||
feed back information based on the batch/queue load it is seeing. The fees will | ||
sit at a target rate and only increase if the load goes above a specified but to | ||
be determined threshold. The governing will be applied across all the fee | ||
criteria. | ||
|
||
### How do clients calculate a transaction's fee | ||
|
||
Transaction fees are currently calculated based on a fixed cost per signature | ||
and implemented via an object in the SDK that took a transaction and returned a | ||
cost. This object is looked up via a blockhash and returned via RPC to | ||
calculate the fee offline. | ||
|
||
The comprehensive fee calculations are more sophisticated and depend on a | ||
greater amount of information (recent program compute meter measurements). To | ||
move to the new fee structure the RPC APIs that return a FeeCalculator object | ||
will be deprecated, and clients will send their transactions over RPC and be | ||
returned the calculated fee. | ||
|
||
Fees will no longer be calculated based on a blockhash since it is | ||
cost-prohibitive to retain the fee cost inputs for each bank (program units, | ||
account sizes). And mainly, the governed fee is based on network load now, not | ||
at some time in the past. This will mean that during offline-signing the actual | ||
fee charged will not be known until the transaction is submitted. |
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.
So, we don't still introduce gas fee bidding, remotely inheriting our deterministic fee cost philosophy? https://docs.solana.com/implemented-proposals/transaction-fees
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.
Fees will be deterministic, but governed based on cluster load so they may vary each slot