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

Add system tests for chain upgrade #1643

Merged
merged 27 commits into from
Oct 13, 2023
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
7 changes: 7 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ jobs:
- run:
name: Build and run system tests
command: make test-system
- run:
command: |
mkdir -p /tmp/system-test-workspace
mv /home/circleci/project/tests/system/testnet /tmp/system-test-workspace
when: on_fail
- store_artifacts:
path: /tmp/system-test-workspace

benchmark:
executor: golang
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ test-system: install
format-tools:
go install mvdan.cc/gofumpt@v0.4.0
go install github.com/client9/misspell/cmd/misspell@v0.3.4
go install golang.org/x/tools/cmd/goimports@latest
go install github.com/daixiang0/gci@v0.11.2

lint: format-tools
golangci-lint run --tests=false
Expand All @@ -170,7 +170,7 @@ lint: format-tools
format: format-tools
find . -name '*.go' -type f -not -path "./vendor*" -not -path "./tests/system/vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gofumpt -w
find . -name '*.go' -type f -not -path "./vendor*" -not -path "./tests/system/vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs misspell -w
find . -name '*.go' -type f -not -path "./vendor*" -not -path "./tests/system/vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs goimports -w -local github.com/CosmWasm/wasmd
find . -name '*.go' -type f -not -path "./vendor*" -not -path "./tests/system/vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gci write --skip-generated -s standard -s default -s "prefix(cosmossdk.io)" -s "prefix(github.com/cosmos/cosmos-sdk)" -s "prefix(github.com/CosmWasm/wasmd)" --custom-order


###############################################################################
Expand Down
7 changes: 6 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,7 @@ func NewWasmApp(

// initialize BaseApp
app.SetInitChainer(app.InitChainer)
app.SetPreBlocker(app.PreBlocker)
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.setAnteHandler(txConfig, wasmConfig, keys[wasmtypes.StoreKey])
Expand Down Expand Up @@ -949,6 +950,11 @@ func (app *WasmApp) setPostHandler() {
// Name returns the name of the App
func (app *WasmApp) Name() string { return app.BaseApp.Name() }

// PreBlocker application updates every pre block
func (app *WasmApp) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
return app.ModuleManager.PreBlock(ctx)
}

// BeginBlocker application updates every begin block
func (app *WasmApp) BeginBlocker(ctx sdk.Context) (sdk.BeginBlock, error) {
return app.ModuleManager.BeginBlock(ctx)
Expand Down Expand Up @@ -1164,6 +1170,5 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
paramsKeeper.Subspace(icahosttypes.SubModuleName)
paramsKeeper.Subspace(icacontrollertypes.SubModuleName)
paramsKeeper.Subspace(wasmtypes.ModuleName)

return paramsKeeper
}
93 changes: 72 additions & 21 deletions app/upgrades.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,90 @@
package app

import (
"context"
"fmt"

icacontrollertypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/types"
icahosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types"
ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
ibcclienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" //nolint:staticcheck
ibcconnectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types"
ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported"

storetypes "cosmossdk.io/store/types"
upgradetypes "cosmossdk.io/x/upgrade/types"

"github.com/cosmos/cosmos-sdk/types/module"
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"

"github.com/CosmWasm/wasmd/app/upgrades"
"github.com/CosmWasm/wasmd/app/upgrades/noop"
v050 "github.com/CosmWasm/wasmd/app/upgrades/v050"
)

// UpgradeName defines the on-chain upgrade name for the sample SimApp upgrade
// from v047 to v050.
//
// NOTE: This upgrade defines a reference implementation of what an upgrade
// could look like when an application is migrating from Cosmos SDK version
// v0.47.x to v0.50.x.
const UpgradeName = "v047-to-v050"
// Upgrades list of chain upgrades
var Upgrades = []upgrades.Upgrade{v050.Upgrade}

// RegisterUpgradeHandlers registers the chain upgrade handlers
func (app WasmApp) RegisterUpgradeHandlers() {
app.UpgradeKeeper.SetUpgradeHandler(
UpgradeName,
func(ctx context.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM)
},
)
setupLegacyKeyTables(app.ParamsKeeper)
if len(Upgrades) == 0 {
// always have a unique upgrade registered for the current version to test in system tests
Upgrades = append(Upgrades, noop.NewUpgrade(app.Version()))

Check warning on line 31 in app/upgrades.go

View check run for this annotation

Codecov / codecov/patch

app/upgrades.go#L31

Added line #L31 was not covered by tests
alpe marked this conversation as resolved.
Show resolved Hide resolved
}

keepers := upgrades.AppKeepers{AccountKeeper: app.AccountKeeper}
// register all upgrade handlers
for _, upgrade := range Upgrades {
app.UpgradeKeeper.SetUpgradeHandler(
upgrade.UpgradeName,
upgrade.CreateUpgradeHandler(
app.ModuleManager,
app.configurator,
&keepers,
),
)
}

upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
if err != nil {
panic(err)
panic(fmt.Sprintf("failed to read upgrade info from disk %s", err))

Check warning on line 49 in app/upgrades.go

View check run for this annotation

Codecov / codecov/patch

app/upgrades.go#L49

Added line #L49 was not covered by tests
}

if upgradeInfo.Name == UpgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := storetypes.StoreUpgrades{}
if app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
return

Check warning on line 53 in app/upgrades.go

View check run for this annotation

Codecov / codecov/patch

app/upgrades.go#L53

Added line #L53 was not covered by tests
}

