forked from CosmWasm/cosmwasm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request CosmWasm#2225 from CosmWasm/webmaster128-patch-1
Redirect from GAS.md and PINNING.md to docs
- Loading branch information
Showing
2 changed files
with
4 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,96 +1,4 @@ | ||
# 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 | ||
|
||
[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 | ||
|
||
## 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](https://www.json.org/) 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> Python3: `(2**64-1) / 10**12` | ||
|
||
<sup>2</sup> Python3: `((2**64-1)/30) / 10**12` | ||
|
||
## CosmWasm 1.x -> 2.0 changes | ||
|
||
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 | | ||
|
||
[#1599]: https://github.com/CosmWasm/cosmwasm/pull/1599 | ||
This page is now maintained in the main CosmWasm docs: | ||
<https://docs.cosmwasm.com/core/architecture/gas> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,4 @@ | ||
# Contract pinning | ||
|
||
Contract pinning is a feature of the CosmWasm virtual machine which ensures that | ||
a previously stored compiled contract code (module) is started from a dedicated | ||
in-memory cache. Starting a module from memory takes ~45µs compared to 1.5ms | ||
when loaded from disk (33x faster). | ||
|
||
In contrast to the node-specific Least recently used (LRU) memory cache, pinning | ||
**guarantees** this performance boost across the network. As a consequence wasmd | ||
can charge discounted gas cost[^1]. | ||
|
||
## The caches | ||
|
||
CosmWasm has 3 different caches for modules: | ||
|
||
1. `FileSystemCache` the `.module` files stored in the cache directory of the | ||
node | ||
2. `InMemoryCache` the LRU cache | ||
3. `PinnedMemoryCache` a separate cache | ||
|
||
Both memory caches (2./3.) work the same in terms of performance but their | ||
elements are tracked separately. A pinned contract is never added to the | ||
standard `InMemoryCache` and the size of pinned contracts is not counted towards | ||
its cache size limit. | ||
|
||
## Pinning and Unpinning | ||
|
||
In order to add a contract to the `PinnedMemoryCache`, you need to call | ||
[`Cache::pin`] in Rust or `func (vm *VM) Pin(checksum Checksum) error` in | ||
wasmvm. To remove a contract from the cache use [`Cache::unpin`] / | ||
`func (vm *VM) Unpin(checksum Checksum) error`. In both cases a contract is | ||
identified by its checksum (sha256 hash of the Wasm blob). | ||
|
||
The VM does not persist pinned memory entries. I.e. you need to call `Pin` every | ||
time you start the process. This is implemented in [`InitializePinnedCodes` in | ||
wasmd][initializepinnedcodes]. | ||
|
||
At the chain level pinning and unpinning are done via governance proposals. See | ||
`MsgPinCodes`/`MsgUnpinCodes` in wasmd. | ||
|
||
When contracts are migrated from one code to another, there is no automatic | ||
pinning or unpinning. This is primarily since the migration of a single instance | ||
does not mean all instances of the same code become unused. In the future we | ||
want to provide hit stats for each checksum in order to easily find unused codes | ||
in the pinned memory cache[^2]. | ||
|
||
## Best practices | ||
|
||
Pinning contracts is a balance between increasing memory usage and boosting | ||
execution speed. Contracts that are known to be heavily used should be pinned. | ||
This can include contracts that are executed as part of begin/end block or the | ||
IBC light client implementations of the Wasm Light Client ([08-wasm]). If a | ||
chain is permissioned and runs on a small number of well known contracts, they | ||
can all be pinned. A permissionless chain might select certain contracts of | ||
strategic importance and pin them. | ||
|
||
The estimated size of the pinned contracts is visible in the [Metrics] struct | ||
you can access through [Prometheus](https://prometheus.io/). | ||
|
||
## History | ||
|
||
Pinning was developed in 2021 (CosmWasm 0.14) for the Proof of Engagement | ||
consensus system of Tgrade which required certain contracts to be executed in | ||
every block. | ||
|
||
[metrics]: | ||
https://github.com/CosmWasm/wasmvm/blob/v2.0.0-rc.2/types/types.go#L174-L185 | ||
[`cache::pin`]: | ||
https://docs.rs/cosmwasm-vm/latest/cosmwasm_vm/struct.Cache.html#method.pin | ||
[`cache::unpin`]: | ||
https://docs.rs/cosmwasm-vm/latest/cosmwasm_vm/struct.Cache.html#method.unpin | ||
[08-wasm]: | ||
https://github.com/cosmos/ibc-go/tree/main/modules/light-clients/08-wasm | ||
[initializepinnedcodes]: | ||
https://github.com/CosmWasm/wasmd/blob/v0.50.0/x/wasm/keeper/keeper.go#L1011-L1028 | ||
|
||
[^1]: https://github.com/CosmWasm/wasmd/pull/1799 | ||
|
||
[^2]: https://github.com/CosmWasm/cosmwasm/issues/2034 | ||
This page is now maintained in the main CosmWasm docs: | ||
<https://docs.cosmwasm.com/core/architecture/pinning> |