-
Notifications
You must be signed in to change notification settings - Fork 163
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
FIP-0032: Gas model adjustment for non-programmable FVM #315
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,267 @@ | ||
--- | ||
fip: "0032" | ||
title: Gas model adjustment for non-programmable FVM | ||
author: Raúl Kripalani (@raulkr), Steven Allen (@stebalien) | ||
discussions-to: https://github.com/filecoin-project/FIPs/discussions/316 | ||
status: Draft | ||
type: Technical | ||
category: Core | ||
created: 2022-03-08 | ||
spec-sections: | ||
- TBD | ||
requires: | ||
- FIP-0030 | ||
- FIP-0031 | ||
replaces: N/A | ||
--- | ||
|
||
# FIP-0032: Gas model adjustment for non-programmable FVM | ||
|
||
## Simple Summary | ||
|
||
This FIP is part of a two-FIP series that adjust the gas model of the Filecoin | ||
blockchain in preparation of user-programmable actors. This FIP focuses on | ||
attaining high-fidelity gas accounting under the Wasm runtime that built-in | ||
system actors will migrate to as part of FIP-0030 and FIP-0031. It does not | ||
cover upcoming system features like actor deployment, actor loading, memory | ||
management, and more. Those will be addressed in a subsequent FIP that focuses | ||
on gas model changes to support user-programmability. | ||
|
||
## Abstract | ||
|
||
With the arrival of the Filecoin Virtual Machine, the Filecoin network will gain | ||
the capability to run untrusted code in the form of user-defined actors. | ||
However, the current gas model is designed strictly for predefined, trusted | ||
code. In order to maintain network security guarantees, the gas model needs to | ||
evolve to accurately charge for computational instructions and resource usage of | ||
actor logic. | ||
|
||
This FIP expands the current gas model by introducing a new gas category to | ||
account for the real compute cost of the logic performed by every actor in the | ||
system. It also rearchitects IPLD state management gas, and adjusts the actor | ||
call fee to account for Wasm invocation container mechanics. | ||
|
||
This is the first FIP out of a two-FIP series to revise the gas model as a | ||
result of the introduction of the Filecoin Virtual Machine in FIP-0030 and | ||
FIP-0031. This FIP should accompany those FIPs under the same network upgrade. | ||
|
||
## Change Motivation | ||
|
||
Gas is an essential mechanism to (a) compensate the network for the computation | ||
performed during transaction execution, and to (b) restrict the compute capacity | ||
of blocks to achieve a designated epoch time (30 seconds). | ||
|
||
Today, Filecoin determines the amount of gas a transaction consumes by | ||
intercepting specific operations and actions, and applying gas explicit gas | ||
charges on them. Concretely: | ||
|
||
- On including a chain message, variable on the length of the message. | ||
- On returning a value, variable on the length of returned payload. | ||
- On performing a call, dependent on the type of call (simple value transfer, or | ||
other). | ||
- On performing an IPLD store get, fixed amount. | ||
- On performing an IPLD store put, variable on block payload size. | ||
- On actor creation, fixed amount. | ||
- On actor deletion, fixed amount. | ||
- On cryptographic operations: | ||
- On signature verification, variable on signature type and plaintext | ||
length. | ||
- On hashing, fixed price. | ||
- On computing the CID of an unsealed sector, variable on proof type and | ||
piece characteristics. | ||
- On verifying a seal, variable on the seal characteristics. | ||
- On verifying a window PoSt, variable on the PoSt characteristics. | ||
- On verifying a consensus fault. | ||
|
||
None of these gas charges accounts for the costs of the execution of the actor’s | ||
compute logic itself. This results in an incomplete resource accounting model. | ||
So far, the network has coped without it because: | ||
|
||
1. The cost of built-in actor logic is negligible when compared to the cost of | ||
the above operations, most of which are triggered through syscalls. | ||
2. Only pre-determined, trusted logic runs on chain in the form of built-in | ||
actors. | ||
3. Technical limitations. Prior to the FVM (FIP-0030, FIP-0031), there was no | ||
portable actor bytecode whose execution could be metered identically across | ||
all implementations. | ||
|
||
With the ability to deploy user-defined actors on the FVM, these assumptions no | ||
longer stand and it becomes important to start tracking real execution costs | ||
with the highest fidelity possible, to preserve security guarantees, and to | ||
compensate the network for the logic it executes. | ||
|
||
## Specification | ||
|
||
Here’s an overview of proposed changes to the existing gas model. We explain | ||
each one in detail in the following sections. | ||
|
||
- Introduce Wasm bytecode-metered execution gas. | ||
- Adjust the *actor call* fee, to account for new call dispatch overhead. | ||
- Rearchitect the IPLD state IO fees. | ||
|
||
### Wasm bytecode-metered execution gas | ||
|
||
We introduce a new category of gas. Execution gas is charged per Wasm | ||
instruction. Every Wasm instruction has a predefined amount of execution units | ||
associated with it. | ||
|
||
Every Wasm instruction expends a flat 1 execution unit, except the following | ||
structural Wasm instructions: `nop`, `drop`, `block`, `loop`, `unreachable`, | ||
`return`, `else` and `end` . These instructions expend 0 execution units | ||
because either they do not translate into machine instructions by themselves, or | ||
they are control flow instructions with no logic to evaluate. | ||
|
||
**Pricing formula** | ||
|
||
The conversion of Wasm execution units to Filecoin gas units is at a predefined | ||
ratio of `<<TODO: currently benchmarking>>`. This equivalence has been | ||
calculated by performing extensive benchmarks, with the goal of honouring the | ||
invariant baseline target of 10 gas units/ns of wall clock time[^1]. | ||
|
||
Both the pricing policy for Wasm instructions and the conversion rate need to be | ||
assessed and revised continuously as technology improves (e.g. Wasm compilers | ||
and processors). The ongoing goal is to sustain high execution fidelity. | ||
|
||
### Call gas fee | ||
|
||
In Filecoin network version 15 and earlier, the call gas fee is higher for value | ||
transfers than it is for actor code invocations. This may sound | ||
counterintuitive, but it follows the fact that the call fee has to cover the | ||
full validation and state update cost of the transaction, because these | ||
transactions don’t invoke actor code. Conversely, the call fee for an actor | ||
invocation represents only the dispatch effort, hence why it’s lower. | ||
|
||
With FVM actors, the call cost structure changes. For actor code invocations, a | ||
Wasm-based invocation container needs to be instantiated, and parameters need to | ||
be serialized and inserted into the IPLD blockstore. In other words, there is | ||
more work to do that than previously, and therefore the fee is adjusted upward. | ||
|
||
**Pricing formula** | ||
|
||
``` | ||
TODO: benchmarking | ||
``` | ||
|
||
### IPLD state management fees | ||
|
||
Currently, IPLD block read incur a fixed fee, and IPLD block writes incur a | ||
variable fee, dependent on the number of bytes written. | ||
|
||
With the FVM, IPLD state I/O is managed through five syscalls, with the | ||
specified overhead and pricing: | ||
|
||
- `block_open`: looks up the supplied CID, loads the block from the state | ||
blockstore into the FVM kernel’s block cache, reports its size and codec. It | ||
returns a numeric block handle. | ||
- Overhead: This syscall traverses the FVM<>client boundary via an extern in | ||
order to query the state blockstore. This leads to disk IO with associated | ||
read amplification. The bytes returned through the extern are copied into | ||
the FVM’s memory so that the buffer can be reclaimed by the client side; | ||
thus there is an alloc and memcpy cost. The bytes are retained in memory | ||
until the actor call finishes and the invocation container is dropped, and | ||
thus the actor is charged for this memory usage. | ||
- Cost: `<<TODO: benchmarking>>`. | ||
- `block_read`: takes a block handle and an output buffer, and copies the | ||
block’s data from the FVM kernel’s block cache into the actor’s memory. | ||
- Overhead: This syscall resolves inside the FVM and doesn’t traverse the | ||
FVM<>node boundary. The overhead is that of a memcpy operation. | ||
- Cost: `<<TODO: benchmarking>>`. | ||
- `block_write`: takes some block data and a codec, and merely copies it to the | ||
FVM kernel’s block cache. It returns a numeric block handle. | ||
- Overhead: This syscall resolves inside the FVM and doesn’t traverse the | ||
FVM<>node boundary. It involves a memcpy to a buffer that is retained | ||
until the actor call finishes. The bytes are retained in memory until the | ||
actor call finishes and the invocation container is dropped, and thus the | ||
actor is charged for this memory usage. | ||
- Cost: `<<TODO: benchmarking>>`. | ||
- `block_link`: computes the CID of a block, and commits the block to the state | ||
blockstore. | ||
- Overhead: This syscall traverses the FVM<>client boundary via an extern in | ||
order to write to the state blockstore (although this is deferred until | ||
the machine flush). This leads to disk IO with associated write | ||
amplification. The bytes are copied over to the client’s memory, thus | ||
there is an alloc and memcpy cost. Computing the CID involves a hashing | ||
operation (akin to the hash syscall, but without the syscall overhead). | ||
Because the CID is returned to the actor via an output buffer, there is | ||
another memcpy involved. | ||
- Cost: `<<TODO: benchmarking>>`. | ||
- `block_stat`: returns the length and the codec of a block. | ||
- Overhead: This syscall resolves inside the FVM and doesn’t traverse the | ||
FVM<>node boundary. It performs a map lookup and returns an integer tuple. | ||
- Cost: `<<TODO: benchmarking>>`. | ||
|
||
## Design Rationale | ||
|
||
To simplify community discussion and align with the FVM deployment roadmap, all | ||
changes related to new system features related to user-programmable actors are | ||
kept out of scope of this FIP. This set of changes covers only the technological | ||
transition to a Wasm runtime for built-in actors. This FIP will be followed by | ||
another FIP introducing the former. | ||
|
||
Concerning the design of each individual change, the specification section | ||
elaborates on overhead that is being accounted for and the variables that make | ||
up every pricing formula. | ||
|
||
## Backwards Compatibility | ||
|
||
The data model by which gas allowance and usage is represented in external | ||
interfaces (gas limit, gas used, etc.) remains unchanged. However, the same | ||
transaction made before and after this FIP will, with very high likelihood, | ||
result in different values for *gas used*. Transactions sitting in the mempool | ||
at the activation epoch of this FIP will need to be re-estimated and replaced. | ||
|
||
## Test Cases | ||
|
||
Testing for this FIP involves two efforts: | ||
|
||
1. An updated corpus of FVM-compatible [test | ||
vectors](https://github.com/filecoin-project/fvm-test-vectors) with the new | ||
gas model. | ||
2. The testnet plan laid out in FIP-0031. | ||
|
||
## Security Considerations | ||
|
||
TODO draft. | ||
|
||
## Incentive Considerations | ||
|
||
With the introduction of execution gas to account for real execution cost, actor | ||
compute logic will no longer be exempted from gas charges, thus resulting in a | ||
net increase in gas expenditure in the network. | ||
|
||
## Product Considerations | ||
|
||
The cost every actor method changes upwards as a result of this FIP. | ||
Furthermore, by charging for actor logic itself, methods that are more | ||
computationally intensive may have their price structure changed significantly. | ||
These two implications may transpire as changes in onboarding, power maintenance, | ||
deal-making, and other features that are noteworthy from a product perspective. | ||
|
||
`<<TODO: More data will be added to this section once benchmarking has been | ||
completed>>.` | ||
|
||
## Implementation | ||
|
||
For clients relying on the reference FVM implementation | ||
([filecoin-project/ref-fvm](https://github.com/filecoin-project/ref-fvm)), the | ||
implementation of this FIP will be transparent, as it is self-contained inside | ||
the FVM. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via | ||
[CC0](https://creativecommons.org/publicdomain/zero/1.0/). | ||
|
||
## Footnotes | ||
|
||
[^1]: The baseline target itself determined by the need to sustain a 30 second | ||
epoch frequency, with a 6 second block propagation time, under these | ||
circumstances, which represent the absolute worst possible scenario: | ||
- Block gas limit of 15B gas units. | ||
- Attaining the maximum winrate at an epoch (11). | ||
- No duplicated messages across blocks in a tipset. | ||
- 100% saturation of every block with compute. | ||
|
||
The choice of 10 gas units/ns as a baseline implies a block validation time | ||
of 1.5s and a fully saturated tipset validation time of 16.5s (given that | ||
message and block execution cannot be parallelized). |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Is your plan that the pricing formulae be constructed so that the existing syscall charges remain fixed, and the other items have proportional values so as to maintain constant relative cost per call? Otherwise, it may be necessary to reprice all the existing syscalls.
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.
This FIP plans to keep the current syscall prices unchanged for simplicity. As stated in the Change Motivation section, execution gas is additive to the current syscall prices because the current system does not charge for the cost of actor logic because it doesn't have a way to do so. In a future FIP (likely #317), we can adjust the syscall price parameters. But the overarching goal is always execution cost fidelity (i.e. what each syscall actually costs), not the maintenance of legacy prices.