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

FIP-0032: Gas model adjustment for non-programmable FVM #315

Merged
merged 3 commits into from
Mar 12, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
267 changes: 267 additions & 0 deletions FIPS/fip-0032.md
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.
Copy link
Member

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.

Copy link
Member Author

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.


## 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).