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 1 commit
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
260 changes: 260 additions & 0 deletions FIPS/fip-0032.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
---
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/issues/204
raulk marked this conversation as resolved.
Show resolved Hide resolved
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

No product considerations apply.
Copy link
Member

Choose a reason for hiding this comment

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

The relative costs of various actor methods are going to change, which is product-relevant whenever the base fee is non-trivial. Once you have the data, we should spell those out here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, I'm not sure I follow your comment about the base fee being non-trivial. There is nothing changing here about how the base fee itself is calculated, which basically depends on total gas used in tipsets AFAIR.

Copy link
Member

@anorth anorth Mar 10, 2022

Choose a reason for hiding this comment

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

There are two bits here:

  1. People will only care about relative gas changes when the base fee is not ~zero, because otherwise everything costs $0.
  2. This proposal will increase total gas usage, which runs a good chance of increasing base fee if we don't also increase the block gas limit (but we probably want to do the opposite to give ourselves buffer in validation times if we don't get the gas costs right first go)

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed with Anoth here, this has a possibility of significantly affecting the ratios of GasUsed of different operations.
We also have the gas balancer in place for the aggregated prove commits, if gas changes significantly it will need to be changed as well.

Copy link
Contributor

@zixuanzh zixuanzh Mar 12, 2022

Choose a reason for hiding this comment

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

Generally agreed but the principle for calculating GasUsed is based on the resources consumed by the messages/operations. As long as we are applying the same principle it should probably be fine. I think the product consideration can be on a different layer. Product teams should work on building experiences that people will be willing to pay for.


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