Skip to content

Commit

Permalink
imp: use wasm VM CreateChecksum (backport #5123) (#5138)
Browse files Browse the repository at this point in the history
* imp: use wasm VM CreateChecksum (#5123)

* use wasm VM CreateChecksum

* review comments

* lint

* lint 2

* Remove raw calls to sha256, clean up handling of Checksums.

* Update modules/light-clients/08-wasm/keeper/keeper.go

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

* Document this bad boy.

---------

Co-authored-by: DimitrisJim <d.f.hilliard@gmail.com>
Co-authored-by: Damian Nolan <damiannolan@gmail.com>
(cherry picked from commit a231fea)

# Conflicts:
#	modules/light-clients/08-wasm/keeper/events.go
#	modules/light-clients/08-wasm/keeper/genesis.go
#	modules/light-clients/08-wasm/keeper/keeper.go
#	modules/light-clients/08-wasm/keeper/msg_server_test.go
#	modules/light-clients/08-wasm/keeper/snapshotter.go
#	modules/light-clients/08-wasm/keeper/snapshotter_test.go
#	modules/light-clients/08-wasm/testing/mock_engine.go
#	modules/light-clients/08-wasm/testing/values.go
#	modules/light-clients/08-wasm/testing/wasm_endpoint.go
#	modules/light-clients/08-wasm/types/client_state_test.go
#	modules/light-clients/08-wasm/types/migrate_contract_test.go
#	modules/light-clients/08-wasm/types/msgs_test.go
#	modules/light-clients/08-wasm/types/types_test.go
#	modules/light-clients/08-wasm/types/validation.go
#	modules/light-clients/08-wasm/types/validation_test.go
#	modules/light-clients/08-wasm/types/vm.go
#	modules/light-clients/08-wasm/types/wasm.go
#	modules/light-clients/08-wasm/types/wasm_test.go

* lint: simplify newHash[:] -> newHash to satifsy linting overlords

---------

Co-authored-by: Carlos Rodriguez <carlos@interchain.io>
Co-authored-by: Damian Nolan <damiannolan@gmail.com>
  • Loading branch information
3 people authored Nov 29, 2023
1 parent e84470f commit 0aac11b
Show file tree
Hide file tree
Showing 19 changed files with 154 additions and 104 deletions.
4 changes: 2 additions & 2 deletions modules/light-clients/08-wasm/keeper/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

// emitStoreWasmCodeEvent emits a store wasm code event
func emitStoreWasmCodeEvent(ctx sdk.Context, checksum []byte) {
func emitStoreWasmCodeEvent(ctx sdk.Context, checksum types.Checksum) {
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeStoreWasmCode,
Expand All @@ -23,7 +23,7 @@ func emitStoreWasmCodeEvent(ctx sdk.Context, checksum []byte) {
}

// emitMigrateContractEvent emits a migrate contract event
func emitMigrateContractEvent(ctx sdk.Context, clientID string, checksum, newChecksum []byte) {
func emitMigrateContractEvent(ctx sdk.Context, clientID string, checksum, newChecksum types.Checksum) {
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeMigrateContract,
Expand Down
9 changes: 0 additions & 9 deletions modules/light-clients/08-wasm/keeper/export_test.go

This file was deleted.

4 changes: 1 addition & 3 deletions modules/light-clients/08-wasm/keeper/genesis.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package keeper

import (
wasmvmtypes "github.com/CosmWasm/wasmvm/types"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types"
Expand Down Expand Up @@ -31,7 +29,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) types.GenesisState {
// Grab code from wasmVM and add to genesis state.
var genesisState types.GenesisState
for _, checksum := range checksums {
code, err := k.wasmVM.GetCode(wasmvmtypes.Checksum(checksum))
code, err := k.wasmVM.GetCode(checksum)
if err != nil {
panic(err)
}
Expand Down
12 changes: 5 additions & 7 deletions modules/light-clients/08-wasm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package keeper

import (
"bytes"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
Expand Down Expand Up @@ -90,11 +89,6 @@ func (k Keeper) GetAuthority() string {
return k.authority
}

func generateWasmChecksum(code []byte) []byte {
hash := sha256.Sum256(code)
return hash[:]
}

func (k Keeper) storeWasmCode(ctx sdk.Context, code []byte) ([]byte, error) {
var err error
if types.IsGzip(code) {
Expand All @@ -106,7 +100,11 @@ func (k Keeper) storeWasmCode(ctx sdk.Context, code []byte) ([]byte, error) {
}

// Check to see if store already has checksum.
checksum := generateWasmChecksum(code)
checksum, err := types.CreateChecksum(code)
if err != nil {
return nil, errorsmod.Wrap(err, "wasm bytecode checksum failed")
}

if types.HasChecksum(ctx, k.cdc, checksum) {
return nil, types.ErrWasmCodeExists
}
Expand Down
64 changes: 46 additions & 18 deletions modules/light-clients/08-wasm/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package keeper_test

import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"os"
"strings"

wasmvm "github.com/CosmWasm/wasmvm"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
Expand All @@ -13,14 +14,15 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"

"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/internal/ibcwasm"
wasmtesting "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/testing"
"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types"
clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
host "github.com/cosmos/ibc-go/v7/modules/core/24-host"
ibcerrors "github.com/cosmos/ibc-go/v7/modules/core/errors"
localhost "github.com/cosmos/ibc-go/v7/modules/light-clients/09-localhost"
ibctesting "github.com/cosmos/ibc-go/v7/testing"

"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/internal/ibcwasm"
wasmtesting "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/testing"
)

func (suite *KeeperTestSuite) TestMsgStoreCode() {
Expand Down Expand Up @@ -53,11 +55,31 @@ func (suite *KeeperTestSuite) TestMsgStoreCode() {
types.ErrWasmCodeExists,
},
{
"fails with invalid wasm code",
"fails with zero-length wasm code",
func() {
msg = types.NewMsgStoreCode(signer, []byte{})
},
types.ErrWasmEmptyCode,
errors.New("Wasm bytes nil or empty"),
},
{
"fails with checksum",
func() {
msg = types.NewMsgStoreCode(signer, []byte{0, 1, 3, 4})
},
errors.New("Wasm bytes do not not start with Wasm magic number"),
},
{
"fails with wasm code too large",
func() {
var sb strings.Builder
for i := 0; i < int(types.MaxWasmByteSize()); i++ {
err := sb.WriteByte(byte(i))
suite.Require().NoError(err)
}

msg = types.NewMsgStoreCode(signer, append(wasmtesting.WasmMagicNumber, []byte(sb.String())...))
},
types.ErrWasmCodeTooLarge,
},
{
"fails with unauthorized signer",
Expand Down Expand Up @@ -114,7 +136,7 @@ func (suite *KeeperTestSuite) TestMsgStoreCode() {
suite.Require().Contains(events, evt)
}
} else {
suite.Require().ErrorIs(err, tc.expError)
suite.Require().Contains(err.Error(), tc.expError.Error())
suite.Require().Nil(res)
suite.Require().Empty(events)
}
Expand All @@ -123,9 +145,11 @@ func (suite *KeeperTestSuite) TestMsgStoreCode() {
}

func (suite *KeeperTestSuite) TestMsgMigrateContract() {
oldChecksum := sha256.Sum256(wasmtesting.Code)
oldChecksum, err := types.CreateChecksum(wasmtesting.Code)
suite.Require().NoError(err)

newByteCode := []byte("MockByteCode-TestMsgMigrateContract")
newByteCode := wasmtesting.WasmMagicNumber
newByteCode = append(newByteCode, []byte("MockByteCode-TestMsgMigrateContract")...)

govAcc := authtypes.NewModuleAddress(govtypes.ModuleName).String()

Expand Down Expand Up @@ -175,7 +199,7 @@ func (suite *KeeperTestSuite) TestMsgMigrateContract() {
{
"failure: same checksum",
func() {
msg = types.NewMsgMigrateContract(govAcc, defaultWasmClientID, oldChecksum[:], []byte("{}"))
msg = types.NewMsgMigrateContract(govAcc, defaultWasmClientID, oldChecksum, []byte("{}"))

suite.mockVM.MigrateFn = func(_ wasmvm.Checksum, _ wasmvmtypes.Env, _ []byte, _ wasmvm.KVStore, _ wasmvm.GoAPI, _ wasmvm.Querier, _ wasmvm.GasMeter, _ uint64, _ wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) {
panic("unreachable")
Expand Down Expand Up @@ -272,7 +296,7 @@ func (suite *KeeperTestSuite) TestMsgMigrateContract() {
sdk.NewEvent(
"migrate_contract",
sdk.NewAttribute(types.AttributeKeyClientID, defaultWasmClientID),
sdk.NewAttribute(types.AttributeKeyWasmChecksum, hex.EncodeToString(oldChecksum[:])),
sdk.NewAttribute(types.AttributeKeyWasmChecksum, hex.EncodeToString(oldChecksum)),
sdk.NewAttribute(types.AttributeKeyNewChecksum, hex.EncodeToString(newChecksum)),
),
sdk.NewEvent(
Expand All @@ -293,7 +317,8 @@ func (suite *KeeperTestSuite) TestMsgMigrateContract() {
}

func (suite *KeeperTestSuite) TestMsgRemoveChecksum() {
checksum := sha256.Sum256(wasmtesting.Code)
checksum, err := types.CreateChecksum(wasmtesting.Code)
suite.Require().NoError(err)

govAcc := authtypes.NewModuleAddress(govtypes.ModuleName).String()

Expand All @@ -310,7 +335,7 @@ func (suite *KeeperTestSuite) TestMsgRemoveChecksum() {
{
"success",
func() {
msg = types.NewMsgRemoveChecksum(govAcc, checksum[:])
msg = types.NewMsgRemoveChecksum(govAcc, checksum)

expChecksums = []types.Checksum{}
},
Expand All @@ -319,17 +344,20 @@ func (suite *KeeperTestSuite) TestMsgRemoveChecksum() {
{
"success: many checksums",
func() {
msg = types.NewMsgRemoveChecksum(govAcc, checksum[:])
msg = types.NewMsgRemoveChecksum(govAcc, checksum)

expChecksums = []types.Checksum{}

for i := 0; i < 20; i++ {
checksum := sha256.Sum256([]byte{byte(i)})
mockCode := []byte{byte(i)}
mockCode = append(wasmtesting.WasmMagicNumber, mockCode...)
checksum, err := types.CreateChecksum(mockCode)
suite.Require().NoError(err)

err := types.AddChecksum(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), ibcwasm.GetWasmStoreKey(), checksum[:])
err = types.AddChecksum(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), ibcwasm.GetWasmStoreKey(), checksum)
suite.Require().NoError(err)

expChecksums = append(expChecksums, checksum[:])
expChecksums = append(expChecksums, checksum)
}
},
nil,
Expand All @@ -344,14 +372,14 @@ func (suite *KeeperTestSuite) TestMsgRemoveChecksum() {
{
"failure: unauthorized signer",
func() {
msg = types.NewMsgRemoveChecksum(suite.chainA.SenderAccount.GetAddress().String(), checksum[:])
msg = types.NewMsgRemoveChecksum(suite.chainA.SenderAccount.GetAddress().String(), checksum)
},
ibcerrors.ErrUnauthorized,
},
{
"failure: code has could not be unpinned",
func() {
msg = types.NewMsgRemoveChecksum(govAcc, checksum[:])
msg = types.NewMsgRemoveChecksum(govAcc, checksum)

suite.mockVM.UnpinFn = func(_ wasmvm.Checksum) error {
return wasmtesting.ErrMockVM
Expand Down
4 changes: 1 addition & 3 deletions modules/light-clients/08-wasm/keeper/snapshotter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"encoding/hex"
"io"

wasmvmtypes "github.com/CosmWasm/wasmvm/types"

errorsmod "cosmossdk.io/errors"
snapshot "github.com/cosmos/cosmos-sdk/snapshots/types"

Expand Down Expand Up @@ -73,7 +71,7 @@ func (ws *WasmSnapshotter) SnapshotExtension(height uint64, payloadWriter snapsh
}

for _, checksum := range checksums {
wasmCode, err := ws.keeper.wasmVM.GetCode(wasmvmtypes.Checksum(checksum))
wasmCode, err := ws.keeper.wasmVM.GetCode(checksum)
if err != nil {
return err
}
Expand Down
8 changes: 5 additions & 3 deletions modules/light-clients/08-wasm/keeper/snapshotter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ import (

tmproto "github.com/cometbft/cometbft/proto/tendermint/types"

"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper"
wasmtesting "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/testing"
"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/testing/simapp"
"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types"
)

func (suite *KeeperTestSuite) TestSnapshotter() {
gzippedContract, err := types.GzipIt([]byte("gzipped-contract"))
gzippedContract, err := types.GzipIt(append(wasmtesting.WasmMagicNumber, []byte("gzipped-contract")...))
suite.Require().NoError(err)

testCases := []struct {
Expand Down Expand Up @@ -109,7 +108,10 @@ func (suite *KeeperTestSuite) TestSnapshotter() {
resp, err := destWasmClientApp.WasmClientKeeper.Code(ctx, &types.QueryCodeRequest{Checksum: hex.EncodeToString(checksum)})
suite.Require().NoError(err)

allDestAppChecksumsInWasmVMStore = append(allDestAppChecksumsInWasmVMStore, keeper.GenerateWasmChecksum(resp.Data)...)
checksum, err := types.CreateChecksum(resp.Data)
suite.Require().NoError(err)

allDestAppChecksumsInWasmVMStore = append(allDestAppChecksumsInWasmVMStore, checksum...)
}

suite.Require().Equal(srcChecksumCodes, allDestAppChecksumsInWasmVMStore)
Expand Down
4 changes: 1 addition & 3 deletions modules/light-clients/08-wasm/testing/mock_engine.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package testing

import (
"crypto/sha256"
"encoding/binary"
"encoding/json"
"errors"
Expand Down Expand Up @@ -58,8 +57,7 @@ func NewMockWasmEngine() *MockWasmEngine {

// Set up default behavior for Store/Pin/Get
m.StoreCodeFn = func(code wasmvm.WasmCode) (wasmvm.Checksum, error) {
hash := sha256.Sum256(code)
checkSum := wasmvm.Checksum(hash[:])
checkSum, _ := types.CreateChecksum(code)

m.storedContracts[binary.LittleEndian.Uint32(checkSum)] = code
return checkSum, nil
Expand Down
5 changes: 3 additions & 2 deletions modules/light-clients/08-wasm/testing/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (

var (
// Represents the code of the wasm contract used in the tests with a mock vm.
Code = []byte("01234567012345670123456701234567")
WasmMagicNumber = []byte("\x00\x61\x73\x6D")
Code = append(WasmMagicNumber, []byte("0123456780123456780123456780")...)
contractClientState = []byte{1}
contractConsensusState = []byte{2}
MockClientStateBz = []byte("client-state-data")
Expand All @@ -26,7 +27,7 @@ var (
)

// CreateMockClientStateBz returns valid client state bytes for use in tests.
func CreateMockClientStateBz(cdc codec.BinaryCodec, checksum []byte) []byte {
func CreateMockClientStateBz(cdc codec.BinaryCodec, checksum types.Checksum) []byte {
mockClientSate := types.NewClientState([]byte{1}, checksum, clienttypes.NewHeight(2000, 2))
return clienttypes.MustMarshalClientState(cdc, mockClientSate)
}
8 changes: 4 additions & 4 deletions modules/light-clients/08-wasm/testing/wasm_endpoint.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package testing

import (
"crypto/sha256"

"github.com/stretchr/testify/require"

"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types"
Expand All @@ -28,8 +26,10 @@ func NewWasmEndpoint(chain *ibctesting.TestChain) *WasmEndpoint {
// The client and consensus states are represented by byte slices
// and the starting height is 1.
func (endpoint *WasmEndpoint) CreateClient() error {
checksum := sha256.Sum256(Code)
clientState := types.NewClientState(contractClientState, checksum[:], clienttypes.NewHeight(0, 1))
checksum, err := types.CreateChecksum(Code)
require.NoError(endpoint.Chain.T, err)

clientState := types.NewClientState(contractClientState, checksum, clienttypes.NewHeight(0, 1))
consensusState := types.NewConsensusState(contractConsensusState, 0)

msg, err := clienttypes.NewMsgCreateClient(
Expand Down
9 changes: 5 additions & 4 deletions modules/light-clients/08-wasm/types/client_state_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package types_test

import (
"crypto/sha256"
"encoding/json"
"time"

Expand Down Expand Up @@ -306,16 +305,18 @@ func (suite *TypesTestSuite) TestInitialize() {
suite.Run(tc.name, func() {
suite.SetupWasmWithMockVM()

checksum := sha256.Sum256(wasmtesting.Code)
clientState = types.NewClientState([]byte{1}, checksum[:], clienttypes.NewHeight(0, 1))
checksum, err := types.CreateChecksum(wasmtesting.Code)
suite.Require().NoError(err)

clientState = types.NewClientState([]byte{1}, checksum, clienttypes.NewHeight(0, 1))
consensusState = types.NewConsensusState([]byte{2}, 0)

clientID := suite.chainA.App.GetIBCKeeper().ClientKeeper.GenerateClientIdentifier(suite.chainA.GetContext(), clientState.ClientType())
clientStore = suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), clientID)

tc.malleate()

err := clientState.Initialize(suite.chainA.GetContext(), suite.chainA.Codec, clientStore, consensusState)
err = clientState.Initialize(suite.chainA.GetContext(), suite.chainA.Codec, clientStore, consensusState)

expPass := tc.expError == nil
if expPass {
Expand Down
Loading

0 comments on commit 0aac11b

Please sign in to comment.