Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Gas

Some thoughts on how we define gas cost in Grug.

The Wasmer runtime provides a Metering middleware that measures how many "points" a Wasm function call consumes.

The question is how to associate Wasmer points to the chain's gas units.

CosmWasm's approach

As documented here, CosmWasm's approach is as follows:

  1. Perform a benchmark to measure how many "points" Wasmer can execute per second. Then, set a target amount of gas per second (they use 10^12 gas per second). Between these two numbers, CosmWasm decides that 1 Wasmer point is to equal 170 gas units.

  2. Perform another benchmark to measure how much time it takes for the host to execute each host function (e.g. addr_validate or secp256k1_verify). Based on this, assign a proper gas cost for each host function.

  3. Divide CosmWasm gas by a constant factor of 100 to arrive at Cosmos SDK gas.

Our approach

For us, defining gas cost is easier, because we don't have a Cosmos SDK to deal with.

  1. We skip step 1, and simply set 1 Wasmer point = 1 Grug gas unit.

  2. We perform the same benchmarks to set proper gas costs for host functions.

  3. We skip this step as well.

In summary,

  • 1 Cosmos SDK gas = 100 CosmWasm gas
  • 1 Wasmer point = 170 CosmWasm gas
  • 1 Wasmer point = 1 Grug gas

Benchmark results

Benchmarks were performed on a MacBook Pro with the M2 Pro CPU.

Relevant code can be found in crates/vm/wasm/benches and crates/crypto/benches.

Wasmer points per second

This corresponds to the step 1 above. This benchmark is irrelevant for our decision making (as we simply set 1 Wasmer point = 1 Grug gas unit), but we still perform it for good measure.

IterationsPointsTime (ms)
200,000159,807,11915.661
400,000319,607,11931.663
600,000479,407,11947.542
800,000639,207,11962.783
1,000,000799,007,15478.803

Extrapolating to 1 second, we arrive at that WasmVm executes 10,026,065,176 points per second. Let's round this to 10^10 points per second, for simplicity.

If we were to target 10^12 gas units per second as CosmWasm does (we don't), this would mean 10^12 / 10^10 = 100 gas units per Wasmer point.

This is roughly in the same ballpark as CosmWasm's result (170 gas units per Wasmer point). The results are of course not directly comparable because they were done using different CPUs, but the numbers being within one degree of magnitude suggests the two VMs are similar in performance.

As said before, we set 1 Wasmer point = 1 gas unit, so we're doing 10^10 gas per second.

Single signature verification

Time for verifying one signature:

VerifierTime (ms)Gas Per Verify
secp256r1_verify0.1881,880,000
secp256k1_verify0.077770,000
secp256k1_pubkey_recover0.1581,580,000
ed25519_verify0.041410,000

We have established that 1 second corresponds to 10^10 gas units. Therefore, secp256k1_verify costing 0.188 millisecond means it should cost = 770,000 gas.

This is comparable to CosmWasm's value.

Batch signature verification

ed25519_batch_verify time for various batch sizes:

Batch SizeTime (ms)
250.552
501.084
751.570
1002.096
1252.493
1502.898

Linear regression shows there's a flat cost 0.134 ms (1,340,000 gas) plus 0.0188 ms (188,000 gas) per item.

Hashes

Time (ms) for the host to perform hashes on inputs of various sizes:

Hasher200 kB400 kB600 kB800 kB1,000 kBGas Per Byte
sha2_2560.5441.0861.6272.2012.71827
sha2_5120.3300.6780.9961.3291.70116
sha3_2560.2980.6060.9181.2201.54315
sha3_5120.6141.1291.7192.3282.89228
keccak2560.3120.6050.9041.2221.53415
blake2s_2560.3050.6320.9071.2121.52615
blake2b_5120.1800.3640.5520.7190.9179
blake30.1050.2210.3210.4110.5125