Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call Pin during app inisitalization (backport #5161) #5254

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions docs/docs/03-light-clients/04-wasm/03-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ The sample code below shows the relevant integration points in `app.go` required
import (
...
"github.com/cosmos/cosmos-sdk/runtime"

cmtos "github.com/cometbft/cometbft/libs/os"

wasm "github.com/cosmos/ibc-go/modules/light-clients/08-wasm"
wasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper"
Expand Down Expand Up @@ -54,13 +56,14 @@ func NewSimApp(
...
wasmtypes.StoreKey,
)
// Instantiate 08-wasm's keeper
// This sample code uses a constructor function that
// accepts a pointer to an existing instance of Wasm VM.
// This is the recommended approach when the chain
// also uses `x/wasm`, and then the Wasm VM instance
// can be shared.
// See the section below for more information.

// Instantiate 08-wasm's keeper
// This sample code uses a constructor function that
// accepts a pointer to an existing instance of Wasm VM.
// This is the recommended approach when the chain
// also uses `x/wasm`, and then the Wasm VM instance
// can be shared.
// See the section below for more information.
app.WasmClientKeeper = wasmkeeper.NewKeeperWithVM(
appCodec,
runtime.NewKVStoreService(keys[wasmtypes.StoreKey]),
Expand Down Expand Up @@ -106,6 +109,17 @@ func NewSimApp(
}
}
...

if loadLatest {
...

ctx := app.BaseApp.NewUncachedContext(true, cmtproto.Header{})

// Initialize pinned codes in wasmvm as they are not persisted there
if err := wasmkeeper.InitializePinnedCodes(ctx); err != nil {
cmtos.Exit(fmt.Sprintf("failed initialize pinned codes %s", err))
}
}
}
```

Expand Down Expand Up @@ -245,4 +259,8 @@ Or alternatively the parameter can be updated via a governance proposal (see at

## Adding snapshot support

In order to use the `08-wasm` module chains are required to register the `WasmSnapshotter` extension in the snapshot manager. This snapshotter takes care of persisting the external state, in the form of contract code, of the Wasm VM instance to disk when the chain is snapshotted.
In order to use the `08-wasm` module chains are required to register the `WasmSnapshotter` extension in the snapshot manager. This snapshotter takes care of persisting the external state, in the form of contract code, of the Wasm VM instance to disk when the chain is snapshotted. [This code](https://github.com/cosmos/ibc-go/blob/2bd29c08fd1fe50b461fc33a25735aa792dc896e/modules/light-clients/08-wasm/testing/simapp/app.go#L768-L776) should be placed in `NewSimApp` function in `app.go`:

## Pin byte codes at start

Wasm byte codes should be pinned to the WasmVM cache on every application start, therefore [this code](https://github.com/cosmos/ibc-go/blob/0ed221f687ffce75984bc57402fd678e07aa6cc5/modules/light-clients/08-wasm/testing/simapp/app.go#L821-L826) should be placed in `NewSimApp` function in `app.go`.
15 changes: 15 additions & 0 deletions modules/light-clients/08-wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,18 @@ func (k Keeper) GetWasmClientState(ctx sdk.Context, clientID string) (*types.Cli

return wasmClientState, nil
}

// InitializePinnedCodes updates wasmvm to pin to cache all contracts marked as pinned
func InitializePinnedCodes(ctx sdk.Context) error {
checksums, err := types.GetAllChecksums(ctx)
if err != nil {
return err
}

for _, checksum := range checksums {
if err := ibcwasm.GetVM().Pin(checksum); err != nil {
return err
}
}
return nil
}
68 changes: 68 additions & 0 deletions modules/light-clients/08-wasm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,71 @@ func (suite *KeeperTestSuite) TestNewKeeper() {
})
}
}

func (suite *KeeperTestSuite) TestInitializedPinnedCodes() {
var capturedChecksums []wasmvm.Checksum

testCases := []struct {
name string
malleate func()
expError error
}{
{
"success",
func() {
suite.mockVM.PinFn = func(checksum wasmvm.Checksum) error {
capturedChecksums = append(capturedChecksums, checksum)
return nil
}
},
nil,
},
{
"failure: pin error",
func() {
suite.mockVM.PinFn = func(checksum wasmvm.Checksum) error {
return wasmtesting.ErrMockVM
}
},
wasmtesting.ErrMockVM,
},
}

for _, tc := range testCases {
tc := tc

suite.Run(tc.name, func() {
suite.SetupWasmWithMockVM()

ctx := suite.chainA.GetContext()
wasmClientKeeper := GetSimApp(suite.chainA).WasmClientKeeper

contracts := [][]byte{wasmtesting.Code, wasmtesting.CreateMockContract([]byte("gzipped-contract"))}
checksumIDs := make([]types.Checksum, len(contracts))
signer := authtypes.NewModuleAddress(govtypes.ModuleName).String()

// store contract on chain
for i, contract := range contracts {
msg := types.NewMsgStoreCode(signer, contract)

res, err := wasmClientKeeper.StoreCode(ctx, msg)
suite.Require().NoError(err)

checksumIDs[i] = res.Checksum
}

// malleate after storing contracts
tc.malleate()

err := keeper.InitializePinnedCodes(ctx)

expPass := tc.expError == nil
if expPass {
suite.Require().NoError(err)
suite.ElementsMatch(checksumIDs, capturedChecksums)
} else {
suite.Require().ErrorIs(err, tc.expError)
}
})
}
}
9 changes: 9 additions & 0 deletions modules/light-clients/08-wasm/testing/simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

abci "github.com/cometbft/cometbft/abci/types"
cmtos "github.com/cometbft/cometbft/libs/os"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"

"github.com/cosmos/ibc-go/modules/capability"
capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper"
Expand Down Expand Up @@ -815,6 +817,13 @@ func NewSimApp(
if err := app.LoadLatestVersion(); err != nil {
panic(fmt.Errorf("error loading last version: %w", err))
}

ctx := app.BaseApp.NewUncachedContext(true, cmtproto.Header{})

// Initialize pinned codes in wasmvm as they are not persisted there
if err := wasmkeeper.InitializePinnedCodes(ctx); err != nil {
cmtos.Exit(fmt.Sprintf("failed initialize pinned codes %s", err))
}
}

app.ScopedIBCKeeper = scopedIBCKeeper
Expand Down