// register store loader for current upgrade
for _, upgrade := range Upgrades {
if upgradeInfo.Name == upgrade.UpgradeName {
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &upgrade.StoreUpgrades)) // nolint:gosec
break

Check warning on line 60 in app/upgrades.go

View check run for this annotation

Codecov / codecov/patch

app/upgrades.go#L59-L60

Added lines #L59 - L60 were not covered by tests
}
}
}

func setupLegacyKeyTables(k paramskeeper.Keeper) {
// Set param key table for params module migration
for _, subspace := range k.GetSubspaces() {
subspace := subspace

var keyTable paramstypes.KeyTable
switch subspace.Name() {
// ibc types
case ibcexported.ModuleName:
keyTable = ibcclienttypes.ParamKeyTable()
keyTable.RegisterParamSet(&ibcconnectiontypes.Params{})
case ibctransfertypes.ModuleName:
keyTable = ibctransfertypes.ParamKeyTable()
case icahosttypes.SubModuleName:
keyTable = icahosttypes.ParamKeyTable()
case icacontrollertypes.SubModuleName:
keyTable = icacontrollertypes.ParamKeyTable()
default:
continue
}

// configure store loader that checks if version == upgradeHeight and applies store upgrades
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades))
if !subspace.HasKeyTable() {
subspace.WithKeyTable(keyTable)
}
}
}
34 changes: 34 additions & 0 deletions app/upgrades/noop/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package noop

import (
"context"

storetypes "cosmossdk.io/store/types"
upgradetypes "cosmossdk.io/x/upgrade/types"

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

"github.com/CosmWasm/wasmd/app/upgrades"
)

// NewUpgrade constructor
func NewUpgrade(semver string) upgrades.Upgrade {
return upgrades.Upgrade{
UpgradeName: semver,
CreateUpgradeHandler: CreateUpgradeHandler,
StoreUpgrades: storetypes.StoreUpgrades{
Added: []string{},
Deleted: []string{},
},
}
}

func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
ak *upgrades.AppKeepers,
) upgradetypes.UpgradeHandler {
return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
return mm.RunMigrations(ctx, configurator, fromVM)
}
}
26 changes: 26 additions & 0 deletions app/upgrades/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package upgrades

import (
storetypes "cosmossdk.io/store/types"
upgradetypes "cosmossdk.io/x/upgrade/types"

"github.com/cosmos/cosmos-sdk/types/module"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
)

type AppKeepers struct {
authkeeper.AccountKeeper
}

// Upgrade defines a struct containing necessary fields that a SoftwareUpgradeProposal
// must have written, in order for the state migration to go smoothly.
// An upgrade must implement this struct, and then set it in the app.go.
// The app.go will then define the handler.
type Upgrade struct {
// Upgrade version name, for the upgrade handler, e.g. `v7`
UpgradeName string

// CreateUpgradeHandler defines the function that creates an upgrade handler
CreateUpgradeHandler func(*module.Manager, module.Configurator, *AppKeepers) upgradetypes.UpgradeHandler
StoreUpgrades storetypes.StoreUpgrades
}
37 changes: 37 additions & 0 deletions app/upgrades/v050/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package v050

