Skip to content

Commit

Permalink
Merge pull request #106 from CosmWasm/aw/move-gas-page
Browse files Browse the repository at this point in the history
Move GAS.md from CosmWasm repo to here
  • Loading branch information
aumetra authored Jul 23, 2024
2 parents 308938a + d3997fc commit beaf72e
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/pages/core/architecture/_meta.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"actor-model": "Actor Model",
"events": "Events",
"gas": "Gas",
"pinning": "Pinning",
"transactions": "Transactions"
}
104 changes: 104 additions & 0 deletions src/pages/core/architecture/gas.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
tags: ["core", "architecture"]
---

# Gas

Gas is a way to measure computational expense of a smart contract execution,
including CPU time and storage cost. Its unit is 1, i.e. you can think of it as
countable points. Gas consumption is deterministic, so executing the same thing
costs the same amount of gas across all hardware and operating systems.

## CosmWasm gas vs. Cosmos SDK gas

CosmWasm charges gas for Wasm operations, calls to host functions and calls to
the Cosmos SDK. _CosmWasm gas_ is different from _Cosmos SDK gas_ as the numbers
here are much larger. Since we charge gas for arbitrary user defined operations,
we need to charge each Wasm operation individually and cannot group larger tasks
together. As a result, the gas values become much larger than in Cosmos SDK even
for very fast executions. There is a [multiplier][defaultgasmultiplier] to
translate between CosmWasm gas and Cosmos SDK. It was measured and set to 100 a
while ago and can be adjusted when necessary.

## CosmWasm gas pricing

For CosmWasm gas, the target gas consumption is 1 Teragas (10^12 gas) per
second. This idea is [inspired by NEAR][neargas] and we encourage you to read
their excellent docs on that topic.

In order to meet this target, we execute Argon2 in a test contract ([#1120]).
This is a CPU and memory intense job that does not call out into the host. At a
constant gas cost per operation of 1 (pre CosmWasm 1.0), this consumed 96837752
gas and took 15ms on our CI system. The ideal cost per operation for this system
is `10^12 / (96837752 / (15 / 1000))`: 154. This is rounded to 150 for
simplicity.

CosmWasm 2.1 update: All gas values were re-evaluated and adjusted to meet the 1
Teragas/second target mentioned above. A rerun of the Argon2 test contract
consumed 5270718300 gas with the previous cost of 150, so the operation count
was `5270718300 / 150 = 35138122`. This took 6ms on our benchmark server, so the
new cost per operation is `10^12 / (35138122 / (6 / 1000))`: 171. This is
rounded to 170 for simplicity.

Benchmarking system:

- CPU: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (4 cores, 8 threads)
- RAM: 32GB DDR4 2133 MHz

Each machine is different, we know that. But the above target helps us in
multiple ways:

1. Develop an intuition what it means to burn X gas or how much gas can be used
if a block should be executable in e.g. 1 second
2. Have a target for adjustments, e.g. when the Wasm runtime becomes faster or
slower
3. Allow pricing of calls that are not executed in Wasm, such as crypto APIs
4. Find significant over or underpricing

## Gas overflow potential

CosmWasm gas aims for 1 Teragas/second, i.e. the uint64 range exceeds after 18
million seconds (5000 hours)<sup>1</sup>. Assuming a max supported block
execution time of 30 seconds, the gas price has to be over-priced by a factor of
614891 (614891 Teragas/second) in order to exceed the uint64 range<sup>2</sup>.
Since serious over or underpricing is considered a bug, using uint64 for gas
measurements is considered safe.

Cosmos SDK gas uses values that are smaller by a factor of 150, so those don't
overflow as well. Since no Cosmos SDK gas values are processed inside of this
repository, this is not our main concern. However, it's good to know that we can
safely pass them in uint64 fields, as long as the full range is supported. This
is the case for the C API as well as [JSON numbers] as long as both sides
support integers in their JSON implementation. Go and Rust do that while many
other implementations don't support integers, and convert them to IEEE-754
doubles, which has a safe integer range up to about 53 bit (e.g. JavaScript and
jq).

<sup>1</sup> `(2^64-1) / 10^12`

<sup>2</sup> `((2^64-1)/30) / 10^12`

<details>

<summary>CosmWasm 1.x -> 2.0 changes</summary>

In all versions before 2.0, the gas values were bigger by a factor of 1000.
There is no need to have them this big and in order to reduce the risk of
overflow, the gas values were lowered in [#1599]. Here is a breakdown of what
this change entails:

| | CosmWasm 1.x | CosmWasm 2.x |
| -------------------------- | --------------------- | --------------------- |
| Cost target | 1 Teragas/millisecond | 1 Teragas/second |
| Exceeds uint64 range after | 5 hours | 5124 hours (213 days) |
| Cost per Wasm op | 150_000 | 150 |
| Multiplier | 140_000_000 | 140_000 |

</details>

[#1599]: https://github.com/CosmWasm/cosmwasm/pull/1599
[JSON numbers]: https://www.json.org/
[defaultgasmultiplier]:
https://github.com/CosmWasm/wasmd/blob/v0.19.0/x/wasm/keeper/gas_register.go#L18
[neargas]: https://docs.near.org/docs/concepts/gas
[#1120]: https://github.com/CosmWasm/cosmwasm/pull/1120
5 changes: 2 additions & 3 deletions src/pages/core/standard-library/cryptography.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ documentation about them.
<Callout>
Note that these values are in CosmWasm Gas (which is not equivalent to Cosmos
SDK Gas; rather, CosmWasm Gas is eventually converted to Cosmos SDK Gas). For
more info on gas, [check this document].
more info on gas, [check this page].
</Callout>

### secp256k1
Expand Down Expand Up @@ -80,7 +80,6 @@ Keep in mind that, thanks to Wasm being our execution environment, contract
execution is quite fast. In most cases the perceived need to move hashing into a
host function is premature optimization and not actually needed.

[check this document]:
https://github.com/CosmWasm/cosmwasm/blob/main/docs/GAS.md
[check this page]: ../architecture/gas
[source code]:
https://github.com/CosmWasm/cosmwasm/blob/main/packages/vm/src/environment.rs#L62-L101

0 comments on commit beaf72e

Please sign in to comment.