Files
wasmd/x/wasm/keeper/genesis_test.go
Alexander Peters 7e936c7fff Cosmos-SDK v0.47 integration brach (#1149)
* Start cosmos-sdk v0.47 integration (#1136)

* Upgrade to sdk v0.47 branch

* More integration work

* SDK version upgrade; fixes

* More fixes

* Fixes

* Deactivate failing tests

* SDK + ibc-go version upgrades

* limix gas fix

(cherry picked from commit f7f841768e5051d96d243b42ce4f231a33020326)

* with valset in bench

(cherry picked from commit 35b2a8fd2c23d6160fca540771fd348913f7f143)

* Revert staking query handler; fix tests

* Minor cleanup

* Rebased

* Address linter issues

* Set legacy router proper

* Deactivate failing test. Race condition needs to handled in SDK

* Address some code smells

* Bump sdk version

* Use gov v1 internally for votes

* Activate test after sdk fix

* Add group test

* Add config template for wasm fields

* Add Rust backtrace flag for more debug output on simulations

* Set unique node folder for tests

* Revert "Add Rust backtrace flag for more debug output on simulations"

This reverts commit 218c3c6ce137dc02f7bc38391408d3460fb27e6f.

* Simulations

* Run also im/export + deterministic sims

* Add package prefix to interfaces

* Add signer annotation (https://github.com/cosmos/cosmos-sdk/issues/10933), minor cleanup

* Bump sdk version

* Review comments

Co-authored-by: vuong <nguyenvuong1122000@gmail.com>

* Bump bufbuild/buf-setup-action from 1.11.0 to 1.12.0

Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/bufbuild/buf-setup-action/releases)
- [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.11.0...v1.12.0)

---
updated-dependencies:
- dependency-name: bufbuild/buf-setup-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit f4905955b5)

* Remove intertx for vanilla ICA

* fix msg format in EVENTS.md

(cherry picked from commit 38d466adfd)

* Better to sdk coin convertion (#1164)

* Better to sdk coin convertion

* Review feedback

(cherry picked from commit a925a9ed61)

* Disallow only address permission (#1163)

* Remove AccessTypeOnlyAddress for store msg

* Remove AccessTypeOnlyAddress for update config msg

* Review feedback

Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com>

Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com>
(cherry picked from commit 8991633de2)

* Integrate wasmvm v1.2.0 (backport #1161) (#1175)

* Integrate wasmvm v1.2.0 (#1161)

* Bump wasmvm version

* Bump wasm test contracts

* Encode weighted votes

* Encode instantiate2

* Handle code info query; better wasmvm errors

* Fix readme

* Make linter happy

* add non cgo build

* Review comments

* Bump wasmvm to release version

Co-authored-by: jhernandezb <contact@jhernandez.me>
(cherry picked from commit 957b38e0a5)

# Conflicts:
#	x/wasm/keeper/handler_plugin_encoders.go
#	x/wasm/keeper/handler_plugin_encoders_test.go
#	x/wasm/keeper/keeper.go
#	x/wasm/keeper/keeper_test.go

* Adress merge conflicts

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>

* Bump bufbuild/buf-setup-action from 1.12.0 to 1.13.0

Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/bufbuild/buf-setup-action/releases)
- [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: bufbuild/buf-setup-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit ffa0e5e5e1)

* Emit events for setContractAdmin + setAccessConfig (#1179)

(cherry picked from commit c9e7830ac1)

* Dependency upgrades (#1172)

* Bump sdk version to lastest

* Bump ibc-go  version to lastest

* Remove channel hack

* Update to ibc-go v7 + protoVer=0.11.5

* Bump bufbuild/buf-setup-action from 1.13.0 to 1.13.1

Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.13.0 to 1.13.1.
- [Release notes](https://github.com/bufbuild/buf-setup-action/releases)
- [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.13.0...v1.13.1)

---
updated-dependencies:
- dependency-name: bufbuild/buf-setup-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit de27e7f82f)

* Fix typos (backport #1185) (#1194)

* Fix typos

(cherry picked from commit c88b8194cb)

# Conflicts:
#	proto/cosmwasm/wasm/v1/tx.proto

* Fix merge conflict

---------

Co-authored-by: Alex Peters <alpe@users.noreply.github.com>

* Bump bufbuild/buf-setup-action from 1.13.1 to 1.14.0 (#1200)

Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.13.1 to 1.14.0.
- [Release notes](https://github.com/bufbuild/buf-setup-action/releases)
- [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.13.1...v1.14.0)

---
updated-dependencies:
- dependency-name: bufbuild/buf-setup-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit f3fc31c386)

* list-contract-by-code bugfix

(cherry picked from commit 2ccffed778)

* fix: stargate querier does not reset the state

(cherry picked from commit fd0323541d)

* test: add unit test

(cherry picked from commit 6d8018ac59)

* Add Windows client support (#1197)

* Add Windows client support

* Separate server and windows client

---------

Co-authored-by: Alex Peters <alpe@users.noreply.github.com>
(cherry picked from commit 8a20779518)

* Bump bufbuild/buf-setup-action from 1.14.0 to 1.15.0

Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/bufbuild/buf-setup-action/releases)
- [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: bufbuild/buf-setup-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit e5fab3da5a)

* Rename windows client binary

(cherry picked from commit de09c7fe2b)

* Return IBC packet sequence number (backport #1225) (#1233)

* Return IBC packet sequence number (#1225)

* Return IBC packet sequence number

* Fix review feedbacks

* Remove names to return values in DispatchMsg method

* Fix comments

(cherry picked from commit 4f1c57fc12)

# Conflicts:
#	x/wasm/keeper/handler_plugin.go

* Fix merge conflict

---------

Co-authored-by: pinosu <95283998+pinosu@users.noreply.github.com>
Co-authored-by: Alex Peters <alpe@users.noreply.github.com>

* Test rust panic for regression

(cherry picked from commit a52e604966)

* Fix client checksum verification (#1234)

* Fix client checksum verification

* Review comments

(cherry picked from commit 1a8019b380)

# Conflicts:
#	x/wasm/client/cli/gov_tx.go

* Fix merge conflict

* Fix linters

* Configure sonarcloud analysis

(cherry picked from commit 85cf1614fb)

* Bump bufbuild/buf-setup-action from 1.15.0 to 1.15.1

Bumps [bufbuild/buf-setup-action](https://github.com/bufbuild/buf-setup-action) from 1.15.0 to 1.15.1.
- [Release notes](https://github.com/bufbuild/buf-setup-action/releases)
- [Commits](https://github.com/bufbuild/buf-setup-action/compare/v1.15.0...v1.15.1)

---
updated-dependencies:
- dependency-name: bufbuild/buf-setup-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 730ea5a1cf)

* Make `CaptureIbcEvents` in ibctesting public.

Before this change, it wasn't possible to implement the
`chain.SendMsgs` method without
[copying](https://github.com/public-awesome/ics721/blob/main/e2e/suite_helpers.go#L81-L98)
them over.

(cherry picked from commit b64fa078a3)

* Upgrade to wasmvm 1.2.1 (backport #1245) (#1254)

* Upgrade to wasmvm 1.2.1 (#1245)

* Use wasmvm store adapter

* Bump wasmvm to v1.2.1

(cherry picked from commit 850f901b2e)

# Conflicts:
#	go.mod
#	go.sum
#	x/wasm/keeper/keeper.go

* Resolve conflicts

---------

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>

* WIP All cometbft (#1244)

* Dep upgrade; use CometBft

* Remove duplicte message events

* Add changelog for v0.31.0 (#1188)

* Start changelog for v0.31.0

* Add ICA upgrade

* Add proto version link to buf.build

* Update changelog (#1239)

* Update changelog

* Update changelog with latest changes

* Set release date

---------

Co-authored-by: pinosu <95283998+pinosu@users.noreply.github.com>
(cherry picked from commit bc0e817912)

* Remove new message type event

* Support msg update params gov proposal (#1247)

* Add MsgUpdateParams support

* Implement UpdateParams msg

* Fix test UpdateParams

* Add migration test

* Fix

* Fix lint issues

* Revert changes according to review feedback

* Remove more x/params dependencies

* Remove x/params from genesis test

* Formatting

* Restore old changes

* fix lint

* Fix tests and restructure migrations

* Rename alias for convention

---------

Co-authored-by: Alex Peters <alpe@users.noreply.github.com>

* Fix test data generator (#1263)

* linting 47 pr (#1261)

* lint cosmwasm for sdk 47

* fix

* remove setGenesis

* remove additional unused functions

* pass tests

* use SDK's errors module

* unecessary conversions

* unnecessary conversions

* remove unneeded event manager

* complete linting of tests for 47

* add test for reimportation

* check errors

* Update x/wasm/keeper/proposal_integration_test.go

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>

* apply suggestion

* suggestions

* lints

* don't return error in when making new transactions

* no todo's in the code

* Fix test data generator

* Update x/wasm/types/genesis_test.go

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>

* use the full string invalid address (2 words) always

---------

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>

* Regenerate from proto; remove dead code; polish code

* Set SDK version to v0.47x.0 (#1262)

* Set SDK version to v0.47x.0

* Set chainID

* Minor updates

* Set chainID for simulations

* Buf mod update

* Use sdk tag instead of hash in buf

* Bump ibc-go to v7.0.0

* faddat/re merge main (#1274)

undefined

---------

Co-authored-by: vuong <nguyenvuong1122000@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: llllllluc <58892938+llllllluc@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Gjermund Garaba <gjermund@garaba.net>
Co-authored-by: Nikhil Suri <nikhilsuri@comcast.net>
Co-authored-by: Paul <p22626262@gmail.com>
Co-authored-by: pinosu <95283998+pinosu@users.noreply.github.com>
Co-authored-by: ekez <zekemedley@gmail.com>
Co-authored-by: Jacob Gadikian <jacobgadikian@gmail.com>
2023-03-20 10:32:22 +01:00

706 lines
21 KiB
Go

package keeper
import (
"crypto/sha256"
"encoding/base64"
"fmt"
"math/rand"
"os"
"testing"
"time"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/baseapp"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
dbm "github.com/cometbft/cometbft-db"
"github.com/cometbft/cometbft/libs/log"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
fuzz "github.com/google/gofuzz"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/CosmWasm/wasmd/x/wasm/types"
)
const firstCodeID = 1
func TestGenesisExportImport(t *testing.T) {
wasmKeeper, srcCtx := setupKeeper(t)
contractKeeper := NewGovPermissionKeeper(wasmKeeper)
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
// store some test data
f := fuzz.New().Funcs(ModelFuzzers...)
err = wasmKeeper.SetParams(srcCtx, types.DefaultParams())
require.NoError(t, err)
for i := 0; i < 25; i++ {
var (
codeInfo types.CodeInfo
contract types.ContractInfo
stateModels []types.Model
history []types.ContractCodeHistoryEntry
pinned bool
contractExtension bool
)
f.Fuzz(&codeInfo)
f.Fuzz(&contract)
f.Fuzz(&stateModels)
f.NilChance(0).Fuzz(&history)
f.Fuzz(&pinned)
f.Fuzz(&contractExtension)
creatorAddr, err := sdk.AccAddressFromBech32(codeInfo.Creator)
require.NoError(t, err)
codeID, _, err := contractKeeper.Create(srcCtx, creatorAddr, wasmCode, &codeInfo.InstantiateConfig)
require.NoError(t, err)
if pinned {
err = contractKeeper.PinCode(srcCtx, codeID)
require.NoError(t, err)
}
if contractExtension {
anyTime := time.Now().UTC()
var nestedType v1beta1.TextProposal
f.NilChance(0).Fuzz(&nestedType)
myExtension, err := v1beta1.NewProposal(&nestedType, 1, anyTime, anyTime)
require.NoError(t, err)
err = contract.SetExtension(&myExtension)
require.NoError(t, err)
}
contract.CodeID = codeID
contractAddr := wasmKeeper.ClassicAddressGenerator()(srcCtx, codeID, nil)
wasmKeeper.storeContractInfo(srcCtx, contractAddr, &contract)
wasmKeeper.appendToContractHistory(srcCtx, contractAddr, history...)
err = wasmKeeper.importContractState(srcCtx, contractAddr, stateModels)
require.NoError(t, err)
}
var wasmParams types.Params
f.NilChance(0).Fuzz(&wasmParams)
err = wasmKeeper.SetParams(srcCtx, wasmParams)
require.NoError(t, err)
// export
exportedState := ExportGenesis(srcCtx, wasmKeeper)
// order should not matter
rand.Shuffle(len(exportedState.Codes), func(i, j int) {
exportedState.Codes[i], exportedState.Codes[j] = exportedState.Codes[j], exportedState.Codes[i]
})
rand.Shuffle(len(exportedState.Contracts), func(i, j int) {
exportedState.Contracts[i], exportedState.Contracts[j] = exportedState.Contracts[j], exportedState.Contracts[i]
})
rand.Shuffle(len(exportedState.Sequences), func(i, j int) {
exportedState.Sequences[i], exportedState.Sequences[j] = exportedState.Sequences[j], exportedState.Sequences[i]
})
exportedGenesis, err := wasmKeeper.cdc.MarshalJSON(exportedState)
require.NoError(t, err)
// setup new instances
dstKeeper, dstCtx := setupKeeper(t)
// reset contract code index in source DB for comparison with dest DB
wasmKeeper.IterateContractInfo(srcCtx, func(address sdk.AccAddress, info types.ContractInfo) bool {
creatorAddress := sdk.MustAccAddressFromBech32(info.Creator)
history := wasmKeeper.GetContractHistory(srcCtx, address)
wasmKeeper.addToContractCodeSecondaryIndex(srcCtx, address, history[len(history)-1])
wasmKeeper.addToContractCreatorSecondaryIndex(srcCtx, creatorAddress, history[0].Updated, address)
return false
})
// re-import
var importState types.GenesisState
err = dstKeeper.cdc.UnmarshalJSON(exportedGenesis, &importState)
require.NoError(t, err)
_, err = InitGenesis(dstCtx, dstKeeper, importState)
require.NoError(t, err)
// compare whole DB
srcIT := srcCtx.KVStore(wasmKeeper.storeKey).Iterator(nil, nil)
dstIT := dstCtx.KVStore(dstKeeper.storeKey).Iterator(nil, nil)
for i := 0; srcIT.Valid(); i++ {
require.True(t, dstIT.Valid(), "[%s] destination DB has less elements than source. Missing: %x", wasmKeeper.storeKey.Name(), srcIT.Key())
require.Equal(t, srcIT.Key(), dstIT.Key(), i)
require.Equal(t, srcIT.Value(), dstIT.Value(), "[%s] element (%d): %X", wasmKeeper.storeKey.Name(), i, srcIT.Key())
dstIT.Next()
srcIT.Next()
}
if !assert.False(t, dstIT.Valid()) {
t.Fatalf("dest Iterator still has key :%X", dstIT.Key())
}
srcIT.Close()
dstIT.Close()
}
func TestGenesisInit(t *testing.T) {
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
myCodeInfo := types.CodeInfoFixture(types.WithSHA256CodeHash(wasmCode))
specs := map[string]struct {
src types.GenesisState
expSuccess bool
}{
"happy path: code info correct": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
expSuccess: true,
},
"happy path: code ids can contain gaps": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}, {
CodeID: 3,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 10},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
expSuccess: true,
},
"happy path: code order does not matter": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: 2,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}, {
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Contracts: nil,
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 3},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
expSuccess: true,
},
"prevent code hash mismatch": {src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: types.CodeInfoFixture(func(i *types.CodeInfo) { i.CodeHash = make([]byte, sha256.Size) }),
CodeBytes: wasmCode,
}},
Params: types.DefaultParams(),
}},
"prevent duplicate codeIDs": {src: types.GenesisState{
Codes: []types.Code{
{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
},
{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
},
},
Params: types.DefaultParams(),
}},
"codes with same checksum can be pinned": {
src: types.GenesisState{
Codes: []types.Code{
{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
Pinned: true,
},
{
CodeID: 2,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
Pinned: true,
},
},
Params: types.DefaultParams(),
},
},
"happy path: code id in info and contract do match": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddressClassic(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{}`),
},
},
},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 2},
},
Params: types.DefaultParams(),
},
expSuccess: true,
},
"happy path: code info with two contracts": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddressClassic(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{}`),
},
},
}, {
ContractAddress: BuildContractAddressClassic(1, 2).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{"foo":"bar"}`),
},
},
},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 3},
},
Params: types.DefaultParams(),
},
expSuccess: true,
},
"prevent contracts that points to non existing codeID": {
src: types.GenesisState{
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddressClassic(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{"foo":"bar"}`),
},
},
},
},
Params: types.DefaultParams(),
},
},
"prevent duplicate contract address": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddressClassic(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{"foo":"bar"}`),
},
},
}, {
ContractAddress: BuildContractAddressClassic(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{"other":"value"}`),
},
},
},
},
Params: types.DefaultParams(),
},
},
"prevent duplicate contract model keys": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddressClassic(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractState: []types.Model{
{
Key: []byte{0x1},
Value: []byte("foo"),
},
{
Key: []byte{0x1},
Value: []byte("bar"),
},
},
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{"foo":"bar"}`),
},
},
},
},
Params: types.DefaultParams(),
},
},
"prevent duplicate sequences": {
src: types.GenesisState{
Sequences: []types.Sequence{
{IDKey: []byte("foo"), Value: 1},
{IDKey: []byte("foo"), Value: 9999},
},
Params: types.DefaultParams(),
},
},
"prevent code id seq init value == max codeID used": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: 2,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 1},
},
Params: types.DefaultParams(),
},
},
"prevent contract id seq init value == count contracts": {
src: types.GenesisState{
Codes: []types.Code{{
CodeID: firstCodeID,
CodeInfo: myCodeInfo,
CodeBytes: wasmCode,
}},
Contracts: []types.Contract{
{
ContractAddress: BuildContractAddressClassic(1, 1).String(),
ContractInfo: types.ContractInfoFixture(func(c *types.ContractInfo) { c.CodeID = 1 }, types.RandCreatedFields),
ContractCodeHistory: []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: 1,
Updated: &types.AbsoluteTxPosition{BlockHeight: rand.Uint64(), TxIndex: rand.Uint64()},
Msg: []byte(`{}`),
},
},
},
},
Sequences: []types.Sequence{
{IDKey: types.KeyLastCodeID, Value: 2},
{IDKey: types.KeyLastInstanceID, Value: 1},
},
Params: types.DefaultParams(),
},
},
}
for msg, spec := range specs {
t.Run(msg, func(t *testing.T) {
keeper, ctx := setupKeeper(t)
require.NoError(t, types.ValidateGenesis(spec.src))
_, gotErr := InitGenesis(ctx, keeper, spec.src)
if !spec.expSuccess {
require.Error(t, gotErr)
return
}
require.NoError(t, gotErr)
for _, c := range spec.src.Codes {
assert.Equal(t, c.Pinned, keeper.IsPinnedCode(ctx, c.CodeID))
}
})
}
}
func TestImportContractWithCodeHistoryPreserved(t *testing.T) {
genesisTemplate := `
{
"params":{
"code_upload_access": {
"permission": "Everybody"
},
"instantiate_default_permission": "Everybody"
},
"codes": [
{
"code_id": "1",
"code_info": {
"code_hash": %q,
"creator": "cosmos1qtu5n0cnhfkjj6l2rq97hmky9fd89gwca9yarx",
"instantiate_config": {
"permission": "OnlyAddress",
"address": "cosmos1qtu5n0cnhfkjj6l2rq97hmky9fd89gwca9yarx"
}
},
"code_bytes": %q
}
],
"contracts": [
{
"contract_address": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr",
"contract_info": {
"code_id": "1",
"creator": "cosmos13x849jzd03vne42ynpj25hn8npjecxqrjghd8x",
"admin": "cosmos1h5t8zxmjr30e9dqghtlpl40f2zz5cgey6esxtn",
"label": "ȀĴnZV芢毤",
"created": {
"block_height" : "100",
"tx_index" : "10"
}
},
"contract_code_history": [
{
"operation": "CONTRACT_CODE_HISTORY_OPERATION_TYPE_INIT",
"code_id": "1",
"updated": {
"block_height" : "100",
"tx_index" : "10"
},
"msg": {"foo": "bar"}
},
{
"operation": "CONTRACT_CODE_HISTORY_OPERATION_TYPE_MIGRATE",
"code_id": "1",
"updated": {
"block_height" : "200",
"tx_index" : "10"
},
"msg": {"other": "msg"}
}
]
}
],
"sequences": [
{"id_key": "BGxhc3RDb2RlSWQ=", "value": "2"},
{"id_key": "BGxhc3RDb250cmFjdElk", "value": "3"}
]
}`
keeper, ctx := setupKeeper(t)
wasmCode, err := os.ReadFile("./testdata/hackatom.wasm")
require.NoError(t, err)
wasmCodeHash := sha256.Sum256(wasmCode)
enc64 := base64.StdEncoding.EncodeToString
genesisStr := fmt.Sprintf(genesisTemplate, enc64(wasmCodeHash[:]), enc64(wasmCode))
var importState types.GenesisState
err = keeper.cdc.UnmarshalJSON([]byte(genesisStr), &importState)
require.NoError(t, err)
require.NoError(t, importState.ValidateBasic(), genesisStr)
ctx = ctx.WithBlockHeight(0).WithGasMeter(sdk.NewInfiniteGasMeter())
// when
_, err = InitGenesis(ctx, keeper, importState)
require.NoError(t, err)
// verify wasm code
gotWasmCode, err := keeper.GetByteCode(ctx, 1)
require.NoError(t, err)
assert.Equal(t, wasmCode, gotWasmCode, "byte code does not match")
// verify code info
gotCodeInfo := keeper.GetCodeInfo(ctx, 1)
require.NotNil(t, gotCodeInfo)
codeCreatorAddr := "cosmos1qtu5n0cnhfkjj6l2rq97hmky9fd89gwca9yarx"
expCodeInfo := types.CodeInfo{
CodeHash: wasmCodeHash[:],
Creator: codeCreatorAddr,
InstantiateConfig: types.AccessConfig{
Permission: types.AccessTypeOnlyAddress,
Address: codeCreatorAddr,
},
}
assert.Equal(t, expCodeInfo, *gotCodeInfo)
// verify contract
contractAddr, _ := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr")
gotContractInfo := keeper.GetContractInfo(ctx, contractAddr)
require.NotNil(t, gotContractInfo)
contractCreatorAddr := "cosmos13x849jzd03vne42ynpj25hn8npjecxqrjghd8x"
adminAddr := "cosmos1h5t8zxmjr30e9dqghtlpl40f2zz5cgey6esxtn"
expContractInfo := types.ContractInfo{
CodeID: firstCodeID,
Creator: contractCreatorAddr,
Admin: adminAddr,
Label: "ȀĴnZV芢毤",
Created: &types.AbsoluteTxPosition{BlockHeight: 100, TxIndex: 10},
}
assert.Equal(t, expContractInfo, *gotContractInfo)
expHistory := []types.ContractCodeHistoryEntry{
{
Operation: types.ContractCodeHistoryOperationTypeInit,
CodeID: firstCodeID,
Updated: &types.AbsoluteTxPosition{
BlockHeight: 100,
TxIndex: 10,
},
Msg: []byte(`{"foo": "bar"}`),
},
{
Operation: types.ContractCodeHistoryOperationTypeMigrate,
CodeID: firstCodeID,
Updated: &types.AbsoluteTxPosition{
BlockHeight: 200,
TxIndex: 10,
},
Msg: []byte(`{"other": "msg"}`),
},
}
assert.Equal(t, expHistory, keeper.GetContractHistory(ctx, contractAddr))
assert.Equal(t, uint64(2), keeper.PeekAutoIncrementID(ctx, types.KeyLastCodeID))
assert.Equal(t, uint64(3), keeper.PeekAutoIncrementID(ctx, types.KeyLastInstanceID))
}
func setupKeeper(t *testing.T) (*Keeper, sdk.Context) {
t.Helper()
tempDir, err := os.MkdirTemp("", "wasm")
require.NoError(t, err)
t.Cleanup(func() { os.RemoveAll(tempDir) })
keyWasm := sdk.NewKVStoreKey(types.StoreKey)
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyWasm, storetypes.StoreTypeIAVL, db)
require.NoError(t, ms.LoadLatestVersion())
ctx := sdk.NewContext(ms, tmproto.Header{
Height: 1234567,
Time: time.Date(2020, time.April, 22, 12, 0, 0, 0, time.UTC),
}, false, log.NewNopLogger())
encodingConfig := MakeEncodingConfig(t)
// register an example extension. must be protobuf
encodingConfig.InterfaceRegistry.RegisterImplementations(
(*types.ContractInfoExtension)(nil),
&v1beta1.Proposal{},
)
// also registering gov interfaces for nested Any type
v1beta1.RegisterInterfaces(encodingConfig.InterfaceRegistry)
wasmConfig := types.DefaultWasmConfig()
srcKeeper := NewKeeper(
encodingConfig.Marshaler,
keyWasm,
authkeeper.AccountKeeper{},
&bankkeeper.BaseKeeper{},
stakingkeeper.Keeper{},
nil,
nil,
nil,
nil,
nil,
nil,
nil,
tempDir,
wasmConfig,
AvailableCapabilities,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
return &srcKeeper, ctx
}
type StakingKeeperMock struct {
err error
validatorUpdate []abci.ValidatorUpdate
gotCalls int
}
func (s *StakingKeeperMock) ApplyAndReturnValidatorSetUpdates(_ sdk.Context) ([]abci.ValidatorUpdate, error) {
s.gotCalls++
return s.validatorUpdate, s.err
}
var _ MessageRouter = &MockMsgHandler{}
type MockMsgHandler struct {
result *sdk.Result
err error
expCalls int //nolint:unused
gotCalls int
expMsg sdk.Msg //nolint:unused
gotMsg sdk.Msg
}
func (m *MockMsgHandler) Handler(msg sdk.Msg) baseapp.MsgServiceHandler {
return m.Handle
}
func (m *MockMsgHandler) Handle(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
m.gotCalls++
m.gotMsg = msg
return m.result, m.err
}