|
| 1 | +# Contract pinning |
| 2 | + |
| 3 | +Contract pinning is a feature of the CosmWasm virtual machine which ensures that |
| 4 | +a previously stored compiled contract code (module) is started from a dedicated |
| 5 | +in-memory cache. Starting a module from memory takes ~45µs compared to 1.5ms |
| 6 | +when loaded from disk (33x faster). |
| 7 | + |
| 8 | +In contast to the node specific Least recently used (LRU) memory cache, pinning |
| 9 | +**guarantees** this performance boost across the network. As a consequence wasmd |
| 10 | +can charge discounted gas cost[^1]. |
| 11 | + |
| 12 | +## The caches |
| 13 | + |
| 14 | +CosmWasm has 3 different caches for modules: |
| 15 | + |
| 16 | +1. `FileSystemCache` the `.module` files stored in the cache directory of the |
| 17 | + node |
| 18 | +2. `InMemoryCache` the LRU cache |
| 19 | +3. `PinnedMemoryCache` a separate cache |
| 20 | + |
| 21 | +Both memory caches (2./3.) work the same in terms of performance but their |
| 22 | +elements are tracked separately. A pinned contract is never added to the |
| 23 | +standard `InMemoryCache` and the size of pinned contracts is not counted towards |
| 24 | +its cache size limit. |
| 25 | + |
| 26 | +## Pinning and Unpinning |
| 27 | + |
| 28 | +In order to add a contract to the `PinnedMemoryCache`, you need to call |
| 29 | +[`Cache::pin`] in Rust or `func (vm *VM) Pin(checksum Checksum) error` in |
| 30 | +wasmvm. To remove a contract from the cache use [`Cache::unpin`] / |
| 31 | +`func (vm *VM) Unpin(checksum Checksum) error`. In both cases a contract is |
| 32 | +identified by its checksum (sha256 hash of the Wasm blob). |
| 33 | + |
| 34 | +The VM does not persist pinned memory entries. I.e. you need to call `Pin` every |
| 35 | +time you start the process. This is implemented in [`InitializePinnedCodes` in |
| 36 | +wasmd][initializepinnedcodes]. |
| 37 | + |
| 38 | +At the chain level pinning and unpinning is done via governance proposals. See |
| 39 | +`MsgPinCodes`/`MsgUnpinCodes` in wasmd. |
| 40 | + |
| 41 | +When contracts are migrated from one code to another, there is no automatic |
| 42 | +pinning or unpinning. This is primarily since the migration of a single instance |
| 43 | +does not means all instances of the same code become unused. In the future we |
| 44 | +want to provide hit stats for each checksum in order to easily find unused codes |
| 45 | +in the pinned memory cache[^2]. |
| 46 | + |
| 47 | +## Best practices |
| 48 | + |
| 49 | +Pinning contracts is a balance between increasing memory usage and boosting |
| 50 | +execution speed. Contracts that are known to be heavily used should be pinned. |
| 51 | +This can includes contracts that are executed as part of begin/end block or the |
| 52 | +IBC light client implementations of the Wasm Light Client ([08-wasm]). If a |
| 53 | +chain is permissioned and runs on a small number of well known contracts, they |
| 54 | +can all be pinned. A permissionless chain might select certain contracts of |
| 55 | +strategic importance and pin them. |
| 56 | + |
| 57 | +The estimated size of the pinned contracts is visible in the [Metrics] struct |
| 58 | +you can access through [Prometheus](https://prometheus.io/). |
| 59 | + |
| 60 | +## History |
| 61 | + |
| 62 | +Pinning was developed in 2021 (CosmWasm 0.14) for the Proof of Engagement |
| 63 | +consensus system of Tgrade which required certain contracts to be executed in |
| 64 | +every block. |
| 65 | + |
| 66 | +[metrics]: |
| 67 | + https://github.com/CosmWasm/wasmvm/blob/v2.0.0-rc.2/types/types.go#L174-L185 |
| 68 | +[`cache::pin`]: |
| 69 | + https://docs.rs/cosmwasm-vm/latest/cosmwasm_vm/struct.Cache.html#method.pin |
| 70 | +[`cache::unpin`]: |
| 71 | + https://docs.rs/cosmwasm-vm/latest/cosmwasm_vm/struct.Cache.html#method.unpin |
| 72 | +[08-wasm]: |
| 73 | + https://github.com/cosmos/ibc-go/tree/main/modules/light-clients/08-wasm |
| 74 | +[initializepinnedcodes]: |
| 75 | + https://github.com/CosmWasm/wasmd/blob/v0.50.0/x/wasm/keeper/keeper.go#L1011-L1028 |
| 76 | + |
| 77 | +[^1]: https://github.com/CosmWasm/wasmd/pull/1799 |
| 78 | +[^2]: https://github.com/CosmWasm/cosmwasm/issues/2034 |
0 commit comments