Skip to content
This repository has been archived by the owner on Dec 26, 2023. It is now read-only.

SVM Gas-Metering #82

Closed
YaronWittenstein opened this issue Dec 28, 2021 · 2 comments
Closed

SVM Gas-Metering #82

YaronWittenstein opened this issue Dec 28, 2021 · 2 comments
Assignees
Labels
svm SMIPs related to SVM

Comments

@YaronWittenstein
Copy link

YaronWittenstein commented Dec 28, 2021

Gas Metering

Overview

This document describes what should be done to support Gas-Metering as a pricing mechanism for running Transactions.
Since the Templates released in the 1st Mainnet will be compliant with the Fixed-Gas, everything described under this piece will be relevant only for future versions.

Goals and Motivation

The motivation for the Fixed-Gas Wasm pricing was that Templates that abide by specific rules would result in more precise pricing for their transactions.

In short, it boils down to whether a Template contains potential infinite loops. If we have code that contains no loops, call-cycles, recursions, and dynamic-dispatch on runtime. We can apply static-analysis techniques and compute the gas price for running a piece of code ahead of time.

Since many Templates fall into that category, we can optimize their pricing.
So the decision was that we'd make sure that the Templates for Genesis would respect these rules.

However, some Templates require more flexibility. In such cases, we'll have to introduce another pricing mechanism.
This SMIP details how to add the Gas Metering into SVM - the Gas Metering is the most commonly used solution today for pricing running code.

The downside is that we can't precisely predict how much Gas would suffice for running a Transaction without hitting Out of Gas (see the Halting Problem).
Current solutions usually simulate a run, and then they add some extra for the Gas Limit set into the Transaction.

Another standard handling is looking at historical Transactions and making a sophisticated guess. Most of the time, it'd work fine. Every now and then, the guess won't work, and the Transaction will reach Out of Gas and fail to complete.

High-level design

Instructions Injection

To implement Gas Metering on a Wasm program (i.e., the Template's code), we need to inject new opcodes into the program. The most naive solution would be to inject a host function call (such as inc_gas) after each instruction. However, that would result in a much slower running time.

The solution should probably update the used Gas once every couple of Wasm instructions.
For example, each new scope should start a new measurement and end the previous one.

Here is an example:

Given this Wasm program sketch:

(block
  op1
  op2
  op3 

  (loop (result i32)
    op4
    op5
    op6
  )

  (if (result i32) 
    (then
      op7
      op8
    )
    (else
      op9
      op10
    )

   op11
   op12
)

After injecting the inc_gas calls (inc_gas is the name of the host function that tracks the gas usage),
the newly transformed code will reflect the changes:

(block
  op1
  op2
  op3 
  i32.const op_price(op1) + op_price(op2) + op_price(op3)
  call inc_gas

  (loop (result i32)
    op4
    op5
    op6
    i32.const op_price(op4) + op_price(op5) + op_price(op6)
    call inc_gas
  )

  (if (result i32) 
    (then
      op7
      op8
      i32.const op_price(op7) + op_price(op8) 
      call inc_gas
    )
    (else
      op9
      op10
      i32.const op_price(op9) + op_price(op10)
      call inc_gas
    )

    op11
    op12
    i32.const op_price(op11) + op_price(op12)
    call inc_gas
)

important:

  • Each Wasm Instruction should have a constant price (that holds to the Fixed-Gas Wasm pricing method as well).
  • The transformation used and the opcode pricing will become part of the consensus.
  • The original Template might be modified differently under different layers having different consensus rules.
    That's why it's crucial to store the original Template intact under the Global State.
  • Caching of compiled Templates should take into account the consensus rules used for the Wasm transformation (i.e., by Layer Number)

Wasm Runtime-Agnostic

The critical thing is that the applied solution won't assume anything specific to the underlying Wasm Runtime used.

Today, SVM uses [Wasmer](https://github.com/wasmerio/wasmer) solely, but it could have also used [Wasmtime](https://github.com/bytecodealliance/wasmtime).
Furthermore, it's advised that SVM will support both in the future and that the used Wasm runtime will be configurable. That would strengthen the system as a whole.

It's good to know that Wasmer has a solution used by some of the Wasm-based Blockchain companies, it's called the Metering Middleware

https://github.com/wasmerio/wasmer/blob/a66226594f5035c6a4816ad338c257f2ce5c5c86/lib/middlewares/src/metering.rs

Due to the described above, it seems that SVM would be better to apply its transformation and not rely on this one.
We don't want the injected code having Globals named wasmer_metering_remaining_points or wasmer_metering_points_exhausted.
Of course, the inc_gas stated above could be an imported Global Variable instead of an imported host function.

In addition, Wasmer's middleware is part of the compilation process. So I'd recommend assuming the least about the Wasm runtime API and just having the transformation execute before compiling the Wasm module. One existing tool for transforming Wasm is [walrus](https://github.com/rustwasm/walrus), and maybe there're other similar Rust libraries.

Hybrid Mode

Once the Gas Metering mechanism is implemented, we could introduce a new one I'm calling Hybrid Gas Pricing.
Given a Template with Fixed-Gas Wasm code, we can set the Gas Limit of the Transaction to the value provided by the Fixed-Gas Pricing.

That value accounts for the most expensive running path the Transaction could end up having.
Having the Hybrid mode used will apply Gas Metering and pay for what's been used.
Since we've set the Gas Limit to the worst-case scenario - we can know for sure that the Transaction won't fail due to Out of Gas.

Questions/concerns

TBD

Stakeholders and reviewers

@neysofu
@avive
@moshababo
@lrettig
@noamnelke

@YaronWittenstein YaronWittenstein added the svm SMIPs related to SVM label Dec 28, 2021
@YaronWittenstein YaronWittenstein self-assigned this Dec 28, 2021
@YaronWittenstein YaronWittenstein changed the title SVM Gas Metering SVM Gas-Metering Dec 28, 2021
@neysofu
Copy link

neysofu commented Feb 16, 2022

Not closing this SMIP because it's not strictly outdated per se, but gas metering within the SVM is so far down the road that it doesn't currently make sense to talk about this.

@lrettig
Copy link
Member

lrettig commented May 29, 2023

Closing this now as we're not currently pursuing a Wasm-based VM. Can revisit in the future if we go this route.

@lrettig lrettig closed this as completed May 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
svm SMIPs related to SVM
Projects
None yet
Development

No branches or pull requests

3 participants