Skip to content

Commit 0dc7790

Browse files
committed
Added pinning chapter.
1 parent 136601a commit 0dc7790

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export default withMermaid({
5050
{text: 'Actor model', link: '/guide/cosmwasm-core/architecture/actor-model'},
5151
{text: 'Events', link: '/guide/cosmwasm-core/architecture/events'},
5252
{text: 'Gas', link: '/guide/cosmwasm-core/architecture/gas'},
53+
{text: 'Pinning', link: '/guide/cosmwasm-core/architecture/pinning'},
5354
{text: 'Transactions', link: '/guide/cosmwasm-core/architecture/transactions'},
5455
]
5556
},
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
[neutron-case-study]: https://medium.com/confio/neutron-case-study-optimizing-gas-usage-with-contract-pinning-5970a109c706
2+
[`cache::pin`]: https://docs.rs/cosmwasm-vm/latest/cosmwasm_vm/struct.Cache.html#method.pin
3+
[`InitializePinnedCodes`]: https://github.com/CosmWasm/wasmd/blob/v0.50.0/x/wasm/keeper/keeper.go#L1011-L1028
4+
[discounted gas cost]: https://github.com/CosmWasm/wasmd/pull/1799
5+
[pinned memory cache]: https://github.com/CosmWasm/cosmwasm/issues/2034
6+
[Prometheus]: https://prometheus.io/
7+
[metrics]: https://github.com/CosmWasm/wasmvm/blob/v2.0.0-rc.2/types/types.go#L174-L185
8+
[`cache::unpin`]: https://docs.rs/cosmwasm-vm/latest/cosmwasm_vm/struct.Cache.html#method.unpin
9+
[08-wasm]: https://github.com/cosmos/ibc-go/tree/main/modules/light-clients/08-wasm
10+
11+
<SectionLabel chapter="core" section="architecture"></SectionLabel>
12+
13+
# Contract pinning
14+
15+
Contract pinning is a feature of the CosmWasm virtual machine which ensures that a previously stored
16+
compiled contract code (module) is started from a dedicated in-memory cache. Starting a module from
17+
memory takes ~45 µs compared to 1.5 ms when loaded from disk (33x faster).
18+
19+
In contrast to the node-specific Least Recently Used (LRU) memory cache, pinning **guarantees** this
20+
performance boost across the network. As a consequence wasmd can charge [discounted gas cost].
21+
22+
::: tip :bulb: Tip
23+
24+
Pinning is an incredibly valuable tool for chains to optimize gas costs.
25+
According to a [case study][neutron-case-study] by one of our subscribers, Neutron, pinning improved
26+
the gas cost of their contracts somewhere between 15 and 50%!
27+
28+
:::
29+
30+
## The caches
31+
32+
CosmWasm has 3 different caches for modules:
33+
34+
1. `FileSystemCache` the `.module` files stored in the cache directory of the node.
35+
2. `InMemoryCache` the LRU cache.
36+
3. `PinnedMemoryCache` a separate cache.
37+
38+
Both memory caches (**2.** and **3.**) work the same in terms of performance but their elements
39+
are tracked separately. A pinned contract is never added to the standard `InMemoryCache`
40+
and the size of pinned contracts is not counted towards its cache size limit.
41+
42+
## Pinning and Unpinning
43+
44+
In order to add a contract to the `PinnedMemoryCache`, you need to call [`Cache::pin`] in Rust or
45+
`func (vm *VM) Pin(checksum Checksum) error` in wasmvm. To remove a contract from the cache use
46+
[`Cache::unpin`] / `func (vm *VM) Unpin(checksum Checksum) error`. In both cases a contract is
47+
identified by its checksum (sha256 hash of the Wasm blob).
48+
49+
The VM does not persist pinned memory entries. I.e. you need to call `Pin` every time you start the
50+
process. This is implemented in [`InitializePinnedCodes`] in wasmd.
51+
52+
At the chain level pinning and unpinning are done via governance proposals. See
53+
`MsgPinCodes`/`MsgUnpinCodes` in wasmd.
54+
55+
When contracts are migrated from one code to another, there is no automatic pinning or unpinning.
56+
This is primarily since the migration of a single instance does not mean all instances of the same
57+
code become unused. In the future we want to provide hit stats for each checksum in order to easily
58+
find unused codes in the [pinned memory cache].
59+
60+
## Best practices
61+
62+
Pinning contracts is a balance between increasing memory usage and boosting execution speed.
63+
Contracts that are known to be heavily used should be pinned. This can include contracts that are
64+
executed as part of begin/end block or the IBC light client implementations of the Wasm Light Client
65+
([08-wasm]). If a chain is permissioned and runs on a small number of well known contracts, they can
66+
all be pinned. A permissionless chain might select certain contracts of strategic importance and pin
67+
them.
68+
69+
The estimated size of the pinned contracts is visible in the [Metrics] struct you can access through
70+
[Prometheus]. In order to better estimate which contracts are worth pinning, CosmWasm also exports
71+
metrics per pinned contract.
72+
73+
These metrics are:
74+
75+
- The contract size.
76+
- The number of times it was loaded from cache.
77+
78+
That way you can better estimate which contracts are worth keeping pinned.
79+
80+
## History
81+
82+
Pinning was developed in 2021 (CosmWasm 0.14) for the Proof of Engagement consensus system
83+
of **Tgrade** which required certain contracts to be executed in every block.

0 commit comments

Comments
 (0)