import (
"context"

storetypes "cosmossdk.io/store/types"
circuittypes "cosmossdk.io/x/circuit/types"
upgradetypes "cosmossdk.io/x/upgrade/types"

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

"github.com/CosmWasm/wasmd/app/upgrades"
)

// UpgradeName defines the on-chain upgrade name
const UpgradeName = "v0.50"

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
StoreUpgrades: storetypes.StoreUpgrades{
Added: []string{
circuittypes.ModuleName,
},
Deleted: []string{},
},
}

func CreateUpgradeHandler(
mm *module.Manager,
configurator module.Configurator,
ak *upgrades.AppKeepers,
) upgradetypes.UpgradeHandler {
return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
return mm.RunMigrations(ctx, configurator, fromVM)
}
}
5 changes: 3 additions & 2 deletions cmd/wasmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type startArgs struct {
outputDir string
printMnemonic bool
rpcAddress string
timeoutCommit time.Duration
}

func addTestnetFlagsToCmd(cmd *cobra.Command) {
Expand Down Expand Up @@ -159,14 +160,13 @@ Example:
if err != nil {
return err
}

return initTestnetFiles(clientCtx, cmd, config, mbm, genBalIterator, clientCtx.TxConfig.SigningContext().ValidatorAddressCodec(), args)
},
}

addTestnetFlagsToCmd(cmd)
cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)")
cmd.Flags().String(flagNodeDaemonHome, "wasmd", "Home directory of the node's daemon configuration")
cmd.Flags().String(flagNodeDaemonHome, version.AppName, "Home directory of the node's daemon configuration")
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1", "Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
cmd.Flags().Duration(flagCommitTimeout, 5*time.Second, "Time to wait after a block commit before starting on the new height")
Expand Down Expand Up @@ -553,6 +553,7 @@ func startTestnet(cmd *cobra.Command, args startArgs) error {
networkConfig.APIAddress = args.apiAddress
networkConfig.GRPCAddress = args.grpcAddress
networkConfig.PrintMnemonic = args.printMnemonic
networkConfig.TimeoutCommit = args.timeoutCommit
networkLogger := network.NewCLILogger(cmd)

baseDir := fmt.Sprintf("%s/%s", args.outputDir, networkConfig.ChainID)
Expand Down
1 change: 1 addition & 0 deletions tests/system/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/testnet
/binaries
3 changes: 1 addition & 2 deletions tests/system/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ test:
format:
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gofumpt -w
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs misspell -w
find . -name '*.go' -type f -not -path "./vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs goimports -w -local github.com/CosmWasm/wasmd

find . -name '*.go' -type f -not -path "./vendor*" -not -path "./tests/system/vendor*" -not -path "*.git*" -not -path "./client/lcd/statik/statik.go" | xargs gci write --skip-generated -s standard -s default -s "prefix(cosmossdk.io)" -s "prefix(github.com/cosmos/cosmos-sdk)" -s "prefix(github.com/CosmWasm/wasmd)" --custom-order

.PHONY: all test format
9 changes: 6 additions & 3 deletions tests/system/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ func TestBasicWasm(t *testing.T) {
t.Cleanup(cleanupFn)

t.Log("Instantiate wasm code")
initMsg := fmt.Sprintf(`{"verifier":%q, "beneficiary":%q}`, randomBech32Addr(), randomBech32Addr())
verifierAddr := randomBech32Addr()
initMsg := fmt.Sprintf(`{"verifier":%q, "beneficiary":%q}`, verifierAddr, randomBech32Addr())
newContractAddr := cli.WasmInstantiate(codeID, initMsg, "--admin="+defaultSrcAddr, "--label=label1", "--from="+defaultSrcAddr)
assert.Equal(t, expContractAddr, newContractAddr)
assert.Len(t, done(), 1)
require.Equal(t, expContractAddr, newContractAddr)
require.Len(t, done(), 1)
gotRsp := cli.QuerySmart(newContractAddr, `{"verifier":{}}`)
require.Equal(t, fmt.Sprintf(`{"data":{"verifier":"%s"}}`, verifierAddr), gotRsp)

t.Log("Update Instantiate Config")
qResult = cli.CustomQuery("q", "wasm", "code-info", fmt.Sprint(codeID))
Expand Down
Loading