Some checks failed
CodeQL / Analyze (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
146 lines
4.6 KiB
Go
146 lines
4.6 KiB
Go
package keeper
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"io"
|
|
|
|
errorsmod "cosmossdk.io/errors"
|
|
snapshot "cosmossdk.io/store/snapshots/types"
|
|
storetypes "cosmossdk.io/store/types"
|
|
|
|
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
|
|
|
|
cmtproto "git.cw.tr/mukan-network/mukan-consensus/proto/tendermint/types"
|
|
|
|
"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/types"
|
|
)
|
|
|
|
var _ snapshot.ExtensionSnapshotter = &WasmSnapshotter{}
|
|
|
|
// SnapshotFormat defines the default snapshot extension encoding format.
|
|
// SnapshotFormat 1 is gzipped wasm byte code for each item payload. No protobuf envelope, no metadata.
|
|
const SnapshotFormat = 1
|
|
|
|
// WasmSnapshotter implements the snapshot.ExtensionSnapshotter interface and is used to
|
|
// import and export state maintained within the wasmvm cache.
|
|
// NOTE: The following ExtensionSnapshotter has been adapted from CosmWasm's x/wasm:
|
|
// https://github.com/CosmWasm/wasmd/blob/v0.43.0/x/wasm/keeper/snapshotter.go
|
|
type WasmSnapshotter struct {
|
|
cms storetypes.MultiStore
|
|
keeper *Keeper
|
|
}
|
|
|
|
// NewWasmSnapshotter creates and returns a new snapshot.ExtensionSnapshotter implementation for the 08-wasm module.
|
|
func NewWasmSnapshotter(cms storetypes.MultiStore, keeper *Keeper) snapshot.ExtensionSnapshotter {
|
|
return &WasmSnapshotter{
|
|
cms: cms,
|
|
keeper: keeper,
|
|
}
|
|
}
|
|
|
|
// SnapshotName implements the snapshot.ExtensionSnapshotter interface.
|
|
// A unique name should be provided such that the implementation can be identified by the manager.
|
|
func (*WasmSnapshotter) SnapshotName() string {
|
|
return types.ModuleName
|
|
}
|
|
|
|
// SnapshotFormat implements the snapshot.ExtensionSnapshotter interface.
|
|
// This is the default format used for encoding payloads when taking a snapshot.
|
|
func (*WasmSnapshotter) SnapshotFormat() uint32 {
|
|
return SnapshotFormat
|
|
}
|
|
|
|
// SupportedFormats implements the snapshot.ExtensionSnapshotter interface.
|
|
// This defines a list of supported formats the snapshotter extension can restore from.
|
|
func (*WasmSnapshotter) SupportedFormats() []uint32 {
|
|
return []uint32{SnapshotFormat}
|
|
}
|
|
|
|
// SnapshotExtension implements the snapshot.ExntensionSnapshotter interface.
|
|
// SnapshotExtension is used to write data payloads into the underlying protobuf stream from the 08-wasm module.
|
|
func (ws *WasmSnapshotter) SnapshotExtension(height uint64, payloadWriter snapshot.ExtensionPayloadWriter) error {
|
|
cacheMS, err := ws.cms.CacheMultiStoreWithVersion(int64(height))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ctx := sdk.NewContext(cacheMS, cmtproto.Header{}, false, nil)
|
|
|
|
checksums, err := ws.keeper.GetAllChecksums(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, checksum := range checksums {
|
|
wasmCode, err := ws.keeper.GetVM().GetCode(checksum)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
compressedWasm, err := types.GzipIt(wasmCode)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = payloadWriter(compressedWasm); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// RestoreExtension implements the snapshot.ExtensionSnapshotter interface.
|
|
// RestoreExtension is used to read data from an existing extension state snapshot into the 08-wasm module.
|
|
// The payload reader returns io.EOF when it has reached the end of the extension state snapshot.
|
|
func (ws *WasmSnapshotter) RestoreExtension(height uint64, format uint32, payloadReader snapshot.ExtensionPayloadReader) error {
|
|
if format == ws.SnapshotFormat() {
|
|
return ws.processAllItems(height, payloadReader, restoreV1)
|
|
}
|
|
|
|
return errorsmod.Wrapf(snapshot.ErrUnknownFormat, "expected %d, got %d", ws.SnapshotFormat(), format)
|
|
}
|
|
|
|
func restoreV1(ctx sdk.Context, k *Keeper, compressedCode []byte) error {
|
|
if !types.IsGzip(compressedCode) {
|
|
return errorsmod.Wrap(types.ErrInvalidData, "expected wasm code is not gzip format")
|
|
}
|
|
|
|
wasmCode, err := types.Uncompress(compressedCode, types.MaxWasmSize)
|
|
if err != nil {
|
|
return errorsmod.Wrap(err, "failed to uncompress wasm code")
|
|
}
|
|
|
|
checksum, err := k.GetVM().StoreCodeUnchecked(wasmCode)
|
|
if err != nil {
|
|
return errorsmod.Wrap(err, "failed to store wasm code")
|
|
}
|
|
|
|
if err := k.GetVM().Pin(checksum); err != nil {
|
|
return errorsmod.Wrapf(err, "failed to pin checksum: %s to in-memory cache", hex.EncodeToString(checksum))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ws *WasmSnapshotter) processAllItems(
|
|
height uint64,
|
|
payloadReader snapshot.ExtensionPayloadReader,
|
|
cb func(sdk.Context, *Keeper, []byte) error,
|
|
) error {
|
|
ctx := sdk.NewContext(ws.cms, cmtproto.Header{Height: int64(height)}, false, nil)
|
|
for {
|
|
payload, err := payloadReader()
|
|
if err == io.EOF {
|
|
break
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := cb(ctx, ws.keeper, payload); err != nil {
|
|
return errorsmod.Wrap(err, "failure processing snapshot item")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|