diff --git a/app/ante.go b/app/ante.go index dd07aefd22..0e14a001c5 100644 --- a/app/ante.go +++ b/app/ante.go @@ -6,8 +6,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/auth/types" - channelkeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/keeper" - ibcante "github.com/cosmos/cosmos-sdk/x/ibc/core/ante" + channelkeeper "github.com/cosmos/ibc-go/modules/core/04-channel/keeper" + ibcante "github.com/cosmos/ibc-go/modules/core/ante" ) // NewAnteHandler returns an AnteHandler that checks and increments sequence @@ -19,8 +19,8 @@ func NewAnteHandler( signModeHandler signing.SignModeHandler, txCounterStoreKey sdk.StoreKey, channelKeeper channelkeeper.Keeper, + fk ante.FeegrantKeeper, ) sdk.AnteHandler { - // copied sdk https://github.com/cosmos/cosmos-sdk/blob/v0.42.9/x/auth/ante/ante.go return sdk.ChainAnteDecorators( ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first wasmkeeper.NewCountTXDecorator(txCounterStoreKey), @@ -30,10 +30,9 @@ func NewAnteHandler( ante.TxTimeoutHeightDecorator{}, ante.NewValidateMemoDecorator(ak), ante.NewConsumeGasForTxSizeDecorator(ak), - ante.NewRejectFeeGranterDecorator(), ante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators ante.NewValidateSigCountDecorator(ak), - ante.NewDeductFeeDecorator(ak, bankKeeper), + ante.NewDeductFeeDecorator(ak, bankKeeper, fk), ante.NewSigGasConsumeDecorator(ak, sigGasConsumer), ante.NewSigVerificationDecorator(ak, signModeHandler), ante.NewIncrementSequenceDecorator(ak), diff --git a/app/app.go b/app/app.go index 118294886d..1bea9880bf 100644 --- a/app/app.go +++ b/app/app.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + "github.com/cosmos/cosmos-sdk/version" "github.com/gorilla/mux" "github.com/rakyll/statik/fs" "github.com/spf13/cast" @@ -31,7 +32,6 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/ante" authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" @@ -56,19 +56,14 @@ import ( "github.com/cosmos/cosmos-sdk/x/evidence" evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + "github.com/cosmos/cosmos-sdk/x/feegrant" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + feegrantmod "github.com/cosmos/cosmos-sdk/x/feegrant/module" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer" - ibctransferkeeper "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" - ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" - ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" "github.com/cosmos/cosmos-sdk/x/mint" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" @@ -87,6 +82,14 @@ import ( upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + transfer "github.com/cosmos/ibc-go/modules/apps/transfer" + ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/modules/core" + ibcclient "github.com/cosmos/ibc-go/modules/core/02-client" + porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types" + ibchost "github.com/cosmos/ibc-go/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper" // unnamed import of statik for swagger UI support _ "github.com/cosmos/cosmos-sdk/client/docs/statik" @@ -170,6 +173,7 @@ var ( evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, vesting.AppModuleBasic{}, + feegrantmod.AppModuleBasic{}, ) // module account permissions @@ -200,7 +204,7 @@ var ( type WasmApp struct { *baseapp.BaseApp legacyAmino *codec.LegacyAmino - appCodec codec.Marshaler + appCodec codec.Codec interfaceRegistry types.InterfaceRegistry invCheckPeriod uint @@ -226,6 +230,7 @@ type WasmApp struct { evidenceKeeper evidencekeeper.Keeper transferKeeper ibctransferkeeper.Keeper wasmKeeper wasm.Keeper + feegrantKeeper feegrantkeeper.Keeper scopedIBCKeeper capabilitykeeper.ScopedKeeper scopedTransferKeeper capabilitykeeper.ScopedKeeper @@ -234,6 +239,9 @@ type WasmApp struct { // the module manager mm *module.Manager + // module configurator + configurator module.Configurator + // simulation manager sm *module.SimulationManager } @@ -249,16 +257,17 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b bApp := baseapp.NewBaseApp(appName, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...) bApp.SetCommitMultiStoreTracer(traceStore) - bApp.SetAppVersion(version.Version) + bApp.SetVersion(version.Version) bApp.SetInterfaceRegistry(interfaceRegistry) keys := sdk.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, - evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, feegrant.StoreKey, wasm.StoreKey, ) + tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -308,7 +317,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b app.crisisKeeper = crisiskeeper.NewKeeper( app.getSubspace(crisistypes.ModuleName), invCheckPeriod, app.bankKeeper, authtypes.FeeCollectorName, ) - app.upgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath) + app.upgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp) // register the staking hooks // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks @@ -316,9 +325,11 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b stakingtypes.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()), ) + app.feegrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.accountKeeper) + // Create IBC Keeper app.ibcKeeper = ibckeeper.NewKeeper( - appCodec, keys[ibchost.StoreKey], app.getSubspace(ibchost.ModuleName), app.stakingKeeper, scopedIBCKeeper, + appCodec, keys[ibchost.StoreKey], app.getSubspace(ibchost.ModuleName), app.stakingKeeper, app.upgradeKeeper, scopedIBCKeeper, ) // register the proposal types @@ -327,7 +338,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.paramsKeeper)). AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.distrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.upgradeKeeper)). - AddRoute(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.ibcKeeper.ClientKeeper)) + AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.ibcKeeper.ClientKeeper)) // Create Transfer Keepers app.transferKeeper = ibctransferkeeper.NewKeeper( @@ -337,10 +348,6 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b ) transferModule := transfer.NewAppModule(app.transferKeeper) - // Create static IBC router, add transfer route, then set and seal it - ibcRouter := porttypes.NewRouter() - ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) - // create evidence keeper with router evidenceKeeper := evidencekeeper.NewKeeper( appCodec, keys[evidencetypes.StoreKey], &app.stakingKeeper, app.slashingKeeper, @@ -369,6 +376,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b scopedWasmKeeper, app.transferKeeper, app.Router(), + app.MsgServiceRouter(), app.GRPCQueryRouter(), wasmDir, wasmConfig, @@ -380,6 +388,10 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b if len(enabledProposals) != 0 { govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(app.wasmKeeper, enabledProposals)) } + + // Create static IBC router, add transfer route, then set and seal it + ibcRouter := porttypes.NewRouter() + ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) ibcRouter.AddRoute(wasm.ModuleName, wasm.NewIBCHandler(app.wasmKeeper, app.ibcKeeper.ChannelKeeper)) app.ibcKeeper.SetRouter(ibcRouter) @@ -421,6 +433,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b ibc.NewAppModule(app.ibcKeeper), params.NewAppModule(app.paramsKeeper), transferModule, + feegrantmod.NewAppModule(appCodec, app.accountKeeper, app.bankKeeper, app.feegrantKeeper, app.interfaceRegistry), ) // During begin block slashing happens after distr.BeginBlocker so that @@ -450,7 +463,8 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b app.mm.RegisterInvariants(&app.crisisKeeper) app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) - app.mm.RegisterServices(module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter())) + app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()) + app.mm.RegisterServices(app.configurator) // add test gRPC service for testing gRPC queries in isolation // testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.QueryImpl{}) // TODO: this is testdata !!!! @@ -471,6 +485,7 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b params.NewAppModule(app.paramsKeeper), wasm.NewAppModule(appCodec, &app.wasmKeeper, app.stakingKeeper), evidence.NewAppModule(app.evidenceKeeper), + feegrantmod.NewAppModule(appCodec, app.accountKeeper, app.bankKeeper, app.feegrantKeeper, app.interfaceRegistry), ibc.NewAppModule(app.ibcKeeper), transferModule, ) @@ -485,12 +500,20 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b // initialize BaseApp app.SetInitChainer(app.InitChainer) app.SetBeginBlocker(app.BeginBlocker) - app.SetAnteHandler( - NewAnteHandler( - app.accountKeeper, app.bankKeeper, ante.DefaultSigVerificationGasConsumer, - encodingConfig.TxConfig.SignModeHandler(), keys[wasm.StoreKey], app.ibcKeeper.ChannelKeeper, - ), + anteHandler, err := ante.NewAnteHandler( + ante.HandlerOptions{ + AccountKeeper: app.accountKeeper, + BankKeeper: app.bankKeeper, + FeegrantKeeper: app.feegrantKeeper, + SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), + SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + }, ) + if err != nil { + tmos.Exit(err.Error()) + } + app.SetAnteHandler(anteHandler) + app.SetEndBlocker(app.EndBlocker) if loadLatest { @@ -506,7 +529,8 @@ func NewWasmApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b // Note that since this reads from the store, we can only perform it when // `loadLatest` is set to true. ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{}) - app.capabilityKeeper.InitializeAndSeal(ctx) + app.capabilityKeeper.InitMemStore(ctx) + app.capabilityKeeper.Seal() // Initialize pinned codes in wasmvm as they are not persisted there if err := app.wasmKeeper.InitializePinnedCodes(ctx); err != nil { @@ -610,7 +634,7 @@ func (app *WasmApp) RegisterTendermintService(clientCtx client.Context) { tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) } -func (app *WasmApp) AppCodec() codec.JSONMarshaler { +func (app *WasmApp) AppCodec() codec.Codec { return app.appCodec } @@ -635,7 +659,7 @@ func GetMaccPerms() map[string][]string { } // initParamsKeeper init params keeper and its subspaces -func initParamsKeeper(appCodec codec.BinaryMarshaler, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper { +func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper { paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey) paramsKeeper.Subspace(authtypes.ModuleName) @@ -652,3 +676,28 @@ func initParamsKeeper(appCodec codec.BinaryMarshaler, legacyAmino *codec.LegacyA return paramsKeeper } + +// GetBaseApp implements the TestingApp interface. +func (app *WasmApp) GetBaseApp() *baseapp.BaseApp { + return app.BaseApp +} + +// GetStakingKeeper implements the TestingApp interface. +func (app *WasmApp) GetStakingKeeper() stakingkeeper.Keeper { + return app.stakingKeeper +} + +// GetIBCKeeper implements the TestingApp interface. +func (app *WasmApp) GetIBCKeeper() *ibckeeper.Keeper { + return app.ibcKeeper +} + +// GetScopedIBCKeeper implements the TestingApp interface. +func (app *WasmApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { + return app.scopedIBCKeeper +} + +// GetTxConfig implements the TestingApp interface. +func (app *WasmApp) GetTxConfig() client.TxConfig { + return MakeEncodingConfig().TxConfig +} diff --git a/app/encoding.go b/app/encoding.go index 1bd14b7827..499be6b887 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -12,7 +12,7 @@ import ( // This is provided for compatibility between protobuf and amino implementations. type EncodingConfig struct { InterfaceRegistry types.InterfaceRegistry - Marshaler codec.Marshaler + Marshaler codec.Codec TxConfig client.TxConfig Amino *codec.LegacyAmino } diff --git a/app/sim_test.go b/app/sim_test.go index adf408e7b9..a03ac57061 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -15,13 +15,13 @@ import ( distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/simulation" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + ibchost "github.com/cosmos/ibc-go/modules/core/24-host" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" diff --git a/app/test_access.go b/app/test_access.go index 3332dcb5fb..219dc7fa5a 100644 --- a/app/test_access.go +++ b/app/test_access.go @@ -7,9 +7,9 @@ import ( "github.com/cosmos/cosmos-sdk/codec" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - ibctransferkeeper "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper" - ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper" + ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper" ) type TestSupport struct { @@ -29,7 +29,7 @@ func (s TestSupport) WasmKeeper() wasm.Keeper { return s.app.wasmKeeper } -func (s TestSupport) AppCodec() codec.Marshaler { +func (s TestSupport) AppCodec() codec.Codec { return s.app.appCodec } func (s TestSupport) ScopedWasmIBCKeeper() capabilitykeeper.ScopedKeeper { diff --git a/app/test_helpers.go b/app/test_helpers.go index 54c896616a..91ee3de453 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -9,8 +9,12 @@ import ( "testing" "time" + "github.com/CosmWasm/wasmd/x/wasm" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting" + "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" @@ -29,6 +33,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -83,6 +88,22 @@ func Setup(isCheckTx bool) *WasmApp { return app } +func SetupTestingApp(opts ...wasm.Option) (ibctesting.TestingApp, map[string]json.RawMessage) { + app := NewWasmApp( + log.NewNopLogger(), + dbm.NewMemDB(), + nil, + true, + map[int64]bool{}, + DefaultNodeHome, + 5, + wasm.EnableAllProposals, + EmptyBaseAppOptions{}, + opts, + ) + return app, NewDefaultGenesisState() +} + // SetupWithGenesisValSet initializes a new WasmApp with a validator set and genesis accounts // that also act as delegators. For simplicity, each validator is bonded with a delegation // of one consensus engine unit (10^6) in the default token of the WasmApp from first genesis @@ -128,7 +149,7 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs totalSupply := sdk.NewCoins() for _, b := range balances { // add genesis acc tokens and delegated tokens to total supply - totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))...) + totalSupply = totalSupply.Add(b.Coins...) } // update total supply @@ -242,9 +263,13 @@ func AddTestAddrsFromPubKeys(app *WasmApp, ctx sdk.Context, pubKeys []cryptotype // setTotalSupply provides the total supply based on accAmt * totalAccounts. func setTotalSupply(app *WasmApp, ctx sdk.Context, accAmt sdk.Int, totalAccounts int) { - totalSupply := sdk.NewCoins(sdk.NewCoin(app.stakingKeeper.BondDenom(ctx), accAmt.MulRaw(int64(totalAccounts)))) - prevSupply := app.bankKeeper.GetSupply(ctx) - app.bankKeeper.SetSupply(ctx, banktypes.NewSupply(prevSupply.GetTotal().Add(totalSupply...))) + totalSupply := sdk.NewCoin(app.stakingKeeper.BondDenom(ctx), accAmt.MulRaw(int64(totalAccounts))) + prevSupply := app.bankKeeper.GetSupply(ctx, app.stakingKeeper.BondDenom(ctx)) + newTotal := totalSupply.Add(prevSupply) + err := app.bankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.NewCoins(newTotal)) + if err != nil { + panic(err) + } } // AddTestAddrs constructs and returns accNum amount of accounts with an @@ -277,7 +302,11 @@ func addTestAddrs(app *WasmApp, ctx sdk.Context, accNum int, accAmt sdk.Int, str func saveAccount(app *WasmApp, ctx sdk.Context, addr sdk.AccAddress, initCoins sdk.Coins) { acc := app.accountKeeper.NewAccountWithAddress(ctx, addr) app.accountKeeper.SetAccount(ctx, acc) - err := app.bankKeeper.AddCoins(ctx, addr, initCoins) + err := app.bankKeeper.MintCoins(ctx, minttypes.ModuleName, initCoins) + if err != nil { + panic(err) + } + err = app.bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, initCoins) if err != nil { panic(err) } @@ -443,3 +472,17 @@ type EmptyBaseAppOptions struct{} func (ao EmptyBaseAppOptions) Get(o string) interface{} { return nil } + +func IBCTestSupport(t *testing.T, chain *ibctesting.TestChain) *TestSupport { + app, ok := chain.App.(*WasmApp) + if !ok { + panic("not a wasmd app") + } + return NewTestSupport(t, app) +} + +// ContractInfo is a helper function to returns the ContractInfo for the given contract address +func ContractInfo(t *testing.T, c *ibctesting.TestChain, contractAddr sdk.AccAddress) *types.ContractInfo { + ibcs := IBCTestSupport(t, c) + return ibcs.WasmKeeper().GetContractInfo(c.GetContext(), contractAddr) +} diff --git a/cmd/wasmd/genaccounts.go b/cmd/wasmd/genaccounts.go index 252301d637..3cdcab2cf6 100644 --- a/cmd/wasmd/genaccounts.go +++ b/cmd/wasmd/genaccounts.go @@ -40,8 +40,8 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { clientCtx := client.GetClientContextFromCmd(cmd) - depCdc := clientCtx.JSONMarshaler - cdc := depCdc.(codec.Marshaler) + depCdc := clientCtx.JSONCodec + cdc := depCdc.(codec.Codec) serverCtx := server.GetServerContextFromCmd(cmd) config := serverCtx.Config diff --git a/cmd/wasmd/root.go b/cmd/wasmd/root.go index 485ac51825..7ea9de968a 100644 --- a/cmd/wasmd/root.go +++ b/cmd/wasmd/root.go @@ -33,7 +33,6 @@ import ( "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/crisis" @@ -52,7 +51,7 @@ func NewRootCmd() (*cobra.Command, app.EncodingConfig) { config.Seal() initClientCtx := client.Context{}. - WithJSONMarshaler(clientcodec.NewProtoCodec(encodingConfig.Marshaler, encodingConfig.InterfaceRegistry)). + WithJSONCodec(clientcodec.NewProtoCodec(encodingConfig.Marshaler, encodingConfig.InterfaceRegistry)). WithInterfaceRegistry(encodingConfig.InterfaceRegistry). WithTxConfig(encodingConfig.TxConfig). WithLegacyAmino(encodingConfig.Amino). @@ -69,7 +68,7 @@ func NewRootCmd() (*cobra.Command, app.EncodingConfig) { return err } - return server.InterceptConfigsPreRunHandler(cmd) + return server.InterceptConfigsPreRunHandler(cmd, "", nil) }, } @@ -79,7 +78,6 @@ func NewRootCmd() (*cobra.Command, app.EncodingConfig) { } func initRootCmd(rootCmd *cobra.Command, encodingConfig app.EncodingConfig) { - authclient.Codec = encodingConfig.Marshaler rootCmd.AddCommand( genutilcli.InitCmd(app.ModuleBasics, app.DefaultNodeHome), diff --git a/go.mod b/go.mod index 6dbfb6f9dc..66985914a7 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,12 @@ module github.com/CosmWasm/wasmd -go 1.16 +go 1.17 require ( github.com/CosmWasm/wasmvm v1.0.0-beta - github.com/cosmos/cosmos-sdk v0.42.10 + github.com/cosmos/cosmos-sdk v0.44.2 github.com/cosmos/iavl v0.17.1 + github.com/cosmos/ibc-go v1.2.1 github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 @@ -19,18 +20,106 @@ require ( github.com/rs/zerolog v1.25.0 github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa github.com/spf13/cast v1.4.1 - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.9.0 github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca - github.com/tendermint/tendermint v0.34.13 + github.com/tendermint/tendermint v0.34.14 github.com/tendermint/tm-db v0.6.4 google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 google.golang.org/grpc v1.40.0 gopkg.in/yaml.v2 v2.4.0 ) +require ( + filippo.io/edwards25519 v1.0.0-beta.2 // indirect + github.com/99designs/keyring v1.1.6 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/Workiva/go-datastructures v1.0.52 // indirect + github.com/armon/go-metrics v0.3.9 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/coinbase/rosetta-sdk-go v0.6.10 // indirect + github.com/confio/ics23/go v0.6.6 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect + github.com/cosmos/ledger-go v0.9.2 // indirect + github.com/danieljoos/wincred v1.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect + github.com/dgraph-io/badger/v2 v2.2007.2 // indirect + github.com/dgraph-io/ristretto v0.0.3 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 // indirect + github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/go-kit/kit v0.10.0 // indirect + github.com/go-logfmt/logfmt v0.5.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/gateway v1.1.0 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/btree v1.0.0 // indirect + github.com/google/orderedcode v0.0.1 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/go-immutable-radix v1.0.0 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect + github.com/improbable-eng/grpc-web v0.14.1 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect + github.com/klauspost/compress v1.11.7 // indirect + github.com/lib/pq v1.10.2 // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/magiconair/properties v1.8.5 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/minio/highwayhash v1.0.1 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.4.2 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/pelletier/go-toml v1.9.4 // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.29.0 // indirect + github.com/prometheus/procfs v0.6.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/rs/cors v1.7.0 // indirect + github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect + github.com/tendermint/btcd v0.1.1 // indirect + github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/zondax/hid v0.9.0 // indirect + go.etcd.io/bbolt v1.3.5 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f // indirect + golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect + golang.org/x/text v0.3.6 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/ini.v1 v1.63.2 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + nhooyr.io/websocket v1.8.6 // indirect +) + replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/go.sum b/go.sum index 3f42719ba8..fcd1419f04 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,6 @@ +4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= @@ -11,6 +13,7 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= @@ -37,18 +40,38 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= +cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.0.0-beta.2 h1:/BZRNzm8N4K4eWfK28dL4yescorxtO7YG1yun8fy+pI= +filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= github.com/99designs/keyring v1.1.6 h1:kVDC2uCgVwecxCk+9zoCt2uEL6dt+dfVzMvGgnVcIuM= github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU= +github.com/Antonboom/errname v0.1.4/go.mod h1:jRXo3m0E0EuCnK3wbsSVH3X55Z4iTDLl6ZfCxwFj4TM= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= @@ -58,7 +81,13 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= @@ -66,12 +95,17 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= github.com/adlio/schema v1.1.13 h1:LeNMVg5Z1FX+Qgz8tJUijBLRdcpbFUElz+d1489On98= github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -81,19 +115,31 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.8 h1:oOxq3KPj0WhCuy50EhzwiyMyG2ovRQZpZLXQuOh2a/M= -github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= +github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= +github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -103,15 +149,23 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= +github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= +github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= @@ -123,10 +177,13 @@ github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charithe/durationcheck v0.0.8/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= +github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -135,9 +192,12 @@ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coinbase/rosetta-sdk-go v0.6.10 h1:rgHD/nHjxLh0lMEdfGDqpTtlvtSBwULqrrZ2qPdNaCM= +github.com/coinbase/rosetta-sdk-go v0.6.10/go.mod h1:J/JFMsfcePrjJZkwQFLh+hJErkAmdm9Iyy3D5Y0LfXo= github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= @@ -154,11 +214,13 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cosmos/cosmos-sdk v0.42.10 h1:CO+V3RqeFVu6TkqDlQj1992BYK0a7p0eekQ2KsH7SZo= -github.com/cosmos/cosmos-sdk v0.42.10/go.mod h1:uRfvOMODP3ltiDN3GMDTKCZnGxG1NSFdoOEKtizoCtc= +github.com/cosmos/cosmos-sdk v0.44.1/go.mod h1:fwQJdw+aECatpTvQTo1tSfHEsxACdZYU80QCZUPnHr4= +github.com/cosmos/cosmos-sdk v0.44.2 h1:EWoj9h9Q9t7uqS3LyqzZWWwnSEodUJlYDMloDoPBD3Y= +github.com/cosmos/cosmos-sdk v0.44.2/go.mod h1:fwQJdw+aECatpTvQTo1tSfHEsxACdZYU80QCZUPnHr4= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -167,6 +229,8 @@ github.com/cosmos/iavl v0.15.0-rc5/go.mod h1:WqoPL9yPTQ85QBMT45OOUzPxG/U/JcJoN7u github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mVvSA4= github.com/cosmos/iavl v0.17.1 h1:b/Cl8h1PRMvsu24+TYNlKchIu7W6tmxIBGe6E9u2Ybw= github.com/cosmos/iavl v0.17.1/go.mod h1:7aisPZK8yCpQdy3PMvKeO+bhq1NwDjUwjzxwwROUxFk= +github.com/cosmos/ibc-go v1.2.1 h1:eWi8EzcgSwVipvhyQ7Rh1KfBe66C1ZdDSskeKMtIg0Q= +github.com/cosmos/ibc-go v1.2.1/go.mod h1:YieSs25Y0TSFR67qg6Elge34yJNEOjYhYB+HNQQLoSQ= github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= @@ -175,14 +239,21 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/daixiang0/gci v0.2.9/go.mod h1:+4dZ7TISfSmqfAGv59ePaHfNzgGtIkHAhhdKggP1JAc= github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU= github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k= github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= @@ -194,33 +265,47 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= +github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/esimonov/ifshort v1.0.2/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= +github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= +github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -230,7 +315,15 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= +github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-critic/go-critic v0.5.6/go.mod h1:cVjj0DfqewQVIlIAGexPCaGaZDAqGE29PYDDADIVNEo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -243,12 +336,44 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -266,6 +391,7 @@ github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71 github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -290,9 +416,21 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.42.1/go.mod h1:MuInrVlgg2jq4do6XI1jbkErbVHVbwdrLLtGv6p2wPI= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/revgrep v0.0.0-20210208091834-cd28932614b5/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -323,6 +461,7 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -332,12 +471,20 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= +github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= +github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= @@ -347,9 +494,21 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= +github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= +github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= +github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= +github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= +github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= @@ -360,6 +519,7 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -385,6 +545,7 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= @@ -408,19 +569,43 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 h1:uUjLpLt6bVvZ72SQc/B4dXcPBw4Vgd7soowdRl52qEM= +github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87/go.mod h1:XGsKKeXxeRr95aEOgipvluMPlgjr7dGlk9ZTWOjcUcg= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/improbable-eng/grpc-web v0.14.1 h1:NrN4PY71A6tAz2sKDvC5JCauENWp0ykG8Oq1H3cpFvw= +github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= +github.com/jhump/protoreflect v1.9.0 h1:npqHz788dryJiR/l6K/RUQAyh2SwV91+d1dnh4RjO9w= +github.com/jhump/protoreflect v1.9.0/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= +github.com/jingyugao/rowserrcheck v1.1.0/go.mod h1:TOQpc2SLx6huPfoFGK3UOnEG+u02D3C1GeosjupAKCA= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -428,19 +613,32 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= +github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -448,60 +646,114 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= +github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2GhLxSfY+oqUsvG30= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/ldez/tagliatelle v0.2.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= +github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.1.1/go.mod h1:PKqk4L74K6wVNwY2b6fr+9Qqr/3hIsHVfZCJdbvozrY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= +github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= +github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= +github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= @@ -509,24 +761,39 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= +github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nishanths/exhaustive v0.2.3/go.mod h1:bhIX678Nx8inLM9PbpvK1yv6oGtoP8BfaIeMzgBNKvc= +github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= +github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= +github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB9sbB1usJ+xjQE= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -558,14 +825,18 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -574,8 +845,10 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -586,7 +859,6 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= -github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -604,10 +876,10 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.23.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE= +github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -615,9 +887,21 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= +github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= +github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= +github.com/quasilyte/go-ruleguard v0.3.4/go.mod h1:57FZgMnoo6jqxkYKmVj5Fc8vOt0rVzoE/UNAmFFIPqA= +github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.2/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20210203162857-b223e0831f88/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -627,26 +911,41 @@ github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzy github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= +github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo= github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II= github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryancurrah/gomodguard v1.2.3/go.mod h1:rYbA/4Tg5c54mV1sv4sQTP5WOPBcoLtnBZ7/TEhXAbg= +github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/securego/gosec/v2 v2.8.1/go.mod h1:pUmsq6+VyFEElJMUX+QB3p3LWNHXg1R3xh2ssVJPs8Q= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v3 v3.21.7/go.mod h1:RGl11Y7XMTQPmHh8F0ayC6haKNBgH4PXMJuTAcMOlz4= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -660,12 +959,13 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -676,8 +976,8 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -689,8 +989,13 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= +github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -698,6 +1003,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -711,6 +1018,7 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= @@ -722,24 +1030,60 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.13 h1:fu+tsHudbOr5PvepjH0q47Jae59hQAvn3IqAHv2EbC8= github.com/tendermint/tendermint v0.34.13/go.mod h1:6RVVRBqwtKhA+H59APKumO+B7Nye4QXSFc6+TYxAxCI= +github.com/tendermint/tendermint v0.34.14 h1:GCXmlS8Bqd2Ix3TQCpwYLUNHe+Y+QyJsm5YE+S/FkPo= +github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= +github.com/tetafro/godot v1.4.9/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= +github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg= +github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/tklauser/go-sysconf v0.3.7/go.mod h1:JZIdXh4RmBvZDBZ41ld2bGxRV3n4daiiqA3skYhAoQ4= +github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tomarrell/wrapcheck/v2 v2.3.0/go.mod h1:aF5rnkdtqNWP/gC7vPUO5pKsB0Oac2FDTQP4F+dpZMU= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= +github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= +github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= +github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -749,12 +1093,15 @@ github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -770,20 +1117,24 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -796,11 +1147,13 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= @@ -824,10 +1177,12 @@ golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -836,6 +1191,7 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -869,10 +1225,12 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -882,7 +1240,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -896,6 +1256,7 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -904,6 +1265,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -935,6 +1297,7 @@ golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -963,10 +1326,12 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -974,11 +1339,11 @@ golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1012,11 +1377,18 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1026,20 +1398,27 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1049,19 +1428,46 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201118003311-bd56c0adb394/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= @@ -1080,6 +1486,7 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1097,6 +1504,7 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -1107,11 +1515,14 @@ google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1120,6 +1531,7 @@ google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dT google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= @@ -1141,6 +1553,8 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1151,7 +1565,7 @@ google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1183,6 +1597,7 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= @@ -1195,16 +1610,20 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1212,6 +1631,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1227,6 +1647,13 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= +mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7/go.mod h1:hBpJkZE8H/sb+VRFvw2+rBpHNsTBcvSpk61hr8mzXZE= +nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/third_party/proto/cosmos/auth/v1beta1/query.proto b/third_party/proto/cosmos/auth/v1beta1/query.proto index a885792683..76d30dd610 100644 --- a/third_party/proto/cosmos/auth/v1beta1/query.proto +++ b/third_party/proto/cosmos/auth/v1beta1/query.proto @@ -1,6 +1,7 @@ syntax = "proto3"; package cosmos.auth.v1beta1; +import "cosmos/base/query/v1beta1/pagination.proto"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; import "google/api/annotations.proto"; @@ -11,6 +12,11 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types"; // Query defines the gRPC querier service. service Query { + // Accounts returns all the existing accounts + rpc Accounts(QueryAccountsRequest) returns (QueryAccountsResponse) { + option (google.api.http).get = "/cosmos/auth/v1beta1/accounts"; + } + // Account returns account details based on address. rpc Account(QueryAccountRequest) returns (QueryAccountResponse) { option (google.api.http).get = "/cosmos/auth/v1beta1/accounts/{address}"; @@ -22,6 +28,21 @@ service Query { } } +// QueryAccountsRequest is the request type for the Query/Accounts RPC method. +message QueryAccountsRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryAccountsResponse is the response type for the Query/Accounts RPC method. +message QueryAccountsResponse { + // accounts are the existing accounts + repeated google.protobuf.Any accounts = 1 [(cosmos_proto.accepts_interface) = "AccountI"]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + // QueryAccountRequest is the request type for the Query/Account RPC method. message QueryAccountRequest { option (gogoproto.equal) = false; diff --git a/third_party/proto/cosmos/authz/v1beta1/authz.proto b/third_party/proto/cosmos/authz/v1beta1/authz.proto new file mode 100644 index 0000000000..c69a93c11f --- /dev/null +++ b/third_party/proto/cosmos/authz/v1beta1/authz.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/timestamp.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz"; +option (gogoproto.goproto_getters_all) = false; + +// GenericAuthorization gives the grantee unrestricted permissions to execute +// the provided method on behalf of the granter's account. +message GenericAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + // Msg, identified by it's type URL, to grant unrestricted permissions to execute + string msg = 1; +} + +// Grant gives permissions to execute +// the provide method with expiration time. +message Grant { + google.protobuf.Any authorization = 1 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; +} diff --git a/third_party/proto/cosmos/authz/v1beta1/event.proto b/third_party/proto/cosmos/authz/v1beta1/event.proto new file mode 100644 index 0000000000..c77cea3e6a --- /dev/null +++ b/third_party/proto/cosmos/authz/v1beta1/event.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz"; + +// EventGrant is emitted on Msg/Grant +message EventGrant { + // Msg type URL for which an autorization is granted + string msg_type_url = 2; + // Granter account address + string granter = 3; + // Grantee account address + string grantee = 4; +} + +// EventRevoke is emitted on Msg/Revoke +message EventRevoke { + // Msg type URL for which an autorization is revoked + string msg_type_url = 2; + // Granter account address + string granter = 3; + // Grantee account address + string grantee = 4; +} diff --git a/third_party/proto/cosmos/authz/v1beta1/genesis.proto b/third_party/proto/cosmos/authz/v1beta1/genesis.proto new file mode 100644 index 0000000000..411fd276fb --- /dev/null +++ b/third_party/proto/cosmos/authz/v1beta1/genesis.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/any.proto"; +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz"; + +// GenesisState defines the authz module's genesis state. +message GenesisState { + repeated GrantAuthorization authorization = 1 [(gogoproto.nullable) = false]; +} + +// GrantAuthorization defines the GenesisState/GrantAuthorization type. +message GrantAuthorization { + string granter = 1; + string grantee = 2; + + google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} diff --git a/third_party/proto/cosmos/authz/v1beta1/query.proto b/third_party/proto/cosmos/authz/v1beta1/query.proto new file mode 100644 index 0000000000..3b66e03107 --- /dev/null +++ b/third_party/proto/cosmos/authz/v1beta1/query.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "google/api/annotations.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "cosmos/authz/v1beta1/authz.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz"; + +// Query defines the gRPC querier service. +service Query { + // Returns list of `Authorization`, granted to the grantee by the granter. + rpc Grants(QueryGrantsRequest) returns (QueryGrantsResponse) { + option (google.api.http).get = "/cosmos/authz/v1beta1/grants"; + } +} + +// QueryGrantsRequest is the request type for the Query/Grants RPC method. +message QueryGrantsRequest { + string granter = 1; + string grantee = 2; + // Optional, msg_type_url, when set, will query only grants matching given msg type. + string msg_type_url = 3; + // pagination defines an pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 4; +} + +// QueryGrantsResponse is the response type for the Query/Authorizations RPC method. +message QueryGrantsResponse { + // authorizations is a list of grants granted for grantee by granter. + repeated cosmos.authz.v1beta1.Grant grants = 1; + // pagination defines an pagination for the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/third_party/proto/cosmos/authz/v1beta1/tx.proto b/third_party/proto/cosmos/authz/v1beta1/tx.proto new file mode 100644 index 0000000000..dd68984e92 --- /dev/null +++ b/third_party/proto/cosmos/authz/v1beta1/tx.proto @@ -0,0 +1,69 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/any.proto"; +import "cosmos/base/abci/v1beta1/abci.proto"; +import "cosmos/authz/v1beta1/authz.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz"; +option (gogoproto.goproto_getters_all) = false; + +// Msg defines the authz Msg service. +service Msg { + // Grant grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. If there is already a grant + // for the given (granter, grantee, Authorization) triple, then the grant + // will be overwritten. + rpc Grant(MsgGrant) returns (MsgGrantResponse); + + // Exec attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + rpc Exec(MsgExec) returns (MsgExecResponse); + + // Revoke revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + rpc Revoke(MsgRevoke) returns (MsgRevokeResponse); +} + +// MsgGrant is a request type for Grant method. It declares authorization to the grantee +// on behalf of the granter with the provided expiration time. +message MsgGrant { + string granter = 1; + string grantee = 2; + + cosmos.authz.v1beta1.Grant grant = 3 [(gogoproto.nullable) = false]; +} + +// MsgExecResponse defines the Msg/MsgExecResponse response type. +message MsgExecResponse { + repeated bytes results = 1; +} + +// MsgExec attempts to execute the provided messages using +// authorizations granted to the grantee. Each message should have only +// one signer corresponding to the granter of the authorization. +message MsgExec { + string grantee = 1; + // Authorization Msg requests to execute. Each msg must implement Authorization interface + // The x/authz will try to find a grant matching (msg.signers[0], grantee, MsgTypeURL(msg)) + // triple and validate it. + repeated google.protobuf.Any msgs = 2 [(cosmos_proto.accepts_interface) = "sdk.Msg, authz.Authorization"]; +} + +// MsgGrantResponse defines the Msg/MsgGrant response type. +message MsgGrantResponse {} + +// MsgRevoke revokes any authorization with the provided sdk.Msg type on the +// granter's account with that has been granted to the grantee. +message MsgRevoke { + string granter = 1; + string grantee = 2; + string msg_type_url = 3; +} + +// MsgRevokeResponse defines the Msg/MsgRevokeResponse response type. +message MsgRevokeResponse {} diff --git a/third_party/proto/cosmos/bank/v1beta1/authz.proto b/third_party/proto/cosmos/bank/v1beta1/authz.proto new file mode 100644 index 0000000000..f3505ad41c --- /dev/null +++ b/third_party/proto/cosmos/bank/v1beta1/authz.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package cosmos.bank.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/bank/types"; + +// SendAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account. +message SendAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + repeated cosmos.base.v1beta1.Coin spend_limit = 1 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; +} diff --git a/third_party/proto/cosmos/bank/v1beta1/bank.proto b/third_party/proto/cosmos/bank/v1beta1/bank.proto index 5a9383362e..eb843b2cb6 100644 --- a/third_party/proto/cosmos/bank/v1beta1/bank.proto +++ b/third_party/proto/cosmos/bank/v1beta1/bank.proto @@ -45,12 +45,14 @@ message Output { // Supply represents a struct that passively keeps track of the total supply // amounts in the network. +// This message is deprecated now that supply is indexed by denom. message Supply { - option (gogoproto.equal) = true; - option (gogoproto.goproto_getters) = false; - option (gogoproto.goproto_stringer) = false; + option deprecated = true; + + option (gogoproto.equal) = true; + option (gogoproto.goproto_getters) = false; - option (cosmos_proto.implements_interface) = "*github.com/cosmos/cosmos-sdk/x/bank/exported.SupplyI"; + option (cosmos_proto.implements_interface) = "*github.com/cosmos/cosmos-sdk/x/bank/legacy/v040.SupplyI"; repeated cosmos.base.v1beta1.Coin total = 1 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; @@ -82,4 +84,9 @@ message Metadata { // display indicates the suggested denom that should be // displayed in clients. string display = 4; + // name defines the name of the token (eg: Cosmos Atom) + string name = 5; + // symbol is the token symbol usually shown on exchanges (eg: ATOM). This can + // be the same as the display. + string symbol = 6; } diff --git a/third_party/proto/cosmos/bank/v1beta1/genesis.proto b/third_party/proto/cosmos/bank/v1beta1/genesis.proto index 25c80a38b5..8fd7329a0a 100644 --- a/third_party/proto/cosmos/bank/v1beta1/genesis.proto +++ b/third_party/proto/cosmos/bank/v1beta1/genesis.proto @@ -15,7 +15,8 @@ message GenesisState { // balances is an array containing the balances of all the accounts. repeated Balance balances = 2 [(gogoproto.nullable) = false]; - // supply represents the total supply. + // supply represents the total supply. If it is left empty, then supply will be calculated based on the provided + // balances. Otherwise, it will be used to validate that the sum of the balances equals this amount. repeated cosmos.base.v1beta1.Coin supply = 3 [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; diff --git a/third_party/proto/cosmos/bank/v1beta1/query.proto b/third_party/proto/cosmos/bank/v1beta1/query.proto index bc5e29137a..e3a464f8ba 100644 --- a/third_party/proto/cosmos/bank/v1beta1/query.proto +++ b/third_party/proto/cosmos/bank/v1beta1/query.proto @@ -90,7 +90,13 @@ message QueryAllBalancesResponse { // QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC // method. -message QueryTotalSupplyRequest {} +message QueryTotalSupplyRequest { + option (gogoproto.equal) = false; + option (gogoproto.goproto_getters) = false; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} // QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC // method @@ -98,6 +104,9 @@ message QueryTotalSupplyResponse { // supply is the supply of the coins repeated cosmos.base.v1beta1.Coin supply = 1 [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; } // QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. diff --git a/third_party/proto/cosmos/base/query/v1beta1/pagination.proto b/third_party/proto/cosmos/base/query/v1beta1/pagination.proto index 2a8cbccedd..784c479562 100644 --- a/third_party/proto/cosmos/base/query/v1beta1/pagination.proto +++ b/third_party/proto/cosmos/base/query/v1beta1/pagination.proto @@ -30,6 +30,9 @@ message PageRequest { // count_total is only respected when offset is used. It is ignored when key // is set. bool count_total = 4; + + // reverse is set to true if results are to be returned in the descending order. + bool reverse = 5; } // PageResponse is to be embedded in gRPC response messages where the diff --git a/third_party/proto/cosmos/base/reflection/v2alpha1/reflection.proto b/third_party/proto/cosmos/base/reflection/v2alpha1/reflection.proto new file mode 100644 index 0000000000..3e8e940482 --- /dev/null +++ b/third_party/proto/cosmos/base/reflection/v2alpha1/reflection.proto @@ -0,0 +1,217 @@ +syntax = "proto3"; +package cosmos.base.reflection.v2alpha1; + +import "google/api/annotations.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/server/grpc/reflection/v2alpha1"; + +// AppDescriptor describes a cosmos-sdk based application +message AppDescriptor { + // AuthnDescriptor provides information on how to authenticate transactions on the application + // NOTE: experimental and subject to change in future releases. + AuthnDescriptor authn = 1; + // chain provides the chain descriptor + ChainDescriptor chain = 2; + // codec provides metadata information regarding codec related types + CodecDescriptor codec = 3; + // configuration provides metadata information regarding the sdk.Config type + ConfigurationDescriptor configuration = 4; + // query_services provides metadata information regarding the available queriable endpoints + QueryServicesDescriptor query_services = 5; + // tx provides metadata information regarding how to send transactions to the given application + TxDescriptor tx = 6; +} + +// TxDescriptor describes the accepted transaction type +message TxDescriptor { + // fullname is the protobuf fullname of the raw transaction type (for instance the tx.Tx type) + // it is not meant to support polymorphism of transaction types, it is supposed to be used by + // reflection clients to understand if they can handle a specific transaction type in an application. + string fullname = 1; + // msgs lists the accepted application messages (sdk.Msg) + repeated MsgDescriptor msgs = 2; +} + +// AuthnDescriptor provides information on how to sign transactions without relying +// on the online RPCs GetTxMetadata and CombineUnsignedTxAndSignatures +message AuthnDescriptor { + // sign_modes defines the supported signature algorithm + repeated SigningModeDescriptor sign_modes = 1; +} + +// SigningModeDescriptor provides information on a signing flow of the application +// NOTE(fdymylja): here we could go as far as providing an entire flow on how +// to sign a message given a SigningModeDescriptor, but it's better to think about +// this another time +message SigningModeDescriptor { + // name defines the unique name of the signing mode + string name = 1; + // number is the unique int32 identifier for the sign_mode enum + int32 number = 2; + // authn_info_provider_method_fullname defines the fullname of the method to call to get + // the metadata required to authenticate using the provided sign_modes + string authn_info_provider_method_fullname = 3; +} + +// ChainDescriptor describes chain information of the application +message ChainDescriptor { + // id is the chain id + string id = 1; +} + +// CodecDescriptor describes the registered interfaces and provides metadata information on the types +message CodecDescriptor { + // interfaces is a list of the registerted interfaces descriptors + repeated InterfaceDescriptor interfaces = 1; +} + +// InterfaceDescriptor describes the implementation of an interface +message InterfaceDescriptor { + // fullname is the name of the interface + string fullname = 1; + // interface_accepting_messages contains information regarding the proto messages which contain the interface as + // google.protobuf.Any field + repeated InterfaceAcceptingMessageDescriptor interface_accepting_messages = 2; + // interface_implementers is a list of the descriptors of the interface implementers + repeated InterfaceImplementerDescriptor interface_implementers = 3; +} + +// InterfaceImplementerDescriptor describes an interface implementer +message InterfaceImplementerDescriptor { + // fullname is the protobuf queryable name of the interface implementer + string fullname = 1; + // type_url defines the type URL used when marshalling the type as any + // this is required so we can provide type safe google.protobuf.Any marshalling and + // unmarshalling, making sure that we don't accept just 'any' type + // in our interface fields + string type_url = 2; +} + +// InterfaceAcceptingMessageDescriptor describes a protobuf message which contains +// an interface represented as a google.protobuf.Any +message InterfaceAcceptingMessageDescriptor { + // fullname is the protobuf fullname of the type containing the interface + string fullname = 1; + // field_descriptor_names is a list of the protobuf name (not fullname) of the field + // which contains the interface as google.protobuf.Any (the interface is the same, but + // it can be in multiple fields of the same proto message) + repeated string field_descriptor_names = 2; +} + +// ConfigurationDescriptor contains metadata information on the sdk.Config +message ConfigurationDescriptor { + // bech32_account_address_prefix is the account address prefix + string bech32_account_address_prefix = 1; +} + +// MsgDescriptor describes a cosmos-sdk message that can be delivered with a transaction +message MsgDescriptor { + // msg_type_url contains the TypeURL of a sdk.Msg. + string msg_type_url = 1; +} + +// ReflectionService defines a service for application reflection. +service ReflectionService { + // GetAuthnDescriptor returns information on how to authenticate transactions in the application + // NOTE: this RPC is still experimental and might be subject to breaking changes or removal in + // future releases of the cosmos-sdk. + rpc GetAuthnDescriptor(GetAuthnDescriptorRequest) returns (GetAuthnDescriptorResponse) { + option (google.api.http).get = "/cosmos/base/reflection/v1beta1/app_descriptor/authn"; + } + // GetChainDescriptor returns the description of the chain + rpc GetChainDescriptor(GetChainDescriptorRequest) returns (GetChainDescriptorResponse) { + option (google.api.http).get = "/cosmos/base/reflection/v1beta1/app_descriptor/chain"; + }; + // GetCodecDescriptor returns the descriptor of the codec of the application + rpc GetCodecDescriptor(GetCodecDescriptorRequest) returns (GetCodecDescriptorResponse) { + option (google.api.http).get = "/cosmos/base/reflection/v1beta1/app_descriptor/codec"; + } + // GetConfigurationDescriptor returns the descriptor for the sdk.Config of the application + rpc GetConfigurationDescriptor(GetConfigurationDescriptorRequest) returns (GetConfigurationDescriptorResponse) { + option (google.api.http).get = "/cosmos/base/reflection/v1beta1/app_descriptor/configuration"; + } + // GetQueryServicesDescriptor returns the available gRPC queryable services of the application + rpc GetQueryServicesDescriptor(GetQueryServicesDescriptorRequest) returns (GetQueryServicesDescriptorResponse) { + option (google.api.http).get = "/cosmos/base/reflection/v1beta1/app_descriptor/query_services"; + } + // GetTxDescriptor returns information on the used transaction object and available msgs that can be used + rpc GetTxDescriptor(GetTxDescriptorRequest) returns (GetTxDescriptorResponse) { + option (google.api.http).get = "/cosmos/base/reflection/v1beta1/app_descriptor/tx_descriptor"; + } +} + +// GetAuthnDescriptorRequest is the request used for the GetAuthnDescriptor RPC +message GetAuthnDescriptorRequest {} +// GetAuthnDescriptorResponse is the response returned by the GetAuthnDescriptor RPC +message GetAuthnDescriptorResponse { + // authn describes how to authenticate to the application when sending transactions + AuthnDescriptor authn = 1; +} + +// GetChainDescriptorRequest is the request used for the GetChainDescriptor RPC +message GetChainDescriptorRequest {} +// GetChainDescriptorResponse is the response returned by the GetChainDescriptor RPC +message GetChainDescriptorResponse { + // chain describes application chain information + ChainDescriptor chain = 1; +} + +// GetCodecDescriptorRequest is the request used for the GetCodecDescriptor RPC +message GetCodecDescriptorRequest {} +// GetCodecDescriptorResponse is the response returned by the GetCodecDescriptor RPC +message GetCodecDescriptorResponse { + // codec describes the application codec such as registered interfaces and implementations + CodecDescriptor codec = 1; +} + +// GetConfigurationDescriptorRequest is the request used for the GetConfigurationDescriptor RPC +message GetConfigurationDescriptorRequest {} +// GetConfigurationDescriptorResponse is the response returned by the GetConfigurationDescriptor RPC +message GetConfigurationDescriptorResponse { + // config describes the application's sdk.Config + ConfigurationDescriptor config = 1; +} + +// GetQueryServicesDescriptorRequest is the request used for the GetQueryServicesDescriptor RPC +message GetQueryServicesDescriptorRequest {} +// GetQueryServicesDescriptorResponse is the response returned by the GetQueryServicesDescriptor RPC +message GetQueryServicesDescriptorResponse { + // queries provides information on the available queryable services + QueryServicesDescriptor queries = 1; +} + +// GetTxDescriptorRequest is the request used for the GetTxDescriptor RPC +message GetTxDescriptorRequest {} +// GetTxDescriptorResponse is the response returned by the GetTxDescriptor RPC +message GetTxDescriptorResponse { + // tx provides information on msgs that can be forwarded to the application + // alongside the accepted transaction protobuf type + TxDescriptor tx = 1; +} + +// QueryServicesDescriptor contains the list of cosmos-sdk queriable services +message QueryServicesDescriptor { + // query_services is a list of cosmos-sdk QueryServiceDescriptor + repeated QueryServiceDescriptor query_services = 1; +} + +// QueryServiceDescriptor describes a cosmos-sdk queryable service +message QueryServiceDescriptor { + // fullname is the protobuf fullname of the service descriptor + string fullname = 1; + // is_module describes if this service is actually exposed by an application's module + bool is_module = 2; + // methods provides a list of query service methods + repeated QueryMethodDescriptor methods = 3; +} + +// QueryMethodDescriptor describes a queryable method of a query service +// no other info is provided beside method name and tendermint queryable path +// because it would be redundant with the grpc reflection service +message QueryMethodDescriptor { + // name is the protobuf name (not fullname) of the method + string name = 1; + // full_query_path is the path that can be used to query + // this method via tendermint abci.Query + string full_query_path = 2; +} diff --git a/third_party/proto/cosmos/base/store/v1beta1/listening.proto b/third_party/proto/cosmos/base/store/v1beta1/listening.proto new file mode 100644 index 0000000000..186ecee4b0 --- /dev/null +++ b/third_party/proto/cosmos/base/store/v1beta1/listening.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package cosmos.base.store.v1beta1; + +option go_package = "github.com/cosmos/cosmos-sdk/store/types"; + +// StoreKVPair is a KVStore KVPair used for listening to state changes (Sets and Deletes) +// It optionally includes the StoreKey for the originating KVStore and a Boolean flag to distinguish between Sets and +// Deletes +message StoreKVPair { + string store_key = 1; // the store key for the KVStore this pair originates from + bool delete = 2; // true indicates a delete operation, false indicates a set operation + bytes key = 3; + bytes value = 4; +} diff --git a/third_party/proto/cosmos/base/tendermint/v1beta1/query.proto b/third_party/proto/cosmos/base/tendermint/v1beta1/query.proto index 50cb5852cd..505d4131d9 100644 --- a/third_party/proto/cosmos/base/tendermint/v1beta1/query.proto +++ b/third_party/proto/cosmos/base/tendermint/v1beta1/query.proto @@ -116,13 +116,14 @@ message GetNodeInfoResponse { // VersionInfo is the type for the GetNodeInfoResponse message. message VersionInfo { - string name = 1; - string app_name = 2; - string version = 3; - string git_commit = 4; - string build_tags = 5; - string go_version = 6; - repeated Module build_deps = 7; + string name = 1; + string app_name = 2; + string version = 3; + string git_commit = 4; + string build_tags = 5; + string go_version = 6; + repeated Module build_deps = 7; + string cosmos_sdk_version = 8; } // Module is the type for VersionInfo diff --git a/third_party/proto/cosmos/crypto/ed25519/keys.proto b/third_party/proto/cosmos/crypto/ed25519/keys.proto index bed9c29cc7..6ffec34483 100644 --- a/third_party/proto/cosmos/crypto/ed25519/keys.proto +++ b/third_party/proto/cosmos/crypto/ed25519/keys.proto @@ -5,18 +5,19 @@ import "gogoproto/gogo.proto"; option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"; -// PubKey defines a ed25519 public key -// Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -// if the y-coordinate is the lexicographically largest of the two associated with -// the x-coordinate. Otherwise the first byte is a 0x03. -// This prefix is followed with the x-coordinate. +// PubKey is an ed25519 public key for handling Tendermint keys in SDK. +// It's needed for Any serialization and SDK compatibility. +// It must not be used in a non Tendermint key context because it doesn't implement +// ADR-28. Nevertheless, you will like to use ed25519 in app user level +// then you must create a new proto message and follow ADR-28 for Address construction. message PubKey { option (gogoproto.goproto_stringer) = false; bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PublicKey"]; } -// PrivKey defines a ed25519 private key. +// Deprecated: PrivKey defines a ed25519 private key. +// NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. message PrivKey { bytes key = 1 [(gogoproto.casttype) = "crypto/ed25519.PrivateKey"]; } diff --git a/third_party/proto/cosmos/crypto/secp256r1/keys.proto b/third_party/proto/cosmos/crypto/secp256r1/keys.proto new file mode 100644 index 0000000000..b0aad99d1f --- /dev/null +++ b/third_party/proto/cosmos/crypto/secp256r1/keys.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +package cosmos.crypto.secp256r1; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"; +option (gogoproto.messagename_all) = true; +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.goproto_getters_all) = false; + +// PubKey defines a secp256r1 ECDSA public key. +message PubKey { + // Point on secp256r1 curve in a compressed representation as specified in section + // 4.3.6 of ANSI X9.62: https://webstore.ansi.org/standards/ascx9/ansix9621998 + bytes key = 1 [(gogoproto.customtype) = "ecdsaPK"]; +} + +// PrivKey defines a secp256r1 ECDSA private key. +message PrivKey { + // secret number serialized using big-endian encoding + bytes secret = 1 [(gogoproto.customtype) = "ecdsaSK"]; +} diff --git a/third_party/proto/cosmos/feegrant/v1beta1/feegrant.proto b/third_party/proto/cosmos/feegrant/v1beta1/feegrant.proto new file mode 100644 index 0000000000..dfd9b7826e --- /dev/null +++ b/third_party/proto/cosmos/feegrant/v1beta1/feegrant.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant"; + +// BasicAllowance implements Allowance with a one-time grant of tokens +// that optionally expires. The grantee can use up to SpendLimit to cover fees. +message BasicAllowance { + option (cosmos_proto.implements_interface) = "FeeAllowanceI"; + + // spend_limit specifies the maximum amount of tokens that can be spent + // by this allowance and will be updated as tokens are spent. If it is + // empty, there is no spend limit and any amount of coins can be spent. + repeated cosmos.base.v1beta1.Coin spend_limit = 1 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // expiration specifies an optional time when this allowance expires + google.protobuf.Timestamp expiration = 2 [(gogoproto.stdtime) = true]; +} + +// PeriodicAllowance extends Allowance to allow for both a maximum cap, +// as well as a limit per time period. +message PeriodicAllowance { + option (cosmos_proto.implements_interface) = "FeeAllowanceI"; + + // basic specifies a struct of `BasicAllowance` + BasicAllowance basic = 1 [(gogoproto.nullable) = false]; + + // period specifies the time duration in which period_spend_limit coins can + // be spent before that allowance is reset + google.protobuf.Duration period = 2 [(gogoproto.stdduration) = true, (gogoproto.nullable) = false]; + + // period_spend_limit specifies the maximum number of coins that can be spent + // in the period + repeated cosmos.base.v1beta1.Coin period_spend_limit = 3 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // period_can_spend is the number of coins left to be spent before the period_reset time + repeated cosmos.base.v1beta1.Coin period_can_spend = 4 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // period_reset is the time at which this period resets and a new one begins, + // it is calculated from the start time of the first transaction after the + // last period ended + google.protobuf.Timestamp period_reset = 5 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; +} + +// AllowedMsgAllowance creates allowance only for specified message types. +message AllowedMsgAllowance { + option (gogoproto.goproto_getters) = false; + option (cosmos_proto.implements_interface) = "FeeAllowanceI"; + + // allowance can be any of basic and filtered fee allowance. + google.protobuf.Any allowance = 1 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; + + // allowed_messages are the messages for which the grantee has the access. + repeated string allowed_messages = 2; +} + +// Grant is stored in the KVStore to record a grant with full context +message Grant { + // granter is the address of the user granting an allowance of their funds. + string granter = 1; + + // grantee is the address of the user being granted an allowance of another user's funds. + string grantee = 2; + + // allowance can be any of basic and filtered fee allowance. + google.protobuf.Any allowance = 3 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; +} diff --git a/third_party/proto/cosmos/feegrant/v1beta1/genesis.proto b/third_party/proto/cosmos/feegrant/v1beta1/genesis.proto new file mode 100644 index 0000000000..4c1e51fdd2 --- /dev/null +++ b/third_party/proto/cosmos/feegrant/v1beta1/genesis.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos/feegrant/v1beta1/feegrant.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant"; + +// GenesisState contains a set of fee allowances, persisted from the store +message GenesisState { + repeated Grant allowances = 1 [(gogoproto.nullable) = false]; +} diff --git a/third_party/proto/cosmos/feegrant/v1beta1/query.proto b/third_party/proto/cosmos/feegrant/v1beta1/query.proto new file mode 100644 index 0000000000..00ea598b1c --- /dev/null +++ b/third_party/proto/cosmos/feegrant/v1beta1/query.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "cosmos/feegrant/v1beta1/feegrant.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "google/api/annotations.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant"; + +// Query defines the gRPC querier service. +service Query { + + // Allowance returns fee granted to the grantee by the granter. + rpc Allowance(QueryAllowanceRequest) returns (QueryAllowanceResponse) { + option (google.api.http).get = "/cosmos/feegrant/v1beta1/allowance/{granter}/{grantee}"; + } + + // Allowances returns all the grants for address. + rpc Allowances(QueryAllowancesRequest) returns (QueryAllowancesResponse) { + option (google.api.http).get = "/cosmos/feegrant/v1beta1/allowances/{grantee}"; + } +} + +// QueryAllowanceRequest is the request type for the Query/Allowance RPC method. +message QueryAllowanceRequest { + // granter is the address of the user granting an allowance of their funds. + string granter = 1; + + // grantee is the address of the user being granted an allowance of another user's funds. + string grantee = 2; +} + +// QueryAllowanceResponse is the response type for the Query/Allowance RPC method. +message QueryAllowanceResponse { + // allowance is a allowance granted for grantee by granter. + cosmos.feegrant.v1beta1.Grant allowance = 1; +} + +// QueryAllowancesRequest is the request type for the Query/Allowances RPC method. +message QueryAllowancesRequest { + string grantee = 1; + + // pagination defines an pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryAllowancesResponse is the response type for the Query/Allowances RPC method. +message QueryAllowancesResponse { + // allowances are allowance's granted for grantee by granter. + repeated cosmos.feegrant.v1beta1.Grant allowances = 1; + + // pagination defines an pagination for the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/third_party/proto/cosmos/feegrant/v1beta1/tx.proto b/third_party/proto/cosmos/feegrant/v1beta1/tx.proto new file mode 100644 index 0000000000..66c27a7982 --- /dev/null +++ b/third_party/proto/cosmos/feegrant/v1beta1/tx.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant"; + +// Msg defines the feegrant msg service. +service Msg { + + // GrantAllowance grants fee allowance to the grantee on the granter's + // account with the provided expiration time. + rpc GrantAllowance(MsgGrantAllowance) returns (MsgGrantAllowanceResponse); + + // RevokeAllowance revokes any fee allowance of granter's account that + // has been granted to the grantee. + rpc RevokeAllowance(MsgRevokeAllowance) returns (MsgRevokeAllowanceResponse); +} + +// MsgGrantAllowance adds permission for Grantee to spend up to Allowance +// of fees from the account of Granter. +message MsgGrantAllowance { + // granter is the address of the user granting an allowance of their funds. + string granter = 1; + + // grantee is the address of the user being granted an allowance of another user's funds. + string grantee = 2; + + // allowance can be any of basic and filtered fee allowance. + google.protobuf.Any allowance = 3 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; +} + +// MsgGrantAllowanceResponse defines the Msg/GrantAllowanceResponse response type. +message MsgGrantAllowanceResponse {} + +// MsgRevokeAllowance removes any existing Allowance from Granter to Grantee. +message MsgRevokeAllowance { + // granter is the address of the user granting an allowance of their funds. + string granter = 1; + + // grantee is the address of the user being granted an allowance of another user's funds. + string grantee = 2; +} + +// MsgRevokeAllowanceResponse defines the Msg/RevokeAllowanceResponse response type. +message MsgRevokeAllowanceResponse {} diff --git a/third_party/proto/cosmos/gov/v1beta1/gov.proto b/third_party/proto/cosmos/gov/v1beta1/gov.proto index 1d72e64321..f040772e8e 100644 --- a/third_party/proto/cosmos/gov/v1beta1/gov.proto +++ b/third_party/proto/cosmos/gov/v1beta1/gov.proto @@ -29,6 +29,16 @@ enum VoteOption { VOTE_OPTION_NO_WITH_VETO = 4 [(gogoproto.enumvalue_customname) = "OptionNoWithVeto"]; } +// WeightedVoteOption defines a unit of vote for vote split. +message WeightedVoteOption { + VoteOption option = 1; + string weight = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"weight\"" + ]; +} + // TextProposal defines a standard text proposal whose changes need to be // manually updated in case of approval. message TextProposal { @@ -119,9 +129,13 @@ message Vote { option (gogoproto.goproto_stringer) = false; option (gogoproto.equal) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - VoteOption option = 3; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + // Deprecated: Prefer to use `options` instead. This field is set in queries + // if and only if `len(options) == 1` and that option has weight 1. In all + // other cases, this field will default to VOTE_OPTION_UNSPECIFIED. + VoteOption option = 3 [deprecated = true]; + repeated WeightedVoteOption options = 4 [(gogoproto.nullable) = false]; } // DepositParams defines the params for deposits on governance proposals. diff --git a/third_party/proto/cosmos/gov/v1beta1/tx.proto b/third_party/proto/cosmos/gov/v1beta1/tx.proto index d4f0c1f99a..ecb1cdfef9 100644 --- a/third_party/proto/cosmos/gov/v1beta1/tx.proto +++ b/third_party/proto/cosmos/gov/v1beta1/tx.proto @@ -17,6 +17,9 @@ service Msg { // Vote defines a method to add a vote on a specific proposal. rpc Vote(MsgVote) returns (MsgVoteResponse); + // VoteWeighted defines a method to add a weighted vote on a specific proposal. + rpc VoteWeighted(MsgVoteWeighted) returns (MsgVoteWeightedResponse); + // Deposit defines a method to add deposit on a specific proposal. rpc Deposit(MsgDeposit) returns (MsgDepositResponse); } @@ -58,6 +61,21 @@ message MsgVote { // MsgVoteResponse defines the Msg/Vote response type. message MsgVoteResponse {} +// MsgVoteWeighted defines a message to cast a vote. +message MsgVoteWeighted { + option (gogoproto.equal) = false; + option (gogoproto.goproto_stringer) = false; + option (gogoproto.stringer) = false; + option (gogoproto.goproto_getters) = false; + + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated WeightedVoteOption options = 3 [(gogoproto.nullable) = false]; +} + +// MsgVoteWeightedResponse defines the Msg/VoteWeighted response type. +message MsgVoteWeightedResponse {} + // MsgDeposit defines a message to submit a deposit to an existing proposal. message MsgDeposit { option (gogoproto.equal) = false; diff --git a/third_party/proto/cosmos/slashing/v1beta1/genesis.proto b/third_party/proto/cosmos/slashing/v1beta1/genesis.proto index c813561343..a7aebcfbad 100644 --- a/third_party/proto/cosmos/slashing/v1beta1/genesis.proto +++ b/third_party/proto/cosmos/slashing/v1beta1/genesis.proto @@ -16,7 +16,7 @@ message GenesisState { repeated SigningInfo signing_infos = 2 [(gogoproto.moretags) = "yaml:\"signing_infos\"", (gogoproto.nullable) = false]; - // signing_infos represents a map between validator addresses and their + // missed_blocks represents a map between validator addresses and their // missed blocks. repeated ValidatorMissedBlocks missed_blocks = 3 [(gogoproto.moretags) = "yaml:\"missed_blocks\"", (gogoproto.nullable) = false]; diff --git a/third_party/proto/cosmos/slashing/v1beta1/slashing.proto b/third_party/proto/cosmos/slashing/v1beta1/slashing.proto index 657a90f1bd..882a0fb60c 100644 --- a/third_party/proto/cosmos/slashing/v1beta1/slashing.proto +++ b/third_party/proto/cosmos/slashing/v1beta1/slashing.proto @@ -15,17 +15,20 @@ message ValidatorSigningInfo { option (gogoproto.goproto_stringer) = false; string address = 1; - // height at which validator was first a candidate OR was unjailed + // Height at which validator was first a candidate OR was unjailed int64 start_height = 2 [(gogoproto.moretags) = "yaml:\"start_height\""]; - // index offset into signed block bit array + // Index which is incremented each time the validator was a bonded + // in a block and may have signed a precommit or not. This in conjunction with the + // `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. int64 index_offset = 3 [(gogoproto.moretags) = "yaml:\"index_offset\""]; - // timestamp validator cannot be unjailed until + // Timestamp until which the validator is jailed due to liveness downtime. google.protobuf.Timestamp jailed_until = 4 [(gogoproto.moretags) = "yaml:\"jailed_until\"", (gogoproto.stdtime) = true, (gogoproto.nullable) = false]; - // whether or not a validator has been tombstoned (killed out of validator - // set) + // Whether or not a validator has been tombstoned (killed out of validator set). It is set + // once the validator commits an equivocation or for any other configured misbehiavor. bool tombstoned = 5; - // missed blocks counter (to avoid scanning the array every time) + // A counter kept to avoid unnecessary array reads. + // Note that `Sum(MissedBlocksBitArray)` always equals `MissedBlocksCounter`. int64 missed_blocks_counter = 6 [(gogoproto.moretags) = "yaml:\"missed_blocks_counter\""]; } diff --git a/third_party/proto/cosmos/staking/v1beta1/authz.proto b/third_party/proto/cosmos/staking/v1beta1/authz.proto new file mode 100644 index 0000000000..6345612f2d --- /dev/null +++ b/third_party/proto/cosmos/staking/v1beta1/authz.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; +package cosmos.staking.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/staking/types"; + +// StakeAuthorization defines authorization for delegate/undelegate/redelegate. +message StakeAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + // max_tokens specifies the maximum amount of tokens can be delegate to a validator. If it is + // empty, there is no spend limit and any amount of coins can be delegated. + cosmos.base.v1beta1.Coin max_tokens = 1 [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"]; + // validators is the oneof that represents either allow_list or deny_list + oneof validators { + // allow_list specifies list of validator addresses to whom grantee can delegate tokens on behalf of granter's + // account. + Validators allow_list = 2; + // deny_list specifies list of validator addresses to whom grantee can not delegate tokens. + Validators deny_list = 3; + } + // Validators defines list of validator addresses. + message Validators { + repeated string address = 1; + } + // authorization_type defines one of AuthorizationType. + AuthorizationType authorization_type = 4; +} + +// AuthorizationType defines the type of staking module authorization type +enum AuthorizationType { + // AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type + AUTHORIZATION_TYPE_UNSPECIFIED = 0; + // AUTHORIZATION_TYPE_DELEGATE defines an authorization type for Msg/Delegate + AUTHORIZATION_TYPE_DELEGATE = 1; + // AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate + AUTHORIZATION_TYPE_UNDELEGATE = 2; + // AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for Msg/BeginRedelegate + AUTHORIZATION_TYPE_REDELEGATE = 3; +} diff --git a/third_party/proto/cosmos/staking/v1beta1/staking.proto b/third_party/proto/cosmos/staking/v1beta1/staking.proto index e37b28b6d0..76e9599e2d 100644 --- a/third_party/proto/cosmos/staking/v1beta1/staking.proto +++ b/third_party/proto/cosmos/staking/v1beta1/staking.proto @@ -28,7 +28,7 @@ message CommissionRates { option (gogoproto.goproto_stringer) = false; // rate is the commission rate charged to delegators, as a fraction. - string rate = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + string rate = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; // max_rate defines the maximum commission rate which validator can ever charge, as a fraction. string max_rate = 2 [ (gogoproto.moretags) = "yaml:\"max_rate\"", @@ -49,9 +49,9 @@ message Commission { option (gogoproto.goproto_stringer) = false; // commission_rates defines the initial commission rates to be used for creating a validator. - CommissionRates commission_rates = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + CommissionRates commission_rates = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; // update_time is the last time the commission rate was changed. - google.protobuf.Timestamp update_time = 2 + google.protobuf.Timestamp update_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"update_time\""]; } @@ -61,15 +61,15 @@ message Description { option (gogoproto.goproto_stringer) = false; // moniker defines a human-readable name for the validator. - string moniker = 1; + string moniker = 1; // identity defines an optional identity signature (ex. UPort or Keybase). - string identity = 2; + string identity = 2; // website defines an optional website link. - string website = 3; + string website = 3; // security_contact defines an optional email for security contact. string security_contact = 4 [(gogoproto.moretags) = "yaml:\"security_contact\""]; // details define other optional details. - string details = 5; + string details = 5; } // Validator defines a validator, together with the total amount of the @@ -86,12 +86,12 @@ message Validator { option (gogoproto.goproto_getters) = false; // operator_address defines the address of the validator's operator; bech encoded in JSON. - string operator_address = 1 [(gogoproto.moretags) = "yaml:\"operator_address\""]; + string operator_address = 1 [(gogoproto.moretags) = "yaml:\"operator_address\""]; // consensus_pubkey is the consensus public key of the validator, as a Protobuf Any. google.protobuf.Any consensus_pubkey = 2 [(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey", (gogoproto.moretags) = "yaml:\"consensus_pubkey\""]; // jailed defined whether the validator has been jailed from bonded status or not. - bool jailed = 3; + bool jailed = 3; // status is the validator status (bonded/unbonding/unbonded). BondStatus status = 4; // tokens define the delegated tokens (incl. self-delegation). @@ -103,16 +103,16 @@ message Validator { (gogoproto.nullable) = false ]; // description defines the description terms for the validator. - Description description = 7 [(gogoproto.nullable) = false]; + Description description = 7 [(gogoproto.nullable) = false]; // unbonding_height defines, if unbonding, the height at which this validator has begun unbonding. - int64 unbonding_height = 8 [(gogoproto.moretags) = "yaml:\"unbonding_height\""]; + int64 unbonding_height = 8 [(gogoproto.moretags) = "yaml:\"unbonding_height\""]; // unbonding_time defines, if unbonding, the min time for the validator to complete unbonding. - google.protobuf.Timestamp unbonding_time = 9 + google.protobuf.Timestamp unbonding_time = 9 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"unbonding_time\""]; // commission defines the commission parameters. - Commission commission = 10 [(gogoproto.nullable) = false]; + Commission commission = 10 [(gogoproto.nullable) = false]; // min_self_delegation is the validator's self declared minimum self delegation. - string min_self_delegation = 11 [ + string min_self_delegation = 11 [ (gogoproto.moretags) = "yaml:\"min_self_delegation\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false @@ -201,9 +201,9 @@ message UnbondingDelegation { option (gogoproto.goproto_stringer) = false; // delegator_address is the bech32-encoded address of the delegator. - string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; // validator_address is the bech32-encoded address of the validator. - string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""]; + string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""]; // entries are the unbonding delegation entries. repeated UnbondingDelegationEntry entries = 3 [(gogoproto.nullable) = false]; // unbonding delegation entries } @@ -214,7 +214,7 @@ message UnbondingDelegationEntry { option (gogoproto.goproto_stringer) = false; // creation_height is the height which the unbonding took place. - int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; // completion_time is the unix time for unbonding completion. google.protobuf.Timestamp completion_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"completion_time\""]; @@ -234,7 +234,7 @@ message RedelegationEntry { option (gogoproto.goproto_stringer) = false; // creation_height defines the height which the redelegation took place. - int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; // completion_time defines the unix time for redelegation completion. google.protobuf.Timestamp completion_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"completion_time\""]; @@ -257,13 +257,13 @@ message Redelegation { option (gogoproto.goproto_stringer) = false; // delegator_address is the bech32-encoded address of the delegator. - string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; // validator_src_address is the validator redelegation source operator address. - string validator_src_address = 2 [(gogoproto.moretags) = "yaml:\"validator_src_address\""]; + string validator_src_address = 2 [(gogoproto.moretags) = "yaml:\"validator_src_address\""]; // validator_dst_address is the validator redelegation destination operator address. - string validator_dst_address = 3 [(gogoproto.moretags) = "yaml:\"validator_dst_address\""]; + string validator_dst_address = 3 [(gogoproto.moretags) = "yaml:\"validator_dst_address\""]; // entries are the redelegation entries. - repeated RedelegationEntry entries = 4 [(gogoproto.nullable) = false]; // redelegation entries + repeated RedelegationEntry entries = 4 [(gogoproto.nullable) = false]; // redelegation entries } // Params defines the parameters for the staking module. @@ -275,13 +275,13 @@ message Params { google.protobuf.Duration unbonding_time = 1 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"unbonding_time\""]; // max_validators is the maximum number of validators. - uint32 max_validators = 2 [(gogoproto.moretags) = "yaml:\"max_validators\""]; + uint32 max_validators = 2 [(gogoproto.moretags) = "yaml:\"max_validators\""]; // max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). - uint32 max_entries = 3 [(gogoproto.moretags) = "yaml:\"max_entries\""]; + uint32 max_entries = 3 [(gogoproto.moretags) = "yaml:\"max_entries\""]; // historical_entries is the number of historical entries to persist. uint32 historical_entries = 4 [(gogoproto.moretags) = "yaml:\"historical_entries\""]; // bond_denom defines the bondable coin denomination. - string bond_denom = 5 [(gogoproto.moretags) = "yaml:\"bond_denom\""]; + string bond_denom = 5 [(gogoproto.moretags) = "yaml:\"bond_denom\""]; } // DelegationResponse is equivalent to Delegation except that it contains a diff --git a/third_party/proto/cosmos/tx/v1beta1/service.proto b/third_party/proto/cosmos/tx/v1beta1/service.proto index 59df75bab1..646175c00d 100644 --- a/third_party/proto/cosmos/tx/v1beta1/service.proto +++ b/third_party/proto/cosmos/tx/v1beta1/service.proto @@ -7,7 +7,8 @@ import "cosmos/tx/v1beta1/tx.proto"; import "gogoproto/gogo.proto"; import "cosmos/base/query/v1beta1/pagination.proto"; -option go_package = "github.com/cosmos/cosmos-sdk/types/tx"; +option (gogoproto.goproto_registration) = true; +option go_package = "github.com/cosmos/cosmos-sdk/types/tx"; // Service defines a gRPC service for interacting with transactions. service Service { @@ -42,6 +43,17 @@ message GetTxsEventRequest { repeated string events = 1; // pagination defines an pagination for the request. cosmos.base.query.v1beta1.PageRequest pagination = 2; + OrderBy order_by = 3; +} + +// OrderBy defines the sorting order +enum OrderBy { + // ORDER_BY_UNSPECIFIED specifies an unknown sorting order. OrderBy defaults to ASC in this case. + ORDER_BY_UNSPECIFIED = 0; + // ORDER_BY_ASC defines ascending order + ORDER_BY_ASC = 1; + // ORDER_BY_DESC defines descending order + ORDER_BY_DESC = 2; } // GetTxsEventResponse is the response type for the Service.TxsByEvents @@ -89,7 +101,10 @@ message BroadcastTxResponse { // RPC method. message SimulateRequest { // tx is the transaction to simulate. - cosmos.tx.v1beta1.Tx tx = 1; + // Deprecated. Send raw tx bytes instead. + cosmos.tx.v1beta1.Tx tx = 1 [deprecated = true]; + // tx_bytes is the raw transaction. + bytes tx_bytes = 2; } // SimulateResponse is the response type for the diff --git a/third_party/proto/cosmos/tx/v1beta1/tx.proto b/third_party/proto/cosmos/tx/v1beta1/tx.proto index 2b02874cc1..6d5caf12c7 100644 --- a/third_party/proto/cosmos/tx/v1beta1/tx.proto +++ b/third_party/proto/cosmos/tx/v1beta1/tx.proto @@ -74,7 +74,9 @@ message TxBody { // transaction. repeated google.protobuf.Any messages = 1; - // memo is any arbitrary memo to be added to the transaction + // memo is any arbitrary note/comment to be added to the transaction. + // WARNING: in clients, any publicly exposed text should not be called memo, + // but should be called `note` instead (see https://github.com/cosmos/cosmos-sdk/issues/9122). string memo = 2; // timeout is the block height after which this transaction will not diff --git a/third_party/proto/cosmos/upgrade/v1beta1/query.proto b/third_party/proto/cosmos/upgrade/v1beta1/query.proto index 9eab27e76b..166a22406e 100644 --- a/third_party/proto/cosmos/upgrade/v1beta1/query.proto +++ b/third_party/proto/cosmos/upgrade/v1beta1/query.proto @@ -26,6 +26,11 @@ service Query { rpc UpgradedConsensusState(QueryUpgradedConsensusStateRequest) returns (QueryUpgradedConsensusStateResponse) { option (google.api.http).get = "/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}"; } + + // ModuleVersions queries the list of module versions from state. + rpc ModuleVersions(QueryModuleVersionsRequest) returns (QueryModuleVersionsResponse) { + option (google.api.http).get = "/cosmos/upgrade/v1beta1/module_versions"; + } } // QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC @@ -64,5 +69,23 @@ message QueryUpgradedConsensusStateRequest { // QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState // RPC method. message QueryUpgradedConsensusStateResponse { - google.protobuf.Any upgraded_consensus_state = 1; + reserved 1; + + bytes upgraded_consensus_state = 2; +} + +// QueryModuleVersionsRequest is the request type for the Query/ModuleVersions +// RPC method. +message QueryModuleVersionsRequest { + // module_name is a field to query a specific module + // consensus version from state. Leaving this empty will + // fetch the full list of module versions from state + string module_name = 1; +} + +// QueryModuleVersionsResponse is the response type for the Query/ModuleVersions +// RPC method. +message QueryModuleVersionsResponse { + // module_versions is a list of module names with their consensus versions. + repeated ModuleVersion module_versions = 1; } diff --git a/third_party/proto/cosmos/upgrade/v1beta1/upgrade.proto b/third_party/proto/cosmos/upgrade/v1beta1/upgrade.proto index 6d6839ca56..4e1d69aaaa 100644 --- a/third_party/proto/cosmos/upgrade/v1beta1/upgrade.proto +++ b/third_party/proto/cosmos/upgrade/v1beta1/upgrade.proto @@ -5,13 +5,13 @@ import "google/protobuf/any.proto"; import "gogoproto/gogo.proto"; import "google/protobuf/timestamp.proto"; -option go_package = "github.com/cosmos/cosmos-sdk/x/upgrade/types"; -option (gogoproto.goproto_stringer_all) = false; -option (gogoproto.goproto_getters_all) = false; +option go_package = "github.com/cosmos/cosmos-sdk/x/upgrade/types"; +option (gogoproto.goproto_getters_all) = false; // Plan specifies information about a planned upgrade and when it should occur. message Plan { - option (gogoproto.equal) = true; + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = false; // Sets the name for the upgrade. This name will be used by the upgraded // version of the software to apply any special "on-upgrade" commands during @@ -22,9 +22,10 @@ message Plan { // reached and the software will exit. string name = 1; - // The time after which the upgrade must be performed. - // Leave set to its zero value to use a pre-defined Height instead. - google.protobuf.Timestamp time = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; + // Deprecated: Time based upgrades have been deprecated. Time based upgrade logic + // has been removed from the SDK. + // If this field is not empty, an error will be thrown. + google.protobuf.Timestamp time = 2 [deprecated = true, (gogoproto.stdtime) = true, (gogoproto.nullable) = false]; // The height at which the upgrade must be performed. // Only used if Time is not set. @@ -34,18 +35,18 @@ message Plan { // such as a git commit that validators could automatically upgrade to string info = 4; - // IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan - // This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, - // so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the - // previous version of the chain. - // This will allow IBC connections to persist smoothly across planned chain upgrades - google.protobuf.Any upgraded_client_state = 5 [(gogoproto.moretags) = "yaml:\"upgraded_client_state\""]; + // Deprecated: UpgradedClientState field has been deprecated. IBC upgrade logic has been + // moved to the IBC module in the sub module 02-client. + // If this field is not empty, an error will be thrown. + google.protobuf.Any upgraded_client_state = 5 + [deprecated = true, (gogoproto.moretags) = "yaml:\"upgraded_client_state\""]; } // SoftwareUpgradeProposal is a gov Content type for initiating a software // upgrade. message SoftwareUpgradeProposal { - option (gogoproto.equal) = true; + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = false; string title = 1; string description = 2; @@ -55,8 +56,21 @@ message SoftwareUpgradeProposal { // CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software // upgrade. message CancelSoftwareUpgradeProposal { - option (gogoproto.equal) = true; + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = false; string title = 1; string description = 2; } + +// ModuleVersion specifies a module and its consensus version. +message ModuleVersion { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = true; + + // name of the app module + string name = 1; + + // consensus version of the app module + uint64 version = 2; +} diff --git a/third_party/proto/cosmos/vesting/v1beta1/vesting.proto b/third_party/proto/cosmos/vesting/v1beta1/vesting.proto index 6bdbbf08e4..26e786831e 100644 --- a/third_party/proto/cosmos/vesting/v1beta1/vesting.proto +++ b/third_party/proto/cosmos/vesting/v1beta1/vesting.proto @@ -71,3 +71,13 @@ message PeriodicVestingAccount { int64 start_time = 2 [(gogoproto.moretags) = "yaml:\"start_time\""]; repeated Period vesting_periods = 3 [(gogoproto.moretags) = "yaml:\"vesting_periods\"", (gogoproto.nullable) = false]; } + +// PermanentLockedAccount implements the VestingAccount interface. It does +// not ever release coins, locking them indefinitely. Coins in this account can +// still be used for delegating and for governance votes even while locked. +message PermanentLockedAccount { + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + BaseVestingAccount base_vesting_account = 1 [(gogoproto.embed) = true]; +} diff --git a/third_party/proto/google/protobuf/any.proto b/third_party/proto/google/protobuf/any.proto index 1431810ea4..58b511583a 100644 --- a/third_party/proto/google/protobuf/any.proto +++ b/third_party/proto/google/protobuf/any.proto @@ -156,6 +156,9 @@ message Any { bytes value = 2; option (gogoproto.typedecl) = false; + option (gogoproto.goproto_stringer) = false; + option (gogoproto.gostring) = false; + option (gogoproto.stringer) = false; } option (gogoproto.goproto_registration) = false; diff --git a/third_party/proto/ibc/applications/transfer/v1/genesis.proto b/third_party/proto/ibc/applications/transfer/v1/genesis.proto index 98cf2296d2..9c6b78ac7b 100644 --- a/third_party/proto/ibc/applications/transfer/v1/genesis.proto +++ b/third_party/proto/ibc/applications/transfer/v1/genesis.proto @@ -1,10 +1,11 @@ syntax = "proto3"; + package ibc.applications.transfer.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; +option go_package = "github.com/cosmos/ibc-go/modules/apps/transfer/types"; -import "gogoproto/gogo.proto"; import "ibc/applications/transfer/v1/transfer.proto"; +import "gogoproto/gogo.proto"; // GenesisState defines the ibc-transfer genesis state message GenesisState { diff --git a/third_party/proto/ibc/applications/transfer/v1/query.proto b/third_party/proto/ibc/applications/transfer/v1/query.proto index e9cbd02a31..cd428413eb 100644 --- a/third_party/proto/ibc/applications/transfer/v1/query.proto +++ b/third_party/proto/ibc/applications/transfer/v1/query.proto @@ -1,4 +1,5 @@ syntax = "proto3"; + package ibc.applications.transfer.v1; import "gogoproto/gogo.proto"; @@ -6,23 +7,23 @@ import "cosmos/base/query/v1beta1/pagination.proto"; import "ibc/applications/transfer/v1/transfer.proto"; import "google/api/annotations.proto"; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; +option go_package = "github.com/cosmos/ibc-go/modules/apps/transfer/types"; // Query provides defines the gRPC querier service. service Query { // DenomTrace queries a denomination trace information. rpc DenomTrace(QueryDenomTraceRequest) returns (QueryDenomTraceResponse) { - option (google.api.http).get = "/ibc/applications/transfer/v1beta1/denom_traces/{hash}"; + option (google.api.http).get = "/ibc/apps/transfer/v1/denom_traces/{hash}"; } // DenomTraces queries all denomination traces. rpc DenomTraces(QueryDenomTracesRequest) returns (QueryDenomTracesResponse) { - option (google.api.http).get = "/ibc/applications/transfer/v1beta1/denom_traces"; + option (google.api.http).get = "/ibc/apps/transfer/v1/denom_traces"; } // Params queries all parameters of the ibc-transfer module. rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { - option (google.api.http).get = "/ibc/applications/transfer/v1beta1/params"; + option (google.api.http).get = "/ibc/apps/transfer/v1/params"; } } diff --git a/third_party/proto/ibc/applications/transfer/v1/transfer.proto b/third_party/proto/ibc/applications/transfer/v1/transfer.proto index b388c3b879..b1c41f6a51 100644 --- a/third_party/proto/ibc/applications/transfer/v1/transfer.proto +++ b/third_party/proto/ibc/applications/transfer/v1/transfer.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.applications.transfer.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; +option go_package = "github.com/cosmos/ibc-go/modules/apps/transfer/types"; import "gogoproto/gogo.proto"; diff --git a/third_party/proto/ibc/applications/transfer/v1/tx.proto b/third_party/proto/ibc/applications/transfer/v1/tx.proto index a0f0827aaf..eb56b4702c 100644 --- a/third_party/proto/ibc/applications/transfer/v1/tx.proto +++ b/third_party/proto/ibc/applications/transfer/v1/tx.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.applications.transfer.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; +option go_package = "github.com/cosmos/ibc-go/modules/apps/transfer/types"; import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; diff --git a/third_party/proto/ibc/core/channel/v1/channel.proto b/third_party/proto/ibc/core/channel/v1/channel.proto index 302a480689..edb39d04b5 100644 --- a/third_party/proto/ibc/core/channel/v1/channel.proto +++ b/third_party/proto/ibc/core/channel/v1/channel.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.channel.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/04-channel/types"; import "gogoproto/gogo.proto"; import "ibc/core/client/v1/client.proto"; diff --git a/third_party/proto/ibc/core/channel/v1/genesis.proto b/third_party/proto/ibc/core/channel/v1/genesis.proto index d3b2c0424e..75bf1fdb02 100644 --- a/third_party/proto/ibc/core/channel/v1/genesis.proto +++ b/third_party/proto/ibc/core/channel/v1/genesis.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.channel.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/04-channel/types"; import "gogoproto/gogo.proto"; import "ibc/core/channel/v1/channel.proto"; diff --git a/third_party/proto/ibc/core/channel/v1/query.proto b/third_party/proto/ibc/core/channel/v1/query.proto index d9e3ceb8a6..194fe86777 100644 --- a/third_party/proto/ibc/core/channel/v1/query.proto +++ b/third_party/proto/ibc/core/channel/v1/query.proto @@ -1,6 +1,9 @@ syntax = "proto3"; + package ibc.core.channel.v1; +option go_package = "github.com/cosmos/ibc-go/modules/core/04-channel/types"; + import "ibc/core/client/v1/client.proto"; import "cosmos/base/query/v1beta1/pagination.proto"; import "ibc/core/channel/v1/channel.proto"; @@ -8,88 +11,92 @@ import "google/api/annotations.proto"; import "google/protobuf/any.proto"; import "gogoproto/gogo.proto"; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; - // Query provides defines the gRPC querier service service Query { // Channel queries an IBC Channel. rpc Channel(QueryChannelRequest) returns (QueryChannelResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}"; } // Channels queries all the IBC channels of a chain. rpc Channels(QueryChannelsRequest) returns (QueryChannelsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels"; + option (google.api.http).get = "/ibc/core/channel/v1/channels"; } // ConnectionChannels queries all the channels associated with a connection // end. rpc ConnectionChannels(QueryConnectionChannelsRequest) returns (QueryConnectionChannelsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/connections/{connection}/channels"; + option (google.api.http).get = "/ibc/core/channel/v1/connections/{connection}/channels"; } // ChannelClientState queries for the client state for the channel associated // with the provided channel identifiers. rpc ChannelClientState(QueryChannelClientStateRequest) returns (QueryChannelClientStateResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/client_state"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/client_state"; } // ChannelConsensusState queries for the consensus state for the channel // associated with the provided channel identifiers. rpc ChannelConsensusState(QueryChannelConsensusStateRequest) returns (QueryChannelConsensusStateResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/consensus_state/revision/" - "{revision_number}/height/{revision_height}"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/consensus_state/revision/" + "{revision_number}/height/{revision_height}"; } // PacketCommitment queries a stored packet commitment hash. rpc PacketCommitment(QueryPacketCommitmentRequest) returns (QueryPacketCommitmentResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{sequence}"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}/" + "packet_commitments/{sequence}"; } // PacketCommitments returns all the packet commitments hashes associated // with a channel. rpc PacketCommitments(QueryPacketCommitmentsRequest) returns (QueryPacketCommitmentsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/packet_commitments"; } - // PacketReceipt queries if a given packet sequence has been received on the queried chain + // PacketReceipt queries if a given packet sequence has been received on the + // queried chain rpc PacketReceipt(QueryPacketReceiptRequest) returns (QueryPacketReceiptResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_receipts/{sequence}"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/packet_receipts/{sequence}"; } // PacketAcknowledgement queries a stored packet acknowledgement hash. rpc PacketAcknowledgement(QueryPacketAcknowledgementRequest) returns (QueryPacketAcknowledgementResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acks/{sequence}"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/packet_acks/{sequence}"; } // PacketAcknowledgements returns all the packet acknowledgements associated // with a channel. rpc PacketAcknowledgements(QueryPacketAcknowledgementsRequest) returns (QueryPacketAcknowledgementsResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acknowledgements"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/packet_acknowledgements"; } // UnreceivedPackets returns all the unreceived IBC packets associated with a // channel and sequences. rpc UnreceivedPackets(QueryUnreceivedPacketsRequest) returns (QueryUnreceivedPacketsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/" + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/ports/{port_id}/" + "packet_commitments/" "{packet_commitment_sequences}/unreceived_packets"; } - // UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a - // channel and sequences. + // UnreceivedAcks returns all the unreceived IBC acknowledgements associated + // with a channel and sequences. rpc UnreceivedAcks(QueryUnreceivedAcksRequest) returns (QueryUnreceivedAcksResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/" + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/packet_commitments/" "{packet_ack_sequences}/unreceived_acks"; } // NextSequenceReceive returns the next receive sequence for a given channel. rpc NextSequenceReceive(QueryNextSequenceReceiveRequest) returns (QueryNextSequenceReceiveResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/next_sequence"; + option (google.api.http).get = "/ibc/core/channel/v1/channels/{channel_id}/" + "ports/{port_id}/next_sequence"; } } @@ -250,8 +257,8 @@ message QueryPacketReceiptRequest { uint64 sequence = 3; } -// QueryPacketReceiptResponse defines the client query response for a packet receipt -// which also includes a proof, and the height from which the proof was +// QueryPacketReceiptResponse defines the client query response for a packet +// receipt which also includes a proof, and the height from which the proof was // retrieved message QueryPacketReceiptResponse { // success flag for if receipt exists diff --git a/third_party/proto/ibc/core/channel/v1/tx.proto b/third_party/proto/ibc/core/channel/v1/tx.proto index 5f84264124..59af0d3f24 100644 --- a/third_party/proto/ibc/core/channel/v1/tx.proto +++ b/third_party/proto/ibc/core/channel/v1/tx.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.channel.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/04-channel/types"; import "gogoproto/gogo.proto"; import "ibc/core/client/v1/client.proto"; @@ -24,7 +25,8 @@ service Msg { // ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. rpc ChannelCloseInit(MsgChannelCloseInit) returns (MsgChannelCloseInitResponse); - // ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. + // ChannelCloseConfirm defines a rpc handler method for + // MsgChannelCloseConfirm. rpc ChannelCloseConfirm(MsgChannelCloseConfirm) returns (MsgChannelCloseConfirmResponse); // RecvPacket defines a rpc handler method for MsgRecvPacket. @@ -61,8 +63,8 @@ message MsgChannelOpenTry { option (gogoproto.goproto_getters) = false; string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - // in the case of crossing hello's, when both chains call OpenInit, we need the channel identifier - // of the previous channel in state INIT + // in the case of crossing hello's, when both chains call OpenInit, we need + // the channel identifier of the previous channel in state INIT string previous_channel_id = 2 [(gogoproto.moretags) = "yaml:\"previous_channel_id\""]; Channel channel = 3 [(gogoproto.nullable) = false]; string counterparty_version = 4 [(gogoproto.moretags) = "yaml:\"counterparty_version\""]; @@ -108,7 +110,8 @@ message MsgChannelOpenConfirm { string signer = 5; } -// MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. +// MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response +// type. message MsgChannelOpenConfirmResponse {} // MsgChannelCloseInit defines a msg sent by a Relayer to Chain A @@ -139,7 +142,8 @@ message MsgChannelCloseConfirm { string signer = 5; } -// MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. +// MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response +// type. message MsgChannelCloseConfirmResponse {} // MsgRecvPacket receives incoming IBC packet diff --git a/third_party/proto/ibc/core/client/v1/client.proto b/third_party/proto/ibc/core/client/v1/client.proto index 11d2195aaf..88a6c343ad 100644 --- a/third_party/proto/ibc/core/client/v1/client.proto +++ b/third_party/proto/ibc/core/client/v1/client.proto @@ -1,10 +1,12 @@ syntax = "proto3"; + package ibc.core.client.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/02-client/types"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; +import "cosmos/upgrade/v1beta1/upgrade.proto"; // IdentifiedClientState defines a client state with an additional client // identifier field. @@ -15,7 +17,8 @@ message IdentifiedClientState { google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""]; } -// ConsensusStateWithHeight defines a consensus state with an additional height field. +// ConsensusStateWithHeight defines a consensus state with an additional height +// field. message ConsensusStateWithHeight { // consensus state height Height height = 1 [(gogoproto.nullable) = false]; @@ -33,9 +36,10 @@ message ClientConsensusStates { [(gogoproto.moretags) = "yaml:\"consensus_states\"", (gogoproto.nullable) = false]; } -// ClientUpdateProposal is a governance proposal. If it passes, the client is -// updated with the provided header. The update may fail if the header is not -// valid given certain conditions specified by the client implementation. +// ClientUpdateProposal is a governance proposal. If it passes, the substitute +// client's latest consensus state is copied over to the subject client. The proposal +// handler may fail if the subject and the substitute do not match in client and +// chain parameters (with exception to latest height, frozen height, and chain-id). message ClientUpdateProposal { option (gogoproto.goproto_getters) = false; // the title of the update proposal @@ -43,20 +47,42 @@ message ClientUpdateProposal { // the description of the proposal string description = 2; // the client identifier for the client to be updated if the proposal passes - string client_id = 3 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // the header used to update the client if the proposal passes - google.protobuf.Any header = 4; + string subject_client_id = 3 [(gogoproto.moretags) = "yaml:\"subject_client_id\""]; + // the substitute client identifier for the client standing in for the subject + // client + string substitute_client_id = 4 [(gogoproto.moretags) = "yaml:\"substitute_client_id\""]; +} + +// UpgradeProposal is a gov Content type for initiating an IBC breaking +// upgrade. +message UpgradeProposal { + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + option (gogoproto.equal) = true; + + string title = 1; + string description = 2; + cosmos.upgrade.v1beta1.Plan plan = 3 [(gogoproto.nullable) = false]; + + // An UpgradedClientState must be provided to perform an IBC breaking upgrade. + // This will make the chain commit to the correct upgraded (self) client state + // before the upgrade occurs, so that connecting chains can verify that the + // new upgraded client is valid by verifying a proof on the previous version + // of the chain. This will allow IBC connections to persist smoothly across + // planned chain upgrades + google.protobuf.Any upgraded_client_state = 4 [(gogoproto.moretags) = "yaml:\"upgraded_client_state\""]; } // Height is a monotonically increasing data type // that can be compared against another Height for the purposes of updating and // freezing clients // -// Normally the RevisionHeight is incremented at each height while keeping RevisionNumber -// the same. However some consensus algorithms may choose to reset the -// height in certain conditions e.g. hard forks, state-machine breaking changes -// In these cases, the RevisionNumber is incremented so that height continues to -// be monitonically increasing even as the RevisionHeight gets reset +// Normally the RevisionHeight is incremented at each height while keeping +// RevisionNumber the same. However some consensus algorithms may choose to +// reset the height in certain conditions e.g. hard forks, state-machine +// breaking changes In these cases, the RevisionNumber is incremented so that +// height continues to be monitonically increasing even as the RevisionHeight +// gets reset message Height { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; diff --git a/third_party/proto/ibc/core/client/v1/genesis.proto b/third_party/proto/ibc/core/client/v1/genesis.proto index 16febbceef..30592cf725 100644 --- a/third_party/proto/ibc/core/client/v1/genesis.proto +++ b/third_party/proto/ibc/core/client/v1/genesis.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.client.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/02-client/types"; import "ibc/core/client/v1/client.proto"; import "gogoproto/gogo.proto"; @@ -38,9 +39,10 @@ message GenesisMetadata { bytes value = 2; } -// IdentifiedGenesisMetadata has the client metadata with the corresponding client id. +// IdentifiedGenesisMetadata has the client metadata with the corresponding +// client id. message IdentifiedGenesisMetadata { string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; repeated GenesisMetadata client_metadata = 2 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_metadata\""]; -} \ No newline at end of file +} diff --git a/third_party/proto/ibc/core/client/v1/query.proto b/third_party/proto/ibc/core/client/v1/query.proto index 97f3acd627..36a5135702 100644 --- a/third_party/proto/ibc/core/client/v1/query.proto +++ b/third_party/proto/ibc/core/client/v1/query.proto @@ -1,42 +1,59 @@ syntax = "proto3"; + package ibc.core.client.v1; +option go_package = "github.com/cosmos/ibc-go/modules/core/02-client/types"; + import "cosmos/base/query/v1beta1/pagination.proto"; import "ibc/core/client/v1/client.proto"; import "google/protobuf/any.proto"; import "google/api/annotations.proto"; import "gogoproto/gogo.proto"; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; - // Query provides defines the gRPC querier service service Query { // ClientState queries an IBC light client. rpc ClientState(QueryClientStateRequest) returns (QueryClientStateResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/client_states/{client_id}"; + option (google.api.http).get = "/ibc/core/client/v1/client_states/{client_id}"; } // ClientStates queries all the IBC light clients of a chain. rpc ClientStates(QueryClientStatesRequest) returns (QueryClientStatesResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/client_states"; + option (google.api.http).get = "/ibc/core/client/v1/client_states"; } // ConsensusState queries a consensus state associated with a client state at // a given height. rpc ConsensusState(QueryConsensusStateRequest) returns (QueryConsensusStateResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/" + option (google.api.http).get = "/ibc/core/client/v1/consensus_states/" + "{client_id}/revision/{revision_number}/" "height/{revision_height}"; } // ConsensusStates queries all the consensus state associated with a given // client. rpc ConsensusStates(QueryConsensusStatesRequest) returns (QueryConsensusStatesResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/consensus_states/{client_id}"; + option (google.api.http).get = "/ibc/core/client/v1/consensus_states/{client_id}"; + } + + // Status queries the status of an IBC client. + rpc ClientStatus(QueryClientStatusRequest) returns (QueryClientStatusResponse) { + option (google.api.http).get = "/ibc/core/client/v1/client_status/{client_id}"; } // ClientParams queries all parameters of the ibc client. rpc ClientParams(QueryClientParamsRequest) returns (QueryClientParamsResponse) { - option (google.api.http).get = "/ibc/client/v1beta1/params"; + option (google.api.http).get = "/ibc/client/v1/params"; + } + + // UpgradedClientState queries an Upgraded IBC light client. + rpc UpgradedClientState(QueryUpgradedClientStateRequest) returns (QueryUpgradedClientStateResponse) { + option (google.api.http).get = "/ibc/core/client/v1/upgraded_client_states"; + } + + // UpgradedConsensusState queries an Upgraded IBC consensus state. + rpc UpgradedConsensusState(QueryUpgradedConsensusStateRequest) returns (QueryUpgradedConsensusStateResponse) { + option (google.api.http).get = "/ibc/core/client/v1/upgraded_consensus_states"; } } @@ -120,11 +137,48 @@ message QueryConsensusStatesResponse { cosmos.base.query.v1beta1.PageResponse pagination = 2; } -// QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. +// QueryClientStatusRequest is the request type for the Query/ClientStatus RPC +// method +message QueryClientStatusRequest { + // client unique identifier + string client_id = 1; +} + +// QueryClientStatusResponse is the response type for the Query/ClientStatus RPC +// method. It returns the current status of the IBC client. +message QueryClientStatusResponse { + string status = 1; +} + +// QueryClientParamsRequest is the request type for the Query/ClientParams RPC +// method. message QueryClientParamsRequest {} -// QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. +// QueryClientParamsResponse is the response type for the Query/ClientParams RPC +// method. message QueryClientParamsResponse { // params defines the parameters of the module. Params params = 1; } + +// QueryUpgradedClientStateRequest is the request type for the +// Query/UpgradedClientState RPC method +message QueryUpgradedClientStateRequest {} + +// QueryUpgradedClientStateResponse is the response type for the +// Query/UpgradedClientState RPC method. +message QueryUpgradedClientStateResponse { + // client state associated with the request identifier + google.protobuf.Any upgraded_client_state = 1; +} + +// QueryUpgradedConsensusStateRequest is the request type for the +// Query/UpgradedConsensusState RPC method +message QueryUpgradedConsensusStateRequest {} + +// QueryUpgradedConsensusStateResponse is the response type for the +// Query/UpgradedConsensusState RPC method. +message QueryUpgradedConsensusStateResponse { + // Consensus state associated with the request identifier + google.protobuf.Any upgraded_consensus_state = 1; +} diff --git a/third_party/proto/ibc/core/client/v1/tx.proto b/third_party/proto/ibc/core/client/v1/tx.proto index a30ec8bbf1..35386adb8a 100644 --- a/third_party/proto/ibc/core/client/v1/tx.proto +++ b/third_party/proto/ibc/core/client/v1/tx.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.client.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/02-client/types"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; @@ -56,7 +57,8 @@ message MsgUpdateClient { // MsgUpdateClientResponse defines the Msg/UpdateClient response type. message MsgUpdateClientResponse {} -// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state +// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client +// state message MsgUpgradeClient { option (gogoproto.equal) = false; option (gogoproto.goproto_getters) = false; @@ -65,7 +67,8 @@ message MsgUpgradeClient { string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; // upgraded client state google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""]; - // upgraded consensus state, only contains enough information to serve as a basis of trust in update logic + // upgraded consensus state, only contains enough information to serve as a + // basis of trust in update logic google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; // proof that old chain committed to new client bytes proof_upgrade_client = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade_client\""]; @@ -92,5 +95,6 @@ message MsgSubmitMisbehaviour { string signer = 3; } -// MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. +// MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response +// type. message MsgSubmitMisbehaviourResponse {} diff --git a/third_party/proto/ibc/core/commitment/v1/commitment.proto b/third_party/proto/ibc/core/commitment/v1/commitment.proto index 51c1027316..47d8239422 100644 --- a/third_party/proto/ibc/core/commitment/v1/commitment.proto +++ b/third_party/proto/ibc/core/commitment/v1/commitment.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.commitment.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/23-commitment/types"; import "gogoproto/gogo.proto"; import "confio/proofs.proto"; @@ -37,4 +38,4 @@ message MerklePath { // MerkleProofs are ordered from leaf-to-root message MerkleProof { repeated ics23.CommitmentProof proofs = 1; -} \ No newline at end of file +} diff --git a/third_party/proto/ibc/core/connection/v1/connection.proto b/third_party/proto/ibc/core/connection/v1/connection.proto index d21e595165..72c0ff7daa 100644 --- a/third_party/proto/ibc/core/connection/v1/connection.proto +++ b/third_party/proto/ibc/core/connection/v1/connection.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.connection.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/03-connection/types"; import "gogoproto/gogo.proto"; import "ibc/core/commitment/v1/commitment.proto"; @@ -24,8 +25,9 @@ message ConnectionEnd { State state = 3; // counterparty chain associated with this connection. Counterparty counterparty = 4 [(gogoproto.nullable) = false]; - // delay period that must pass before a consensus state can be used for packet-verification - // NOTE: delay period logic is only implemented by some clients. + // delay period that must pass before a consensus state can be used for + // packet-verification NOTE: delay period logic is only implemented by some + // clients. uint64 delay_period = 5 [(gogoproto.moretags) = "yaml:\"delay_period\""]; } @@ -102,3 +104,11 @@ message Version { // list of features compatible with the specified identifier repeated string features = 2; } + +// Params defines the set of Connection parameters. +message Params { + // maximum expected time per block (in nanoseconds), used to enforce block delay. This parameter should reflect the + // largest amount of time that the chain might reasonably take to produce the next block under normal operating + // conditions. A safe choice is 3-5x the expected time per block. + uint64 max_expected_time_per_block = 1 [(gogoproto.moretags) = "yaml:\"max_expected_time_per_block\""]; +} diff --git a/third_party/proto/ibc/core/connection/v1/genesis.proto b/third_party/proto/ibc/core/connection/v1/genesis.proto index 11df4ba180..64f2e026ac 100644 --- a/third_party/proto/ibc/core/connection/v1/genesis.proto +++ b/third_party/proto/ibc/core/connection/v1/genesis.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.connection.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/03-connection/types"; import "gogoproto/gogo.proto"; import "ibc/core/connection/v1/connection.proto"; @@ -13,4 +14,5 @@ message GenesisState { [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_connection_paths\""]; // the sequence for the next generated connection identifier uint64 next_connection_sequence = 3 [(gogoproto.moretags) = "yaml:\"next_connection_sequence\""]; + Params params = 4 [(gogoproto.nullable) = false]; } diff --git a/third_party/proto/ibc/core/connection/v1/query.proto b/third_party/proto/ibc/core/connection/v1/query.proto index c5085a131f..ca90e0eeb4 100644 --- a/third_party/proto/ibc/core/connection/v1/query.proto +++ b/third_party/proto/ibc/core/connection/v1/query.proto @@ -1,6 +1,9 @@ syntax = "proto3"; + package ibc.core.connection.v1; +option go_package = "github.com/cosmos/ibc-go/modules/core/03-connection/types"; + import "gogoproto/gogo.proto"; import "cosmos/base/query/v1beta1/pagination.proto"; import "ibc/core/client/v1/client.proto"; @@ -8,36 +11,34 @@ import "ibc/core/connection/v1/connection.proto"; import "google/api/annotations.proto"; import "google/protobuf/any.proto"; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; - // Query provides defines the gRPC querier service service Query { // Connection queries an IBC connection end. rpc Connection(QueryConnectionRequest) returns (QueryConnectionResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections/{connection_id}"; + option (google.api.http).get = "/ibc/core/connection/v1/connections/{connection_id}"; } // Connections queries all the IBC connections of a chain. rpc Connections(QueryConnectionsRequest) returns (QueryConnectionsResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections"; + option (google.api.http).get = "/ibc/core/connection/v1/connections"; } // ClientConnections queries the connection paths associated with a client // state. rpc ClientConnections(QueryClientConnectionsRequest) returns (QueryClientConnectionsResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/client_connections/{client_id}"; + option (google.api.http).get = "/ibc/core/connection/v1/client_connections/{client_id}"; } // ConnectionClientState queries the client state associated with the // connection. rpc ConnectionClientState(QueryConnectionClientStateRequest) returns (QueryConnectionClientStateResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections/{connection_id}/client_state"; + option (google.api.http).get = "/ibc/core/connection/v1/connections/{connection_id}/client_state"; } // ConnectionConsensusState queries the consensus state associated with the // connection. rpc ConnectionConsensusState(QueryConnectionConsensusStateRequest) returns (QueryConnectionConsensusStateResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections/{connection_id}/consensus_state/" + option (google.api.http).get = "/ibc/core/connection/v1/connections/{connection_id}/consensus_state/" "revision/{revision_number}/height/{revision_height}"; } } diff --git a/third_party/proto/ibc/core/connection/v1/tx.proto b/third_party/proto/ibc/core/connection/v1/tx.proto index 19b40c69c3..6318f9fd25 100644 --- a/third_party/proto/ibc/core/connection/v1/tx.proto +++ b/third_party/proto/ibc/core/connection/v1/tx.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.connection.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/03-connection/types"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; @@ -19,7 +20,8 @@ service Msg { // ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. rpc ConnectionOpenAck(MsgConnectionOpenAck) returns (MsgConnectionOpenAckResponse); - // ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. + // ConnectionOpenConfirm defines a rpc handler method for + // MsgConnectionOpenConfirm. rpc ConnectionOpenConfirm(MsgConnectionOpenConfirm) returns (MsgConnectionOpenConfirmResponse); } @@ -36,7 +38,8 @@ message MsgConnectionOpenInit { string signer = 5; } -// MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. +// MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response +// type. message MsgConnectionOpenInitResponse {} // MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a @@ -46,8 +49,8 @@ message MsgConnectionOpenTry { option (gogoproto.goproto_getters) = false; string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // in the case of crossing hello's, when both chains call OpenInit, we need the connection identifier - // of the previous connection in state INIT + // in the case of crossing hello's, when both chains call OpenInit, we need + // the connection identifier of the previous connection in state INIT string previous_connection_id = 2 [(gogoproto.moretags) = "yaml:\"previous_connection_id\""]; google.protobuf.Any client_state = 3 [(gogoproto.moretags) = "yaml:\"client_state\""]; Counterparty counterparty = 4 [(gogoproto.nullable) = false]; @@ -111,5 +114,6 @@ message MsgConnectionOpenConfirm { string signer = 4; } -// MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. +// MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm +// response type. message MsgConnectionOpenConfirmResponse {} diff --git a/third_party/proto/ibc/core/types/v1/genesis.proto b/third_party/proto/ibc/core/types/v1/genesis.proto index ace5085993..2451da3233 100644 --- a/third_party/proto/ibc/core/types/v1/genesis.proto +++ b/third_party/proto/ibc/core/types/v1/genesis.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.core.types.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/types"; import "gogoproto/gogo.proto"; import "ibc/core/client/v1/genesis.proto"; diff --git a/third_party/proto/ibc/lightclients/localhost/v1/localhost.proto b/third_party/proto/ibc/lightclients/localhost/v1/localhost.proto index d48a1c0076..77e17bc327 100644 --- a/third_party/proto/ibc/lightclients/localhost/v1/localhost.proto +++ b/third_party/proto/ibc/lightclients/localhost/v1/localhost.proto @@ -1,11 +1,12 @@ syntax = "proto3"; + package ibc.lightclients.localhost.v1; +option go_package = "github.com/cosmos/ibc-go/modules/light-clients/09-localhost/types"; + import "gogoproto/gogo.proto"; import "ibc/core/client/v1/client.proto"; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types"; - // ClientState defines a loopback (localhost) client. It requires (read-only) // access to keys outside the client prefix. message ClientState { diff --git a/third_party/proto/ibc/lightclients/solomachine/v1/solomachine.proto b/third_party/proto/ibc/lightclients/solomachine/v1/solomachine.proto index 89686f3b7f..4ba0da259a 100644 --- a/third_party/proto/ibc/lightclients/solomachine/v1/solomachine.proto +++ b/third_party/proto/ibc/lightclients/solomachine/v1/solomachine.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.lightclients.solomachine.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types"; +option go_package = "github.com/cosmos/ibc-go/modules/core/02-client/legacy/v100"; import "ibc/core/connection/v1/connection.proto"; import "ibc/core/channel/v1/channel.proto"; @@ -22,14 +23,16 @@ message ClientState { bool allow_update_after_proposal = 4 [(gogoproto.moretags) = "yaml:\"allow_update_after_proposal\""]; } -// ConsensusState defines a solo machine consensus state. The sequence of a consensus state -// is contained in the "height" key used in storing the consensus state. +// ConsensusState defines a solo machine consensus state. The sequence of a +// consensus state is contained in the "height" key used in storing the +// consensus state. message ConsensusState { option (gogoproto.goproto_getters) = false; // public key of the solo machine google.protobuf.Any public_key = 1 [(gogoproto.moretags) = "yaml:\"public_key\""]; - // diversifier allows the same public key to be re-used across different solo machine clients - // (potentially on different chains) without being considered misbehaviour. + // diversifier allows the same public key to be re-used across different solo + // machine clients (potentially on different chains) without being considered + // misbehaviour. string diversifier = 2; uint64 timestamp = 3; } @@ -86,8 +89,8 @@ message SignBytes { bytes data = 5; } -// DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different -// data sign byte encodings. +// DataType defines the type of solo machine proof being created. This is done +// to preserve uniqueness of different data sign byte encodings. enum DataType { option (gogoproto.goproto_enum_prefix) = false; diff --git a/third_party/proto/ibc/lightclients/solomachine/v2/solomachine.proto b/third_party/proto/ibc/lightclients/solomachine/v2/solomachine.proto new file mode 100644 index 0000000000..fdb659f60c --- /dev/null +++ b/third_party/proto/ibc/lightclients/solomachine/v2/solomachine.proto @@ -0,0 +1,189 @@ +syntax = "proto3"; + +package ibc.lightclients.solomachine.v2; + +option go_package = "github.com/cosmos/ibc-go/modules/light-clients/06-solomachine/types"; + +import "ibc/core/connection/v1/connection.proto"; +import "ibc/core/channel/v1/channel.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; + +// ClientState defines a solo machine client that tracks the current consensus +// state and if the client is frozen. +message ClientState { + option (gogoproto.goproto_getters) = false; + // latest sequence of the client state + uint64 sequence = 1; + // frozen sequence of the solo machine + bool is_frozen = 2 [(gogoproto.moretags) = "yaml:\"is_frozen\""]; + ConsensusState consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; + // when set to true, will allow governance to update a solo machine client. + // The client will be unfrozen if it is frozen. + bool allow_update_after_proposal = 4 [(gogoproto.moretags) = "yaml:\"allow_update_after_proposal\""]; +} + +// ConsensusState defines a solo machine consensus state. The sequence of a +// consensus state is contained in the "height" key used in storing the +// consensus state. +message ConsensusState { + option (gogoproto.goproto_getters) = false; + // public key of the solo machine + google.protobuf.Any public_key = 1 [(gogoproto.moretags) = "yaml:\"public_key\""]; + // diversifier allows the same public key to be re-used across different solo + // machine clients (potentially on different chains) without being considered + // misbehaviour. + string diversifier = 2; + uint64 timestamp = 3; +} + +// Header defines a solo machine consensus header +message Header { + option (gogoproto.goproto_getters) = false; + // sequence to update solo machine public key at + uint64 sequence = 1; + uint64 timestamp = 2; + bytes signature = 3; + google.protobuf.Any new_public_key = 4 [(gogoproto.moretags) = "yaml:\"new_public_key\""]; + string new_diversifier = 5 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; +} + +// Misbehaviour defines misbehaviour for a solo machine which consists +// of a sequence and two signatures over different messages at that sequence. +message Misbehaviour { + option (gogoproto.goproto_getters) = false; + string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; + uint64 sequence = 2; + SignatureAndData signature_one = 3 [(gogoproto.moretags) = "yaml:\"signature_one\""]; + SignatureAndData signature_two = 4 [(gogoproto.moretags) = "yaml:\"signature_two\""]; +} + +// SignatureAndData contains a signature and the data signed over to create that +// signature. +message SignatureAndData { + option (gogoproto.goproto_getters) = false; + bytes signature = 1; + DataType data_type = 2 [(gogoproto.moretags) = "yaml:\"data_type\""]; + bytes data = 3; + uint64 timestamp = 4; +} + +// TimestampedSignatureData contains the signature data and the timestamp of the +// signature. +message TimestampedSignatureData { + option (gogoproto.goproto_getters) = false; + bytes signature_data = 1 [(gogoproto.moretags) = "yaml:\"signature_data\""]; + uint64 timestamp = 2; +} + +// SignBytes defines the signed bytes used for signature verification. +message SignBytes { + option (gogoproto.goproto_getters) = false; + + uint64 sequence = 1; + uint64 timestamp = 2; + string diversifier = 3; + // type of the data used + DataType data_type = 4 [(gogoproto.moretags) = "yaml:\"data_type\""]; + // marshaled data + bytes data = 5; +} + +// DataType defines the type of solo machine proof being created. This is done +// to preserve uniqueness of different data sign byte encodings. +enum DataType { + option (gogoproto.goproto_enum_prefix) = false; + + // Default State + DATA_TYPE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNSPECIFIED"]; + // Data type for client state verification + DATA_TYPE_CLIENT_STATE = 1 [(gogoproto.enumvalue_customname) = "CLIENT"]; + // Data type for consensus state verification + DATA_TYPE_CONSENSUS_STATE = 2 [(gogoproto.enumvalue_customname) = "CONSENSUS"]; + // Data type for connection state verification + DATA_TYPE_CONNECTION_STATE = 3 [(gogoproto.enumvalue_customname) = "CONNECTION"]; + // Data type for channel state verification + DATA_TYPE_CHANNEL_STATE = 4 [(gogoproto.enumvalue_customname) = "CHANNEL"]; + // Data type for packet commitment verification + DATA_TYPE_PACKET_COMMITMENT = 5 [(gogoproto.enumvalue_customname) = "PACKETCOMMITMENT"]; + // Data type for packet acknowledgement verification + DATA_TYPE_PACKET_ACKNOWLEDGEMENT = 6 [(gogoproto.enumvalue_customname) = "PACKETACKNOWLEDGEMENT"]; + // Data type for packet receipt absence verification + DATA_TYPE_PACKET_RECEIPT_ABSENCE = 7 [(gogoproto.enumvalue_customname) = "PACKETRECEIPTABSENCE"]; + // Data type for next sequence recv verification + DATA_TYPE_NEXT_SEQUENCE_RECV = 8 [(gogoproto.enumvalue_customname) = "NEXTSEQUENCERECV"]; + // Data type for header verification + DATA_TYPE_HEADER = 9 [(gogoproto.enumvalue_customname) = "HEADER"]; +} + +// HeaderData returns the SignBytes data for update verification. +message HeaderData { + option (gogoproto.goproto_getters) = false; + + // header public key + google.protobuf.Any new_pub_key = 1 [(gogoproto.moretags) = "yaml:\"new_pub_key\""]; + // header diversifier + string new_diversifier = 2 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; +} + +// ClientStateData returns the SignBytes data for client state verification. +message ClientStateData { + option (gogoproto.goproto_getters) = false; + + bytes path = 1; + google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""]; +} + +// ConsensusStateData returns the SignBytes data for consensus state +// verification. +message ConsensusStateData { + option (gogoproto.goproto_getters) = false; + + bytes path = 1; + google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; +} + +// ConnectionStateData returns the SignBytes data for connection state +// verification. +message ConnectionStateData { + option (gogoproto.goproto_getters) = false; + + bytes path = 1; + ibc.core.connection.v1.ConnectionEnd connection = 2; +} + +// ChannelStateData returns the SignBytes data for channel state +// verification. +message ChannelStateData { + option (gogoproto.goproto_getters) = false; + + bytes path = 1; + ibc.core.channel.v1.Channel channel = 2; +} + +// PacketCommitmentData returns the SignBytes data for packet commitment +// verification. +message PacketCommitmentData { + bytes path = 1; + bytes commitment = 2; +} + +// PacketAcknowledgementData returns the SignBytes data for acknowledgement +// verification. +message PacketAcknowledgementData { + bytes path = 1; + bytes acknowledgement = 2; +} + +// PacketReceiptAbsenceData returns the SignBytes data for +// packet receipt absence verification. +message PacketReceiptAbsenceData { + bytes path = 1; +} + +// NextSequenceRecvData returns the SignBytes data for verification of the next +// sequence to be received. +message NextSequenceRecvData { + bytes path = 1; + uint64 next_seq_recv = 2 [(gogoproto.moretags) = "yaml:\"next_seq_recv\""]; +} diff --git a/third_party/proto/ibc/lightclients/tendermint/v1/tendermint.proto b/third_party/proto/ibc/lightclients/tendermint/v1/tendermint.proto index a6882bf432..17a6cce40c 100644 --- a/third_party/proto/ibc/lightclients/tendermint/v1/tendermint.proto +++ b/third_party/proto/ibc/lightclients/tendermint/v1/tendermint.proto @@ -1,7 +1,8 @@ syntax = "proto3"; + package ibc.lightclients.tendermint.v1; -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"; +option go_package = "github.com/cosmos/ibc-go/modules/light-clients/07-tendermint/types"; import "tendermint/types/validator.proto"; import "tendermint/types/types.proto"; @@ -43,10 +44,12 @@ message ClientState { repeated ics23.ProofSpec proof_specs = 8 [(gogoproto.moretags) = "yaml:\"proof_specs\""]; // Path at which next upgraded client will be committed. - // Each element corresponds to the key for a single CommitmentProof in the chained proof. - // NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` - // ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` - // For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` + // Each element corresponds to the key for a single CommitmentProof in the + // chained proof. NOTE: ClientState must stored under + // `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored + // under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using + // the default upgrade module, upgrade_path should be []string{"upgrade", + // "upgradedIBCState"}` repeated string upgrade_path = 9 [(gogoproto.moretags) = "yaml:\"upgrade_path\""]; // This flag, when set to true, will allow governance to recover a client @@ -104,7 +107,8 @@ message Header { .tendermint.types.ValidatorSet trusted_validators = 4 [(gogoproto.moretags) = "yaml:\"trusted_validators\""]; } -// Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. +// Fraction defines the protobuf message type for tmmath.Fraction that only +// supports positive values. message Fraction { uint64 numerator = 1; uint64 denominator = 2; diff --git a/x/wasm/README.md b/x/wasm/README.md index ad5fb1f54b..cba9c5cf41 100644 --- a/x/wasm/README.md +++ b/x/wasm/README.md @@ -53,7 +53,7 @@ was sent: }, { "key": "_contract_address", - "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" } ] } @@ -70,7 +70,7 @@ provide a initial balance in the same `MsgInstantiateContract`. We see the follo "Attr": [ { "key": "recipient", - "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" }, { "key": "sender", @@ -97,7 +97,7 @@ Here is an example from the escrow contract successfully releasing funds to the "Attr": [ { "key": "_contract_address", - "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" }, { "key": "action", @@ -131,7 +131,7 @@ was executed (which always appears, while 2 is optional and has information as r "Attr": [ { "key": "recipient", - "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" }, { "key": "sender", @@ -148,7 +148,7 @@ was executed (which always appears, while 2 is optional and has information as r "Attr": [ { "key": "_contract_address", - "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" }, { "key": "action", @@ -169,7 +169,7 @@ was executed (which always appears, while 2 is optional and has information as r }, { "key": "sender", - "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" }, { "key": "amount", @@ -194,7 +194,7 @@ was executed (which always appears, while 2 is optional and has information as r }, { "key": "_contract_address", - "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + "value": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" } ] } diff --git a/x/wasm/client/cli/genesis_msg.go b/x/wasm/client/cli/genesis_msg.go index 12d89c432d..2329bcb840 100644 --- a/x/wasm/client/cli/genesis_msg.go +++ b/x/wasm/client/cli/genesis_msg.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/CosmWasm/wasmd/x/wasm/keeper" "github.com/CosmWasm/wasmd/x/wasm/types" @@ -337,7 +338,7 @@ func hasAccountBalance(cmd *cobra.Command, appState map[string]json.RawMessage, if err != nil { return false, err } - cdc := clientCtx.JSONMarshaler + cdc := clientCtx.JSONCodec var genBalIterator banktypes.GenesisBalancesIterator err = genutil.ValidateAccountInGenesis(appState, genBalIterator, sender, coins, cdc) if err != nil { @@ -392,7 +393,7 @@ func (d DefaultGenesisReader) ReadWasmGenesis(cmd *cobra.Command) (*GenesisData, var wasmGenesisState types.GenesisState if appState[types.ModuleName] != nil { clientCtx := client.GetClientContextFromCmd(cmd) - clientCtx.JSONMarshaler.MustUnmarshalJSON(appState[types.ModuleName], &wasmGenesisState) + clientCtx.JSONCodec.MustUnmarshalJSON(appState[types.ModuleName], &wasmGenesisState) } return NewGenesisData( @@ -434,7 +435,7 @@ func (x DefaultGenesisIO) AlterWasmModuleState(cmd *cobra.Command, callback func return err } clientCtx := client.GetClientContextFromCmd(cmd) - wasmGenStateBz, err := clientCtx.JSONMarshaler.MarshalJSON(g.WasmModuleState) + wasmGenStateBz, err := clientCtx.JSONCodec.MarshalJSON(g.WasmModuleState) if err != nil { return sdkerrors.Wrap(err, "marshal wasm genesis state") } diff --git a/x/wasm/client/cli/genesis_msg_test.go b/x/wasm/client/cli/genesis_msg_test.go index ea1a7987a4..2143db5e23 100644 --- a/x/wasm/client/cli/genesis_msg_test.go +++ b/x/wasm/client/cli/genesis_msg_test.go @@ -302,7 +302,7 @@ func TestInstantiateContractCmd(t *testing.T) { } func TestExecuteContractCmd(t *testing.T) { - const firstContractAddress = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + const firstContractAddress = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" minimalWasmGenesis := types.GenesisState{ Params: types.DefaultParams(), } @@ -384,7 +384,7 @@ func TestExecuteContractCmd(t *testing.T) { }, mutator: func(cmd *cobra.Command) { // See TestBuildContractAddress in keeper_test.go - cmd.SetArgs([]string{"cosmos1mujpjkwhut9yjw4xueyugc02evfv46y04aervg", `{}`}) + cmd.SetArgs([]string{"cosmos1mujpjkwhut9yjw4xueyugc02evfv46y0dtmnz4lh8xxkkdapym9stu5qm8", `{}`}) flagSet := cmd.Flags() flagSet.Set("run-as", myWellFundedAccount) }, @@ -534,8 +534,8 @@ func TestGetAllContracts(t *testing.T) { "read from message state": { src: types.GenesisState{ GenMsgs: []types.GenesisState_GenMsgs{ - {Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Label: "first"}}}, - {Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Label: "second"}}}, + {Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{CodeID: 0, Label: "first"}}}, + {Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{CodeID: 0, Label: "second"}}}, }, }, exp: []contractMeta{ @@ -555,7 +555,7 @@ func TestGetAllContracts(t *testing.T) { {IDKey: types.KeyLastInstanceID, Value: 100}, }, GenMsgs: []types.GenesisState_GenMsgs{ - {Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{Label: "hundred"}}}, + {Sum: &types.GenesisState_GenMsgs_InstantiateContract{InstantiateContract: &types.MsgInstantiateContract{CodeID: 0, Label: "hundred"}}}, }, }, exp: []contractMeta{ @@ -637,7 +637,7 @@ func executeCmdWithContext(t *testing.T, homeDir string, cmd *cobra.Command) err require.NoError(t, err) appCodec := keeper.MakeEncodingConfig(t).Marshaler serverCtx := server.NewContext(viper.New(), cfg, logger) - clientCtx := client.Context{}.WithJSONMarshaler(appCodec).WithHomeDir(homeDir) + clientCtx := client.Context{}.WithJSONCodec(appCodec).WithHomeDir(homeDir) ctx := context.Background() ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) diff --git a/x/wasm/client/codec/marshaller.go b/x/wasm/client/codec/marshaller.go index ba5cc4d631..6f26283e82 100644 --- a/x/wasm/client/codec/marshaller.go +++ b/x/wasm/client/codec/marshaller.go @@ -3,27 +3,28 @@ package codec import ( "bytes" "fmt" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/proto" ) -var _ codec.Marshaler = (*ProtoCodec)(nil) +var _ codec.Codec = (*ProtoCodec)(nil) // ProtoCodec that omits empty values. // This Marshaler can be used globally when setting up the client context or individually -// for each command via `clientCtx.WithJSONMarshaler(myMarshaler)`. +// for each command via `clientCtx.WithJSONCodec(myMarshaler)`. type ProtoCodec struct { - codec.Marshaler + codec.Codec interfaceRegistry types.InterfaceRegistry } -func NewProtoCodec(marshaler codec.Marshaler, registry types.InterfaceRegistry) *ProtoCodec { - return &ProtoCodec{Marshaler: marshaler, interfaceRegistry: registry} +func NewProtoCodec(marshaler codec.Codec, registry types.InterfaceRegistry) *ProtoCodec { + return &ProtoCodec{Codec: marshaler, interfaceRegistry: registry} } -// MarshalJSON implements JSONMarshaler.MarshalJSON method, +// MarshalJSON implements JSONCodec.MarshalJSON method, // it marshals to JSON using proto codec. func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) { m, ok := o.(codec.ProtoMarshaler) @@ -33,7 +34,7 @@ func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) { return ProtoMarshalJSON(m, pc.interfaceRegistry) } -// MustMarshalJSON implements JSONMarshaler.MustMarshalJSON method, +// MustMarshalJSON implements JSONCodec.MustMarshalJSON method, // it executes MarshalJSON except it panics upon failure. func (pc *ProtoCodec) MustMarshalJSON(o proto.Message) []byte { bz, err := pc.MarshalJSON(o) diff --git a/x/wasm/client/proposal_handler_test.go b/x/wasm/client/proposal_handler_test.go index 735dbd73e2..376dcc72a7 100644 --- a/x/wasm/client/proposal_handler_test.go +++ b/x/wasm/client/proposal_handler_test.go @@ -32,7 +32,7 @@ func TestGovRestHandlers(t *testing.T) { ) encodingConfig := keeper.MakeEncodingConfig(t) clientCtx := client.Context{}. - WithJSONMarshaler(encodingConfig.Marshaler). + WithJSONCodec(encodingConfig.Marshaler). WithTxConfig(encodingConfig.TxConfig). WithLegacyAmino(encodingConfig.Amino). WithInput(os.Stdin). @@ -172,7 +172,7 @@ func TestGovRestHandlers(t *testing.T) { "title": "Test Proposal", "description": "My proposal", "type": "migrate", - "contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", + "contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", "code_id": "1", "msg": dict{"foo": "bar"}, "run_as": "cosmos100dejzacpanrldpjjwksjm62shqhyss44jf5xz", @@ -188,7 +188,7 @@ func TestGovRestHandlers(t *testing.T) { "title": "Test Proposal", "description": "My proposal", "type": "migrate", - "contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", + "contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", "new_admin": "cosmos100dejzacpanrldpjjwksjm62shqhyss44jf5xz", "deposit": []dict{{"denom": "ustake", "amount": "10"}}, "proposer": "cosmos1ve557a5g9yw2g2z57js3pdmcvd5my6g8ze20np", @@ -202,7 +202,7 @@ func TestGovRestHandlers(t *testing.T) { "title": "Test Proposal", "description": "My proposal", "type": "migrate", - "contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", + "contract": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", "deposit": []dict{{"denom": "ustake", "amount": "10"}}, "proposer": "cosmos1ve557a5g9yw2g2z57js3pdmcvd5my6g8ze20np", "base_req": aBaseReq, diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index 2d00e7ee06..e2eed49f0d 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -1,15 +1,17 @@ package wasm import ( + "math" + types "github.com/CosmWasm/wasmd/x/wasm/types" wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "math" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types" + host "github.com/cosmos/ibc-go/modules/core/24-host" + "github.com/cosmos/ibc-go/modules/core/exported" ) var _ porttypes.IBCModule = IBCHandler{} @@ -213,28 +215,41 @@ func toWasmVMChannel(portID, channelID string, channelInfo channeltypes.Channel) } } +type Ack struct{ result []byte } + +func (a Ack) Success() bool { return true } +func (a Ack) Acknowledgement() []byte { return a.result } + +type Nack struct{} + +func (Nack) Success() bool { return false } +func (Nack) Acknowledgement() []byte { return nil } + // OnRecvPacket implements the IBCModule interface func (i IBCHandler) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, -) (*sdk.Result, []byte, error) { + relayer sdk.AccAddress, +) exported.Acknowledgement { contractAddr, err := ContractFromPortID(packet.DestinationPort) if err != nil { - return nil, nil, sdkerrors.Wrapf(err, "contract port id") + return Nack{} } msg := wasmvmtypes.IBCPacketReceiveMsg{Packet: newIBCPacket(packet)} ack, err := i.keeper.OnRecvPacket(ctx, contractAddr, msg) if err != nil { - return nil, nil, err + return Nack{} } - return &sdk.Result{ // the response is ignored - Events: ctx.EventManager().Events().ToABCIEvents(), - }, ack, nil + return Ack{ + result: ack, + } } // OnAcknowledgementPacket implements the IBCModule interface -func (i IBCHandler) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte) (*sdk.Result, error) { +func (i IBCHandler) OnAcknowledgementPacket( + ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress, +) (*sdk.Result, error) { contractAddr, err := ContractFromPortID(packet.SourcePort) if err != nil { return nil, sdkerrors.Wrapf(err, "contract port id") @@ -255,7 +270,9 @@ func (i IBCHandler) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes } // OnTimeoutPacket implements the IBCModule interface -func (i IBCHandler) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet) (*sdk.Result, error) { +func (i IBCHandler) OnTimeoutPacket( + ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, +) (*sdk.Result, error) { contractAddr, err := ContractFromPortID(packet.SourcePort) if err != nil { return nil, sdkerrors.Wrapf(err, "contract port id") diff --git a/x/wasm/ibc_reflect_test.go b/x/wasm/ibc_reflect_test.go index fb5e04ec84..0ec2ebbf4d 100644 --- a/x/wasm/ibc_reflect_test.go +++ b/x/wasm/ibc_reflect_test.go @@ -1,14 +1,16 @@ package wasm_test import ( - "github.com/CosmWasm/wasmd/x/wasm/ibctesting" + "testing" + + wasmd "github.com/CosmWasm/wasmd/app" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmvmtypes "github.com/CosmWasm/wasmvm/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting" ) func TestIBCReflectContract(t *testing.T) { @@ -18,7 +20,7 @@ func TestIBCReflectContract(t *testing.T) { // // Chain A "ibc_reflect_send" sends a IBC packet "on channel connect" event to chain B "ibc_reflect" // "ibc_reflect" sends a submessage to "reflect" which is returned as submessage. - + ibctesting.DefaultTestingAppInit = wasmd.SetupTestingApp var ( coordinator = ibctesting.NewCoordinator(t, 2, nil, nil) chainA = coordinator.GetChain(ibctesting.GetChainID(0)) @@ -38,42 +40,29 @@ func TestIBCReflectContract(t *testing.T) { reflectContractAddr := chainB.InstantiateContract(codeID, initMsg) var ( - sourcePortID = chainA.ContractInfo(sendContractAddr).IBCPortID - counterpartPortID = chainB.ContractInfo(reflectContractAddr).IBCPortID + sourcePortID = wasmd.ContractInfo(t, chainA, sendContractAddr).IBCPortID + counterpartPortID = wasmd.ContractInfo(t, chainB, reflectContractAddr).IBCPortID ) - clientA, clientB, connA, connB := coordinator.SetupClientConnections(chainA, chainB, ibcexported.Tendermint) - connA.NextChannelVersion = "ibc-reflect-v1" - connB.NextChannelVersion = "ibc-reflect-v1" - // flip instantiation so that we do not run into https://github.com/cosmos/cosmos-sdk/issues/8334 - channelA, channelB := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartPortID, channeltypes.ORDERED) - - // TODO: query both contracts directly to ensure they have registered the proper connection - // (and the chainB has created a reflect contract) - - // there should be one packet to relay back and forth (whoami) - // TODO: how do I find the packet that was previously sent by the smart contract? - // Coordinator.RecvPacket requires channeltypes.Packet as input? - // Given the source (portID, channelID), we should be able to count how many packets are pending, query the data - // and submit them to the other side (same with acks). This is what the real relayer does. I guess the test framework doesn't? - - // Update: I dug through the code, expecially channel.Keeper.SendPacket, and it only writes a commitment - // only writes I see: https://github.com/cosmos/cosmos-sdk/blob/31fdee0228bd6f3e787489c8e4434aabc8facb7d/x/ibc/core/04-channel/keeper/packet.go#L115-L116 - // commitment is hashed packet: https://github.com/cosmos/cosmos-sdk/blob/31fdee0228bd6f3e787489c8e4434aabc8facb7d/x/ibc/core/04-channel/types/packet.go#L14-L34 - // how is the relayer supposed to get the original packet data?? - // eg. ibctransfer doesn't store the packet either: https://github.com/cosmos/cosmos-sdk/blob/master/x/ibc/applications/transfer/keeper/relay.go#L145-L162 - // ... or I guess the original packet data is only available in the event logs???? - // https://github.com/cosmos/cosmos-sdk/blob/31fdee0228bd6f3e787489c8e4434aabc8facb7d/x/ibc/core/04-channel/keeper/packet.go#L121-L132 + + path := ibctesting.NewPath(chainA, chainB) + path.SetChannelOrdered() + path.EndpointA.ChannelConfig.PortID = sourcePortID + path.EndpointB.ChannelConfig.PortID = counterpartPortID + path.EndpointA.ChannelConfig.Version = "ibc-reflect-v1" + path.EndpointB.ChannelConfig.Version = "ibc-reflect-v1" + + coordinator.Setup(path) // ensure the expected packet was prepared, and relay it require.Equal(t, 1, len(chainA.PendingSendPackets)) require.Equal(t, 0, len(chainB.PendingSendPackets)) - err := coordinator.RelayAndAckPendingPackets(chainA, chainB, clientA, clientB) + err := coordinator.RelayAndAckPendingPackets(path) require.NoError(t, err) require.Equal(t, 0, len(chainA.PendingSendPackets)) require.Equal(t, 0, len(chainB.PendingSendPackets)) // let's query the source contract and make sure it registered an address - query := ReflectSendQueryMsg{Account: &AccountQuery{ChannelID: channelA.ID}} + query := ReflectSendQueryMsg{Account: &AccountQuery{ChannelID: path.EndpointA.ChannelID}} var account AccountResponse err = chainA.SmartQuery(sendContractAddr.String(), query, &account) require.NoError(t, err) @@ -81,15 +70,14 @@ func TestIBCReflectContract(t *testing.T) { require.Empty(t, account.RemoteBalance) // close channel - coordinator.CloseChannel(chainA, chainB, channelA, channelB) + err = path.CloseChannels() + require.NoError(t, err) // let's query the source contract and make sure it registered an address account = AccountResponse{} err = chainA.SmartQuery(sendContractAddr.String(), query, &account) require.Error(t, err) assert.Contains(t, err.Error(), "not found") - - _ = clientB } type ReflectSendQueryMsg struct { diff --git a/x/wasm/ibc_test.go b/x/wasm/ibc_test.go index 25106d42ee..0b23f3e311 100644 --- a/x/wasm/ibc_test.go +++ b/x/wasm/ibc_test.go @@ -2,8 +2,8 @@ package wasm import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" "github.com/stretchr/testify/assert" "testing" ) diff --git a/x/wasm/ibctesting/README.md b/x/wasm/ibctesting/README.md index 1c9286995d..e159d3ee5e 100644 --- a/x/wasm/ibctesting/README.md +++ b/x/wasm/ibctesting/README.md @@ -1,2 +1,289 @@ -# testing package for ibc -Customized version of cosmos-sdk x/ibc/testing \ No newline at end of file +# IBC Testing Package + +## Components + +The testing package comprises of four parts constructed as a stack. +- coordinator +- chain +- path +- endpoint + +A coordinator sits at the highest level and contains all the chains which have been initialized. +It also stores and updates the current global time. The time is manually incremented by a `TimeIncrement`. +This allows all the chains to remain in synchrony avoiding the issue of a counterparty being perceived to +be in the future. The coordinator also contains functions to do basic setup of clients, connections, and channels +between two chains. + +A chain is an SDK application (as represented by an app.go file). Inside the chain is an `TestingApp` which allows +the chain to simulate block production and transaction processing. The chain contains by default a single tendermint +validator. A chain is used to process SDK messages. + +A path connects two channel endpoints. It contains all the information needed to relay between two endpoints. + +An endpoint represents a channel (and its associated client and connections) on some specific chain. It contains +references to the chain it is on and the counterparty endpoint it is connected to. The endpoint contains functions +to interact with initialization and updates of its associated clients, connections, and channels. It can send, receive, +and acknowledge packets. + +In general: +- endpoints are used for initialization and execution of IBC logic on one side of an IBC connection +- paths are used to relay packets +- chains are used to commit SDK messages +- coordinator is used to setup a path between two chains + +## Integration + +To integrate the testing package into your tests, you will need to define: +- a testing application +- a function to initialize the testing application + +### TestingApp + +Your project will likely already have an application defined. This application +will need to be extended to fulfill the `TestingApp` interface. + +```go +type TestingApp interface { + abci.Application + + // ibc-go additions + GetBaseApp() *baseapp.BaseApp + GetStakingKeeper() stakingkeeper.Keeper + GetIBCKeeper() *keeper.Keeper + GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper + GetTxConfig() client.TxConfig + + // Implemented by SimApp + AppCodec() codec.Codec + + // Implemented by BaseApp + LastCommitID() sdk.CommitID + LastBlockHeight() int64 +} +``` + +To begin, you will need to extend your application by adding the following functions: + +```go +// TestingApp functions +// Example using SimApp to implement TestingApp + +// GetBaseApp implements the TestingApp interface. +func (app *SimApp) GetBaseApp() *baseapp.BaseApp { + return app.BaseApp +} + +// GetStakingKeeper implements the TestingApp interface. +func (app *SimApp) GetStakingKeeper() stakingkeeper.Keeper { + return app.StakingKeeper +} + +// GetIBCKeeper implements the TestingApp interface. +func (app *SimApp) GetIBCKeeper() *ibckeeper.Keeper { + return app.IBCKeeper +} + +// GetScopedIBCKeeper implements the TestingApp interface. +func (app *SimApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { + return app.ScopedIBCKeeper +} + +// GetTxConfig implements the TestingApp interface. +func (app *SimApp) GetTxConfig() client.TxConfig { + return MakeTestEncodingConfig().TxConfig +} + +``` + +Your application may need to define `AppCodec()` if it does not already exist: + +```go +// AppCodec returns SimApp's app codec. +// +// NOTE: This is solely to be used for testing purposes as it may be desirable +// for modules to register their own custom testing types. +func (app *SimApp) AppCodec() codec.Codec { + return app.appCodec +} +``` + +It is assumed your application contains an embedded BaseApp and thus implements the abci.Application interface, `LastCommitID()` and `LastBlockHeight()` + +### Initialize TestingApp + +The testing package requires that you provide a function to initialize your TestingApp. This is how ibc-go implements the initialize function with its `SimApp`: + +```go +func SetupTestingApp() (TestingApp, map[string]json.RawMessage) { + db := dbm.NewMemDB() + encCdc := simapp.MakeTestEncodingConfig() + app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{}) + return app, simapp.NewDefaultGenesisState(encCdc.Marshaler) +} +``` + +This function returns the TestingApp and the default genesis state used to initialize the testing app. + +Change the value of `DefaultTestingAppInit` to use your function: +```go +func init() { + ibctesting.DefaultTestingAppInit = MySetupTestingAppFunction +} + +``` + +## Example + +Here is an example of how to setup your testing environment in every package you are testing: +```go +// KeeperTestSuite is a testing suite to test keeper functions. +type KeeperTestSuite struct { + suite.Suite + + coordinator *ibctesting.Coordinator + + // testing chains used for convenience and readability + chainA *ibctesting.TestChain + chainB *ibctesting.TestChain +} + +// TestKeeperTestSuite runs all the tests within this package. +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} + +// SetupTest creates a coordinator with 2 test chains. +func (suite *KeeperTestSuite) SetupTest() { + suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) // initializes 2 test chains + suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) // convenience and readability + suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) // convenience and readability +} + +``` + +To create interaction between chainA and chainB, we need to contruct a `Path` these chains will use. +A path contains two endpoints, `EndpointA` and `EndpointB` (corresponding to the order of the chains passed +into the `NewPath` function). A path is a pointer and its values will be filled in as necessary during the +setup portion of testing. + +Endpoint Struct: +```go +// Endpoint is a which represents a channel endpoint and its associated +// client and connections. It contains client, connection, and channel +// configuration parameters. Endpoint functions will utilize the parameters +// set in the configuration structs when executing IBC messages. +type Endpoint struct { + Chain *TestChain + Counterparty *Endpoint + ClientID string + ConnectionID string + ChannelID string + + ClientConfig ClientConfig + ConnectionConfig *ConnectionConfig + ChannelConfig *ChannelConfig +} +``` + +The fields empty after `NewPath` is called are `ClientID`, `ConnectionID` and +`ChannelID` as the clients, connections, and channels for these endpoints have not yet been created. The +`ClientConfig`, `ConnectionConfig` and `ChannelConfig` contain all the necessary information for clients, +connections, and channels to be initialized. If you would like to use endpoints which are intitialized to +use your Port IDs, you might add a helper function similar to the one found in transfer: + +```go +func NewTransferPath(chainA, chainB *ibctesting.TestChain) *ibctesting.Path { + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort + path.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort + + return path +} + +``` + +Path configurations should be set to the desired values before calling any `Setup` coordinator functions. + +To initialize the clients, connections, and channels for a path we can call the Setup functions of the coordinator: +- Setup() -> setup clients, connections, channels +- SetupClients() -> setup clients only +- SetupConnections() -> setup clients and connections only + + +Here is a basic example of the testing package being used to simulate IBC functionality: + +```go + path := ibctesting.NewPath(suite.chainA, suite.chainB) // clientID, connectionID, channelID empty + suite.coordinator.Setup(path) // clientID, connectionID, channelID filled + suite.Require().Equal("07-tendermint-0", path.EndpointA.ClientID) + suite.Require().Equal("connection-0", path.EndpointA.ClientID) + suite.Require().Equal("channel-0", path.EndpointA.ClientID) + + // create packet 1 + packet1 := NewPacket() // NewPacket would construct your packet + + // send on endpointA + path.EndpointA.SendPacket(packet1) + + // receive on endpointB + path.EndpointB.RecvPacket(packet1) + + // acknowledge the receipt of the packet + path.EndpointA.AcknowledgePacket(packet1, ack) + + // we can also relay + packet2 := NewPacket() + + path.EndpointA.SendPacket(packet2) + + path.Relay(packet2, expectedAck) + + // if needed we can update our clients + path.EndpointB.UpdateClient() +``` + +### Transfer Testing Example + +If ICS 20 had its own simapp, its testing setup might include a `testing/app.go` file with the following contents: + +```go +package transfertesting + +import ( + "encoding/json" + + "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/ibc-go/modules/apps/transfer/simapp" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting" +) + +func SetupTransferTestingApp() (ibctesting.TestingApp, map[string]json.RawMessage) { + db := dbm.NewMemDB() + encCdc := simapp.MakeTestEncodingConfig() + app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{}) + return app, simapp.NewDefaultGenesisState(encCdc.Marshaler) +} + +func init() { + ibctesting.DefaultTestingAppInit = SetupTransferTestingApp +} + +func NewTransferPath(chainA, chainB *ibctesting.TestChain) *ibctesting.Path { + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort + path.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort + + return path +} + +func GetTransferSimApp(chain *ibctesting.TestChain) *simapp.SimApp { + app, ok := chain.App.(*simapp.SimApp) + if !ok { + panic("not transfer app") + } + + return app +} +``` diff --git a/x/wasm/ibctesting/app.go b/x/wasm/ibctesting/app.go new file mode 100644 index 0000000000..16d2fbf12c --- /dev/null +++ b/x/wasm/ibctesting/app.go @@ -0,0 +1,137 @@ +package ibctesting + +import ( + "encoding/json" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/ibc-go/modules/core/keeper" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtypes "github.com/tendermint/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" +) + +var DefaultTestingAppInit func(opts ...wasmkeeper.Option) (TestingApp, map[string]json.RawMessage) = SetupTestingApp + +type TestingApp interface { + abci.Application + + // ibc-go additions + GetBaseApp() *baseapp.BaseApp + GetStakingKeeper() stakingkeeper.Keeper + GetIBCKeeper() *keeper.Keeper + GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper + GetTxConfig() client.TxConfig + + // Implemented by SimApp + AppCodec() codec.Codec + + // Implemented by BaseApp + LastCommitID() sdk.CommitID + LastBlockHeight() int64 +} + +func SetupTestingApp(opts ...wasmkeeper.Option) (TestingApp, map[string]json.RawMessage) { + db := dbm.NewMemDB() + encCdc := simapp.MakeTestEncodingConfig() + app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{}) + return app, simapp.NewDefaultGenesisState(encCdc.Marshaler) +} + +// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts +// that also act as delegators. For simplicity, each validator is bonded with a delegation +// of one consensus engine unit (10^6) in the default token of the simapp from first genesis +// account. A Nop logger is set in SimApp. +func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, opts []wasmkeeper.Option, balances ...banktypes.Balance) TestingApp { + app, genesisState := DefaultTestingAppInit(opts...) + // set genesis accounts + authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) + genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) + + validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) + delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) + + bondAmt := sdk.NewInt(1000000) + + for _, val := range valSet.Validators { + pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) + require.NoError(t, err) + pkAny, err := codectypes.NewAnyWithValue(pk) + require.NoError(t, err) + validator := stakingtypes.Validator{ + OperatorAddress: sdk.ValAddress(val.Address).String(), + ConsensusPubkey: pkAny, + Jailed: false, + Status: stakingtypes.Bonded, + Tokens: bondAmt, + DelegatorShares: sdk.OneDec(), + Description: stakingtypes.Description{}, + UnbondingHeight: int64(0), + UnbondingTime: time.Unix(0, 0).UTC(), + Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + MinSelfDelegation: sdk.ZeroInt(), + } + validators = append(validators, validator) + delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) + + } + // set validators and delegations + stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) + genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis) + + totalSupply := sdk.NewCoins() + for _, b := range balances { + // add genesis acc tokens and delegated tokens to total supply + totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))...) + } + + // add bonded amount to bonded pool module account + balances = append(balances, banktypes.Balance{ + Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), + Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, + }) + + // update total supply + bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}) + genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) + + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + require.NoError(t, err) + + // init chain will set the validator set and initialize the genesis accounts + app.InitChain( + abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: simapp.DefaultConsensusParams, + AppStateBytes: stateBytes, + }, + ) + + // commit genesis changes + app.Commit() + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{ + Height: app.LastBlockHeight() + 1, + AppHash: app.LastCommitID().Hash, + ValidatorsHash: valSet.Hash(), + NextValidatorsHash: valSet.Hash(), + }}) + + return app +} diff --git a/x/wasm/ibctesting/chain.go b/x/wasm/ibctesting/chain.go index 7c7729f340..ad9e8f18a1 100644 --- a/x/wasm/ibctesting/chain.go +++ b/x/wasm/ibctesting/chain.go @@ -3,24 +3,11 @@ package ibctesting import ( "bytes" "fmt" - wasmd "github.com/CosmWasm/wasmd/app" - "github.com/CosmWasm/wasmd/x/wasm/keeper" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - "io/ioutil" - "os" "strconv" "strings" "testing" "time" - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/tmhash" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmprotoversion "github.com/tendermint/tendermint/proto/tendermint/version" - tmtypes "github.com/tendermint/tendermint/types" - tmversion "github.com/tendermint/tendermint/version" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -29,56 +16,29 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -const ( - // Default params constants used to create a TM client - TrustingPeriod time.Duration = time.Hour * 24 * 7 * 2 - UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3 - MaxClockDrift time.Duration = time.Second * 10 - DefaultDelayPeriod uint64 = 0 - - DefaultChannelVersion = ibctransfertypes.Version - InvalidID = "IDisInvalid" - - ConnectionIDPrefix = "conn" - ChannelIDPrefix = "chan" - - TransferPort = ibctransfertypes.ModuleName - MockPort = mock.ModuleName - - // used for testing UpdateClientProposal - Title = "title" - Description = "description" -) - -var ( - DefaultOpenInitVersion *connectiontypes.Version - - // Default params variables used to create a TM client - DefaultTrustLevel ibctmtypes.Fraction = ibctmtypes.DefaultTrustLevel - TestHash = tmhash.Sum([]byte("TESTING HASH")) - TestCoin = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - - UpgradePath = []string{"upgrade", "upgradedIBCState"} + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/tmhash" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmprotoversion "github.com/tendermint/tendermint/proto/tendermint/version" + tmtypes "github.com/tendermint/tendermint/types" + tmversion "github.com/tendermint/tendermint/version" - ConnectionVersion = connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions())[0] + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + commitmenttypes "github.com/cosmos/ibc-go/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/modules/core/24-host" + "github.com/cosmos/ibc-go/modules/core/exported" + "github.com/cosmos/ibc-go/modules/core/types" + ibctmtypes "github.com/cosmos/ibc-go/modules/light-clients/07-tendermint/types" - MockAcknowledgement = mock.MockAcknowledgement - MockCommitment = mock.MockCommitment + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/mock" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + "github.com/CosmWasm/wasmd/x/wasm/keeper" ) // TestChain is a testing struct that wraps a simapp with the last TM Header, the current ABCI @@ -89,13 +49,14 @@ var ( type TestChain struct { t *testing.T - App *wasmd.WasmApp + Coordinator *Coordinator + App TestingApp ChainID string LastHeader *ibctmtypes.Header // header for last block height committed CurrentHeader tmproto.Header // header for current block height QueryServer types.QueryServer TxConfig client.TxConfig - Codec codec.BinaryMarshaler + Codec codec.BinaryCodec Vals *tmtypes.ValidatorSet Signers []tmtypes.PrivValidator @@ -103,10 +64,6 @@ type TestChain struct { senderPrivKey cryptotypes.PrivKey SenderAccount authtypes.AccountI - // IBC specific helpers - ClientIDs []string // ClientID's used on this chain - Connections []*ibctesting.TestConnection // track connectionID's created for this chain - PendingSendPackets []channeltypes.Packet PendingAckPackets []PacketAck } @@ -124,7 +81,7 @@ type PacketAck struct { // // Time management is handled by the Coordinator in order to ensure synchrony between chains. // Each update of any chain increments the block header time for all chains by 5 seconds. -func NewTestChain(t *testing.T, chainID string, opt ...keeper.Option) *TestChain { +func NewTestChain(t *testing.T, coord *Coordinator, chainID string, opts ...keeper.Option) *TestChain { // generate validator private/public key privVal := mock.NewPV() pubKey, err := privVal.GetPubKey() @@ -143,63 +100,65 @@ func NewTestChain(t *testing.T, chainID string, opt ...keeper.Option) *TestChain Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))), } - // make a temp dir for the wasm files for this chain - tempDir, err := ioutil.TempDir("", "wasm") - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { os.RemoveAll(tempDir) }) - - app := wasmd.SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, opt, balance) + app := SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, opts, balance) // create current header and call begin block header := tmproto.Header{ ChainID: chainID, Height: 1, - Time: globalStartTime, + Time: coord.CurrentTime.UTC(), } - txConfig := wasmd.MakeEncodingConfig().TxConfig + txConfig := app.GetTxConfig() - testScope := wasmd.NewTestSupport(t, app) - ibcKeeper := testScope.IBCKeeper() + // create an account to send transactions from chain := &TestChain{ t: t, + Coordinator: coord, ChainID: chainID, App: app, CurrentHeader: header, - QueryServer: ibcKeeper, + QueryServer: app.GetIBCKeeper(), TxConfig: txConfig, - Codec: testScope.AppCodec(), + Codec: app.AppCodec(), Vals: valSet, Signers: signers, senderPrivKey: senderPrivKey, SenderAccount: acc, - ClientIDs: make([]string, 0), - Connections: make([]*ibctesting.TestConnection, 0), } - portKeeper := &ibcKeeper.PortKeeper - cap := portKeeper.BindPort(chain.GetContext(), MockPort) - err = testScope.ScopedWasmIBCKeeper().ClaimCapability(chain.GetContext(), cap, host.PortPath(MockPort)) - require.NoError(t, err) - - chain.NextBlock() + coord.CommitBlock(chain) return chain } // GetContext returns the current context for the application. func (chain *TestChain) GetContext() sdk.Context { - return chain.App.BaseApp.NewContext(false, chain.CurrentHeader) + return chain.App.GetBaseApp().NewContext(false, chain.CurrentHeader) +} + +// GetSimApp returns the SimApp to allow usage ofnon-interface fields. +// CONTRACT: This function should not be called by third parties implementing +// their own SimApp. +func (chain *TestChain) GetSimApp() *simapp.SimApp { + app, ok := chain.App.(*simapp.SimApp) + require.True(chain.t, ok) + + return app } // QueryProof performs an abci query with the given key and returns the proto encoded merkle proof // for the query and the height at which the proof will succeed on a tendermint verifier. func (chain *TestChain) QueryProof(key []byte) ([]byte, clienttypes.Height) { + return chain.QueryProofAtHeight(key, chain.App.LastBlockHeight()) +} + +// QueryProof performs an abci query with the given key and returns the proto encoded merkle proof +// for the query and the height at which the proof will succeed on a tendermint verifier. +func (chain *TestChain) QueryProofAtHeight(key []byte, height int64) ([]byte, clienttypes.Height) { res := chain.App.Query(abci.RequestQuery{ Path: fmt.Sprintf("store/%s/key", host.StoreKey), - Height: chain.App.LastBlockHeight() - 1, + Height: height - 1, Data: key, Prove: true, }) @@ -207,7 +166,7 @@ func (chain *TestChain) QueryProof(key []byte) ([]byte, clienttypes.Height) { merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) require.NoError(chain.t, err) - proof, err := chain.Codec.MarshalBinaryBare(&merkleProof) + proof, err := chain.App.AppCodec().Marshal(&merkleProof) require.NoError(chain.t, err) revision := clienttypes.ParseChainID(chain.ChainID) @@ -231,7 +190,7 @@ func (chain *TestChain) QueryUpgradeProof(key []byte, height uint64) ([]byte, cl merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) require.NoError(chain.t, err) - proof, err := chain.Codec.MarshalBinaryBare(&merkleProof) + proof, err := chain.App.AppCodec().Marshal(&merkleProof) require.NoError(chain.t, err) revision := clienttypes.ParseChainID(chain.ChainID) @@ -242,19 +201,6 @@ func (chain *TestChain) QueryUpgradeProof(key []byte, height uint64) ([]byte, cl return proof, clienttypes.NewHeight(revision, uint64(res.Height+1)) } -// QueryClientStateProof performs and abci query for a client state -// stored with a given clientID and returns the ClientState along with the proof -func (chain *TestChain) QueryClientStateProof(clientID string) (exported.ClientState, []byte) { - // retrieve client state to provide proof for - clientState, found := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ClientKeeper.GetClientState(chain.GetContext(), clientID) - require.True(chain.t, found) - - clientKey := host.FullClientStateKey(clientID) - proofClient, _ := chain.QueryProof(clientKey) - - return clientState, proofClient -} - // QueryConsensusStateProof performs an abci query for a consensus state // stored on the given clientID. The proof and consensusHeight are returned. func (chain *TestChain) QueryConsensusStateProof(clientID string) ([]byte, clienttypes.Height) { @@ -289,7 +235,6 @@ func (chain *TestChain) NextBlock() { } chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - } // sendMsgs delivers a transaction through the application without returning the result. @@ -302,10 +247,14 @@ func (chain *TestChain) sendMsgs(msgs ...sdk.Msg) error { // number and updates the TestChain's headers. It returns the result and error if one // occurred. func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { - _, r, err := wasmd.SignCheckDeliver( + + // ensure the chain has the latest time + chain.Coordinator.UpdateTimeForChain(chain) + + _, r, err := simapp.SignAndDeliver( chain.t, chain.TxConfig, - chain.App.BaseApp, + chain.App.GetBaseApp(), chain.GetContext().BlockHeader(), msgs, chain.ChainID, @@ -317,12 +266,14 @@ func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { return nil, err } - // SignCheckDeliver calls app.Commit() + // SignAndDeliver calls app.Commit() chain.NextBlock() // increment sequence for successful transaction execution chain.SenderAccount.SetSequence(chain.SenderAccount.GetSequence() + 1) + chain.Coordinator.IncrementTime() + // TODO: also return acks needed to send toSend := getSendPackets(r.Events) if len(toSend) > 0 { @@ -364,14 +315,6 @@ func getAckPackets(evts []abci.Event) []PacketAck { return res } -// Used for various debug statements above when needed... do not remove -func showEvent(evt abci.Event) { - fmt.Printf("evt.Type: %s\n", evt.Type) - for _, attr := range evt.Attributes { - fmt.Printf(" %s = %s\n", string(attr.Key), string(attr.Value)) - } -} - func parsePacketFromEvent(evt abci.Event) channeltypes.Packet { return channeltypes.Packet{ Sequence: getUintField(evt, "packet_sequence"), @@ -422,7 +365,7 @@ func parseTimeoutHeight(raw string) clienttypes.Height { // GetClientState retrieves the client state for the provided clientID. The client is // expected to exist otherwise testing will fail. func (chain *TestChain) GetClientState(clientID string) exported.ClientState { - clientState, found := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ClientKeeper.GetClientState(chain.GetContext(), clientID) + clientState, found := chain.App.GetIBCKeeper().ClientKeeper.GetClientState(chain.GetContext(), clientID) require.True(chain.t, found) return clientState @@ -431,48 +374,30 @@ func (chain *TestChain) GetClientState(clientID string) exported.ClientState { // GetConsensusState retrieves the consensus state for the provided clientID and height. // It will return a success boolean depending on if consensus state exists or not. func (chain *TestChain) GetConsensusState(clientID string, height exported.Height) (exported.ConsensusState, bool) { - return wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ClientKeeper.GetClientConsensusState(chain.GetContext(), clientID, height) + return chain.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(chain.GetContext(), clientID, height) } // GetValsAtHeight will return the validator set of the chain at a given height. It will return // a success boolean depending on if the validator set exists or not at that height. func (chain *TestChain) GetValsAtHeight(height int64) (*tmtypes.ValidatorSet, bool) { - histInfo, ok := wasmd.NewTestSupport(chain.t, chain.App).StakingKeeper().GetHistoricalInfo(chain.GetContext(), height) + histInfo, ok := chain.App.GetStakingKeeper().GetHistoricalInfo(chain.GetContext(), height) if !ok { return nil, false } valSet := stakingtypes.Validators(histInfo.Valset) - tmValidators, err := teststaking.ToTmValidators(valSet) + tmValidators, err := teststaking.ToTmValidators(valSet, sdk.DefaultPowerReduction) if err != nil { panic(err) } return tmtypes.NewValidatorSet(tmValidators), true } -// GetConnection retrieves an IBC Connection for the provided TestConnection. The -// connection is expected to exist otherwise testing will fail. -func (chain *TestChain) GetConnection(testConnection *ibctesting.TestConnection) connectiontypes.ConnectionEnd { - connection, found := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ConnectionKeeper.GetConnection(chain.GetContext(), testConnection.ID) - require.True(chain.t, found) - - return connection -} - -// GetChannel retrieves an IBC Channel for the provided ibctesting.TestChannel. The channel -// is expected to exist otherwise testing will fail. -func (chain *TestChain) GetChannel(testChannel ibctesting.TestChannel) channeltypes.Channel { - channel, found := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ChannelKeeper.GetChannel(chain.GetContext(), testChannel.PortID, testChannel.ID) - require.True(chain.t, found) - - return channel -} - // GetAcknowledgement retrieves an acknowledgement for the provided packet. If the // acknowledgement does not exist then testing will fail. func (chain *TestChain) GetAcknowledgement(packet exported.PacketI) []byte { - ack, found := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ChannelKeeper.GetPacketAcknowledgement(chain.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + ack, found := chain.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(chain.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) require.True(chain.t, found) return ack @@ -480,138 +405,23 @@ func (chain *TestChain) GetAcknowledgement(packet exported.PacketI) []byte { // GetPrefix returns the prefix for used by a chain in connection creation func (chain *TestChain) GetPrefix() commitmenttypes.MerklePrefix { - return commitmenttypes.NewMerklePrefix(wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ConnectionKeeper.GetCommitmentPrefix().Bytes()) -} - -// NewClientID appends a new clientID string in the format: -// ClientFor -func (chain *TestChain) NewClientID(clientType string) string { - clientID := fmt.Sprintf("%s-%s", clientType, strconv.Itoa(len(chain.ClientIDs))) - chain.ClientIDs = append(chain.ClientIDs, clientID) - return clientID -} - -// AddTestConnection appends a new TestConnection which contains references -// to the connection id, client id and counterparty client id. -func (chain *TestChain) AddTestConnection(clientID, counterpartyClientID string) *ibctesting.TestConnection { - conn := chain.ConstructNextTestConnection(clientID, counterpartyClientID) - - chain.Connections = append(chain.Connections, conn) - return conn -} - -// ConstructNextTestConnection constructs the next test connection to be -// created given a clientID and counterparty clientID. The connection id -// format: -conn -func (chain *TestChain) ConstructNextTestConnection(clientID, counterpartyClientID string) *ibctesting.TestConnection { - connectionID := connectiontypes.FormatConnectionIdentifier(uint64(len(chain.Connections))) - return &ibctesting.TestConnection{ - ID: connectionID, - ClientID: clientID, - NextChannelVersion: DefaultChannelVersion, - CounterpartyClientID: counterpartyClientID, - } -} - -// GetFirstTestConnection returns the first test connection for a given clientID. -// The connection may or may not exist in the chain state. -func (chain *TestChain) GetFirstTestConnection(clientID, counterpartyClientID string) *ibctesting.TestConnection { - if len(chain.Connections) > 0 { - return chain.Connections[0] - } - - return chain.ConstructNextTestConnection(clientID, counterpartyClientID) + return commitmenttypes.NewMerklePrefix(chain.App.GetIBCKeeper().ConnectionKeeper.GetCommitmentPrefix().Bytes()) } -// Add ibctesting.TestChannel appends a new ibctesting.TestChannel which contains references to the port and channel ID -// used for channel creation and interaction. See 'Next ibctesting.TestChannel' for channel ID naming format. -func (chain *TestChain) AddTestChannel(conn *ibctesting.TestConnection, portID string) ibctesting.TestChannel { - channel := chain.NextChannel(conn, portID) - conn.Channels = append(conn.Channels, channel) - return channel -} - -// Next ibctesting.TestChannel returns the next test channel to be created on this connection, but does not -// add it to the list of created channels. This function is expected to be used when the caller -// has not created the associated channel in app state, but would still like to refer to the -// non-existent channel usually to test for its non-existence. -// -// channel ID format: -chan -// -// The port is passed in by the caller. -func (chain *TestChain) NextChannel(conn *ibctesting.TestConnection, portID string) ibctesting.TestChannel { - nextChanSeq := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ChannelKeeper.GetNextChannelSequence(chain.GetContext()) - channelID := channeltypes.FormatChannelIdentifier(nextChanSeq) - return ibctesting.TestChannel{ - PortID: portID, - ID: channelID, - ClientID: conn.ClientID, - CounterpartyClientID: conn.CounterpartyClientID, - Version: conn.NextChannelVersion, - } -} - -// ConstructMsgCreateClient constructs a message to create a new client state (tendermint or solomachine). -// NOTE: a solo machine client will be created with an empty diversifier. -func (chain *TestChain) ConstructMsgCreateClient(counterparty *TestChain, clientID string, clientType string) *clienttypes.MsgCreateClient { - var ( - clientState exported.ClientState - consensusState exported.ConsensusState - ) - - switch clientType { - case exported.Tendermint: - height := counterparty.LastHeader.GetHeight().(clienttypes.Height) - clientState = ibctmtypes.NewClientState( - counterparty.ChainID, DefaultTrustLevel, TrustingPeriod, UnbondingPeriod, MaxClockDrift, - height, commitmenttypes.GetSDKSpecs(), UpgradePath, false, false, - ) - consensusState = counterparty.LastHeader.ConsensusState() - case exported.Solomachine: - solo := ibctesting.NewSolomachine(chain.t, chain.Codec, clientID, "", 1) - clientState = solo.ClientState() - consensusState = solo.ConsensusState() - default: - chain.t.Fatalf("unsupported client state type %s", clientType) - } - - msg, err := clienttypes.NewMsgCreateClient( - clientState, consensusState, chain.SenderAccount.GetAddress(), - ) - require.NoError(chain.t, err) - return msg -} - -// CreateTMClient will construct and execute a 07-tendermint MsgCreateClient. A counterparty -// client will be created on the (target) chain. -func (chain *TestChain) CreateTMClient(counterparty *TestChain, clientID string) error { - // construct MsgCreateClient using counterparty - msg := chain.ConstructMsgCreateClient(counterparty, clientID, exported.Tendermint) - return chain.sendMsgs(msg) -} - -// UpdateTMClient will construct and execute a 07-tendermint MsgUpdateClient. The counterparty -// client will be updated on the (target) chain. UpdateTMClient mocks the relayer flow -// necessary for updating a Tendermint client. -func (chain *TestChain) UpdateTMClient(counterparty *TestChain, clientID string) error { - header, err := chain.ConstructUpdateTMClientHeader(counterparty, clientID) - require.NoError(chain.t, err) - - msg, err := clienttypes.NewMsgUpdateClient( - clientID, header, - chain.SenderAccount.GetAddress(), - ) - require.NoError(chain.t, err) - - return chain.sendMsgs(msg) +// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the +// light client on the source chain. +func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctmtypes.Header, error) { + return chain.ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty, clientID, clienttypes.ZeroHeight()) } // ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the // light client on the source chain. -func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctmtypes.Header, error) { +func (chain *TestChain) ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty *TestChain, clientID string, trustedHeight clienttypes.Height) (*ibctmtypes.Header, error) { header := counterparty.LastHeader - // Relayer must query for LatestHeight on client to get TrustedHeight - trustedHeight := chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height) + // Relayer must query for LatestHeight on client to get TrustedHeight if the trusted height is not set + if trustedHeight.IsZero() { + trustedHeight = chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height) + } var ( tmTrustedVals *tmtypes.ValidatorSet ok bool @@ -648,7 +458,7 @@ func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, c // ExpireClient fast forwards the chain's block time by the provided amount of time which will // expire any clients with a trusting period less than or equal to this amount of time. func (chain *TestChain) ExpireClient(amount time.Duration) { - chain.CurrentHeader.Time = chain.CurrentHeader.Time.Add(amount) + chain.Coordinator.IncrementTimeBy(amount) } // CurrentTMClientHeader creates a TM header using the current header parameters @@ -751,105 +561,21 @@ func CreateSortedSignerArray(altPrivVal, suitePrivVal tmtypes.PrivValidator, } } -// ConnectionOpenInit will construct and execute a MsgConnectionOpenInit. -func (chain *TestChain) ConnectionOpenInit( - counterparty *TestChain, - connection, counterpartyConnection *ibctesting.TestConnection, -) error { - msg := connectiontypes.NewMsgConnectionOpenInit( - connection.ClientID, - connection.CounterpartyClientID, - counterparty.GetPrefix(), DefaultOpenInitVersion, DefaultDelayPeriod, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ConnectionOpenTry will construct and execute a MsgConnectionOpenTry. -func (chain *TestChain) ConnectionOpenTry( - counterparty *TestChain, - connection, counterpartyConnection *ibctesting.TestConnection, -) error { - counterpartyClient, proofClient := counterparty.QueryClientStateProof(counterpartyConnection.ClientID) - - connectionKey := host.ConnectionKey(counterpartyConnection.ID) - proofInit, proofHeight := counterparty.QueryProof(connectionKey) - - proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID) - - msg := connectiontypes.NewMsgConnectionOpenTry( - "", connection.ClientID, // does not support handshake continuation - counterpartyConnection.ID, counterpartyConnection.ClientID, - counterpartyClient, counterparty.GetPrefix(), []*connectiontypes.Version{ConnectionVersion}, DefaultDelayPeriod, - proofInit, proofClient, proofConsensus, - proofHeight, consensusHeight, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ConnectionOpenAck will construct and execute a MsgConnectionOpenAck. -func (chain *TestChain) ConnectionOpenAck( - counterparty *TestChain, - connection, counterpartyConnection *ibctesting.TestConnection, -) error { - counterpartyClient, proofClient := counterparty.QueryClientStateProof(counterpartyConnection.ClientID) - - connectionKey := host.ConnectionKey(counterpartyConnection.ID) - proofTry, proofHeight := counterparty.QueryProof(connectionKey) - - proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID) - - msg := connectiontypes.NewMsgConnectionOpenAck( - connection.ID, counterpartyConnection.ID, counterpartyClient, // testing doesn't use flexible selection - proofTry, proofClient, proofConsensus, - proofHeight, consensusHeight, - ConnectionVersion, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ConnectionOpenConfirm will construct and execute a MsgConnectionOpenConfirm. -func (chain *TestChain) ConnectionOpenConfirm( - counterparty *TestChain, - connection, counterpartyConnection *ibctesting.TestConnection, -) error { - connectionKey := host.ConnectionKey(counterpartyConnection.ID) - proof, height := counterparty.QueryProof(connectionKey) - - msg := connectiontypes.NewMsgConnectionOpenConfirm( - connection.ID, - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - // CreatePortCapability binds and claims a capability for the given portID if it does not // already exist. This function will fail testing on any resulting error. // NOTE: only creation of a capbility for a transfer or mock port is supported // Other applications must bind to the port in InitGenesis or modify this code. -func (chain *TestChain) CreatePortCapability(portID string) { +func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID string) { // check if the portId is already binded, if not bind it - _, ok := chain.TestSupport().ScopeIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) + _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) if !ok { // create capability using the IBC capability keeper - cap, err := chain.TestSupport().ScopeIBCKeeper().NewCapability(chain.GetContext(), host.PortPath(portID)) + cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), host.PortPath(portID)) require.NoError(chain.t, err) - switch portID { - case MockPort: - // claim capability using the mock capability keeper - err = wasmd.NewTestSupport(chain.t, chain.App).ScopedWasmIBCKeeper().ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) - require.NoError(chain.t, err) - case TransferPort: - // claim capability using the transfer capability keeper - err = chain.TestSupport().ScopedTransferKeeper().ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) - require.NoError(chain.t, err) - default: - panic(fmt.Sprintf("unsupported ibc testing package port ID %s", portID)) - } + // claim capability using the scopedKeeper + err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) + require.NoError(chain.t, err) } chain.App.Commit() @@ -860,22 +586,23 @@ func (chain *TestChain) CreatePortCapability(portID string) { // GetPortCapability returns the port capability for the given portID. The capability must // exist, otherwise testing will fail. func (chain *TestChain) GetPortCapability(portID string) *capabilitytypes.Capability { - cap, ok := chain.TestSupport().ScopeIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) + cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) require.True(chain.t, ok) return cap } // CreateChannelCapability binds and claims a capability for the given portID and channelID -// if it does not already exist. This function will fail testing on any resulting error. -func (chain *TestChain) CreateChannelCapability(portID, channelID string) { +// if it does not already exist. This function will fail testing on any resulting error. The +// scoped keeper passed in will claim the new capability. +func (chain *TestChain) CreateChannelCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID, channelID string) { capName := host.ChannelCapabilityPath(portID, channelID) // check if the portId is already binded, if not bind it - _, ok := chain.TestSupport().ScopeIBCKeeper().GetCapability(chain.GetContext(), capName) + _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), capName) if !ok { - cap, err := chain.TestSupport().ScopeIBCKeeper().NewCapability(chain.GetContext(), capName) + cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), capName) require.NoError(chain.t, err) - err = chain.TestSupport().ScopedTransferKeeper().ClaimCapability(chain.GetContext(), cap, capName) + err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, capName) require.NoError(chain.t, err) } @@ -887,139 +614,8 @@ func (chain *TestChain) CreateChannelCapability(portID, channelID string) { // GetChannelCapability returns the channel capability for the given portID and channelID. // The capability must exist, otherwise testing will fail. func (chain *TestChain) GetChannelCapability(portID, channelID string) *capabilitytypes.Capability { - cap, ok := chain.TestSupport().ScopeIBCKeeper().GetCapability(chain.GetContext(), host.ChannelCapabilityPath(portID, channelID)) + cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.ChannelCapabilityPath(portID, channelID)) require.True(chain.t, ok) return cap } - -// ChanOpenInit will construct and execute a MsgChannelOpenInit. -func (chain *TestChain) ChanOpenInit( - ch, counterparty ibctesting.TestChannel, - order channeltypes.Order, - connectionID string, -) error { - msg := channeltypes.NewMsgChannelOpenInit( - ch.PortID, - ch.Version, order, []string{connectionID}, - counterparty.PortID, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanOpenTry will construct and execute a MsgChannelOpenTry. -func (chain *TestChain) ChanOpenTry( - counterparty *TestChain, - ch, counterpartyCh ibctesting.TestChannel, - order channeltypes.Order, - connectionID string, -) error { - proof, height := counterparty.QueryProof(host.ChannelKey(counterpartyCh.PortID, counterpartyCh.ID)) - - msg := channeltypes.NewMsgChannelOpenTry( - ch.PortID, "", // does not support handshake continuation - ch.Version, order, []string{connectionID}, - counterpartyCh.PortID, counterpartyCh.ID, counterpartyCh.Version, - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanOpenAck will construct and execute a MsgChannelOpenAck. -func (chain *TestChain) ChanOpenAck( - counterparty *TestChain, - ch, counterpartyCh ibctesting.TestChannel, -) error { - proof, height := counterparty.QueryProof(host.ChannelKey(counterpartyCh.PortID, counterpartyCh.ID)) - - msg := channeltypes.NewMsgChannelOpenAck( - ch.PortID, ch.ID, - counterpartyCh.ID, counterpartyCh.Version, // testing doesn't use flexible selection - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm. -func (chain *TestChain) ChanOpenConfirm( - counterparty *TestChain, - ch, counterpartyCh ibctesting.TestChannel, -) error { - proof, height := counterparty.QueryProof(host.ChannelKey(counterpartyCh.PortID, counterpartyCh.ID)) - - msg := channeltypes.NewMsgChannelOpenConfirm( - ch.PortID, ch.ID, - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanCloseInit will construct and execute a MsgChannelCloseInit. -// -// NOTE: does not work with ibc-transfer module -func (chain *TestChain) ChanCloseInit( - counterparty *TestChain, - channel ibctesting.TestChannel, -) error { - msg := channeltypes.NewMsgChannelCloseInit( - channel.PortID, channel.ID, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// GetPacketData returns a ibc-transfer marshalled packet to be used for -// callback testing. -func (chain *TestChain) GetPacketData(counterparty *TestChain) []byte { - packet := ibctransfertypes.FungibleTokenPacketData{ - Denom: TestCoin.Denom, - Amount: TestCoin.Amount.Uint64(), - Sender: chain.SenderAccount.GetAddress().String(), - Receiver: counterparty.SenderAccount.GetAddress().String(), - } - - return packet.GetBytes() -} - -// SendPacket simulates sending a packet through the channel keeper. No message needs to be -// passed since this call is made from a module. -func (chain *TestChain) SendPacket( - packet exported.PacketI, -) error { - channelCap := chain.GetChannelCapability(packet.GetSourcePort(), packet.GetSourceChannel()) - - // no need to send message, acting as a module - err := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ChannelKeeper.SendPacket(chain.GetContext(), channelCap, packet) - if err != nil { - return err - } - - // commit changes - chain.App.Commit() - chain.NextBlock() - - return nil -} - -// WriteAcknowledgement simulates writing an acknowledgement to the chain. -func (chain *TestChain) WriteAcknowledgement( - packet exported.PacketI, -) error { - channelCap := chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel()) - - // no need to send message, acting as a handler - err := wasmd.NewTestSupport(chain.t, chain.App).IBCKeeper().ChannelKeeper.WriteAcknowledgement(chain.GetContext(), channelCap, packet, TestHash) - if err != nil { - return err - } - - // commit changes - chain.App.Commit() - chain.NextBlock() - - return nil -} diff --git a/x/wasm/ibctesting/chain_test.go b/x/wasm/ibctesting/chain_test.go new file mode 100644 index 0000000000..8af4bd79af --- /dev/null +++ b/x/wasm/ibctesting/chain_test.go @@ -0,0 +1,47 @@ +package ibctesting_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/mock" +) + +func TestCreateSortedSignerArray(t *testing.T) { + privVal1 := mock.NewPV() + pubKey1, err := privVal1.GetPubKey() + require.NoError(t, err) + + privVal2 := mock.NewPV() + pubKey2, err := privVal2.GetPubKey() + require.NoError(t, err) + + validator1 := tmtypes.NewValidator(pubKey1, 1) + validator2 := tmtypes.NewValidator(pubKey2, 2) + + expected := []tmtypes.PrivValidator{privVal2, privVal1} + + actual := ibctesting.CreateSortedSignerArray(privVal1, privVal2, validator1, validator2) + require.Equal(t, expected, actual) + + // swap order + actual = ibctesting.CreateSortedSignerArray(privVal2, privVal1, validator2, validator1) + require.Equal(t, expected, actual) + + // smaller address + validator1.Address = []byte{1} + validator2.Address = []byte{2} + validator2.VotingPower = 1 + + expected = []tmtypes.PrivValidator{privVal1, privVal2} + + actual = ibctesting.CreateSortedSignerArray(privVal1, privVal2, validator1, validator2) + require.Equal(t, expected, actual) + + // swap order + actual = ibctesting.CreateSortedSignerArray(privVal2, privVal1, validator2, validator1) + require.Equal(t, expected, actual) +} diff --git a/x/wasm/ibctesting/config.go b/x/wasm/ibctesting/config.go new file mode 100644 index 0000000000..ad2bf07af2 --- /dev/null +++ b/x/wasm/ibctesting/config.go @@ -0,0 +1,66 @@ +package ibctesting + +import ( + "time" + + connectiontypes "github.com/cosmos/ibc-go/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/modules/core/exported" + ibctmtypes "github.com/cosmos/ibc-go/modules/light-clients/07-tendermint/types" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/mock" +) + +type ClientConfig interface { + GetClientType() string +} + +type TendermintConfig struct { + TrustLevel ibctmtypes.Fraction + TrustingPeriod time.Duration + UnbondingPeriod time.Duration + MaxClockDrift time.Duration + AllowUpdateAfterExpiry bool + AllowUpdateAfterMisbehaviour bool +} + +func NewTendermintConfig() *TendermintConfig { + return &TendermintConfig{ + TrustLevel: DefaultTrustLevel, + TrustingPeriod: TrustingPeriod, + UnbondingPeriod: UnbondingPeriod, + MaxClockDrift: MaxClockDrift, + AllowUpdateAfterExpiry: false, + AllowUpdateAfterMisbehaviour: false, + } +} + +func (tmcfg *TendermintConfig) GetClientType() string { + return exported.Tendermint +} + +type ConnectionConfig struct { + DelayPeriod uint64 + Version *connectiontypes.Version +} + +func NewConnectionConfig() *ConnectionConfig { + return &ConnectionConfig{ + DelayPeriod: DefaultDelayPeriod, + Version: ConnectionVersion, + } +} + +type ChannelConfig struct { + PortID string + Version string + Order channeltypes.Order +} + +func NewChannelConfig() *ChannelConfig { + return &ChannelConfig{ + PortID: mock.ModuleName, + Version: DefaultChannelVersion, + Order: channeltypes.UNORDERED, + } +} diff --git a/x/wasm/ibctesting/coordinator.go b/x/wasm/ibctesting/coordinator.go index ab0c22b257..bc2d1452f0 100644 --- a/x/wasm/ibctesting/coordinator.go +++ b/x/wasm/ibctesting/coordinator.go @@ -2,22 +2,21 @@ package ibctesting import ( "fmt" - "github.com/CosmWasm/wasmd/x/wasm/keeper" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" "strconv" "testing" "time" - sdk "github.com/cosmos/cosmos-sdk/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/modules/core/24-host" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + + "github.com/CosmWasm/wasmd/x/wasm/keeper" ) +const ChainIDPrefix = "testchain" + var ( - ChainIDPrefix = "testchain" globalStartTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) TimeIncrement = time.Second * 5 ) @@ -27,398 +26,150 @@ var ( type Coordinator struct { t *testing.T - Chains map[string]*TestChain + CurrentTime time.Time + Chains map[string]*TestChain } // NewCoordinator initializes Coordinator with N TestChain's func NewCoordinator(t *testing.T, n int, opts ...[]keeper.Option) *Coordinator { chains := make(map[string]*TestChain) - if len(opts) != 0 && len(opts) != n { - t.Fatalf("opts not matching number of instances: %d", len(opts)) + coord := &Coordinator{ + t: t, + CurrentTime: globalStartTime, } + for i := 0; i < n; i++ { chainID := GetChainID(i) - var iOpts []keeper.Option + var iopts []keeper.Option if len(opts) != 0 { - iOpts = opts[i] + iopts = opts[i] } - chains[chainID] = NewTestChain(t, chainID, iOpts...) + chains[chainID] = NewTestChain(t, coord, chainID, iopts...) } - return &Coordinator{ - t: t, - Chains: chains, + coord.Chains = chains + + return coord +} + +// IncrementTime iterates through all the TestChain's and increments their current header time +// by 5 seconds. +// +// CONTRACT: this function must be called after every Commit on any TestChain. +func (coord *Coordinator) IncrementTime() { + coord.IncrementTimeBy(TimeIncrement) +} + +// IncrementTimeBy iterates through all the TestChain's and increments their current header time +// by specified time. +func (coord *Coordinator) IncrementTimeBy(increment time.Duration) { + coord.CurrentTime = coord.CurrentTime.Add(increment).UTC() + coord.UpdateTime() + +} + +// UpdateTime updates all clocks for the TestChains to the current global time. +func (coord *Coordinator) UpdateTime() { + for _, chain := range coord.Chains { + coord.UpdateTimeForChain(chain) } } +// UpdateTimeForChain updates the clock for a specific chain. +func (coord *Coordinator) UpdateTimeForChain(chain *TestChain) { + chain.CurrentHeader.Time = coord.CurrentTime.UTC() + chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) +} + // Setup constructs a TM client, connection, and channel on both chains provided. It will // fail if any error occurs. The clientID's, TestConnections, and TestChannels are returned // for both chains. The channels created are connected to the ibc-transfer application. -func (coord *Coordinator) Setup( - chainA, chainB *TestChain, order channeltypes.Order, -) (string, string, *ibctesting.TestConnection, *ibctesting.TestConnection, ibctesting.TestChannel, ibctesting.TestChannel) { - clientA, clientB, connA, connB := coord.SetupClientConnections(chainA, chainB, exported.Tendermint) +func (coord *Coordinator) Setup(path *Path) { + coord.SetupConnections(path) // channels can also be referenced through the returned connections - channelA, channelB := coord.CreateMockChannels(chainA, chainB, connA, connB, order) - - return clientA, clientB, connA, connB, channelA, channelB + coord.CreateChannels(path) } // SetupClients is a helper function to create clients on both chains. It assumes the // caller does not anticipate any errors. -func (coord *Coordinator) SetupClients( - chainA, chainB *TestChain, - clientType string, -) (string, string) { - - clientA, err := coord.CreateClient(chainA, chainB, clientType) +func (coord *Coordinator) SetupClients(path *Path) { + err := path.EndpointA.CreateClient() require.NoError(coord.t, err) - clientB, err := coord.CreateClient(chainB, chainA, clientType) + err = path.EndpointB.CreateClient() require.NoError(coord.t, err) - - return clientA, clientB } // SetupClientConnections is a helper function to create clients and the appropriate // connections on both the source and counterparty chain. It assumes the caller does not // anticipate any errors. -func (coord *Coordinator) SetupClientConnections( - chainA, chainB *TestChain, - clientType string, -) (string, string, *ibctesting.TestConnection, *ibctesting.TestConnection) { - - clientA, clientB := coord.SetupClients(chainA, chainB, clientType) - - connA, connB := coord.CreateConnection(chainA, chainB, clientA, clientB) - - return clientA, clientB, connA, connB -} +func (coord *Coordinator) SetupConnections(path *Path) { + coord.SetupClients(path) -// CreateClient creates a counterparty client on the source chain and returns the clientID. -func (coord *Coordinator) CreateClient( - source, counterparty *TestChain, - clientType string, -) (clientID string, err error) { - coord.CommitBlock(source, counterparty) - - clientID = source.NewClientID(clientType) - - switch clientType { - case exported.Tendermint: - err = source.CreateTMClient(counterparty, clientID) - - default: - err = fmt.Errorf("client type %s is not supported", clientType) - } - - if err != nil { - return "", err - } - - coord.IncrementTime() - - return clientID, nil -} - -// UpdateClient updates a counterparty client on the source chain. -func (coord *Coordinator) UpdateClient( - source, counterparty *TestChain, - clientID string, - clientType string, -) (err error) { - coord.CommitBlock(source, counterparty) - - switch clientType { - case exported.Tendermint: - err = source.UpdateTMClient(counterparty, clientID) - - default: - err = fmt.Errorf("client type %s is not supported", clientType) - } - - if err != nil { - return err - } - - coord.IncrementTime() - - return nil + coord.CreateConnections(path) } // CreateConnection constructs and executes connection handshake messages in order to create // OPEN channels on chainA and chainB. The connection information of for chainA and chainB // are returned within a TestConnection struct. The function expects the connections to be // successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateConnection( - chainA, chainB *TestChain, - clientA, clientB string, -) (*ibctesting.TestConnection, *ibctesting.TestConnection) { +func (coord *Coordinator) CreateConnections(path *Path) { - connA, connB, err := coord.ConnOpenInit(chainA, chainB, clientA, clientB) + err := path.EndpointA.ConnOpenInit() require.NoError(coord.t, err) - err = coord.ConnOpenTry(chainB, chainA, connB, connA) + err = path.EndpointB.ConnOpenTry() require.NoError(coord.t, err) - err = coord.ConnOpenAck(chainA, chainB, connA, connB) + err = path.EndpointA.ConnOpenAck() require.NoError(coord.t, err) - err = coord.ConnOpenConfirm(chainB, chainA, connB, connA) + err = path.EndpointB.ConnOpenConfirm() require.NoError(coord.t, err) - return connA, connB + // ensure counterparty is up to date + path.EndpointA.UpdateClient() } // CreateMockChannels constructs and executes channel handshake messages to create OPEN // channels that use a mock application module that returns nil on all callbacks. This // function is expects the channels to be successfully opened otherwise testing will // fail. -func (coord *Coordinator) CreateMockChannels( - chainA, chainB *TestChain, - connA, connB *ibctesting.TestConnection, - order channeltypes.Order, -) (ibctesting.TestChannel, ibctesting.TestChannel) { - return coord.CreateChannel(chainA, chainB, connA, connB, MockPort, MockPort, order) +func (coord *Coordinator) CreateMockChannels(path *Path) { + path.EndpointA.ChannelConfig.PortID = MockPort + path.EndpointB.ChannelConfig.PortID = MockPort + + coord.CreateChannels(path) } // CreateTransferChannels constructs and executes channel handshake messages to create OPEN // ibc-transfer channels on chainA and chainB. The function expects the channels to be // successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateTransferChannels( - chainA, chainB *TestChain, - connA, connB *ibctesting.TestConnection, - order channeltypes.Order, -) (ibctesting.TestChannel, ibctesting.TestChannel) { - return coord.CreateChannel(chainA, chainB, connA, connB, TransferPort, TransferPort, order) +func (coord *Coordinator) CreateTransferChannels(path *Path) { + path.EndpointA.ChannelConfig.PortID = TransferPort + path.EndpointB.ChannelConfig.PortID = TransferPort + + coord.CreateChannels(path) } // CreateChannel constructs and executes channel handshake messages in order to create // OPEN channels on chainA and chainB. The function expects the channels to be successfully // opened otherwise testing will fail. -func (coord *Coordinator) CreateChannel( - chainA, chainB *TestChain, - connA, connB *ibctesting.TestConnection, - sourcePortID, counterpartyPortID string, - order channeltypes.Order, -) (ibctesting.TestChannel, ibctesting.TestChannel) { - - channelA, channelB, err := coord.ChanOpenInit(chainA, chainB, connA, connB, sourcePortID, counterpartyPortID, order) +func (coord *Coordinator) CreateChannels(path *Path) { + err := path.EndpointA.ChanOpenInit() require.NoError(coord.t, err) - err = coord.ChanOpenTry(chainB, chainA, channelB, channelA, connB, order) + err = path.EndpointB.ChanOpenTry() require.NoError(coord.t, err) - err = coord.ChanOpenAck(chainA, chainB, channelA, channelB) + err = path.EndpointA.ChanOpenAck() require.NoError(coord.t, err) - err = coord.ChanOpenConfirm(chainB, chainA, channelB, channelA) + err = path.EndpointB.ChanOpenConfirm() require.NoError(coord.t, err) - return channelA, channelB -} - -// SendPacket sends a packet through the channel keeper on the source chain and updates the -// counterparty client for the source chain. -func (coord *Coordinator) SendPacket( - source, counterparty *TestChain, - packet exported.PacketI, - counterpartyClientID string, -) error { - if err := source.SendPacket(packet); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ) -} - -// RecvPacket receives a channel packet on the counterparty chain and updates -// the client on the source chain representing the counterparty. -func (coord *Coordinator) RecvPacket( - source, counterparty *TestChain, - sourceClient string, - packet channeltypes.Packet, -) error { - // get proof of packet commitment on source - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := source.QueryProof(packetKey) - - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(source, counterparty) - - recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, counterparty.SenderAccount.GetAddress()) - - // receive on counterparty and update source client - return coord.SendMsgs(counterparty, source, sourceClient, []sdk.Msg{recvMsg}) -} - -// TimeoutPacket returns the package to source chain to let the IBC app revert any operation. -func (coord *Coordinator) TimeoutPacket( - source, counterparty *TestChain, - counterpartyClient string, - packet channeltypes.Packet, -) error { - // get proof of packet unreceived on dest - packetKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proofUnreceived, proofHeight := counterparty.QueryProof(packetKey) - - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(source, counterparty) - - timeoutMsg := channeltypes.NewMsgTimeout(packet, packet.Sequence, proofUnreceived, proofHeight, source.SenderAccount.GetAddress()) - return coord.SendMsgs(source, counterparty, counterpartyClient, []sdk.Msg{timeoutMsg}) -} - -// WriteAcknowledgement writes an acknowledgement to the channel keeper on the source chain and updates the -// counterparty client for the source chain. -func (coord *Coordinator) WriteAcknowledgement( - source, counterparty *TestChain, - packet exported.PacketI, - counterpartyClientID string, -) error { - if err := source.WriteAcknowledgement(packet); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ) -} - -// AcknowledgePacket acknowledges on the source chain the packet received on -// the counterparty chain and updates the client on the counterparty representing -// the source chain. -// TODO: add a query for the acknowledgement by events -// - https://github.com/cosmos/cosmos-sdk/issues/6509 -func (coord *Coordinator) AcknowledgePacket( - source, counterparty *TestChain, - counterpartyClient string, - packet channeltypes.Packet, ack []byte, -) error { - // get proof of acknowledgement on counterparty - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := counterparty.QueryProof(packetKey) - - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(source, counterparty) - - ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, source.SenderAccount.GetAddress()) - return coord.SendMsgs(source, counterparty, counterpartyClient, []sdk.Msg{ackMsg}) -} - -// RelayPacket receives a channel packet on counterparty, queries the ack -// and acknowledges the packet on source. The clients are updated as needed. -func (coord *Coordinator) RelayPacket( - source, counterparty *TestChain, - sourceClient, counterpartyClient string, - packet channeltypes.Packet, ack []byte, -) error { - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(counterparty) - - if err := coord.RecvPacket(source, counterparty, sourceClient, packet); err != nil { - return err - } - - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(source) - - return coord.AcknowledgePacket(source, counterparty, counterpartyClient, packet, ack) -} - -// IncrementTime iterates through all the TestChain's and increments their current header time -// by 5 seconds. -// -// CONTRACT: this function must be called after every commit on any TestChain. -func (coord *Coordinator) IncrementTime() { - for _, chain := range coord.Chains { - chain.CurrentHeader.Time = chain.CurrentHeader.Time.Add(TimeIncrement) - chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - } -} - -// IncrementTimeBy iterates through all the TestChain's and increments their current header time -// by specified time. -func (coord *Coordinator) IncrementTimeBy(increment time.Duration) { - for _, chain := range coord.Chains { - chain.CurrentHeader.Time = chain.CurrentHeader.Time.Add(increment) - chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - } -} - -// SendMsg delivers a single provided message to the chain. The counterparty -// client is update with the new source consensus state. -func (coord *Coordinator) SendMsg(source, counterparty *TestChain, counterpartyClientID string, msg sdk.Msg) error { - return coord.SendMsgs(source, counterparty, counterpartyClientID, []sdk.Msg{msg}) -} - -// SendMsgs delivers the provided messages to the chain. The counterparty -// client is updated with the new source consensus state. -func (coord *Coordinator) SendMsgs(source, counterparty *TestChain, counterpartyClientID string, msgs []sdk.Msg) error { - if err := source.sendMsgs(msgs...); err != nil { - return err - } - - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ) -} - -func (coord *Coordinator) RelayAndAckPendingPackets(src, dest *TestChain, srcClientID, dstClientID string) error { - // get all the packet to relay src->dest - toSend := src.PendingSendPackets - src.PendingSendPackets = nil - fmt.Printf("Relay %d Packets A->B\n", len(toSend)) - - // send this to the other side - coord.IncrementTime() - coord.CommitBlock(src) - err := coord.UpdateClient(dest, src, dstClientID, exported.Tendermint) - for _, packet := range toSend { - err = coord.RecvPacket(src, dest, srcClientID, packet) - if err != nil { - return err - } - } - - // get all the acks to relay dest->src - toAck := dest.PendingAckPackets - dest.PendingAckPackets = nil - // TODO: assert >= len(toSend)? - fmt.Printf("Ack %d Packets B->A\n", len(toAck)) - - // send the ack back from dest -> src - coord.IncrementTime() - coord.CommitBlock(dest) - err = coord.UpdateClient(src, dest, srcClientID, exported.Tendermint) - if err != nil { - return err - } - for _, ack := range toAck { - err = coord.AcknowledgePacket(src, dest, srcClientID, ack.Packet, ack.Ack) - if err != nil { - return err - } - } - - return nil + // ensure counterparty is up to date + path.EndpointA.UpdateClient() } // GetChain returns the TestChain using the given chainID and returns an error if it does @@ -455,345 +206,98 @@ func (coord *Coordinator) CommitNBlocks(chain *TestChain, n uint64) { } } -// ConnOpenInit initializes a connection on the source chain with the state INIT -// using the OpenInit handshake call. -// -// NOTE: The counterparty testing connection will be created even if it is not created in the -// application state. -func (coord *Coordinator) ConnOpenInit( - source, counterparty *TestChain, - clientID, counterpartyClientID string, -) (*ibctesting.TestConnection, *ibctesting.TestConnection, error) { - sourceConnection := source.AddTestConnection(clientID, counterpartyClientID) - counterpartyConnection := counterparty.AddTestConnection(counterpartyClientID, clientID) - - // initialize connection on source - if err := source.ConnectionOpenInit(counterparty, sourceConnection, counterpartyConnection); err != nil { - return sourceConnection, counterpartyConnection, err - } - coord.IncrementTime() - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ); err != nil { - return sourceConnection, counterpartyConnection, err - } - - return sourceConnection, counterpartyConnection, nil -} - -// ConnOpenInitOnBothChains initializes a connection on the source chain with the state INIT +// ConnOpenInitOnBothChains initializes a connection on both endpoints with the state INIT // using the OpenInit handshake call. -func (coord *Coordinator) ConnOpenInitOnBothChains( - source, counterparty *TestChain, - clientID, counterpartyClientID string, -) (*ibctesting.TestConnection, *ibctesting.TestConnection, error) { - sourceConnection := source.AddTestConnection(clientID, counterpartyClientID) - counterpartyConnection := counterparty.AddTestConnection(counterpartyClientID, clientID) - - // initialize connection on source - if err := source.ConnectionOpenInit(counterparty, sourceConnection, counterpartyConnection); err != nil { - return sourceConnection, counterpartyConnection, err - } - coord.IncrementTime() - - // initialize connection on counterparty - if err := counterparty.ConnectionOpenInit(source, counterpartyConnection, sourceConnection); err != nil { - return sourceConnection, counterpartyConnection, err - } - coord.IncrementTime() - - // update counterparty client on source connection - if err := coord.UpdateClient( - source, counterparty, - clientID, exported.Tendermint, - ); err != nil { - return sourceConnection, counterpartyConnection, err - } - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ); err != nil { - return sourceConnection, counterpartyConnection, err - } - - return sourceConnection, counterpartyConnection, nil -} - -// ConnOpenTry initializes a connection on the source chain with the state TRYOPEN -// using the OpenTry handshake call. -func (coord *Coordinator) ConnOpenTry( - source, counterparty *TestChain, - sourceConnection, counterpartyConnection *ibctesting.TestConnection, -) error { - // initialize TRYOPEN connection on source - if err := source.ConnectionOpenTry(counterparty, sourceConnection, counterpartyConnection); err != nil { +func (coord *Coordinator) ConnOpenInitOnBothChains(path *Path) error { + if err := path.EndpointA.ConnOpenInit(); err != nil { return err } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ) -} -// ConnOpenAck initializes a connection on the source chain with the state OPEN -// using the OpenAck handshake call. -func (coord *Coordinator) ConnOpenAck( - source, counterparty *TestChain, - sourceConnection, counterpartyConnection *ibctesting.TestConnection, -) error { - // set OPEN connection on source using OpenAck - if err := source.ConnectionOpenAck(counterparty, sourceConnection, counterpartyConnection); err != nil { + if err := path.EndpointB.ConnOpenInit(); err != nil { return err } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ) -} -// ConnOpenConfirm initializes a connection on the source chain with the state OPEN -// using the OpenConfirm handshake call. -func (coord *Coordinator) ConnOpenConfirm( - source, counterparty *TestChain, - sourceConnection, counterpartyConnection *ibctesting.TestConnection, -) error { - if err := source.ConnectionOpenConfirm(counterparty, sourceConnection, counterpartyConnection); err != nil { + if err := path.EndpointA.UpdateClient(); err != nil { return err } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ) -} -// ChanOpenInit initializes a channel on the source chain with the state INIT -// using the OpenInit handshake call. -// -// NOTE: The counterparty testing channel will be created even if it is not created in the -// application state. -func (coord *Coordinator) ChanOpenInit( - source, counterparty *TestChain, - connection, counterpartyConnection *ibctesting.TestConnection, - sourcePortID, counterpartyPortID string, - order channeltypes.Order, -) (ibctesting.TestChannel, ibctesting.TestChannel, error) { - sourceChannel := source.AddTestChannel(connection, sourcePortID) - counterpartyChannel := counterparty.AddTestChannel(counterpartyConnection, counterpartyPortID) - - // NOTE: only creation of a capability for a transfer or mock port is supported - // Other applications must bind to the port in InitGenesis or modify this code. - source.CreatePortCapability(sourceChannel.PortID) - coord.IncrementTime() - - // initialize channel on source - if err := source.ChanOpenInit(sourceChannel, counterpartyChannel, order, connection.ID); err != nil { - return sourceChannel, counterpartyChannel, err - } - coord.IncrementTime() - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ); err != nil { - return sourceChannel, counterpartyChannel, err + if err := path.EndpointB.UpdateClient(); err != nil { + return err } - return sourceChannel, counterpartyChannel, nil + return nil } // ChanOpenInitOnBothChains initializes a channel on the source chain and counterparty chain // with the state INIT using the OpenInit handshake call. -func (coord *Coordinator) ChanOpenInitOnBothChains( - source, counterparty *TestChain, - connection, counterpartyConnection *ibctesting.TestConnection, - sourcePortID, counterpartyPortID string, - order channeltypes.Order, -) (ibctesting.TestChannel, ibctesting.TestChannel, error) { - sourceChannel := source.AddTestChannel(connection, sourcePortID) - counterpartyChannel := counterparty.AddTestChannel(counterpartyConnection, counterpartyPortID) - +func (coord *Coordinator) ChanOpenInitOnBothChains(path *Path) error { // NOTE: only creation of a capability for a transfer or mock port is supported // Other applications must bind to the port in InitGenesis or modify this code. - source.CreatePortCapability(sourceChannel.PortID) - counterparty.CreatePortCapability(counterpartyChannel.PortID) - coord.IncrementTime() - // initialize channel on source - if err := source.ChanOpenInit(sourceChannel, counterpartyChannel, order, connection.ID); err != nil { - return sourceChannel, counterpartyChannel, err - } - coord.IncrementTime() - - // initialize channel on counterparty - if err := counterparty.ChanOpenInit(counterpartyChannel, sourceChannel, order, counterpartyConnection.ID); err != nil { - return sourceChannel, counterpartyChannel, err - } - coord.IncrementTime() - - // update counterparty client on source connection - if err := coord.UpdateClient( - source, counterparty, - connection.ClientID, exported.Tendermint, - ); err != nil { - return sourceChannel, counterpartyChannel, err - } - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ); err != nil { - return sourceChannel, counterpartyChannel, err + if err := path.EndpointA.ChanOpenInit(); err != nil { + return err } - return sourceChannel, counterpartyChannel, nil -} - -// ChanOpenTry initializes a channel on the source chain with the state TRYOPEN -// using the OpenTry handshake call. -func (coord *Coordinator) ChanOpenTry( - source, counterparty *TestChain, - sourceChannel, counterpartyChannel ibctesting.TestChannel, - connection *ibctesting.TestConnection, - order channeltypes.Order, -) error { - - // initialize channel on source - if err := source.ChanOpenTry(counterparty, sourceChannel, counterpartyChannel, order, connection.ID); err != nil { + if err := path.EndpointB.ChanOpenInit(); err != nil { return err } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - connection.CounterpartyClientID, exported.Tendermint, - ) -} - -// ChanOpenAck initializes a channel on the source chain with the state OPEN -// using the OpenAck handshake call. -func (coord *Coordinator) ChanOpenAck( - source, counterparty *TestChain, - sourceChannel, counterpartyChannel ibctesting.TestChannel, -) error { - if err := source.ChanOpenAck(counterparty, sourceChannel, counterpartyChannel); err != nil { + if err := path.EndpointA.UpdateClient(); err != nil { return err } - coord.IncrementTime() - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - sourceChannel.CounterpartyClientID, exported.Tendermint, - ) -} - -// ChanOpenConfirm initializes a channel on the source chain with the state OPEN -// using the OpenConfirm handshake call. -func (coord *Coordinator) ChanOpenConfirm( - source, counterparty *TestChain, - sourceChannel, counterpartyChannel ibctesting.TestChannel, -) error { - - if err := source.ChanOpenConfirm(counterparty, sourceChannel, counterpartyChannel); err != nil { + if err := path.EndpointB.UpdateClient(); err != nil { return err } - coord.IncrementTime() - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - sourceChannel.CounterpartyClientID, exported.Tendermint, - ) + return nil } -func (coord *Coordinator) CloseChannel( - source, counterparty *TestChain, - channel, counterpartyChannel ibctesting.TestChannel, -) { - err := source.ChanCloseInit(counterparty, channel) - require.NoError(coord.t, err) +func (coord *Coordinator) RelayAndAckPendingPackets(path *Path) error { + // get all the packet to relay src->dest + toSend := path.EndpointA.Chain.PendingSendPackets + path.EndpointA.Chain.PendingSendPackets = nil + fmt.Printf("Relay %d Packets A->B\n", len(toSend)) - coord.IncrementTime() - err = coord.UpdateClient(counterparty, source, counterpartyChannel.ClientID, exported.Tendermint) - require.NoError(coord.t, err) - err = coord.ChanCloseConfirm(source, counterparty, channel, counterpartyChannel) - require.NoError(coord.t, err) -} + // send this to the other side + for _, packet := range toSend { + packet.Sequence++ + if err := path.EndpointA.SendPacket(packet); err != nil { + return err + } + packet.Sequence-- + if err := path.EndpointB.RecvPacket(packet); err != nil { + return err + } + } -// ChanCloseInit closes a channel on the source chain resulting in the channels state -// being set to CLOSED. -// -// NOTE: does not work with ibc-transfer module -func (coord *Coordinator) ChanCloseInit( - source, counterparty *TestChain, - channel ibctesting.TestChannel, -) error { + // get all the acks to relay dest->src + toAck := path.EndpointB.Chain.PendingAckPackets + path.EndpointB.Chain.PendingAckPackets = nil + fmt.Printf("Ack %d Packets B->A\n", len(toAck)) - if err := source.ChanCloseInit(counterparty, channel); err != nil { - return err + // send the ack back from dest -> src + for _, ack := range toAck { + if err := path.EndpointA.AcknowledgePacket(ack.Packet, ack.Ack); err != nil { + return err + } } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - channel.CounterpartyClientID, exported.Tendermint, - ) -} -// ChanCloseConfirm closes a channel on the counterparty chain resulting in the channels state -// being set to CLOSED. -// -// NOTE: does not work with ibc-transfer module -func (coord *Coordinator) ChanCloseConfirm( - source, counterparty *TestChain, - channel, counterpartyChannel ibctesting.TestChannel, -) error { - channelKey := host.ChannelKey(channel.PortID, channel.ID) - proof, proofHeight := source.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelCloseConfirm( - counterpartyChannel.PortID, counterpartyChannel.ID, - proof, proofHeight, - counterparty.SenderAccount.GetAddress(), - ) - return coord.SendMsgs(counterparty, source, counterpartyChannel.CounterpartyClientID, []sdk.Msg{msg}) + return nil } -// SetChannelClosed sets a channel state to CLOSED. -func (coord *Coordinator) SetChannelClosed( - source, counterparty *TestChain, - testChannel ibctesting.TestChannel, -) error { - channel := source.GetChannel(testChannel) - - channel.State = channeltypes.CLOSED - source.TestSupport(). - IBCKeeper().ChannelKeeper.SetChannel(source.GetContext(), testChannel.PortID, testChannel.ID, channel) +// TimeoutPacket returns the package to source chain to let the IBC app revert any operation. +func (coord *Coordinator) TimeoutPacket(path *Path, packet channeltypes.Packet) error { + // get proof of packet unreceived on dest + packetKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + proofUnreceived, proofHeight := path.EndpointB.QueryProof(packetKey) - coord.CommitBlock(source) + // Increment time and commit block so that a delay period passes between send and receive + coord.IncrementTime() + coord.CommitBlock(path.EndpointA.Chain, path.EndpointB.Chain) - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - testChannel.CounterpartyClientID, exported.Tendermint, - ) + timeoutMsg := channeltypes.NewMsgTimeout( + packet, packet.Sequence, proofUnreceived, proofHeight, path.EndpointA.Chain.SenderAccount.GetAddress().String()) + _, err := path.EndpointA.Chain.SendMsgs(timeoutMsg) + return err } diff --git a/x/wasm/ibctesting/endpoint.go b/x/wasm/ibctesting/endpoint.go new file mode 100644 index 0000000000..e32d0cdfbf --- /dev/null +++ b/x/wasm/ibctesting/endpoint.go @@ -0,0 +1,493 @@ +package ibctesting + +import ( + "fmt" + + // sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + connectiontypes "github.com/cosmos/ibc-go/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + commitmenttypes "github.com/cosmos/ibc-go/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/modules/core/24-host" + "github.com/cosmos/ibc-go/modules/core/exported" + ibctmtypes "github.com/cosmos/ibc-go/modules/light-clients/07-tendermint/types" +) + +// Endpoint is a which represents a channel endpoint and its associated +// client and connections. It contains client, connection, and channel +// configuration parameters. Endpoint functions will utilize the parameters +// set in the configuration structs when executing IBC messages. +type Endpoint struct { + Chain *TestChain + Counterparty *Endpoint + ClientID string + ConnectionID string + ChannelID string + + ClientConfig ClientConfig + ConnectionConfig *ConnectionConfig + ChannelConfig *ChannelConfig +} + +// NewEndpoint constructs a new endpoint without the counterparty. +// CONTRACT: the counterparty endpoint must be set by the caller. +func NewEndpoint( + chain *TestChain, clientConfig ClientConfig, + connectionConfig *ConnectionConfig, channelConfig *ChannelConfig, +) *Endpoint { + return &Endpoint{ + Chain: chain, + ClientConfig: clientConfig, + ConnectionConfig: connectionConfig, + ChannelConfig: channelConfig, + } +} + +// NewDefaultEndpoint constructs a new endpoint using default values. +// CONTRACT: the counterparty endpoitn must be set by the caller. +func NewDefaultEndpoint(chain *TestChain) *Endpoint { + return &Endpoint{ + Chain: chain, + ClientConfig: NewTendermintConfig(), + ConnectionConfig: NewConnectionConfig(), + ChannelConfig: NewChannelConfig(), + } +} + +// QueryProof queries proof associated with this endpoint using the lastest client state +// height on the counterparty chain. +func (endpoint *Endpoint) QueryProof(key []byte) ([]byte, clienttypes.Height) { + // obtain the counterparty client representing the chain associated with the endpoint + clientState := endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID) + + // query proof on the counterparty using the latest height of the IBC client + return endpoint.QueryProofAtHeight(key, clientState.GetLatestHeight().GetRevisionHeight()) +} + +// QueryProofAtHeight queries proof associated with this endpoint using the proof height +// providied +func (endpoint *Endpoint) QueryProofAtHeight(key []byte, height uint64) ([]byte, clienttypes.Height) { + // query proof on the counterparty using the latest height of the IBC client + return endpoint.Chain.QueryProofAtHeight(key, int64(height)) +} + +// CreateClient creates an IBC client on the endpoint. It will update the +// clientID for the endpoint if the message is successfully executed. +// NOTE: a solo machine client will be created with an empty diversifier. +func (endpoint *Endpoint) CreateClient() (err error) { + // ensure counterparty has committed state + endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) + + var ( + clientState exported.ClientState + consensusState exported.ConsensusState + ) + + switch endpoint.ClientConfig.GetClientType() { + case exported.Tendermint: + tmConfig, ok := endpoint.ClientConfig.(*TendermintConfig) + require.True(endpoint.Chain.t, ok) + + height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height) + clientState = ibctmtypes.NewClientState( + endpoint.Counterparty.Chain.ChainID, tmConfig.TrustLevel, tmConfig.TrustingPeriod, tmConfig.UnbondingPeriod, tmConfig.MaxClockDrift, + height, commitmenttypes.GetSDKSpecs(), UpgradePath, tmConfig.AllowUpdateAfterExpiry, tmConfig.AllowUpdateAfterMisbehaviour, + ) + consensusState = endpoint.Counterparty.Chain.LastHeader.ConsensusState() + case exported.Solomachine: + // TODO + // solo := NewSolomachine(chain.t, endpoint.Chain.Codec, clientID, "", 1) + // clientState = solo.ClientState() + // consensusState = solo.ConsensusState() + + default: + err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType()) + } + + if err != nil { + return err + } + + msg, err := clienttypes.NewMsgCreateClient( + clientState, consensusState, endpoint.Chain.SenderAccount.GetAddress().String(), + ) + require.NoError(endpoint.Chain.t, err) + + res, err := endpoint.Chain.SendMsgs(msg) + if err != nil { + return err + } + + endpoint.ClientID, err = ParseClientIDFromEvents(res.GetEvents()) + require.NoError(endpoint.Chain.t, err) + + return nil +} + +// UpdateClient updates the IBC client associated with the endpoint. +func (endpoint *Endpoint) UpdateClient() (err error) { + // ensure counterparty has committed state + endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) + + var ( + header exported.Header + ) + + switch endpoint.ClientConfig.GetClientType() { + case exported.Tendermint: + header, err = endpoint.Chain.ConstructUpdateTMClientHeader(endpoint.Counterparty.Chain, endpoint.ClientID) + + default: + err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType()) + } + + if err != nil { + return err + } + + msg, err := clienttypes.NewMsgUpdateClient( + endpoint.ClientID, header, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + require.NoError(endpoint.Chain.t, err) + + return endpoint.Chain.sendMsgs(msg) + +} + +// ConnOpenInit will construct and execute a MsgConnectionOpenInit on the associated endpoint. +func (endpoint *Endpoint) ConnOpenInit() error { + msg := connectiontypes.NewMsgConnectionOpenInit( + endpoint.ClientID, + endpoint.Counterparty.ClientID, + endpoint.Counterparty.Chain.GetPrefix(), DefaultOpenInitVersion, endpoint.ConnectionConfig.DelayPeriod, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + res, err := endpoint.Chain.SendMsgs(msg) + if err != nil { + return err + } + + endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) + require.NoError(endpoint.Chain.t, err) + + return nil +} + +// ConnOpenTry will construct and execute a MsgConnectionOpenTry on the associated endpoint. +func (endpoint *Endpoint) ConnOpenTry() error { + endpoint.UpdateClient() + + counterpartyClient, proofClient, proofConsensus, consensusHeight, proofInit, proofHeight := endpoint.QueryConnectionHandshakeProof() + + msg := connectiontypes.NewMsgConnectionOpenTry( + "", endpoint.ClientID, // does not support handshake continuation + endpoint.Counterparty.ConnectionID, endpoint.Counterparty.ClientID, + counterpartyClient, endpoint.Counterparty.Chain.GetPrefix(), []*connectiontypes.Version{ConnectionVersion}, endpoint.ConnectionConfig.DelayPeriod, + proofInit, proofClient, proofConsensus, + proofHeight, consensusHeight, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + res, err := endpoint.Chain.SendMsgs(msg) + if err != nil { + return err + } + + if endpoint.ConnectionID == "" { + endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) + require.NoError(endpoint.Chain.t, err) + } + + return nil +} + +// ConnOpenAck will construct and execute a MsgConnectionOpenAck on the associated endpoint. +func (endpoint *Endpoint) ConnOpenAck() error { + endpoint.UpdateClient() + + counterpartyClient, proofClient, proofConsensus, consensusHeight, proofTry, proofHeight := endpoint.QueryConnectionHandshakeProof() + + msg := connectiontypes.NewMsgConnectionOpenAck( + endpoint.ConnectionID, endpoint.Counterparty.ConnectionID, counterpartyClient, // testing doesn't use flexible selection + proofTry, proofClient, proofConsensus, + proofHeight, consensusHeight, + ConnectionVersion, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + return endpoint.Chain.sendMsgs(msg) +} + +// ConnOpenConfirm will construct and execute a MsgConnectionOpenConfirm on the associated endpoint. +func (endpoint *Endpoint) ConnOpenConfirm() error { + endpoint.UpdateClient() + + connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID) + proof, height := endpoint.Counterparty.Chain.QueryProof(connectionKey) + + msg := connectiontypes.NewMsgConnectionOpenConfirm( + endpoint.ConnectionID, + proof, height, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + return endpoint.Chain.sendMsgs(msg) +} + +// QueryConnectionHandshakeProof returns all the proofs necessary to execute OpenTry or Open Ack of +// the connection handshakes. It returns the counterparty client state, proof of the counterparty +// client state, proof of the counterparty consensus state, the consensus state height, proof of +// the counterparty connection, and the proof height for all the proofs returned. +func (endpoint *Endpoint) QueryConnectionHandshakeProof() ( + clientState exported.ClientState, proofClient, + proofConsensus []byte, consensusHeight clienttypes.Height, + proofConnection []byte, proofHeight clienttypes.Height, +) { + // obtain the client state on the counterparty chain + clientState = endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID) + + // query proof for the client state on the counterparty + clientKey := host.FullClientStateKey(endpoint.Counterparty.ClientID) + proofClient, proofHeight = endpoint.Counterparty.QueryProof(clientKey) + + consensusHeight = clientState.GetLatestHeight().(clienttypes.Height) + + // query proof for the consensus state on the counterparty + consensusKey := host.FullConsensusStateKey(endpoint.Counterparty.ClientID, consensusHeight) + proofConsensus, _ = endpoint.Counterparty.QueryProofAtHeight(consensusKey, proofHeight.GetRevisionHeight()) + + // query proof for the connection on the counterparty + connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID) + proofConnection, _ = endpoint.Counterparty.QueryProofAtHeight(connectionKey, proofHeight.GetRevisionHeight()) + + return +} + +// ChanOpenInit will construct and execute a MsgChannelOpenInit on the associated endpoint. +func (endpoint *Endpoint) ChanOpenInit() error { + msg := channeltypes.NewMsgChannelOpenInit( + endpoint.ChannelConfig.PortID, + endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID}, + endpoint.Counterparty.ChannelConfig.PortID, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + res, err := endpoint.Chain.SendMsgs(msg) + if err != nil { + return err + } + + endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) + require.NoError(endpoint.Chain.t, err) + + return nil +} + +// ChanOpenTry will construct and execute a MsgChannelOpenTry on the associated endpoint. +func (endpoint *Endpoint) ChanOpenTry() error { + endpoint.UpdateClient() + + channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) + proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) + + msg := channeltypes.NewMsgChannelOpenTry( + endpoint.ChannelConfig.PortID, "", // does not support handshake continuation + endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID}, + endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, + proof, height, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + res, err := endpoint.Chain.SendMsgs(msg) + if err != nil { + return err + } + + if endpoint.ChannelID == "" { + endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) + require.NoError(endpoint.Chain.t, err) + } + + return nil +} + +// ChanOpenAck will construct and execute a MsgChannelOpenAck on the associated endpoint. +func (endpoint *Endpoint) ChanOpenAck() error { + endpoint.UpdateClient() + + channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) + proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) + + msg := channeltypes.NewMsgChannelOpenAck( + endpoint.ChannelConfig.PortID, endpoint.ChannelID, + endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, // testing doesn't use flexible selection + proof, height, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + return endpoint.Chain.sendMsgs(msg) +} + +// ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm on the associated endpoint. +func (endpoint *Endpoint) ChanOpenConfirm() error { + endpoint.UpdateClient() + + channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) + proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) + + msg := channeltypes.NewMsgChannelOpenConfirm( + endpoint.ChannelConfig.PortID, endpoint.ChannelID, + proof, height, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + return endpoint.Chain.sendMsgs(msg) +} + +// ChanCloseInit will construct and execute a MsgChannelCloseInit on the associated endpoint. +// +// NOTE: does not work with ibc-transfer module +func (endpoint *Endpoint) ChanCloseInit() error { + msg := channeltypes.NewMsgChannelCloseInit( + endpoint.ChannelConfig.PortID, endpoint.ChannelID, + endpoint.Chain.SenderAccount.GetAddress().String(), + ) + return endpoint.Chain.sendMsgs(msg) +} + +// SendPacket sends a packet through the channel keeper using the associated endpoint +// The counterparty client is updated so proofs can be sent to the counterparty chain. +func (endpoint *Endpoint) SendPacket(packet exported.PacketI) error { + channelCap := endpoint.Chain.GetChannelCapability(packet.GetSourcePort(), packet.GetSourceChannel()) + + // no need to send message, acting as a module + err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SendPacket(endpoint.Chain.GetContext(), channelCap, packet) + if err != nil { + return err + } + + // commit changes since no message was sent + endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) + + return endpoint.Counterparty.UpdateClient() +} + +// RecvPacket receives a packet on the associated endpoint. +// The counterparty client is updated. +func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error { + // get proof of packet commitment on source + packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) + proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey) + + recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) + + // receive on counterparty and update source client + if err := endpoint.Chain.sendMsgs(recvMsg); err != nil { + return err + } + + return endpoint.Counterparty.UpdateClient() +} + +// WriteAcknowledgement writes an acknowledgement on the channel associated with the endpoint. +// The counterparty client is updated. +func (endpoint *Endpoint) WriteAcknowledgement(ack exported.Acknowledgement, packet exported.PacketI) error { + channelCap := endpoint.Chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel()) + + // no need to send message, acting as a handler + err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(endpoint.Chain.GetContext(), channelCap, packet, ack.Acknowledgement()) + if err != nil { + return err + } + + // commit changes since no message was sent + endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) + + return endpoint.Counterparty.UpdateClient() +} + +// AcknowledgePacket sends a MsgAcknowledgement to the channel associated with the endpoint. +// TODO: add a query for the acknowledgement by events +// - https://github.com/cosmos/cosmos-sdk/issues/6509 +func (endpoint *Endpoint) AcknowledgePacket(packet channeltypes.Packet, ack []byte) error { + // get proof of acknowledgement on counterparty + packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) + + ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) + + return endpoint.Chain.sendMsgs(ackMsg) +} + +// SetChannelClosed sets a channel state to CLOSED. +func (endpoint *Endpoint) SetChannelClosed() error { + channel := endpoint.GetChannel() + + channel.State = channeltypes.CLOSED + endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel) + + endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) + + return endpoint.Counterparty.UpdateClient() +} + +// GetClientState retrieves the Client State for this endpoint. The +// client state is expected to exist otherwise testing will fail. +func (endpoint *Endpoint) GetClientState() exported.ClientState { + return endpoint.Chain.GetClientState(endpoint.ClientID) +} + +// SetClientState sets the client state for this endpoint. +func (endpoint *Endpoint) SetClientState(clientState exported.ClientState) { + endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientState(endpoint.Chain.GetContext(), endpoint.ClientID, clientState) +} + +// GetConsensusState retrieves the Consensus State for this endpoint at the provided height. +// The consensus state is expected to exist otherwise testing will fail. +func (endpoint *Endpoint) GetConsensusState(height exported.Height) exported.ConsensusState { + consensusState, found := endpoint.Chain.GetConsensusState(endpoint.ClientID, height) + require.True(endpoint.Chain.t, found) + + return consensusState +} + +// SetConsensusState sets the consensus state for this endpoint. +func (endpoint *Endpoint) SetConsensusState(consensusState exported.ConsensusState, height exported.Height) { + endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(endpoint.Chain.GetContext(), endpoint.ClientID, height, consensusState) +} + +// GetConnection retrieves an IBC Connection for the endpoint. The +// connection is expected to exist otherwise testing will fail. +func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd { + connection, found := endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.GetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID) + require.True(endpoint.Chain.t, found) + + return connection +} + +// SetConnection sets the connection for this endpoint. +func (endpoint *Endpoint) SetConnection(connection connectiontypes.ConnectionEnd) { + endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.SetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID, connection) +} + +// GetChannel retrieves an IBC Channel for the endpoint. The channel +// is expected to exist otherwise testing will fail. +func (endpoint *Endpoint) GetChannel() channeltypes.Channel { + channel, found := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) + require.True(endpoint.Chain.t, found) + + return channel +} + +// SetChannel sets the channel for this endpoint. +func (endpoint *Endpoint) SetChannel(channel channeltypes.Channel) { + endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel) +} + +// QueryClientStateProof performs and abci query for a client stat associated +// with this endpoint and returns the ClientState along with the proof. +func (endpoint *Endpoint) QueryClientStateProof() (exported.ClientState, []byte) { + // retrieve client state to provide proof for + clientState := endpoint.GetClientState() + + clientKey := host.FullClientStateKey(endpoint.ClientID) + proofClient, _ := endpoint.QueryProof(clientKey) + + return clientState, proofClient +} diff --git a/x/wasm/ibctesting/events.go b/x/wasm/ibctesting/events.go new file mode 100644 index 0000000000..b8eb2822a4 --- /dev/null +++ b/x/wasm/ibctesting/events.go @@ -0,0 +1,56 @@ +package ibctesting + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + connectiontypes "github.com/cosmos/ibc-go/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" +) + +// ParseClientIDFromEvents parses events emitted from a MsgCreateClient and returns the +// client identifier. +func ParseClientIDFromEvents(events sdk.Events) (string, error) { + for _, ev := range events { + if ev.Type == clienttypes.EventTypeCreateClient { + for _, attr := range ev.Attributes { + if string(attr.Key) == clienttypes.AttributeKeyClientID { + return string(attr.Value), nil + } + } + } + } + return "", fmt.Errorf("client identifier event attribute not found") +} + +// ParseConnectionIDFromEvents parses events emitted from a MsgConnectionOpenInit or +// MsgConnectionOpenTry and returns the connection identifier. +func ParseConnectionIDFromEvents(events sdk.Events) (string, error) { + for _, ev := range events { + if ev.Type == connectiontypes.EventTypeConnectionOpenInit || + ev.Type == connectiontypes.EventTypeConnectionOpenTry { + for _, attr := range ev.Attributes { + if string(attr.Key) == connectiontypes.AttributeKeyConnectionID { + return string(attr.Value), nil + } + } + } + } + return "", fmt.Errorf("connection identifier event attribute not found") +} + +// ParseChannelIDFromEvents parses events emitted from a MsgChannelOpenInit or +// MsgChannelOpenTry and returns the channel identifier. +func ParseChannelIDFromEvents(events sdk.Events) (string, error) { + for _, ev := range events { + if ev.Type == channeltypes.EventTypeChannelOpenInit || ev.Type == channeltypes.EventTypeChannelOpenTry { + for _, attr := range ev.Attributes { + if string(attr.Key) == channeltypes.AttributeKeyChannelID { + return string(attr.Value), nil + } + } + } + } + return "", fmt.Errorf("channel identifier event attribute not found") +} diff --git a/x/wasm/ibctesting/mock/README.md b/x/wasm/ibctesting/mock/README.md new file mode 100644 index 0000000000..5da403f9c3 --- /dev/null +++ b/x/wasm/ibctesting/mock/README.md @@ -0,0 +1,6 @@ +This package is only intended to be used for testing core IBC. In order to maintain secure +testing, we need to do message passing and execution which requires connecting an IBC application +module that fulfills all the callbacks. We cannot connect to ibc-transfer which does not support +all channel types so instead we create a mock application module which does nothing. It simply +return nil in all cases so no error ever occurs. It is intended to be as minimal and lightweight +as possible and should never import simapp. diff --git a/x/wasm/ibctesting/mock/doc.go b/x/wasm/ibctesting/mock/doc.go new file mode 100644 index 0000000000..eaaa42b2ab --- /dev/null +++ b/x/wasm/ibctesting/mock/doc.go @@ -0,0 +1,9 @@ +/* +This package is only intended to be used for testing core IBC. In order to maintain secure +testing, we need to do message passing and execution which requires connecting an IBC application +module that fulfills all the callbacks. We cannot connect to ibc-transfer which does not support +all channel types so instead we create a mock application module which does nothing. It simply +return nil in all cases so no error ever occurs. It is intended to be as minimal and lightweight +as possible and should never import simapp. +*/ +package mock diff --git a/x/wasm/ibctesting/mock/mock.go b/x/wasm/ibctesting/mock/mock.go new file mode 100644 index 0000000000..bd36ee355e --- /dev/null +++ b/x/wasm/ibctesting/mock/mock.go @@ -0,0 +1,218 @@ +package mock + +import ( + "bytes" + "encoding/json" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" + + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/modules/core/24-host" + "github.com/cosmos/ibc-go/modules/core/exported" +) + +const ( + ModuleName = "mock" +) + +var ( + MockAcknowledgement = channeltypes.NewResultAcknowledgement([]byte("mock acknowledgement")) + MockFailAcknowledgement = channeltypes.NewErrorAcknowledgement("mock failed acknowledgement") + MockPacketData = []byte("mock packet data") + MockFailPacketData = []byte("mock failed packet data") + MockAsyncPacketData = []byte("mock async packet data") + MockCanaryCapabilityName = "mock canary capability name" +) + +// Expected Interface +// PortKeeper defines the expected IBC port keeper +type PortKeeper interface { + BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability +} + +// AppModuleBasic is the mock AppModuleBasic. +type AppModuleBasic struct{} + +// Name implements AppModuleBasic interface. +func (AppModuleBasic) Name() string { + return ModuleName +} + +// RegisterLegacyAminoCodec implements AppModuleBasic interface. +func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} + +// RegisterInterfaces implements AppModuleBasic interface. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {} + +// DefaultGenesis implements AppModuleBasic interface. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return nil +} + +// ValidateGenesis implements the AppModuleBasic interface. +func (AppModuleBasic) ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error { + return nil +} + +// RegisterRESTRoutes implements AppModuleBasic interface. +func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {} + +// RegisterGRPCGatewayRoutes implements AppModuleBasic interface. +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *runtime.ServeMux) {} + +// GetTxCmd implements AppModuleBasic interface. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +// GetQueryCmd implements AppModuleBasic interface. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return nil +} + +// AppModule represents the AppModule for the mock module. +type AppModule struct { + AppModuleBasic + scopedKeeper capabilitykeeper.ScopedKeeper + portKeeper PortKeeper +} + +// NewAppModule returns a mock AppModule instance. +func NewAppModule(sk capabilitykeeper.ScopedKeeper, pk PortKeeper) AppModule { + return AppModule{ + scopedKeeper: sk, + portKeeper: pk, + } +} + +// RegisterInvariants implements the AppModule interface. +func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// Route implements the AppModule interface. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(ModuleName, nil) +} + +// QuerierRoute implements the AppModule interface. +func (AppModule) QuerierRoute() string { + return "" +} + +// LegacyQuerierHandler implements the AppModule interface. +func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { + return nil +} + +// RegisterServices implements the AppModule interface. +func (am AppModule) RegisterServices(module.Configurator) {} + +// InitGenesis implements the AppModule interface. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + // bind mock port ID + cap := am.portKeeper.BindPort(ctx, ModuleName) + am.scopedKeeper.ClaimCapability(ctx, cap, host.PortPath(ModuleName)) + + return []abci.ValidatorUpdate{} +} + +// ExportGenesis implements the AppModule interface. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + return nil +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +// BeginBlock implements the AppModule interface +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { +} + +// EndBlock implements the AppModule interface +func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// OnChanOpenInit implements the IBCModule interface. +func (am AppModule) OnChanOpenInit( + ctx sdk.Context, _ channeltypes.Order, _ []string, portID string, + channelID string, chanCap *capabilitytypes.Capability, _ channeltypes.Counterparty, _ string, +) error { + // Claim channel capability passed back by IBC module + if err := am.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { + return err + } + + return nil +} + +// OnChanOpenTry implements the IBCModule interface. +func (am AppModule) OnChanOpenTry( + ctx sdk.Context, _ channeltypes.Order, _ []string, portID string, + channelID string, chanCap *capabilitytypes.Capability, _ channeltypes.Counterparty, _, _ string, +) error { + // Claim channel capability passed back by IBC module + if err := am.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { + return err + } + + return nil +} + +// OnChanOpenAck implements the IBCModule interface. +func (am AppModule) OnChanOpenAck(sdk.Context, string, string, string) error { + return nil +} + +// OnChanOpenConfirm implements the IBCModule interface. +func (am AppModule) OnChanOpenConfirm(sdk.Context, string, string) error { + return nil +} + +// OnChanCloseInit implements the IBCModule interface. +func (am AppModule) OnChanCloseInit(sdk.Context, string, string) error { + return nil +} + +// OnChanCloseConfirm implements the IBCModule interface. +func (am AppModule) OnChanCloseConfirm(sdk.Context, string, string) error { + return nil +} + +// OnRecvPacket implements the IBCModule interface. +func (am AppModule) OnRecvPacket( + ctx sdk.Context, packet channeltypes.Packet, _ sdk.AccAddress, +) exported.Acknowledgement { + // set state by claiming capability to check if revert happens return + am.scopedKeeper.NewCapability(ctx, MockCanaryCapabilityName) + if bytes.Equal(MockPacketData, packet.GetData()) { + return MockAcknowledgement + } else if bytes.Equal(MockAsyncPacketData, packet.GetData()) { + return nil + } + + return MockFailAcknowledgement +} + +// OnAcknowledgementPacket implements the IBCModule interface. +func (am AppModule) OnAcknowledgementPacket( + sdk.Context, channeltypes.Packet, []byte, sdk.AccAddress, +) (*sdk.Result, error) { + return nil, nil +} + +// OnTimeoutPacket implements the IBCModule interface. +func (am AppModule) OnTimeoutPacket( + sdk.Context, channeltypes.Packet, sdk.AccAddress, +) (*sdk.Result, error) { + return nil, nil +} diff --git a/x/wasm/ibctesting/mock/privval.go b/x/wasm/ibctesting/mock/privval.go new file mode 100644 index 0000000000..fe46659b3d --- /dev/null +++ b/x/wasm/ibctesting/mock/privval.go @@ -0,0 +1,50 @@ +package mock + +import ( + "github.com/tendermint/tendermint/crypto" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtypes "github.com/tendermint/tendermint/types" + + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +var _ tmtypes.PrivValidator = PV{} + +// MockPV implements PrivValidator without any safety or persistence. +// Only use it for testing. +type PV struct { + PrivKey cryptotypes.PrivKey +} + +func NewPV() PV { + return PV{ed25519.GenPrivKey()} +} + +// GetPubKey implements PrivValidator interface +func (pv PV) GetPubKey() (crypto.PubKey, error) { + return cryptocodec.ToTmPubKeyInterface(pv.PrivKey.PubKey()) +} + +// SignVote implements PrivValidator interface +func (pv PV) SignVote(chainID string, vote *tmproto.Vote) error { + signBytes := tmtypes.VoteSignBytes(chainID, vote) + sig, err := pv.PrivKey.Sign(signBytes) + if err != nil { + return err + } + vote.Signature = sig + return nil +} + +// SignProposal implements PrivValidator interface +func (pv PV) SignProposal(chainID string, proposal *tmproto.Proposal) error { + signBytes := tmtypes.ProposalSignBytes(chainID, proposal) + sig, err := pv.PrivKey.Sign(signBytes) + if err != nil { + return err + } + proposal.Signature = sig + return nil +} diff --git a/x/wasm/ibctesting/mock/privval_test.go b/x/wasm/ibctesting/mock/privval_test.go new file mode 100644 index 0000000000..3ebbbad26e --- /dev/null +++ b/x/wasm/ibctesting/mock/privval_test.go @@ -0,0 +1,44 @@ +package mock_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/mock" +) + +const chainID = "testChain" + +func TestGetPubKey(t *testing.T) { + pv := mock.NewPV() + pk, err := pv.GetPubKey() + require.NoError(t, err) + require.Equal(t, "ed25519", pk.Type()) +} + +func TestSignVote(t *testing.T) { + pv := mock.NewPV() + pk, _ := pv.GetPubKey() + + vote := &tmproto.Vote{Height: 2} + pv.SignVote(chainID, vote) + + msg := tmtypes.VoteSignBytes(chainID, vote) + ok := pk.VerifySignature(msg, vote.Signature) + require.True(t, ok) +} + +func TestSignProposal(t *testing.T) { + pv := mock.NewPV() + pk, _ := pv.GetPubKey() + + proposal := &tmproto.Proposal{Round: 2} + pv.SignProposal(chainID, proposal) + + msg := tmtypes.ProposalSignBytes(chainID, proposal) + ok := pk.VerifySignature(msg, proposal.Signature) + require.True(t, ok) +} diff --git a/x/wasm/ibctesting/path.go b/x/wasm/ibctesting/path.go new file mode 100644 index 0000000000..180fce7de8 --- /dev/null +++ b/x/wasm/ibctesting/path.go @@ -0,0 +1,85 @@ +package ibctesting + +import ( + "bytes" + "fmt" + + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" +) + +// Path contains two endpoints representing two chains connected over IBC +type Path struct { + EndpointA *Endpoint + EndpointB *Endpoint +} + +// NewPath constructs an endpoint for each chain using the default values +// for the endpoints. Each endpoint is updated to have a pointer to the +// counterparty endpoint. +func NewPath(chainA, chainB *TestChain) *Path { + endpointA := NewDefaultEndpoint(chainA) + endpointB := NewDefaultEndpoint(chainB) + + endpointA.Counterparty = endpointB + endpointB.Counterparty = endpointA + + return &Path{ + EndpointA: endpointA, + EndpointB: endpointB, + } +} + +// SetChannelOrdered sets the channel order for both endpoints to ORDERED. +func (path *Path) SetChannelOrdered() { + path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED + path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED +} + +// RelayPacket attempts to relay the packet first on EndpointA and then on EndpointB +// if EndpointA does not contain a packet commitment for that packet. An error is returned +// if a relay step fails or the packet commitment does not exist on either endpoint. +func (path *Path) RelayPacket(packet channeltypes.Packet, ack []byte) error { + pc := path.EndpointA.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointA.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) + if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointA.Chain.App.AppCodec(), packet)) { + + // packet found, relay from A to B + path.EndpointB.UpdateClient() + + if err := path.EndpointB.RecvPacket(packet); err != nil { + return err + } + + if err := path.EndpointA.AcknowledgePacket(packet, ack); err != nil { + return err + } + return nil + + } + + pc = path.EndpointB.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointB.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) + if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointB.Chain.App.AppCodec(), packet)) { + + // packet found, relay B to A + path.EndpointA.UpdateClient() + + if err := path.EndpointA.RecvPacket(packet); err != nil { + return err + } + if err := path.EndpointB.AcknowledgePacket(packet, ack); err != nil { + return err + } + return nil + } + + return fmt.Errorf("packet commitment does not exist on either endpoint for provided packet") +} + +func (path *Path) CloseChannels() error { + if err := path.EndpointA.ChanCloseInit(); err != nil { + return err + } + if err := path.EndpointB.ChanCloseInit(); err != nil { + return err + } + return nil +} diff --git a/x/wasm/ibctesting/sdk_test.go b/x/wasm/ibctesting/sdk_test.go new file mode 100644 index 0000000000..b6f7f09545 --- /dev/null +++ b/x/wasm/ibctesting/sdk_test.go @@ -0,0 +1,341 @@ +package ibctesting_test + +import ( + "fmt" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" + authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/suite" + tmrand "github.com/tendermint/tendermint/libs/rand" + dbm "github.com/tendermint/tm-db" + + ibcclientcli "github.com/cosmos/ibc-go/modules/core/02-client/client/cli" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/params" +) + +/* + This file contains tests from the SDK which had to deleted during the migration of + the IBC module from the SDK into this repository. https://github.com/cosmos/cosmos-sdk/pull/8735 + + They can be removed once the SDK deprecates amino. +*/ + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := DefaultConfig() + + cfg.NumValidators = 2 + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + kb := s.network.Validators[0].ClientCtx.Keyring + _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + s.Require().NoError(err) + + account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + s.Require().NoError(err) + + account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + s.Require().NoError(err) + + multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{account1.GetPubKey(), account2.GetPubKey()}) + _, err = kb.SaveMultisig("multi", multi) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + s.Require().NoError(s.network.WaitForNextBlock()) +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} + +// NewAppConstructor returns a new simapp AppConstructor +func NewAppConstructor(encodingCfg params.EncodingConfig) network.AppConstructor { + return func(val network.Validator) servertypes.Application { + return simapp.NewSimApp( + val.Ctx.Logger, dbm.NewMemDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0, + encodingCfg, + simapp.EmptyAppOptions{}, + baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)), + baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices), + ) + } +} + +// DefaultConfig returns a sane default configuration suitable for nearly all +// testing requirements. +func DefaultConfig() network.Config { + encCfg := simapp.MakeTestEncodingConfig() + + return network.Config{ + Codec: encCfg.Marshaler, + TxConfig: encCfg.TxConfig, + LegacyAmino: encCfg.Amino, + InterfaceRegistry: encCfg.InterfaceRegistry, + AccountRetriever: authtypes.AccountRetriever{}, + AppConstructor: NewAppConstructor(encCfg), + GenesisState: simapp.ModuleBasics.DefaultGenesis(encCfg.Marshaler), + TimeoutCommit: 2 * time.Second, + ChainID: "chain-" + tmrand.NewRand().Str(6), + NumValidators: 4, + BondDenom: sdk.DefaultBondDenom, + MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), + AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction), + StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction), + BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction), + PruningStrategy: storetypes.PruningOptionNothing, + CleanupDir: true, + SigningAlgo: string(hd.Secp256k1Type), + KeyringOptions: []keyring.Option{}, + } +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +// Create an IBC tx that's encoded as amino-JSON. Since we can't amino-marshal +// a tx with "cosmos-sdk/MsgTransfer" using the SDK, we just hardcode the tx +// here. But external clients might, see https://github.com/cosmos/cosmos-sdk/issues/8022. +func mkIBCStdTx() []byte { + ibcTx := `{ + "account_number": "68", + "chain_id": "stargate-4", + "fee": { + "amount": [ + { + "amount": "3500", + "denom": "umuon" + } + ], + "gas": "350000" + }, + "memo": "", + "msg": [ + { + "type": "cosmos-sdk/MsgTransfer", + "value": { + "receiver": "cosmos1q9wtnlwdjrhwtcjmt2uq77jrgx7z3usrq2yz7z", + "sender": "cosmos1q9wtnlwdjrhwtcjmt2uq77jrgx7z3usrq2yz7z", + "source_channel": "channel-0", + "source_port": "transfer", + "token": { + "amount": "1000000", + "denom": "umuon" + } + } + } + ], + "sequence": "24" + }` + req := fmt.Sprintf(`{"tx":%s,"mode":"async"}`, ibcTx) + + return []byte(req) +} + +func (s *IntegrationTestSuite) TestEncodeIBCTx() { + val := s.network.Validators[0] + + req := mkIBCStdTx() + res, err := rest.PostRequest(fmt.Sprintf("%s/txs/encode", val.APIAddress), "application/json", []byte(req)) + s.Require().NoError(err) + + resVal := string(res) + s.Require().Contains(resVal, "") +} + +func (s *IntegrationTestSuite) TestBroadcastIBCTxRequest() { + val := s.network.Validators[0] + + req := mkIBCStdTx() + res, err := rest.PostRequest(fmt.Sprintf("%s/txs", val.APIAddress), "application/json", []byte(req)) + s.Require().NoError(err) + + s.Require().NotContains(string(res), "this transaction cannot be broadcasted via legacy REST endpoints", string(res)) +} + +// TestLegacyRestErrMessages creates two IBC txs, one that fails, one that +// succeeds, and make sure we cannot query any of them (with pretty error msg). +// Our intension is to test the error message of querying a message which is +// signed with proto, since IBC won't support legacy amino at all we are +// considering a message from IBC module. +func (s *IntegrationTestSuite) TestLegacyRestErrMessages() { + val := s.network.Validators[0] + + // Write client state json to temp file, used for an IBC message. + // Generated by printing the result of cdc.MarshalIntefaceJSON on + // a solo machine client state + clientStateJSON := testutil.WriteToNewTempFile( + s.T(), + `{"@type":"/ibc.lightclients.solomachine.v2.ClientState","sequence":"1","is_frozen":false,"consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"},"allow_update_after_proposal":false}`, + ) + + badClientStateJSON := testutil.WriteToNewTempFile( + s.T(), + `{"@type":"/ibc.lightclients.solomachine.v2.ClientState","sequence":"1","is_frozen":false,"consensus_state":{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"DIFFERENT","timestamp":"10"},"allow_update_after_proposal":false}`, + ) + + // Write consensus json to temp file, used for an IBC message. + // Generated by printing the result of cdc.MarshalIntefaceJSON on + // a solo machine consensus state + consensusJSON := testutil.WriteToNewTempFile( + s.T(), + `{"@type":"/ibc.lightclients.solomachine.v2.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, + ) + + testCases := []struct { + desc string + cmd *cobra.Command + args []string + code uint32 + }{ + { + "Failing IBC message", + ibcclientcli.NewCreateClientCmd(), + []string{ + badClientStateJSON.Name(), // path to client state json + consensusJSON.Name(), // path to consensus json, + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=foobar", flags.FlagNote), + }, + uint32(8), + }, + { + "Successful IBC message", + ibcclientcli.NewCreateClientCmd(), + []string{ + clientStateJSON.Name(), // path to client state json + consensusJSON.Name(), // path to consensus json, + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=foobar", flags.FlagNote), + }, + uint32(0), + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.desc), func() { + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, tc.cmd, tc.args) + s.Require().NoError(err) + var txRes sdk.TxResponse + s.Require().NoError(val.ClientCtx.JSONCodec.UnmarshalJSON(out.Bytes(), &txRes)) + s.Require().Equal(tc.code, txRes.Code) + + s.Require().NoError(s.network.WaitForNextBlock()) + + s.testQueryIBCTx(txRes, tc.cmd, tc.args) + }) + } +} + +// testQueryIBCTx is a helper function to test querying txs which: +// - show an error message on legacy REST endpoints +// - succeed using gRPC +// In practice, we call this function on IBC txs. +func (s *IntegrationTestSuite) testQueryIBCTx(txRes sdk.TxResponse, cmd *cobra.Command, args []string) { + val := s.network.Validators[0] + + errMsg := "this transaction cannot be displayed via legacy REST endpoints, because it does not support" + + " Amino serialization. Please either use CLI, gRPC, gRPC-gateway, or directly query the Tendermint RPC" + + " endpoint to query this transaction. The new REST endpoint (via gRPC-gateway) is " + + // Test that legacy endpoint return the above error message on IBC txs. + testCases := []struct { + desc string + url string + }{ + { + "Query by hash", + fmt.Sprintf("%s/txs/%s", val.APIAddress, txRes.TxHash), + }, + { + "Query by height", + fmt.Sprintf("%s/txs?tx.height=%d", val.APIAddress, txRes.Height), + }, + } + + for _, tc := range testCases { + s.Run(fmt.Sprintf("Case %s", tc.desc), func() { + txJSON, err := rest.GetRequest(tc.url) + s.Require().NoError(err) + + var errResp rest.ErrorResponse + s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(txJSON, &errResp)) + + s.Require().Contains(errResp.Error, errMsg) + }) + } + + // try fetching the txn using gRPC req, it will fetch info since it has proto codec. + grpcJSON, err := rest.GetRequest(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", val.APIAddress, txRes.TxHash)) + s.Require().NoError(err) + + var getTxRes txtypes.GetTxResponse + s.Require().NoError(val.ClientCtx.JSONCodec.UnmarshalJSON(grpcJSON, &getTxRes)) + s.Require().Equal(getTxRes.Tx.Body.Memo, "foobar") + + // generate broadcast only txn. + args = append(args, fmt.Sprintf("--%s=true", flags.FlagGenerateOnly)) + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args) + s.Require().NoError(err) + + txFile := testutil.WriteToNewTempFile(s.T(), string(out.Bytes())) + txFileName := txFile.Name() + + // encode the generated txn. + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, authcli.GetEncodeCommand(), []string{txFileName}) + s.Require().NoError(err) + + bz, err := val.ClientCtx.LegacyAmino.MarshalJSON(authrest.DecodeReq{Tx: string(out.Bytes())}) + s.Require().NoError(err) + + // try to decode the txn using legacy rest, it fails. + res, err := rest.PostRequest(fmt.Sprintf("%s/txs/decode", val.APIAddress), "application/json", bz) + s.Require().NoError(err) + + var errResp rest.ErrorResponse + s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(res, &errResp)) + s.Require().Contains(errResp.Error, errMsg) +} diff --git a/x/wasm/ibctesting/simapp/README.md b/x/wasm/ibctesting/simapp/README.md new file mode 100644 index 0000000000..fc449f7f2d --- /dev/null +++ b/x/wasm/ibctesting/simapp/README.md @@ -0,0 +1,51 @@ +--- +order: false +--- + +# simapp + +simapp is an application built using the Cosmos SDK for testing and educational purposes. + +## Running testnets with `simd` + +If you want to spin up a quick testnet with your friends, you can follow these steps. +Unless otherwise noted, every step must be done by everyone who wants to participate +in this testnet. + +1. `$ make build`. This will build the `simd` binary and install it in your Cosmos SDK repo, + inside a new `build` directory. The following instructions are run from inside + that directory. +2. If you've run `simd` before, you may need to reset your database before starting a new + testnet: `$ ./simd unsafe-reset-all` +3. `$ ./simd init [moniker]`. This will initialize a new working directory, by default at + `~/.simapp`. You need a provide a "moniker," but it doesn't matter what it is. +4. `$ ./simd keys add [key_name]`. This will create a new key, with a name of your choosing. + Save the output of this command somewhere; you'll need the address generated here later. +5. `$ ./simd add-genesis-account $(simd keys show [key_name] -a) [amount]`, where `key_name` + is the same key name as before; and `amount` is something like `10000000000000000000000000stake`. +6. `$ ./simd gentx [key_name] [amount] --chain-id [chain-id]`. This will create the + genesis transaction for your new chain. +7. Now, one person needs to create the genesis file `genesis.json` using the genesis transactions + from every participant, by gathering all the genesis transactions under `config/gentx` and then + calling `./simd collect-gentxs`. This will create a new `genesis.json` file that includes data + from all the validators (we sometimes call it the "super genesis file" to distinguish it from + single-validator genesis files). +8. Once you've received the super genesis file, overwrite your original `genesis.json` file with + the new super `genesis.json`. +9. Modify your `config/config.toml` (in the simapp working directory) to include the other participants as + persistent peers: + + ``` + # Comma separated list of nodes to keep persistent connections to + persistent_peers = "[validator address]@[ip address]:[port],[validator address]@[ip address]:[port]" + ``` + + You can find `validator address` by running `./simd tendermint show-node-id`. (It will be hex-encoded.) + By default, `port` is 26656. +10. Now you can start your nodes: `$ ./simd start`. + +Now you have a small testnet that you can use to try out changes to the Cosmos SDK or Tendermint! + +NOTE: Sometimes creating the network through the `collect-gentxs` will fail, and validators will start +in a funny state (and then panic). If this happens, you can try to create and start the network first +with a single validator and then add additional validators using a `create-validator` transaction. \ No newline at end of file diff --git a/x/wasm/ibctesting/simapp/app.go b/x/wasm/ibctesting/simapp/app.go new file mode 100644 index 0000000000..590d2b7025 --- /dev/null +++ b/x/wasm/ibctesting/simapp/app.go @@ -0,0 +1,667 @@ +package simapp + +import ( + "encoding/json" + "io" + "net/http" + "os" + "path/filepath" + + "github.com/gorilla/mux" + "github.com/rakyll/statik/fs" + "github.com/spf13/cast" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmos "github.com/tendermint/tendermint/libs/os" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + + simappparams "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/params" + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/server/api" + "github.com/cosmos/cosmos-sdk/server/config" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/ante" + authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" + "github.com/cosmos/cosmos-sdk/x/bank" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/capability" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + + ibcmock "github.com/CosmWasm/wasmd/x/wasm/ibctesting/mock" + "github.com/cosmos/cosmos-sdk/x/crisis" + crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper" + crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" + distr "github.com/cosmos/cosmos-sdk/x/distribution" + distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/evidence" + evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + "github.com/cosmos/cosmos-sdk/x/feegrant" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/cosmos/cosmos-sdk/x/gov" + govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/cosmos-sdk/x/mint" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/cosmos/cosmos-sdk/x/params" + paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" + "github.com/cosmos/cosmos-sdk/x/slashing" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/cosmos-sdk/x/upgrade" + upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" + upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + transfer "github.com/cosmos/ibc-go/modules/apps/transfer" + ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/modules/core" + ibcclient "github.com/cosmos/ibc-go/modules/core/02-client" + ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client" + ibcclienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + porttypes "github.com/cosmos/ibc-go/modules/core/05-port/types" + ibchost "github.com/cosmos/ibc-go/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper" + + authz "github.com/cosmos/cosmos-sdk/x/authz" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" + + // unnamed import of statik for swagger UI support + _ "github.com/cosmos/cosmos-sdk/client/docs/statik" +) + +const appName = "SimApp" + +var ( + // DefaultNodeHome default home directories for the application daemon + DefaultNodeHome string + + // ModuleBasics defines the module BasicManager is in charge of setting up basic, + // non-dependant module elements, such as codec registration + // and genesis verification. + ModuleBasics = module.NewBasicManager( + auth.AppModuleBasic{}, + genutil.AppModuleBasic{}, + bank.AppModuleBasic{}, + capability.AppModuleBasic{}, + staking.AppModuleBasic{}, + mint.AppModuleBasic{}, + distr.AppModuleBasic{}, + gov.NewAppModuleBasic( + paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, + ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, + ), + params.AppModuleBasic{}, + crisis.AppModuleBasic{}, + slashing.AppModuleBasic{}, + ibc.AppModuleBasic{}, + feegrantmodule.AppModuleBasic{}, + upgrade.AppModuleBasic{}, + evidence.AppModuleBasic{}, + transfer.AppModuleBasic{}, + ibcmock.AppModuleBasic{}, + authzmodule.AppModuleBasic{}, + vesting.AppModuleBasic{}, + ) + + // module account permissions + maccPerms = map[string][]string{ + authtypes.FeeCollectorName: nil, + distrtypes.ModuleName: nil, + minttypes.ModuleName: {authtypes.Minter}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + govtypes.ModuleName: {authtypes.Burner}, + ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + } +) + +var ( + _ App = (*SimApp)(nil) + _ servertypes.Application = (*SimApp)(nil) +) + +// SimApp extends an ABCI application, but with most of its parameters exported. +// They are exported for convenience in creating helper functions, as object +// capabilities aren't needed for testing. +type SimApp struct { + *baseapp.BaseApp + legacyAmino *codec.LegacyAmino + appCodec codec.Codec + interfaceRegistry types.InterfaceRegistry + + invCheckPeriod uint + + // keys to access the substores + keys map[string]*sdk.KVStoreKey + tkeys map[string]*sdk.TransientStoreKey + memKeys map[string]*sdk.MemoryStoreKey + + // keepers + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + CapabilityKeeper *capabilitykeeper.Keeper + StakingKeeper stakingkeeper.Keeper + SlashingKeeper slashingkeeper.Keeper + MintKeeper mintkeeper.Keeper + DistrKeeper distrkeeper.Keeper + GovKeeper govkeeper.Keeper + CrisisKeeper crisiskeeper.Keeper + UpgradeKeeper upgradekeeper.Keeper + ParamsKeeper paramskeeper.Keeper + AuthzKeeper authzkeeper.Keeper + IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly + EvidenceKeeper evidencekeeper.Keeper + TransferKeeper ibctransferkeeper.Keeper + FeeGrantKeeper feegrantkeeper.Keeper + + // make scoped keepers public for test purposes + ScopedIBCKeeper capabilitykeeper.ScopedKeeper + ScopedTransferKeeper capabilitykeeper.ScopedKeeper + ScopedIBCMockKeeper capabilitykeeper.ScopedKeeper + + // the module manager + mm *module.Manager + + // simulation manager + sm *module.SimulationManager + + // the configurator + configurator module.Configurator +} + +func init() { + userHomeDir, err := os.UserHomeDir() + if err != nil { + panic(err) + } + + DefaultNodeHome = filepath.Join(userHomeDir, ".simapp") +} + +// NewSimApp returns a reference to an initialized SimApp. +func NewSimApp( + logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool, + homePath string, invCheckPeriod uint, encodingConfig simappparams.EncodingConfig, + appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), +) *SimApp { + + appCodec := encodingConfig.Marshaler + legacyAmino := encodingConfig.Amino + interfaceRegistry := encodingConfig.InterfaceRegistry + + bApp := baseapp.NewBaseApp(appName, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...) + bApp.SetCommitMultiStoreTracer(traceStore) + bApp.SetVersion(version.Version) + bApp.SetInterfaceRegistry(interfaceRegistry) + + keys := sdk.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, + evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + authzkeeper.StoreKey, + ) + tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) + memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) + + app := &SimApp{ + BaseApp: bApp, + legacyAmino: legacyAmino, + appCodec: appCodec, + interfaceRegistry: interfaceRegistry, + invCheckPeriod: invCheckPeriod, + keys: keys, + tkeys: tkeys, + memKeys: memKeys, + } + + app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey]) + + // set the BaseApp's parameter store + bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable())) + + // add capability keeper and ScopeToModule for ibc module + app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey]) + scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName) + scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName) + // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do + // note replicate if you do not need to test core IBC or light clients. + scopedIBCMockKeeper := app.CapabilityKeeper.ScopeToModule(ibcmock.ModuleName) + + // add keepers + app.AccountKeeper = authkeeper.NewAccountKeeper( + appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, + ) + app.BankKeeper = bankkeeper.NewBaseKeeper( + appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(), + ) + stakingKeeper := stakingkeeper.NewKeeper( + appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), + ) + app.MintKeeper = mintkeeper.NewKeeper( + appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper, + app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, + ) + app.DistrKeeper = distrkeeper.NewKeeper( + appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper, + &stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(), + ) + app.SlashingKeeper = slashingkeeper.NewKeeper( + appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName), + ) + app.CrisisKeeper = crisiskeeper.NewKeeper( + app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName, + ) + + app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper) + app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp) + + // register the staking hooks + // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks + app.StakingKeeper = *stakingKeeper.SetHooks( + stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()), + ) + + // Create IBC Keeper + app.IBCKeeper = ibckeeper.NewKeeper( + appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, + ) + + app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter()) + + // register the proposal types + govRouter := govtypes.NewRouter() + govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). + AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). + AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). + AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). + AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) + app.GovKeeper = govkeeper.NewKeeper( + appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, + &stakingKeeper, govRouter, + ) + + // Create Transfer Keepers + app.TransferKeeper = ibctransferkeeper.NewKeeper( + appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, + ) + transferModule := transfer.NewAppModule(app.TransferKeeper) + + // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do + // note replicate if you do not need to test core IBC or light clients. + mockModule := ibcmock.NewAppModule(scopedIBCMockKeeper, &app.IBCKeeper.PortKeeper) + + // Create static IBC router, add transfer route, then set and seal it + ibcRouter := porttypes.NewRouter() + ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) + ibcRouter.AddRoute(ibcmock.ModuleName, mockModule) + app.IBCKeeper.SetRouter(ibcRouter) + + // create evidence keeper with router + evidenceKeeper := evidencekeeper.NewKeeper( + appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper, + ) + // If evidence needs to be handled for the app, set routes in router here and seal + app.EvidenceKeeper = *evidenceKeeper + + /**** Module Options ****/ + + // NOTE: we may consider parsing `appOpts` inside module constructors. For the moment + // we prefer to be more strict in what arguments the modules expect. + var skipGenesisInvariants = cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants)) + + // NOTE: Any module instantiated in the module manager that is later modified + // must be passed by reference here. + app.mm = module.NewManager( + genutil.NewAppModule( + app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx, + encodingConfig.TxConfig, + ), + auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), + vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), + capability.NewAppModule(appCodec, *app.CapabilityKeeper), + crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), + feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), + mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), + slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), + upgrade.NewAppModule(app.UpgradeKeeper), + evidence.NewAppModule(app.EvidenceKeeper), + ibc.NewAppModule(app.IBCKeeper), + params.NewAppModule(app.ParamsKeeper), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + transferModule, + mockModule, + ) + + // During begin block slashing happens after distr.BeginBlocker so that + // there is nothing left over in the validator fee pool, so as to keep the + // CanWithdrawInvariant invariant. + // NOTE: staking module is required if HistoricalEntries param > 0 + app.mm.SetOrderBeginBlockers( + upgradetypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName, + evidencetypes.ModuleName, stakingtypes.ModuleName, ibchost.ModuleName, + ) + app.mm.SetOrderEndBlockers(crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName) + + // NOTE: The genutils module must occur after staking so that pools are + // properly initialized with tokens from genesis accounts. + // NOTE: Capability module must occur first so that it can initialize any capabilities + // so that other modules that want to create or claim capabilities afterwards in InitChain + // can do so safely. + app.mm.SetOrderInitGenesis( + capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, + slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, + ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, ibctransfertypes.ModuleName, + ibcmock.ModuleName, feegrant.ModuleName, + ) + + app.mm.RegisterInvariants(&app.CrisisKeeper) + app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) + app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()) + app.mm.RegisterServices(app.configurator) + + // add test gRPC service for testing gRPC queries in isolation + testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{}) + + // create the simulation manager and define the order of the modules for deterministic simulations + // + // NOTE: this is not required apps that don't use the simulator for fuzz testing + // transactions + app.sm = module.NewSimulationManager( + auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), + capability.NewAppModule(appCodec, *app.CapabilityKeeper), + feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), + mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), + distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + params.NewAppModule(app.ParamsKeeper), + evidence.NewAppModule(app.EvidenceKeeper), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + ibc.NewAppModule(app.IBCKeeper), + transferModule, + ) + + app.sm.RegisterStoreDecoders() + + // initialize stores + app.MountKVStores(keys) + app.MountTransientStores(tkeys) + app.MountMemoryStores(memKeys) + + // initialize BaseApp + app.SetInitChainer(app.InitChainer) + app.SetBeginBlocker(app.BeginBlocker) + anteHandler, err := ante.NewAnteHandler( + ante.HandlerOptions{ + AccountKeeper: app.AccountKeeper, + BankKeeper: app.BankKeeper, + SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), + FeegrantKeeper: app.FeeGrantKeeper, + SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + }, + ) + if err != nil { + panic(err) + } + + app.SetAnteHandler(anteHandler) + + app.SetEndBlocker(app.EndBlocker) + + if loadLatest { + if err := app.LoadLatestVersion(); err != nil { + tmos.Exit(err.Error()) + } + + // Initialize and seal the capability keeper so all persistent capabilities + // are loaded in-memory and prevent any further modules from creating scoped + // sub-keepers. + // This must be done during creation of baseapp rather than in InitChain so + // that in-memory capabilities get regenerated on app restart. + // Note that since this reads from the store, we can only perform it when + // `loadLatest` is set to true. + ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{}) + app.CapabilityKeeper.InitMemStore(ctx) + app.CapabilityKeeper.Seal() + } + + app.ScopedIBCKeeper = scopedIBCKeeper + app.ScopedTransferKeeper = scopedTransferKeeper + + // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do + // note replicate if you do not need to test core IBC or light clients. + app.ScopedIBCMockKeeper = scopedIBCMockKeeper + + return app +} + +// Name returns the name of the App +func (app *SimApp) Name() string { return app.BaseApp.Name() } + +// BeginBlocker application updates every begin block +func (app *SimApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { + return app.mm.BeginBlock(ctx, req) +} + +// EndBlocker application updates every end block +func (app *SimApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { + return app.mm.EndBlock(ctx, req) +} + +// InitChainer application update at chain initialization +func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { + var genesisState GenesisState + if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil { + panic(err) + } + app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap()) + return app.mm.InitGenesis(ctx, app.appCodec, genesisState) +} + +// LoadHeight loads a particular height +func (app *SimApp) LoadHeight(height int64) error { + return app.LoadVersion(height) +} + +// ModuleAccountAddrs returns all the app's module account addresses. +func (app *SimApp) ModuleAccountAddrs() map[string]bool { + modAccAddrs := make(map[string]bool) + for acc := range maccPerms { + modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true + } + + return modAccAddrs +} + +// LegacyAmino returns SimApp's amino codec. +// +// NOTE: This is solely to be used for testing purposes as it may be desirable +// for modules to register their own custom testing types. +func (app *SimApp) LegacyAmino() *codec.LegacyAmino { + return app.legacyAmino +} + +// AppCodec returns SimApp's app codec. +// +// NOTE: This is solely to be used for testing purposes as it may be desirable +// for modules to register their own custom testing types. +func (app *SimApp) AppCodec() codec.Codec { + return app.appCodec +} + +// InterfaceRegistry returns SimApp's InterfaceRegistry +func (app *SimApp) InterfaceRegistry() types.InterfaceRegistry { + return app.interfaceRegistry +} + +// GetKey returns the KVStoreKey for the provided store key. +// +// NOTE: This is solely to be used for testing purposes. +func (app *SimApp) GetKey(storeKey string) *sdk.KVStoreKey { + return app.keys[storeKey] +} + +// GetTKey returns the TransientStoreKey for the provided store key. +// +// NOTE: This is solely to be used for testing purposes. +func (app *SimApp) GetTKey(storeKey string) *sdk.TransientStoreKey { + return app.tkeys[storeKey] +} + +// GetMemKey returns the MemStoreKey for the provided mem key. +// +// NOTE: This is solely used for testing purposes. +func (app *SimApp) GetMemKey(storeKey string) *sdk.MemoryStoreKey { + return app.memKeys[storeKey] +} + +// GetSubspace returns a param subspace for a given module name. +// +// NOTE: This is solely to be used for testing purposes. +func (app *SimApp) GetSubspace(moduleName string) paramstypes.Subspace { + subspace, _ := app.ParamsKeeper.GetSubspace(moduleName) + return subspace +} + +// TestingApp functions + +// GetBaseApp implements the TestingApp interface. +func (app *SimApp) GetBaseApp() *baseapp.BaseApp { + return app.BaseApp +} + +// GetStakingKeeper implements the TestingApp interface. +func (app *SimApp) GetStakingKeeper() stakingkeeper.Keeper { + return app.StakingKeeper +} + +// GetIBCKeeper implements the TestingApp interface. +func (app *SimApp) GetIBCKeeper() *ibckeeper.Keeper { + return app.IBCKeeper +} + +// GetScopedIBCKeeper implements the TestingApp interface. +func (app *SimApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { + return app.ScopedIBCKeeper +} + +// GetTxConfig implements the TestingApp interface. +func (app *SimApp) GetTxConfig() client.TxConfig { + return MakeTestEncodingConfig().TxConfig +} + +// SimulationManager implements the SimulationApp interface +func (app *SimApp) SimulationManager() *module.SimulationManager { + return app.sm +} + +// RegisterAPIRoutes registers all application module routes with the provided +// API server. +func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { + clientCtx := apiSvr.ClientCtx + rpc.RegisterRoutes(clientCtx, apiSvr.Router) + // Register legacy tx routes. + authrest.RegisterTxRoutes(clientCtx, apiSvr.Router) + // Register new tx routes from grpc-gateway. + authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + // Register new tendermint queries routes from grpc-gateway. + tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + + // Register legacy and grpc-gateway routes for all modules. + ModuleBasics.RegisterRESTRoutes(clientCtx, apiSvr.Router) + ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + + // register swagger API from root so that other applications can override easily + if apiConfig.Swagger { + RegisterSwaggerAPI(clientCtx, apiSvr.Router) + } +} + +// RegisterTxService implements the Application.RegisterTxService method. +func (app *SimApp) RegisterTxService(clientCtx client.Context) { + authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry) +} + +// RegisterTendermintService implements the Application.RegisterTendermintService method. +func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { + tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) +} + +// RegisterSwaggerAPI registers swagger route with API Server +func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) { + statikFS, err := fs.New() + if err != nil { + panic(err) + } + + staticServer := http.FileServer(statikFS) + rtr.PathPrefix("/swagger/").Handler(http.StripPrefix("/swagger/", staticServer)) +} + +// GetMaccPerms returns a copy of the module account permissions +func GetMaccPerms() map[string][]string { + dupMaccPerms := make(map[string][]string) + for k, v := range maccPerms { + dupMaccPerms[k] = v + } + return dupMaccPerms +} + +// initParamsKeeper init params keeper and its subspaces +func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper { + paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey) + + paramsKeeper.Subspace(authtypes.ModuleName) + paramsKeeper.Subspace(banktypes.ModuleName) + paramsKeeper.Subspace(stakingtypes.ModuleName) + paramsKeeper.Subspace(minttypes.ModuleName) + paramsKeeper.Subspace(distrtypes.ModuleName) + paramsKeeper.Subspace(slashingtypes.ModuleName) + paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable()) + paramsKeeper.Subspace(crisistypes.ModuleName) + paramsKeeper.Subspace(ibctransfertypes.ModuleName) + paramsKeeper.Subspace(ibchost.ModuleName) + + return paramsKeeper +} diff --git a/x/wasm/ibctesting/simapp/config.go b/x/wasm/ibctesting/simapp/config.go new file mode 100644 index 0000000000..98df982bd3 --- /dev/null +++ b/x/wasm/ibctesting/simapp/config.go @@ -0,0 +1,75 @@ +package simapp + +import ( + "flag" + + "github.com/cosmos/cosmos-sdk/types/simulation" +) + +// List of available flags for the simulator +var ( + FlagGenesisFileValue string + FlagParamsFileValue string + FlagExportParamsPathValue string + FlagExportParamsHeightValue int + FlagExportStatePathValue string + FlagExportStatsPathValue string + FlagSeedValue int64 + FlagInitialBlockHeightValue int + FlagNumBlocksValue int + FlagBlockSizeValue int + FlagLeanValue bool + FlagCommitValue bool + FlagOnOperationValue bool // TODO: Remove in favor of binary search for invariant violation + FlagAllInvariantsValue bool + + FlagEnabledValue bool + FlagVerboseValue bool + FlagPeriodValue uint + FlagGenesisTimeValue int64 +) + +// GetSimulatorFlags gets the values of all the available simulation flags +func GetSimulatorFlags() { + // config fields + flag.StringVar(&FlagGenesisFileValue, "Genesis", "", "custom simulation genesis file; cannot be used with params file") + flag.StringVar(&FlagParamsFileValue, "Params", "", "custom simulation params file which overrides any random params; cannot be used with genesis") + flag.StringVar(&FlagExportParamsPathValue, "ExportParamsPath", "", "custom file path to save the exported params JSON") + flag.IntVar(&FlagExportParamsHeightValue, "ExportParamsHeight", 0, "height to which export the randomly generated params") + flag.StringVar(&FlagExportStatePathValue, "ExportStatePath", "", "custom file path to save the exported app state JSON") + flag.StringVar(&FlagExportStatsPathValue, "ExportStatsPath", "", "custom file path to save the exported simulation statistics JSON") + flag.Int64Var(&FlagSeedValue, "Seed", 42, "simulation random seed") + flag.IntVar(&FlagInitialBlockHeightValue, "InitialBlockHeight", 1, "initial block to start the simulation") + flag.IntVar(&FlagNumBlocksValue, "NumBlocks", 500, "number of new blocks to simulate from the initial block height") + flag.IntVar(&FlagBlockSizeValue, "BlockSize", 200, "operations per block") + flag.BoolVar(&FlagLeanValue, "Lean", false, "lean simulation log output") + flag.BoolVar(&FlagCommitValue, "Commit", false, "have the simulation commit") + flag.BoolVar(&FlagOnOperationValue, "SimulateEveryOperation", false, "run slow invariants every operation") + flag.BoolVar(&FlagAllInvariantsValue, "PrintAllInvariants", false, "print all invariants if a broken invariant is found") + + // simulation flags + flag.BoolVar(&FlagEnabledValue, "Enabled", false, "enable the simulation") + flag.BoolVar(&FlagVerboseValue, "Verbose", false, "verbose log output") + flag.UintVar(&FlagPeriodValue, "Period", 0, "run slow invariants only once every period assertions") + flag.Int64Var(&FlagGenesisTimeValue, "GenesisTime", 0, "override genesis UNIX time instead of using a random UNIX time") +} + +// NewConfigFromFlags creates a simulation from the retrieved values of the flags. +func NewConfigFromFlags() simulation.Config { + return simulation.Config{ + GenesisFile: FlagGenesisFileValue, + ParamsFile: FlagParamsFileValue, + ExportParamsPath: FlagExportParamsPathValue, + ExportParamsHeight: FlagExportParamsHeightValue, + ExportStatePath: FlagExportStatePathValue, + ExportStatsPath: FlagExportStatsPathValue, + Seed: FlagSeedValue, + InitialBlockHeight: FlagInitialBlockHeightValue, + NumBlocks: FlagNumBlocksValue, + BlockSize: FlagBlockSizeValue, + Lean: FlagLeanValue, + Commit: FlagCommitValue, + OnOperation: FlagOnOperationValue, + AllInvariants: FlagAllInvariantsValue, + } +} diff --git a/x/wasm/ibctesting/simapp/encoding.go b/x/wasm/ibctesting/simapp/encoding.go new file mode 100644 index 0000000000..78ea2a07a6 --- /dev/null +++ b/x/wasm/ibctesting/simapp/encoding.go @@ -0,0 +1,19 @@ +package simapp + +import ( + simappparams "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/params" + "github.com/cosmos/cosmos-sdk/std" +) + +// MakeTestEncodingConfig creates an EncodingConfig for testing. This function +// should be used only in tests or when creating a new app instance (NewApp*()). +// App user shouldn't create new codecs - use the app.AppCodec instead. +// [DEPRECATED] +func MakeTestEncodingConfig() simappparams.EncodingConfig { + encodingConfig := simappparams.MakeTestEncodingConfig() + std.RegisterLegacyAminoCodec(encodingConfig.Amino) + std.RegisterInterfaces(encodingConfig.InterfaceRegistry) + ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino) + ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry) + return encodingConfig +} diff --git a/x/wasm/ibctesting/simapp/export.go b/x/wasm/ibctesting/simapp/export.go new file mode 100644 index 0000000000..8d09e333a2 --- /dev/null +++ b/x/wasm/ibctesting/simapp/export.go @@ -0,0 +1,193 @@ +package simapp + +import ( + "encoding/json" + "log" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + servertypes "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// ExportAppStateAndValidators exports the state of the application for a genesis +// file. +func (app *SimApp) ExportAppStateAndValidators( + forZeroHeight bool, jailAllowedAddrs []string, +) (servertypes.ExportedApp, error) { + // as if they could withdraw from the start of the next block + ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) + + // We export at last height + 1, because that's the height at which + // Tendermint will start InitChain. + height := app.LastBlockHeight() + 1 + if forZeroHeight { + height = 0 + app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs) + } + + genState := app.mm.ExportGenesis(ctx, app.appCodec) + appState, err := json.MarshalIndent(genState, "", " ") + if err != nil { + return servertypes.ExportedApp{}, err + } + + validators, err := staking.WriteValidators(ctx, app.StakingKeeper) + return servertypes.ExportedApp{ + AppState: appState, + Validators: validators, + Height: height, + ConsensusParams: app.BaseApp.GetConsensusParams(ctx), + }, err +} + +// prepare for fresh start at zero height +// NOTE zero height genesis is a temporary feature which will be deprecated +// in favour of export at a block height +func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []string) { + applyAllowedAddrs := false + + // check if there is a allowed address list + if len(jailAllowedAddrs) > 0 { + applyAllowedAddrs = true + } + + allowedAddrsMap := make(map[string]bool) + + for _, addr := range jailAllowedAddrs { + _, err := sdk.ValAddressFromBech32(addr) + if err != nil { + log.Fatal(err) + } + allowedAddrsMap[addr] = true + } + + /* Just to be safe, assert the invariants on current state. */ + app.CrisisKeeper.AssertInvariants(ctx) + + /* Handle fee distribution state. */ + + // withdraw all validator commission + app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) { + _, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator()) + return false + }) + + // withdraw all delegator rewards + dels := app.StakingKeeper.GetAllDelegations(ctx) + for _, delegation := range dels { + valAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) + if err != nil { + panic(err) + } + + delAddr, err := sdk.AccAddressFromBech32(delegation.DelegatorAddress) + if err != nil { + panic(err) + } + _, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr) + } + + // clear validator slash events + app.DistrKeeper.DeleteAllValidatorSlashEvents(ctx) + + // clear validator historical rewards + app.DistrKeeper.DeleteAllValidatorHistoricalRewards(ctx) + + // set context height to zero + height := ctx.BlockHeight() + ctx = ctx.WithBlockHeight(0) + + // reinitialize all validators + app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) { + // donate any unwithdrawn outstanding reward fraction tokens to the community pool + scraps := app.DistrKeeper.GetValidatorOutstandingRewardsCoins(ctx, val.GetOperator()) + feePool := app.DistrKeeper.GetFeePool(ctx) + feePool.CommunityPool = feePool.CommunityPool.Add(scraps...) + app.DistrKeeper.SetFeePool(ctx, feePool) + + app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, val.GetOperator()) + return false + }) + + // reinitialize all delegations + for _, del := range dels { + valAddr, err := sdk.ValAddressFromBech32(del.ValidatorAddress) + if err != nil { + panic(err) + } + delAddr, err := sdk.AccAddressFromBech32(del.DelegatorAddress) + if err != nil { + panic(err) + } + app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr) + app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr) + } + + // reset context height + ctx = ctx.WithBlockHeight(height) + + /* Handle staking state. */ + + // iterate through redelegations, reset creation height + app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) { + for i := range red.Entries { + red.Entries[i].CreationHeight = 0 + } + app.StakingKeeper.SetRedelegation(ctx, red) + return false + }) + + // iterate through unbonding delegations, reset creation height + app.StakingKeeper.IterateUnbondingDelegations(ctx, func(_ int64, ubd stakingtypes.UnbondingDelegation) (stop bool) { + for i := range ubd.Entries { + ubd.Entries[i].CreationHeight = 0 + } + app.StakingKeeper.SetUnbondingDelegation(ctx, ubd) + return false + }) + + // Iterate through validators by power descending, reset bond heights, and + // update bond intra-tx counters. + store := ctx.KVStore(app.keys[stakingtypes.StoreKey]) + iter := sdk.KVStoreReversePrefixIterator(store, stakingtypes.ValidatorsKey) + counter := int16(0) + + for ; iter.Valid(); iter.Next() { + addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key())) + validator, found := app.StakingKeeper.GetValidator(ctx, addr) + if !found { + panic("expected validator, not found") + } + + validator.UnbondingHeight = 0 + if applyAllowedAddrs && !allowedAddrsMap[addr.String()] { + validator.Jailed = true + } + + app.StakingKeeper.SetValidator(ctx, validator) + counter++ + } + + iter.Close() + + _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) + if err != nil { + log.Fatal(err) + } + + /* Handle slashing state. */ + + // reset start height on signing infos + app.SlashingKeeper.IterateValidatorSigningInfos( + ctx, + func(addr sdk.ConsAddress, info slashingtypes.ValidatorSigningInfo) (stop bool) { + info.StartHeight = 0 + app.SlashingKeeper.SetValidatorSigningInfo(ctx, addr, info) + return false + }, + ) +} diff --git a/x/wasm/ibctesting/simapp/genesis.go b/x/wasm/ibctesting/simapp/genesis.go new file mode 100644 index 0000000000..772e452d44 --- /dev/null +++ b/x/wasm/ibctesting/simapp/genesis.go @@ -0,0 +1,21 @@ +package simapp + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" +) + +// The genesis state of the blockchain is represented here as a map of raw json +// messages key'd by a identifier string. +// The identifier is used to determine which module genesis information belongs +// to so it may be appropriately routed during init chain. +// Within this application default genesis information is retrieved from +// the ModuleBasicManager which populates json from each BasicModule +// object provided to it during init. +type GenesisState map[string]json.RawMessage + +// NewDefaultGenesisState generates the default state for the application. +func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { + return ModuleBasics.DefaultGenesis(cdc) +} diff --git a/x/wasm/ibctesting/simapp/genesis_account.go b/x/wasm/ibctesting/simapp/genesis_account.go new file mode 100644 index 0000000000..5c9c7f9a03 --- /dev/null +++ b/x/wasm/ibctesting/simapp/genesis_account.go @@ -0,0 +1,47 @@ +package simapp + +import ( + "errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var _ authtypes.GenesisAccount = (*SimGenesisAccount)(nil) + +// SimGenesisAccount defines a type that implements the GenesisAccount interface +// to be used for simulation accounts in the genesis state. +type SimGenesisAccount struct { + *authtypes.BaseAccount + + // vesting account fields + OriginalVesting sdk.Coins `json:"original_vesting" yaml:"original_vesting"` // total vesting coins upon initialization + DelegatedFree sdk.Coins `json:"delegated_free" yaml:"delegated_free"` // delegated vested coins at time of delegation + DelegatedVesting sdk.Coins `json:"delegated_vesting" yaml:"delegated_vesting"` // delegated vesting coins at time of delegation + StartTime int64 `json:"start_time" yaml:"start_time"` // vesting start time (UNIX Epoch time) + EndTime int64 `json:"end_time" yaml:"end_time"` // vesting end time (UNIX Epoch time) + + // module account fields + ModuleName string `json:"module_name" yaml:"module_name"` // name of the module account + ModulePermissions []string `json:"module_permissions" yaml:"module_permissions"` // permissions of module account +} + +// Validate checks for errors on the vesting and module account parameters +func (sga SimGenesisAccount) Validate() error { + if !sga.OriginalVesting.IsZero() { + if sga.StartTime >= sga.EndTime { + return errors.New("vesting start-time cannot be before end-time") + } + } + + if sga.ModuleName != "" { + ma := authtypes.ModuleAccount{ + BaseAccount: sga.BaseAccount, Name: sga.ModuleName, Permissions: sga.ModulePermissions, + } + if err := ma.Validate(); err != nil { + return err + } + } + + return sga.BaseAccount.Validate() +} diff --git a/x/wasm/ibctesting/simapp/genesis_account_test.go b/x/wasm/ibctesting/simapp/genesis_account_test.go new file mode 100644 index 0000000000..4b2185c0ed --- /dev/null +++ b/x/wasm/ibctesting/simapp/genesis_account_test.go @@ -0,0 +1,88 @@ +package simapp_test + +import ( + "testing" + "time" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" +) + +func TestSimGenesisAccountValidate(t *testing.T) { + pubkey := secp256k1.GenPrivKey().PubKey() + addr := sdk.AccAddress(pubkey.Address()) + + vestingStart := time.Now().UTC() + + coins := sdk.NewCoins(sdk.NewInt64Coin("test", 1000)) + baseAcc := authtypes.NewBaseAccount(addr, pubkey, 0, 0) + + testCases := []struct { + name string + sga simapp.SimGenesisAccount + wantErr bool + }{ + { + "valid basic account", + simapp.SimGenesisAccount{ + BaseAccount: baseAcc, + }, + false, + }, + { + "invalid basic account with mismatching address/pubkey", + simapp.SimGenesisAccount{ + BaseAccount: authtypes.NewBaseAccount(addr, secp256k1.GenPrivKey().PubKey(), 0, 0), + }, + true, + }, + { + "valid basic account with module name", + simapp.SimGenesisAccount{ + BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(crypto.AddressHash([]byte("testmod"))), nil, 0, 0), + ModuleName: "testmod", + }, + false, + }, + { + "valid basic account with invalid module name/pubkey pair", + simapp.SimGenesisAccount{ + BaseAccount: baseAcc, + ModuleName: "testmod", + }, + true, + }, + { + "valid basic account with valid vesting attributes", + simapp.SimGenesisAccount{ + BaseAccount: baseAcc, + OriginalVesting: coins, + StartTime: vestingStart.Unix(), + EndTime: vestingStart.Add(1 * time.Hour).Unix(), + }, + false, + }, + { + "valid basic account with invalid vesting end time", + simapp.SimGenesisAccount{ + BaseAccount: baseAcc, + OriginalVesting: coins, + StartTime: vestingStart.Add(2 * time.Hour).Unix(), + EndTime: vestingStart.Add(1 * time.Hour).Unix(), + }, + true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.wantErr, tc.sga.Validate() != nil) + }) + } +} diff --git a/x/wasm/ibctesting/simapp/helpers/test_helpers.go b/x/wasm/ibctesting/simapp/helpers/test_helpers.go new file mode 100644 index 0000000000..4b2d97e58a --- /dev/null +++ b/x/wasm/ibctesting/simapp/helpers/test_helpers.go @@ -0,0 +1,80 @@ +package helpers + +import ( + "math/rand" + "time" + + "github.com/cosmos/cosmos-sdk/client" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsign "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +// SimAppChainID hardcoded chainID for simulation +const ( + DefaultGenTxGas = 2400000 + SimAppChainID = "simulation-app" +) + +// GenTx generates a signed mock transaction. +func GenTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, accSeqs []uint64, priv ...cryptotypes.PrivKey) (sdk.Tx, error) { + sigs := make([]signing.SignatureV2, len(priv)) + + // create a random length memo + r := rand.New(rand.NewSource(time.Now().UnixNano())) + + memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100)) + + signMode := gen.SignModeHandler().DefaultMode() + + // 1st round: set SignatureV2 with empty signatures, to set correct + // signer infos. + for i, p := range priv { + sigs[i] = signing.SignatureV2{ + PubKey: p.PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: signMode, + }, + Sequence: accSeqs[i], + } + } + + tx := gen.NewTxBuilder() + err := tx.SetMsgs(msgs...) + if err != nil { + return nil, err + } + err = tx.SetSignatures(sigs...) + if err != nil { + return nil, err + } + tx.SetMemo(memo) + tx.SetFeeAmount(feeAmt) + tx.SetGasLimit(gas) + + // 2nd round: once all signer infos are set, every signer can sign. + for i, p := range priv { + signerData := authsign.SignerData{ + ChainID: chainID, + AccountNumber: accNums[i], + Sequence: accSeqs[i], + } + signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx()) + if err != nil { + panic(err) + } + sig, err := p.Sign(signBytes) + if err != nil { + panic(err) + } + sigs[i].Data.(*signing.SingleSignatureData).Signature = sig + err = tx.SetSignatures(sigs...) + if err != nil { + panic(err) + } + } + + return tx.GetTx(), nil +} diff --git a/x/wasm/ibctesting/simapp/params/amino.go b/x/wasm/ibctesting/simapp/params/amino.go new file mode 100644 index 0000000000..440c29f817 --- /dev/null +++ b/x/wasm/ibctesting/simapp/params/amino.go @@ -0,0 +1,26 @@ +// +build test_amino + +package params + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" +) + +// MakeTestEncodingConfig creates an EncodingConfig for an amino based test configuration. +// This function should be used only internally (in the SDK). +// App user should'nt create new codecs - use the app.AppCodec instead. +// [DEPRECATED] +func MakeTestEncodingConfig() EncodingConfig { + cdc := codec.NewLegacyAmino() + interfaceRegistry := types.NewInterfaceRegistry() + marshaler := codec.NewAminoCodec(cdc) + + return EncodingConfig{ + InterfaceRegistry: interfaceRegistry, + Marshaler: marshaler, + TxConfig: legacytx.StdTxConfig{Cdc: cdc}, + Amino: cdc, + } +} diff --git a/x/wasm/ibctesting/simapp/params/doc.go b/x/wasm/ibctesting/simapp/params/doc.go new file mode 100644 index 0000000000..1c721342a9 --- /dev/null +++ b/x/wasm/ibctesting/simapp/params/doc.go @@ -0,0 +1,19 @@ +/* +Package params defines the simulation parameters in the simapp. + +It contains the default weights used for each transaction used on the module's +simulation. These weights define the chance for a transaction to be simulated at +any gived operation. + +You can repace the default values for the weights by providing a params.json +file with the weights defined for each of the transaction operations: + + { + "op_weight_msg_send": 60, + "op_weight_msg_delegate": 100, + } + +In the example above, the `MsgSend` has 60% chance to be simulated, while the +`MsgDelegate` will always be simulated. +*/ +package params diff --git a/x/wasm/ibctesting/simapp/params/encoding.go b/x/wasm/ibctesting/simapp/params/encoding.go new file mode 100644 index 0000000000..3d634abf16 --- /dev/null +++ b/x/wasm/ibctesting/simapp/params/encoding.go @@ -0,0 +1,16 @@ +package params + +import ( + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" +) + +// EncodingConfig specifies the concrete encoding types to use for a given app. +// This is provided for compatibility between protobuf and amino implementations. +type EncodingConfig struct { + InterfaceRegistry types.InterfaceRegistry + Marshaler codec.Codec + TxConfig client.TxConfig + Amino *codec.LegacyAmino +} diff --git a/x/wasm/ibctesting/simapp/params/params.go b/x/wasm/ibctesting/simapp/params/params.go new file mode 100644 index 0000000000..b6aa5fb55e --- /dev/null +++ b/x/wasm/ibctesting/simapp/params/params.go @@ -0,0 +1,7 @@ +package params + +// Simulation parameter constants +const ( + StakePerAccount = "stake_per_account" + InitiallyBondedValidators = "initially_bonded_validators" +) diff --git a/x/wasm/ibctesting/simapp/params/proto.go b/x/wasm/ibctesting/simapp/params/proto.go new file mode 100644 index 0000000000..04aa524b90 --- /dev/null +++ b/x/wasm/ibctesting/simapp/params/proto.go @@ -0,0 +1,26 @@ +// +build !test_amino + +package params + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/x/auth/tx" +) + +// MakeTestEncodingConfig creates an EncodingConfig for a non-amino based test configuration. +// This function should be used only internally (in the SDK). +// App user should'nt create new codecs - use the app.AppCodec instead. +// [DEPRECATED] +func MakeTestEncodingConfig() EncodingConfig { + cdc := codec.NewLegacyAmino() + interfaceRegistry := types.NewInterfaceRegistry() + marshaler := codec.NewProtoCodec(interfaceRegistry) + + return EncodingConfig{ + InterfaceRegistry: interfaceRegistry, + Marshaler: marshaler, + TxConfig: tx.NewTxConfig(marshaler, tx.DefaultSignModes), + Amino: cdc, + } +} diff --git a/x/wasm/ibctesting/simapp/params/weights.go b/x/wasm/ibctesting/simapp/params/weights.go new file mode 100644 index 0000000000..81400a2fc2 --- /dev/null +++ b/x/wasm/ibctesting/simapp/params/weights.go @@ -0,0 +1,28 @@ +package params + +// Default simulation operation weights for messages and gov proposals +const ( + DefaultWeightMsgSend int = 100 + DefaultWeightMsgMultiSend int = 10 + DefaultWeightMsgSetWithdrawAddress int = 50 + DefaultWeightMsgWithdrawDelegationReward int = 50 + DefaultWeightMsgWithdrawValidatorCommission int = 50 + DefaultWeightMsgFundCommunityPool int = 50 + DefaultWeightMsgDeposit int = 100 + DefaultWeightMsgVote int = 67 + DefaultWeightMsgVoteWeighted int = 33 + DefaultWeightMsgUnjail int = 100 + DefaultWeightMsgCreateValidator int = 100 + DefaultWeightMsgEditValidator int = 5 + DefaultWeightMsgDelegate int = 100 + DefaultWeightMsgUndelegate int = 100 + DefaultWeightMsgBeginRedelegate int = 100 + + DefaultWeightCommunitySpendProposal int = 5 + DefaultWeightTextProposal int = 5 + DefaultWeightParamChangeProposal int = 5 + + // feegrant + DefaultWeightGrantFeeAllowance int = 100 + DefaultWeightRevokeFeeAllowance int = 100 +) diff --git a/x/wasm/ibctesting/simapp/sim_bench_test.go b/x/wasm/ibctesting/simapp/sim_bench_test.go new file mode 100644 index 0000000000..f7c46a322b --- /dev/null +++ b/x/wasm/ibctesting/simapp/sim_bench_test.go @@ -0,0 +1,122 @@ +package simapp + +import ( + "fmt" + "os" + "testing" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +// Profile with: +// /usr/local/go/bin/go test -benchmem -run=^$ CosmWasm/wasmd/x/wasm/ibctesting/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out +func BenchmarkFullAppSimulation(b *testing.B) { + b.ReportAllocs() + config, db, dir, logger, _, err := SetupSimulation("goleveldb-app-sim", "Simulation") + if err != nil { + b.Fatalf("simulation setup failed: %s", err.Error()) + } + + defer func() { + db.Close() + err = os.RemoveAll(dir) + if err != nil { + b.Fatal(err) + } + }() + + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, interBlockCacheOpt()) + + // run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + b, + os.Stdout, + app.BaseApp, + AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + SimulationOperations(app, app.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + if err = CheckExportSimulation(app, config, simParams); err != nil { + b.Fatal(err) + } + + if simErr != nil { + b.Fatal(simErr) + } + + if config.Commit { + PrintStats(db) + } +} + +func BenchmarkInvariants(b *testing.B) { + b.ReportAllocs() + config, db, dir, logger, _, err := SetupSimulation("leveldb-app-invariant-bench", "Simulation") + if err != nil { + b.Fatalf("simulation setup failed: %s", err.Error()) + } + + config.AllInvariants = false + + defer func() { + db.Close() + err = os.RemoveAll(dir) + if err != nil { + b.Fatal(err) + } + }() + + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, interBlockCacheOpt()) + + // run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + b, + os.Stdout, + app.BaseApp, + AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + SimulationOperations(app, app.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + if err = CheckExportSimulation(app, config, simParams); err != nil { + b.Fatal(err) + } + + if simErr != nil { + b.Fatal(simErr) + } + + if config.Commit { + PrintStats(db) + } + + ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight() + 1}) + + // 3. Benchmark each invariant separately + // + // NOTE: We use the crisis keeper as it has all the invariants registered with + // their respective metadata which makes it useful for testing/benchmarking. + for _, cr := range app.CrisisKeeper.Routes() { + cr := cr + b.Run(fmt.Sprintf("%s/%s", cr.ModuleName, cr.Route), func(b *testing.B) { + if res, stop := cr.Invar(ctx); stop { + b.Fatalf( + "broken invariant at block %d of %d\n%s", + ctx.BlockHeight()-1, config.NumBlocks, res, + ) + } + }) + } +} diff --git a/x/wasm/ibctesting/simapp/sim_test.go b/x/wasm/ibctesting/simapp/sim_test.go new file mode 100644 index 0000000000..9c0329c353 --- /dev/null +++ b/x/wasm/ibctesting/simapp/sim_test.go @@ -0,0 +1,340 @@ +package simapp + +import ( + "encoding/json" + "fmt" + "math/rand" + "os" + "testing" + + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/cosmos/cosmos-sdk/x/simulation" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + ibchost "github.com/cosmos/ibc-go/modules/core/24-host" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/helpers" +) + +// Get flags every time the simulator is run +func init() { + GetSimulatorFlags() +} + +type StoreKeysPrefixes struct { + A sdk.StoreKey + B sdk.StoreKey + Prefixes [][]byte +} + +// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of +// an IAVLStore for faster simulation speed. +func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { + bapp.SetFauxMerkleMode() +} + +// interBlockCacheOpt returns a BaseApp option function that sets the persistent +// inter-block write-through cache. +func interBlockCacheOpt() func(*baseapp.BaseApp) { + return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) +} + +func TestFullAppSimulation(t *testing.T) { + config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-sim", "Simulation") + if skip { + t.Skip("skipping application simulation") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + db.Close() + require.NoError(t, os.RemoveAll(dir)) + }() + + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "SimApp", app.Name()) + + // run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + SimulationOperations(app, app.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = CheckExportSimulation(app, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + PrintStats(db) + } +} + +func TestAppImportExport(t *testing.T) { + config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-sim", "Simulation") + if skip { + t.Skip("skipping application import/export simulation") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + db.Close() + require.NoError(t, os.RemoveAll(dir)) + }() + + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "SimApp", app.Name()) + + // Run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + SimulationOperations(app, app.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = CheckExportSimulation(app, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + PrintStats(db) + } + + fmt.Printf("exporting genesis...\n") + + exported, err := app.ExportAppStateAndValidators(false, []string{}) + require.NoError(t, err) + + fmt.Printf("importing genesis...\n") + + _, newDB, newDir, _, _, err := SetupSimulation("leveldb-app-sim-2", "Simulation-2") + require.NoError(t, err, "simulation setup failed") + + defer func() { + newDB.Close() + require.NoError(t, os.RemoveAll(newDir)) + }() + + newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "SimApp", newApp.Name()) + + var genesisState GenesisState + err = json.Unmarshal(exported.AppState, &genesisState) + require.NoError(t, err) + + ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) + ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) + newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState) + newApp.StoreConsensusParams(ctxB, exported.ConsensusParams) + + fmt.Printf("comparing stores...\n") + + storeKeysPrefixes := []StoreKeysPrefixes{ + {app.keys[authtypes.StoreKey], newApp.keys[authtypes.StoreKey], [][]byte{}}, + {app.keys[stakingtypes.StoreKey], newApp.keys[stakingtypes.StoreKey], + [][]byte{ + stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey, + stakingtypes.HistoricalInfoKey, + }}, // ordering may change but it doesn't matter + {app.keys[slashingtypes.StoreKey], newApp.keys[slashingtypes.StoreKey], [][]byte{}}, + {app.keys[minttypes.StoreKey], newApp.keys[minttypes.StoreKey], [][]byte{}}, + {app.keys[distrtypes.StoreKey], newApp.keys[distrtypes.StoreKey], [][]byte{}}, + {app.keys[banktypes.StoreKey], newApp.keys[banktypes.StoreKey], [][]byte{banktypes.BalancesPrefix}}, + {app.keys[paramtypes.StoreKey], newApp.keys[paramtypes.StoreKey], [][]byte{}}, + {app.keys[govtypes.StoreKey], newApp.keys[govtypes.StoreKey], [][]byte{}}, + {app.keys[evidencetypes.StoreKey], newApp.keys[evidencetypes.StoreKey], [][]byte{}}, + {app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}}, + {app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}}, + {app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}}, + {app.keys[authzkeeper.StoreKey], newApp.keys[authzkeeper.StoreKey], [][]byte{}}, + } + + for _, skp := range storeKeysPrefixes { + storeA := ctxA.KVStore(skp.A) + storeB := ctxB.KVStore(skp.B) + + failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, skp.Prefixes) + require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare") + + fmt.Printf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), skp.A, skp.B) + require.Equal(t, len(failedKVAs), 0, GetSimulationLog(skp.A.Name(), app.SimulationManager().StoreDecoders, failedKVAs, failedKVBs)) + } +} + +func TestAppSimulationAfterImport(t *testing.T) { + config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-sim", "Simulation") + if skip { + t.Skip("skipping application simulation after import") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + db.Close() + require.NoError(t, os.RemoveAll(dir)) + }() + + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "SimApp", app.Name()) + + // Run randomized simulation + stopEarly, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + SimulationOperations(app, app.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = CheckExportSimulation(app, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + PrintStats(db) + } + + if stopEarly { + fmt.Println("can't export or import a zero-validator genesis, exiting test...") + return + } + + fmt.Printf("exporting genesis...\n") + + exported, err := app.ExportAppStateAndValidators(true, []string{}) + require.NoError(t, err) + + fmt.Printf("importing genesis...\n") + + _, newDB, newDir, _, _, err := SetupSimulation("leveldb-app-sim-2", "Simulation-2") + require.NoError(t, err, "simulation setup failed") + + defer func() { + newDB.Close() + require.NoError(t, os.RemoveAll(newDir)) + }() + + newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "SimApp", newApp.Name()) + + newApp.InitChain(abci.RequestInitChain{ + AppStateBytes: exported.AppState, + }) + + _, _, err = simulation.SimulateFromSeed( + t, + os.Stdout, + newApp.GetBaseApp(), + AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + SimulationOperations(newApp, newApp.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + require.NoError(t, err) +} + +// TODO: Make another test for the fuzzer itself, which just has noOp txs +// and doesn't depend on the application. +func TestAppStateDeterminism(t *testing.T) { + if !FlagEnabledValue { + t.Skip("skipping application simulation") + } + + config := NewConfigFromFlags() + config.InitialBlockHeight = 1 + config.ExportParamsPath = "" + config.OnOperation = false + config.AllInvariants = false + config.ChainID = helpers.SimAppChainID + + numSeeds := 3 + numTimesToRunPerSeed := 5 + appHashList := make([]json.RawMessage, numTimesToRunPerSeed) + + for i := 0; i < numSeeds; i++ { + config.Seed = rand.Int63() + + for j := 0; j < numTimesToRunPerSeed; j++ { + var logger log.Logger + if FlagVerboseValue { + logger = log.TestingLogger() + } else { + logger = log.NewNopLogger() + } + + db := dbm.NewMemDB() + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, interBlockCacheOpt()) + + fmt.Printf( + "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", + config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + + _, _, err := simulation.SimulateFromSeed( + t, + os.Stdout, + app.BaseApp, + AppStateFn(app.AppCodec(), app.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + SimulationOperations(app, app.AppCodec(), config), + app.ModuleAccountAddrs(), + config, + app.AppCodec(), + ) + require.NoError(t, err) + + if config.Commit { + PrintStats(db) + } + + appHash := app.LastCommitID().Hash + appHashList[j] = appHash + + if j != 0 { + require.Equal( + t, string(appHashList[0]), string(appHashList[j]), + "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + } + } + } +} diff --git a/x/wasm/ibctesting/simapp/simd/cmd/cmd_test.go b/x/wasm/ibctesting/simapp/simd/cmd/cmd_test.go new file mode 100644 index 0000000000..778cffe032 --- /dev/null +++ b/x/wasm/ibctesting/simapp/simd/cmd/cmd_test.go @@ -0,0 +1,26 @@ +package cmd_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/simd/cmd" + + "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" +) + +func TestInitCmd(t *testing.T) { + rootCmd, _ := cmd.NewRootCmd() + rootCmd.SetArgs([]string{ + "init", // Test the init cmd + "simapp-test", // Moniker + fmt.Sprintf("--%s=%s", cli.FlagOverwrite, "true"), // Overwrite genesis.json, in case it already exists + }) + + require.NoError(t, svrcmd.Execute(rootCmd, simapp.DefaultNodeHome)) +} diff --git a/x/wasm/ibctesting/simapp/simd/cmd/genaccounts.go b/x/wasm/ibctesting/simapp/simd/cmd/genaccounts.go new file mode 100644 index 0000000000..5c04059b7d --- /dev/null +++ b/x/wasm/ibctesting/simapp/simd/cmd/genaccounts.go @@ -0,0 +1,181 @@ +package cmd + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" +) + +const ( + flagVestingStart = "vesting-start-time" + flagVestingEnd = "vesting-end-time" + flagVestingAmt = "vesting-amount" +) + +// AddGenesisAccountCmd returns add-genesis-account cobra Command. +func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command { + cmd := &cobra.Command{ + Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", + Short: "Add a genesis account to genesis.json", + Long: `Add a genesis account to genesis.json. The provided account must specify +the account address or key name and a list of initial coins. If a key name is given, +the address will be looked up in the local Keybase. The list of initial tokens must +contain valid denominations. Accounts may optionally be supplied with vesting parameters. +`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + depCdc := clientCtx.JSONCodec + cdc := depCdc.(codec.Codec) + + serverCtx := server.GetServerContextFromCmd(cmd) + config := serverCtx.Config + + config.SetRoot(clientCtx.HomeDir) + + addr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + inBuf := bufio.NewReader(cmd.InOrStdin()) + keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) + + // attempt to lookup address from Keybase if no address was provided + kb, err := keyring.New(sdk.KeyringServiceName(), keyringBackend, clientCtx.HomeDir, inBuf) + if err != nil { + return err + } + + info, err := kb.Key(args[0]) + if err != nil { + return fmt.Errorf("failed to get address from Keybase: %w", err) + } + + addr = info.GetAddress() + } + + coins, err := sdk.ParseCoinsNormalized(args[1]) + if err != nil { + return fmt.Errorf("failed to parse coins: %w", err) + } + + vestingStart, _ := cmd.Flags().GetInt64(flagVestingStart) + vestingEnd, _ := cmd.Flags().GetInt64(flagVestingEnd) + vestingAmtStr, _ := cmd.Flags().GetString(flagVestingAmt) + + vestingAmt, err := sdk.ParseCoinsNormalized(vestingAmtStr) + if err != nil { + return fmt.Errorf("failed to parse vesting amount: %w", err) + } + + // create concrete account type based on input parameters + var genAccount authtypes.GenesisAccount + + balances := banktypes.Balance{Address: addr.String(), Coins: coins.Sort()} + baseAccount := authtypes.NewBaseAccount(addr, nil, 0, 0) + + if !vestingAmt.IsZero() { + baseVestingAccount := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd) + + if (balances.Coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) || + baseVestingAccount.OriginalVesting.IsAnyGT(balances.Coins) { + return errors.New("vesting amount cannot be greater than total amount") + } + + switch { + case vestingStart != 0 && vestingEnd != 0: + genAccount = authvesting.NewContinuousVestingAccountRaw(baseVestingAccount, vestingStart) + + case vestingEnd != 0: + genAccount = authvesting.NewDelayedVestingAccountRaw(baseVestingAccount) + + default: + return errors.New("invalid vesting parameters; must supply start and end time or end time") + } + } else { + genAccount = baseAccount + } + + if err := genAccount.Validate(); err != nil { + return fmt.Errorf("failed to validate new genesis account: %w", err) + } + + genFile := config.GenesisFile() + appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) + if err != nil { + return fmt.Errorf("failed to unmarshal genesis state: %w", err) + } + + authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState) + + accs, err := authtypes.UnpackAccounts(authGenState.Accounts) + if err != nil { + return fmt.Errorf("failed to get accounts from any: %w", err) + } + + if accs.Contains(addr) { + return fmt.Errorf("cannot add account at existing address %s", addr) + } + + // Add the new account to the set of genesis accounts and sanitize the + // accounts afterwards. + accs = append(accs, genAccount) + accs = authtypes.SanitizeGenesisAccounts(accs) + + genAccs, err := authtypes.PackAccounts(accs) + if err != nil { + return fmt.Errorf("failed to convert accounts into any's: %w", err) + } + authGenState.Accounts = genAccs + + authGenStateBz, err := cdc.MarshalJSON(&authGenState) + if err != nil { + return fmt.Errorf("failed to marshal auth genesis state: %w", err) + } + + appState[authtypes.ModuleName] = authGenStateBz + + bankGenState := banktypes.GetGenesisStateFromAppState(depCdc, appState) + bankGenState.Balances = append(bankGenState.Balances, balances) + bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + bankGenState.Supply = bankGenState.Supply.Add(balances.Coins...) + + bankGenStateBz, err := cdc.MarshalJSON(bankGenState) + if err != nil { + return fmt.Errorf("failed to marshal bank genesis state: %w", err) + } + + appState[banktypes.ModuleName] = bankGenStateBz + + appStateJSON, err := json.Marshal(appState) + if err != nil { + return fmt.Errorf("failed to marshal application genesis state: %w", err) + } + + genDoc.AppState = appStateJSON + return genutil.ExportGenesisFile(genDoc, genFile) + }, + } + + cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") + cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") + cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts") + cmd.Flags().Int64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts") + cmd.Flags().Int64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts") + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/wasm/ibctesting/simapp/simd/cmd/genaccounts_test.go b/x/wasm/ibctesting/simapp/simd/cmd/genaccounts_test.go new file mode 100644 index 0000000000..dcc754acf8 --- /dev/null +++ b/x/wasm/ibctesting/simapp/simd/cmd/genaccounts_test.go @@ -0,0 +1,86 @@ +package cmd_test + +import ( + "context" + "fmt" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltest "github.com/cosmos/cosmos-sdk/x/genutil/client/testutil" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + simcmd "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/simd/cmd" +) + +var testMbm = module.NewBasicManager(genutil.AppModuleBasic{}) + +func TestAddGenesisAccountCmd(t *testing.T) { + _, _, addr1 := testdata.KeyTestPubAddr() + tests := []struct { + name string + addr string + denom string + expectErr bool + }{ + { + name: "invalid address", + addr: "", + denom: "1000atom", + expectErr: true, + }, + { + name: "valid address", + addr: addr1.String(), + denom: "1000atom", + expectErr: false, + }, + { + name: "multiple denoms", + addr: addr1.String(), + denom: "1000atom, 2000stake", + expectErr: false, + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + home := t.TempDir() + logger := log.NewNopLogger() + cfg, err := genutiltest.CreateDefaultTendermintConfig(home) + require.NoError(t, err) + + appCodec := simapp.MakeTestEncodingConfig().Marshaler + err = genutiltest.ExecInitCmd(testMbm, home, appCodec) + require.NoError(t, err) + + serverCtx := server.NewContext(viper.New(), cfg, logger) + clientCtx := client.Context{}.WithJSONCodec(appCodec).WithHomeDir(home) + + ctx := context.Background() + ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) + ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx) + + cmd := simcmd.AddGenesisAccountCmd(home) + cmd.SetArgs([]string{ + tc.addr, + tc.denom, + fmt.Sprintf("--%s=home", flags.FlagHome)}) + + if tc.expectErr { + require.Error(t, cmd.ExecuteContext(ctx)) + } else { + require.NoError(t, cmd.ExecuteContext(ctx)) + } + }) + } +} diff --git a/x/wasm/ibctesting/simapp/simd/cmd/root.go b/x/wasm/ibctesting/simapp/simd/cmd/root.go new file mode 100644 index 0000000000..4f3fe55e95 --- /dev/null +++ b/x/wasm/ibctesting/simapp/simd/cmd/root.go @@ -0,0 +1,242 @@ +package cmd + +import ( + "errors" + "io" + "os" + "path/filepath" + + "github.com/spf13/cast" + "github.com/spf13/cobra" + tmcli "github.com/tendermint/tendermint/libs/cli" + "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + config "github.com/cosmos/cosmos-sdk/client/config" + "github.com/cosmos/cosmos-sdk/client/debug" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/server" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/cosmos/cosmos-sdk/snapshots" + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + "github.com/cosmos/cosmos-sdk/x/auth/types" + vestingcli "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/crisis" + genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/params" +) + +// NewRootCmd creates a new root command for simd. It is called once in the +// main function. +func NewRootCmd() (*cobra.Command, params.EncodingConfig) { + encodingConfig := simapp.MakeTestEncodingConfig() + initClientCtx := client.Context{}. + WithJSONCodec(encodingConfig.Marshaler). + WithInterfaceRegistry(encodingConfig.InterfaceRegistry). + WithTxConfig(encodingConfig.TxConfig). + WithLegacyAmino(encodingConfig.Amino). + WithInput(os.Stdin). + WithAccountRetriever(types.AccountRetriever{}). + WithBroadcastMode(flags.BroadcastBlock). + WithHomeDir(simapp.DefaultNodeHome). + WithViper("") // In simapp, we don't use any prefix for env variables. + + rootCmd := &cobra.Command{ + Use: "simd", + Short: "simulation app", + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { + // set the default command outputs + cmd.SetOut(cmd.OutOrStdout()) + cmd.SetErr(cmd.ErrOrStderr()) + + initClientCtx = client.ReadHomeFlag(initClientCtx, cmd) + + initClientCtx, err := config.ReadFromClientConfig(initClientCtx) + if err != nil { + return err + } + + if err := client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil { + return err + } + + return server.InterceptConfigsPreRunHandler(cmd, "", nil) + }, + } + + initRootCmd(rootCmd, encodingConfig) + + return rootCmd, encodingConfig +} + +func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { + rootCmd.AddCommand( + genutilcli.InitCmd(simapp.ModuleBasics, simapp.DefaultNodeHome), + genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{}, simapp.DefaultNodeHome), + genutilcli.MigrateGenesisCmd(), + genutilcli.GenTxCmd(simapp.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{}, simapp.DefaultNodeHome), + genutilcli.ValidateGenesisCmd(simapp.ModuleBasics), + AddGenesisAccountCmd(simapp.DefaultNodeHome), + tmcli.NewCompletionCmd(rootCmd, true), + testnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}), + debug.Cmd(), + config.Cmd(), + ) + + a := appCreator{encodingConfig} + server.AddCommands(rootCmd, simapp.DefaultNodeHome, a.newApp, a.appExport, addModuleInitFlags) + + // add keybase, auxiliary RPC, query, and tx child commands + rootCmd.AddCommand( + rpc.StatusCommand(), + queryCommand(), + txCommand(), + keys.Commands(simapp.DefaultNodeHome), + ) + + // add rosetta + rootCmd.AddCommand(server.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler)) +} + +func addModuleInitFlags(startCmd *cobra.Command) { + crisis.AddModuleInitFlags(startCmd) +} + +func queryCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "query", + Aliases: []string{"q"}, + Short: "Querying subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + authcmd.GetAccountCmd(), + rpc.ValidatorCommand(), + rpc.BlockCommand(), + authcmd.QueryTxsByEventsCmd(), + authcmd.QueryTxCmd(), + ) + + simapp.ModuleBasics.AddQueryCommands(cmd) + cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") + + return cmd +} + +func txCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "tx", + Short: "Transactions subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + authcmd.GetSignCommand(), + authcmd.GetSignBatchCommand(), + authcmd.GetMultiSignCommand(), + authcmd.GetMultiSignBatchCmd(), + authcmd.GetValidateSignaturesCommand(), + flags.LineBreak, + authcmd.GetBroadcastCommand(), + authcmd.GetEncodeCommand(), + authcmd.GetDecodeCommand(), + flags.LineBreak, + vestingcli.GetTxCmd(), + ) + + simapp.ModuleBasics.AddTxCommands(cmd) + cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") + + return cmd +} + +type appCreator struct { + encCfg params.EncodingConfig +} + +// newApp is an AppCreator +func (a appCreator) newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application { + var cache sdk.MultiStorePersistentCache + + if cast.ToBool(appOpts.Get(server.FlagInterBlockCache)) { + cache = store.NewCommitKVStoreCacheManager() + } + + skipUpgradeHeights := make(map[int64]bool) + for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) { + skipUpgradeHeights[int64(h)] = true + } + + pruningOpts, err := server.GetPruningOptionsFromFlags(appOpts) + if err != nil { + panic(err) + } + + snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots") + snapshotDB, err := sdk.NewLevelDB("metadata", snapshotDir) + if err != nil { + panic(err) + } + snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) + if err != nil { + panic(err) + } + + return simapp.NewSimApp( + logger, db, traceStore, true, skipUpgradeHeights, + cast.ToString(appOpts.Get(flags.FlagHome)), + cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), + a.encCfg, + appOpts, + baseapp.SetPruning(pruningOpts), + baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(server.FlagMinGasPrices))), + baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(server.FlagHaltHeight))), + baseapp.SetHaltTime(cast.ToUint64(appOpts.Get(server.FlagHaltTime))), + baseapp.SetMinRetainBlocks(cast.ToUint64(appOpts.Get(server.FlagMinRetainBlocks))), + baseapp.SetInterBlockCache(cache), + baseapp.SetTrace(cast.ToBool(appOpts.Get(server.FlagTrace))), + baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents))), + baseapp.SetSnapshotStore(snapshotStore), + baseapp.SetSnapshotInterval(cast.ToUint64(appOpts.Get(server.FlagStateSyncSnapshotInterval))), + baseapp.SetSnapshotKeepRecent(cast.ToUint32(appOpts.Get(server.FlagStateSyncSnapshotKeepRecent))), + ) +} + +// appExport creates a new simapp (optionally at a given height) +// and exports state. +func (a appCreator) appExport( + logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, + appOpts servertypes.AppOptions) (servertypes.ExportedApp, error) { + + var simApp *simapp.SimApp + homePath, ok := appOpts.Get(flags.FlagHome).(string) + if !ok || homePath == "" { + return servertypes.ExportedApp{}, errors.New("application home not set") + } + + if height != -1 { + simApp = simapp.NewSimApp(logger, db, traceStore, false, map[int64]bool{}, homePath, uint(1), a.encCfg, appOpts) + + if err := simApp.LoadHeight(height); err != nil { + return servertypes.ExportedApp{}, err + } + } else { + simApp = simapp.NewSimApp(logger, db, traceStore, true, map[int64]bool{}, homePath, uint(1), a.encCfg, appOpts) + } + + return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs) +} diff --git a/x/wasm/ibctesting/simapp/simd/cmd/testnet.go b/x/wasm/ibctesting/simapp/simd/cmd/testnet.go new file mode 100644 index 0000000000..d188253a63 --- /dev/null +++ b/x/wasm/ibctesting/simapp/simd/cmd/testnet.go @@ -0,0 +1,400 @@ +package cmd + +// DONTCOVER + +import ( + "bufio" + "encoding/json" + "fmt" + "net" + "os" + "path/filepath" + + "github.com/spf13/cobra" + tmconfig "github.com/tendermint/tendermint/config" + tmos "github.com/tendermint/tendermint/libs/os" + tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/types" + tmtime "github.com/tendermint/tendermint/types/time" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/server" + srvconfig "github.com/cosmos/cosmos-sdk/server/config" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +var ( + flagNodeDirPrefix = "node-dir-prefix" + flagNumValidators = "v" + flagOutputDir = "output-dir" + flagNodeDaemonHome = "node-daemon-home" + flagStartingIPAddress = "starting-ip-address" +) + +// get cmd to initialize all files for tendermint testnet and application +func testnetCmd(mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator) *cobra.Command { + cmd := &cobra.Command{ + Use: "testnet", + Short: "Initialize files for a simapp testnet", + Long: `testnet will create "v" number of directories and populate each with +necessary files (private validator, genesis, config, etc.). + +Note, strict routability for addresses is turned off in the config file. + +Example: + simd testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2 + `, + RunE: func(cmd *cobra.Command, _ []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + serverCtx := server.GetServerContextFromCmd(cmd) + config := serverCtx.Config + + outputDir, _ := cmd.Flags().GetString(flagOutputDir) + keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) + chainID, _ := cmd.Flags().GetString(flags.FlagChainID) + minGasPrices, _ := cmd.Flags().GetString(server.FlagMinGasPrices) + nodeDirPrefix, _ := cmd.Flags().GetString(flagNodeDirPrefix) + nodeDaemonHome, _ := cmd.Flags().GetString(flagNodeDaemonHome) + startingIPAddress, _ := cmd.Flags().GetString(flagStartingIPAddress) + numValidators, _ := cmd.Flags().GetInt(flagNumValidators) + algo, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm) + + return InitTestnet( + clientCtx, cmd, config, mbm, genBalIterator, outputDir, chainID, minGasPrices, + nodeDirPrefix, nodeDaemonHome, startingIPAddress, keyringBackend, algo, numValidators, + ) + }, + } + + cmd.Flags().Int(flagNumValidators, 4, "Number of validators to initialize the testnet with") + cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet", "Directory to store initialization data for the testnet") + cmd.Flags().String(flagNodeDirPrefix, "node", "Prefix the directory name for each node with (node results in node0, node1, ...)") + cmd.Flags().String(flagNodeDaemonHome, "simd", "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.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created") + cmd.Flags().String(server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), "Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)") + cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") + cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for") + + return cmd +} + +const nodeDirPerm = 0755 + +// Initialize the testnet +func InitTestnet( + clientCtx client.Context, + cmd *cobra.Command, + nodeConfig *tmconfig.Config, + mbm module.BasicManager, + genBalIterator banktypes.GenesisBalancesIterator, + outputDir, + chainID, + minGasPrices, + nodeDirPrefix, + nodeDaemonHome, + startingIPAddress, + keyringBackend, + algoStr string, + numValidators int, +) error { + + if chainID == "" { + chainID = "chain-" + tmrand.NewRand().Str(6) + } + + nodeIDs := make([]string, numValidators) + valPubKeys := make([]cryptotypes.PubKey, numValidators) + + simappConfig := srvconfig.DefaultConfig() + simappConfig.MinGasPrices = minGasPrices + simappConfig.API.Enable = true + simappConfig.Telemetry.Enabled = true + simappConfig.Telemetry.PrometheusRetentionTime = 60 + simappConfig.Telemetry.EnableHostnameLabel = false + simappConfig.Telemetry.GlobalLabels = [][]string{{"chain_id", chainID}} + + var ( + genAccounts []authtypes.GenesisAccount + genBalances []banktypes.Balance + genFiles []string + ) + + inBuf := bufio.NewReader(cmd.InOrStdin()) + // generate private keys, node IDs, and initial transactions + for i := 0; i < numValidators; i++ { + nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i) + nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome) + gentxsDir := filepath.Join(outputDir, "gentxs") + + nodeConfig.SetRoot(nodeDir) + nodeConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657" + + if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil { + _ = os.RemoveAll(outputDir) + return err + } + + nodeConfig.Moniker = nodeDirName + + ip, err := getIP(i, startingIPAddress) + if err != nil { + _ = os.RemoveAll(outputDir) + return err + } + + nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig) + if err != nil { + _ = os.RemoveAll(outputDir) + return err + } + + memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip) + genFiles = append(genFiles, nodeConfig.GenesisFile()) + + kb, err := keyring.New(sdk.KeyringServiceName(), keyringBackend, nodeDir, inBuf) + if err != nil { + return err + } + + keyringAlgos, _ := kb.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(algoStr, keyringAlgos) + if err != nil { + return err + } + + addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo) + if err != nil { + _ = os.RemoveAll(outputDir) + return err + } + + info := map[string]string{"secret": secret} + + cliPrint, err := json.Marshal(info) + if err != nil { + return err + } + + // save private key seed words + if err := writeFile(fmt.Sprintf("%v.json", "key_seed"), nodeDir, cliPrint); err != nil { + return err + } + + accTokens := sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction) + accStakingTokens := sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction) + coins := sdk.Coins{ + sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), accTokens), + sdk.NewCoin(sdk.DefaultBondDenom, accStakingTokens), + } + + genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: coins.Sort()}) + genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) + + valTokens := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction) + createValMsg, err := stakingtypes.NewMsgCreateValidator( + sdk.ValAddress(addr), + valPubKeys[i], + sdk.NewCoin(sdk.DefaultBondDenom, valTokens), + stakingtypes.NewDescription(nodeDirName, "", "", "", ""), + stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()), + sdk.OneInt(), + ) + if err != nil { + return err + } + + txBuilder := clientCtx.TxConfig.NewTxBuilder() + if err := txBuilder.SetMsgs(createValMsg); err != nil { + return err + } + + txBuilder.SetMemo(memo) + + txFactory := tx.Factory{} + txFactory = txFactory. + WithChainID(chainID). + WithMemo(memo). + WithKeybase(kb). + WithTxConfig(clientCtx.TxConfig) + + if err := tx.Sign(txFactory, nodeDirName, txBuilder, true); err != nil { + return err + } + + txBz, err := clientCtx.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) + if err != nil { + return err + } + + if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil { + return err + } + + srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), simappConfig) + } + + if err := initGenFiles(clientCtx, mbm, chainID, genAccounts, genBalances, genFiles, numValidators); err != nil { + return err + } + + err := collectGenFiles( + clientCtx, nodeConfig, chainID, nodeIDs, valPubKeys, numValidators, + outputDir, nodeDirPrefix, nodeDaemonHome, genBalIterator, + ) + if err != nil { + return err + } + + cmd.PrintErrf("Successfully initialized %d node directories\n", numValidators) + return nil +} + +func initGenFiles( + clientCtx client.Context, mbm module.BasicManager, chainID string, + genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, + genFiles []string, numValidators int, +) error { + + appGenState := mbm.DefaultGenesis(clientCtx.JSONCodec) + + // set the accounts in the genesis state + var authGenState authtypes.GenesisState + clientCtx.JSONCodec.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState) + + accounts, err := authtypes.PackAccounts(genAccounts) + if err != nil { + return err + } + + authGenState.Accounts = accounts + appGenState[authtypes.ModuleName] = clientCtx.JSONCodec.MustMarshalJSON(&authGenState) + + // set the balances in the genesis state + var bankGenState banktypes.GenesisState + clientCtx.JSONCodec.MustUnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState) + + bankGenState.Balances = genBalances + appGenState[banktypes.ModuleName] = clientCtx.JSONCodec.MustMarshalJSON(&bankGenState) + + appGenStateJSON, err := json.MarshalIndent(appGenState, "", " ") + if err != nil { + return err + } + + genDoc := types.GenesisDoc{ + ChainID: chainID, + AppState: appGenStateJSON, + Validators: nil, + } + + // generate empty genesis files for each validator and save + for i := 0; i < numValidators; i++ { + if err := genDoc.SaveAs(genFiles[i]); err != nil { + return err + } + } + return nil +} + +func collectGenFiles( + clientCtx client.Context, nodeConfig *tmconfig.Config, chainID string, + nodeIDs []string, valPubKeys []cryptotypes.PubKey, numValidators int, + outputDir, nodeDirPrefix, nodeDaemonHome string, genBalIterator banktypes.GenesisBalancesIterator, +) error { + + var appState json.RawMessage + genTime := tmtime.Now() + + for i := 0; i < numValidators; i++ { + nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i) + nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome) + gentxsDir := filepath.Join(outputDir, "gentxs") + nodeConfig.Moniker = nodeDirName + + nodeConfig.SetRoot(nodeDir) + + nodeID, valPubKey := nodeIDs[i], valPubKeys[i] + initCfg := genutiltypes.NewInitConfig(chainID, gentxsDir, nodeID, valPubKey) + + genDoc, err := types.GenesisDocFromFile(nodeConfig.GenesisFile()) + if err != nil { + return err + } + + nodeAppState, err := genutil.GenAppStateFromConfig(clientCtx.JSONCodec, clientCtx.TxConfig, nodeConfig, initCfg, *genDoc, genBalIterator) + if err != nil { + return err + } + + if appState == nil { + // set the canonical application state (they should not differ) + appState = nodeAppState + } + + genFile := nodeConfig.GenesisFile() + + // overwrite each validator's genesis file to have a canonical genesis time + if err := genutil.ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime); err != nil { + return err + } + } + + return nil +} + +func getIP(i int, startingIPAddr string) (ip string, err error) { + if len(startingIPAddr) == 0 { + ip, err = server.ExternalIP() + if err != nil { + return "", err + } + return ip, nil + } + return calculateIP(startingIPAddr, i) +} + +func calculateIP(ip string, i int) (string, error) { + ipv4 := net.ParseIP(ip).To4() + if ipv4 == nil { + return "", fmt.Errorf("%v: non ipv4 address", ip) + } + + for j := 0; j < i; j++ { + ipv4[3]++ + } + + return ipv4.String(), nil +} + +func writeFile(name string, dir string, contents []byte) error { + writePath := filepath.Join(dir) + file := filepath.Join(writePath, name) + + err := tmos.EnsureDir(writePath, 0755) + if err != nil { + return err + } + + err = tmos.WriteFile(file, contents, 0644) + if err != nil { + return err + } + + return nil +} diff --git a/x/wasm/ibctesting/simapp/simd/main.go b/x/wasm/ibctesting/simapp/simd/main.go new file mode 100644 index 0000000000..56126b336c --- /dev/null +++ b/x/wasm/ibctesting/simapp/simd/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "os" + + "github.com/cosmos/cosmos-sdk/server" + svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp" + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/simd/cmd" +) + +func main() { + rootCmd, _ := cmd.NewRootCmd() + + if err := svrcmd.Execute(rootCmd, simapp.DefaultNodeHome); err != nil { + switch e := err.(type) { + case server.ErrorCode: + os.Exit(e.Code) + + default: + os.Exit(1) + } + } +} diff --git a/x/wasm/ibctesting/simapp/state.go b/x/wasm/ibctesting/simapp/state.go new file mode 100644 index 0000000000..34d0f2fc49 --- /dev/null +++ b/x/wasm/ibctesting/simapp/state.go @@ -0,0 +1,234 @@ +package simapp + +import ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "math/rand" + "time" + + tmjson "github.com/tendermint/tendermint/libs/json" + tmtypes "github.com/tendermint/tendermint/types" + + simappparams "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/params" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// AppStateFn returns the initial application state using a genesis or the simulation parameters. +// It panics if the user provides files for both of them. +// If a file is not given for the genesis or the sim params, it creates a randomized one. +func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn { + return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, + ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { + + if FlagGenesisTimeValue == 0 { + genesisTimestamp = simtypes.RandTimestamp(r) + } else { + genesisTimestamp = time.Unix(FlagGenesisTimeValue, 0) + } + + chainID = config.ChainID + switch { + case config.ParamsFile != "" && config.GenesisFile != "": + panic("cannot provide both a genesis file and a params file") + + case config.GenesisFile != "": + // override the default chain-id from simapp to set it later to the config + genesisDoc, accounts := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile) + + if FlagGenesisTimeValue == 0 { + // use genesis timestamp if no custom timestamp is provided (i.e no random timestamp) + genesisTimestamp = genesisDoc.GenesisTime + } + + appState = genesisDoc.AppState + chainID = genesisDoc.ChainID + simAccs = accounts + + case config.ParamsFile != "": + appParams := make(simtypes.AppParams) + bz, err := ioutil.ReadFile(config.ParamsFile) + if err != nil { + panic(err) + } + + err = json.Unmarshal(bz, &appParams) + if err != nil { + panic(err) + } + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + + default: + appParams := make(simtypes.AppParams) + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + } + + rawState := make(map[string]json.RawMessage) + err := json.Unmarshal(appState, &rawState) + if err != nil { + panic(err) + } + + stakingStateBz, ok := rawState[stakingtypes.ModuleName] + if !ok { + panic("staking genesis state is missing") + } + + stakingState := new(stakingtypes.GenesisState) + err = cdc.UnmarshalJSON(stakingStateBz, stakingState) + if err != nil { + panic(err) + } + // compute not bonded balance + notBondedTokens := sdk.ZeroInt() + for _, val := range stakingState.Validators { + if val.Status != stakingtypes.Unbonded { + continue + } + notBondedTokens = notBondedTokens.Add(val.GetTokens()) + } + notBondedCoins := sdk.NewCoin(stakingState.Params.BondDenom, notBondedTokens) + // edit bank state to make it have the not bonded pool tokens + bankStateBz, ok := rawState[banktypes.ModuleName] + // TODO(fdymylja/jonathan): should we panic in this case + if !ok { + panic("bank genesis state is missing") + } + bankState := new(banktypes.GenesisState) + err = cdc.UnmarshalJSON(bankStateBz, bankState) + if err != nil { + panic(err) + } + + bankState.Balances = append(bankState.Balances, banktypes.Balance{ + Address: authtypes.NewModuleAddress(stakingtypes.NotBondedPoolName).String(), + Coins: sdk.NewCoins(notBondedCoins), + }) + + // change appState back + rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) + rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) + + // replace appstate + appState, err = json.Marshal(rawState) + if err != nil { + panic(err) + } + return appState, simAccs, chainID, genesisTimestamp + } +} + +// AppStateRandomizedFn creates calls each module's GenesisState generator function +// and creates the simulation params +func AppStateRandomizedFn( + simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec, + accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams, +) (json.RawMessage, []simtypes.Account) { + numAccs := int64(len(accs)) + genesisState := NewDefaultGenesisState(cdc) + + // generate a random amount of initial stake coins and a random initial + // number of bonded accounts + var initialStake, numInitiallyBonded int64 + appParams.GetOrGenerate( + cdc, simappparams.StakePerAccount, &initialStake, r, + func(r *rand.Rand) { initialStake = r.Int63n(1e12) }, + ) + appParams.GetOrGenerate( + cdc, simappparams.InitiallyBondedValidators, &numInitiallyBonded, r, + func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) }, + ) + + if numInitiallyBonded > numAccs { + numInitiallyBonded = numAccs + } + + fmt.Printf( + `Selected randomly generated parameters for simulated genesis: +{ + stake_per_account: "%d", + initially_bonded_validators: "%d" +} +`, initialStake, numInitiallyBonded, + ) + + simState := &module.SimulationState{ + AppParams: appParams, + Cdc: cdc, + Rand: r, + GenState: genesisState, + Accounts: accs, + InitialStake: initialStake, + NumBonded: numInitiallyBonded, + GenTimestamp: genesisTimestamp, + } + + simManager.GenerateGenesisStates(simState) + + appState, err := json.Marshal(genesisState) + if err != nil { + panic(err) + } + + return appState, accs +} + +// AppStateFromGenesisFileFn util function to generate the genesis AppState +// from a genesis.json file. +func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account) { + bytes, err := ioutil.ReadFile(genesisFile) + if err != nil { + panic(err) + } + + var genesis tmtypes.GenesisDoc + // NOTE: Tendermint uses a custom JSON decoder for GenesisDoc + err = tmjson.Unmarshal(bytes, &genesis) + if err != nil { + panic(err) + } + + var appState GenesisState + err = json.Unmarshal(genesis.AppState, &appState) + if err != nil { + panic(err) + } + + var authGenesis authtypes.GenesisState + if appState[authtypes.ModuleName] != nil { + cdc.MustUnmarshalJSON(appState[authtypes.ModuleName], &authGenesis) + } + + newAccs := make([]simtypes.Account, len(authGenesis.Accounts)) + for i, acc := range authGenesis.Accounts { + // Pick a random private key, since we don't know the actual key + // This should be fine as it's only used for mock Tendermint validators + // and these keys are never actually used to sign by mock Tendermint. + privkeySeed := make([]byte, 15) + if _, err := r.Read(privkeySeed); err != nil { + panic(err) + } + + privKey := secp256k1.GenPrivKeyFromSecret(privkeySeed) + + a, ok := acc.GetCachedValue().(authtypes.AccountI) + if !ok { + panic("expected account") + } + + // create simulator accounts + simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress()} + newAccs[i] = simAcc + } + + return genesis, newAccs +} diff --git a/x/wasm/ibctesting/simapp/test_helpers.go b/x/wasm/ibctesting/simapp/test_helpers.go new file mode 100644 index 0000000000..dfee8f69f7 --- /dev/null +++ b/x/wasm/ibctesting/simapp/test_helpers.go @@ -0,0 +1,350 @@ +package simapp + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "strconv" + "testing" + "time" + + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtypes "github.com/tendermint/tendermint/types" + dbm "github.com/tendermint/tm-db" + + bam "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/helpers" +) + +// DefaultConsensusParams defines the default Tendermint consensus params used in +// SimApp testing. +var DefaultConsensusParams = &abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxBytes: 200000, + MaxGas: 2000000, + }, + Evidence: &tmproto.EvidenceParams{ + MaxAgeNumBlocks: 302400, + MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration + MaxBytes: 10000, + }, + Validator: &tmproto.ValidatorParams{ + PubKeyTypes: []string{ + tmtypes.ABCIPubKeyTypeEd25519, + }, + }, +} + +func setup(withGenesis bool, invCheckPeriod uint) (*SimApp, GenesisState) { + db := dbm.NewMemDB() + encCdc := MakeTestEncodingConfig() + app := NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, invCheckPeriod, encCdc, EmptyAppOptions{}) + if withGenesis { + return app, NewDefaultGenesisState(encCdc.Marshaler) + } + return app, GenesisState{} +} + +// Setup initializes a new SimApp. A Nop logger is set in SimApp. +func Setup(isCheckTx bool) *SimApp { + app, genesisState := setup(!isCheckTx, 5) + if !isCheckTx { + // init chain must be called to stop deliverState from being nil + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + if err != nil { + panic(err) + } + + // Initialize the chain + app.InitChain( + abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: DefaultConsensusParams, + AppStateBytes: stateBytes, + }, + ) + } + + return app +} + +// SetupWithGenesisAccounts initializes a new SimApp with the provided genesis +// accounts and possible balances. +func SetupWithGenesisAccounts(genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *SimApp { + app, genesisState := setup(true, 0) + authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) + genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) + + totalSupply := sdk.NewCoins() + for _, b := range balances { + totalSupply = totalSupply.Add(b.Coins...) + } + + bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}) + genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) + + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + if err != nil { + panic(err) + } + + app.InitChain( + abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: DefaultConsensusParams, + AppStateBytes: stateBytes, + }, + ) + + app.Commit() + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1}}) + + return app +} + +type GenerateAccountStrategy func(int) []sdk.AccAddress + +// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order. +func createRandomAccounts(accNum int) []sdk.AccAddress { + testAddrs := make([]sdk.AccAddress, accNum) + for i := 0; i < accNum; i++ { + pk := ed25519.GenPrivKey().PubKey() + testAddrs[i] = sdk.AccAddress(pk.Address()) + } + + return testAddrs +} + +// createIncrementalAccounts is a strategy used by addTestAddrs() in order to generated addresses in ascending order. +func createIncrementalAccounts(accNum int) []sdk.AccAddress { + var addresses []sdk.AccAddress + var buffer bytes.Buffer + + // start at 100 so we can make up to 999 test addresses with valid test addresses + for i := 100; i < (accNum + 100); i++ { + numString := strconv.Itoa(i) + buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") // base address string + + buffer.WriteString(numString) // adding on final two digits to make addresses unique + res, _ := sdk.AccAddressFromHex(buffer.String()) + bech := res.String() + addr, _ := TestAddr(buffer.String(), bech) + + addresses = append(addresses, addr) + buffer.Reset() + } + + return addresses +} + +// AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys. +func AddTestAddrsFromPubKeys(app *SimApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt sdk.Int) { + initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) + + for _, pk := range pubKeys { + initAccountWithCoins(app, ctx, sdk.AccAddress(pk.Address()), initCoins) + } +} + +// AddTestAddrs constructs and returns accNum amount of accounts with an +// initial balance of accAmt in random order +func AddTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress { + return addTestAddrs(app, ctx, accNum, accAmt, createRandomAccounts) +} + +// AddTestAddrs constructs and returns accNum amount of accounts with an +// initial balance of accAmt in random order +func AddTestAddrsIncremental(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress { + return addTestAddrs(app, ctx, accNum, accAmt, createIncrementalAccounts) +} + +func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt sdk.Int, strategy GenerateAccountStrategy) []sdk.AccAddress { + testAddrs := strategy(accNum) + + initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) + + for _, addr := range testAddrs { + initAccountWithCoins(app, ctx, addr, initCoins) + } + + return testAddrs +} + +func initAccountWithCoins(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) { + err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, coins) + if err != nil { + panic(err) + } + + err = app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) + if err != nil { + panic(err) + } +} + +// ConvertAddrsToValAddrs converts the provided addresses to ValAddress. +func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress { + valAddrs := make([]sdk.ValAddress, len(addrs)) + + for i, addr := range addrs { + valAddrs[i] = sdk.ValAddress(addr) + } + + return valAddrs +} + +func TestAddr(addr string, bech string) (sdk.AccAddress, error) { + res, err := sdk.AccAddressFromHex(addr) + if err != nil { + return nil, err + } + bechexpected := res.String() + if bech != bechexpected { + return nil, fmt.Errorf("bech encoding doesn't match reference") + } + + bechres, err := sdk.AccAddressFromBech32(bech) + if err != nil { + return nil, err + } + if !bytes.Equal(bechres, res) { + return nil, err + } + + return res, nil +} + +// CheckBalance checks the balance of an account. +func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, balances sdk.Coins) { + ctxCheck := app.BaseApp.NewContext(true, tmproto.Header{}) + require.True(t, balances.IsEqual(app.BankKeeper.GetAllBalances(ctxCheck, addr))) +} + +// SignAndDeliver signs and delivers a transaction. No simulation occurs as the +// ibc testing package causes checkState and deliverState to diverge in block time. +func SignAndDeliver( + t *testing.T, txCfg client.TxConfig, app *bam.BaseApp, header tmproto.Header, msgs []sdk.Msg, + chainID string, accNums, accSeqs []uint64, expSimPass, expPass bool, priv ...cryptotypes.PrivKey, +) (sdk.GasInfo, *sdk.Result, error) { + + tx, err := helpers.GenTx( + txCfg, + msgs, + sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, + helpers.DefaultGenTxGas, + chainID, + accNums, + accSeqs, + priv..., + ) + require.NoError(t, err) + + // Simulate a sending a transaction and committing a block + app.BeginBlock(abci.RequestBeginBlock{Header: header}) + gInfo, res, err := app.Deliver(txCfg.TxEncoder(), tx) + + if expPass { + require.NoError(t, err) + require.NotNil(t, res) + } else { + require.Error(t, err) + require.Nil(t, res) + } + + app.EndBlock(abci.RequestEndBlock{}) + app.Commit() + + return gInfo, res, err +} + +// GenSequenceOfTxs generates a set of signed transactions of messages, such +// that they differ only by having the sequence numbers incremented between +// every transaction. +func GenSequenceOfTxs(txGen client.TxConfig, msgs []sdk.Msg, accNums []uint64, initSeqNums []uint64, numToGenerate int, priv ...cryptotypes.PrivKey) ([]sdk.Tx, error) { + txs := make([]sdk.Tx, numToGenerate) + var err error + for i := 0; i < numToGenerate; i++ { + txs[i], err = helpers.GenTx( + txGen, + msgs, + sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, + helpers.DefaultGenTxGas, + "", + accNums, + initSeqNums, + priv..., + ) + if err != nil { + break + } + incrementAllSequenceNumbers(initSeqNums) + } + + return txs, err +} + +func incrementAllSequenceNumbers(initSeqNums []uint64) { + for i := 0; i < len(initSeqNums); i++ { + initSeqNums[i]++ + } +} + +// CreateTestPubKeys returns a total of numPubKeys public keys in ascending order. +func CreateTestPubKeys(numPubKeys int) []cryptotypes.PubKey { + var publicKeys []cryptotypes.PubKey + var buffer bytes.Buffer + + // start at 10 to avoid changing 1 to 01, 2 to 02, etc + for i := 100; i < (numPubKeys + 100); i++ { + numString := strconv.Itoa(i) + buffer.WriteString("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AF") // base pubkey string + buffer.WriteString(numString) // adding on final two digits to make pubkeys unique + publicKeys = append(publicKeys, NewPubKeyFromHex(buffer.String())) + buffer.Reset() + } + + return publicKeys +} + +// NewPubKeyFromHex returns a PubKey from a hex string. +func NewPubKeyFromHex(pk string) (res cryptotypes.PubKey) { + pkBytes, err := hex.DecodeString(pk) + if err != nil { + panic(err) + } + if len(pkBytes) != ed25519.PubKeySize { + panic(errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size")) + } + return &ed25519.PubKey{Key: pkBytes} +} + +// EmptyAppOptions is a stub implementing AppOptions +type EmptyAppOptions struct{} + +// Get implements AppOptions +func (ao EmptyAppOptions) Get(o string) interface{} { + return nil +} + +// FundAccount is a utility function that funds an account by minting and sending the coins to the address +// TODO(fdymylja): instead of using the mint module account, which has the permission of minting, create a "faucet" account +func FundAccount(app *SimApp, ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + err := app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts) + if err != nil { + return err + } + return app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) +} diff --git a/x/wasm/ibctesting/simapp/types.go b/x/wasm/ibctesting/simapp/types.go new file mode 100644 index 0000000000..0e190af1bc --- /dev/null +++ b/x/wasm/ibctesting/simapp/types.go @@ -0,0 +1,44 @@ +package simapp + +import ( + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" +) + +// App implements the common methods for a Cosmos SDK-based application +// specific blockchain. +type App interface { + // The assigned name of the app. + Name() string + + // The application types codec. + // NOTE: This shoult be sealed before being returned. + LegacyAmino() *codec.LegacyAmino + + // Application updates every begin block. + BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock + + // Application updates every end block. + EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock + + // Application update at chain (i.e app) initialization. + InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain + + // Loads the app at a given height. + LoadHeight(height int64) error + + // Exports the state of the application for a genesis file. + ExportAppStateAndValidators( + forZeroHeight bool, jailAllowedAddrs []string, + ) (types.ExportedApp, error) + + // All the registered module account addreses. + ModuleAccountAddrs() map[string]bool + + // Helper for the simulation framework. + SimulationManager() *module.SimulationManager +} diff --git a/x/wasm/ibctesting/simapp/utils.go b/x/wasm/ibctesting/simapp/utils.go new file mode 100644 index 0000000000..19a33219ab --- /dev/null +++ b/x/wasm/ibctesting/simapp/utils.go @@ -0,0 +1,132 @@ +package simapp + +import ( + "encoding/json" + "fmt" + "io/ioutil" + + "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/simapp/helpers" +) + +// SetupSimulation creates the config, db (levelDB), temporary directory and logger for +// the simulation tests. If `FlagEnabledValue` is false it skips the current test. +// Returns error on an invalid db intantiation or temp dir creation. +func SetupSimulation(dirPrefix, dbName string) (simtypes.Config, dbm.DB, string, log.Logger, bool, error) { + if !FlagEnabledValue { + return simtypes.Config{}, nil, "", nil, true, nil + } + + config := NewConfigFromFlags() + config.ChainID = helpers.SimAppChainID + + var logger log.Logger + if FlagVerboseValue { + logger = log.TestingLogger() + } else { + logger = log.NewNopLogger() + } + + dir, err := ioutil.TempDir("", dirPrefix) + if err != nil { + return simtypes.Config{}, nil, "", nil, false, err + } + + db, err := sdk.NewLevelDB(dbName, dir) + if err != nil { + return simtypes.Config{}, nil, "", nil, false, err + } + + return config, db, dir, logger, false, nil +} + +// SimulationOperations retrieves the simulation params from the provided file path +// and returns all the modules weighted operations +func SimulationOperations(app App, cdc codec.JSONCodec, config simtypes.Config) []simtypes.WeightedOperation { + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + } + + if config.ParamsFile != "" { + bz, err := ioutil.ReadFile(config.ParamsFile) + if err != nil { + panic(err) + } + + err = json.Unmarshal(bz, &simState.AppParams) + if err != nil { + panic(err) + } + } + + simState.ParamChanges = app.SimulationManager().GenerateParamChanges(config.Seed) + simState.Contents = app.SimulationManager().GetProposalContents(simState) + return app.SimulationManager().WeightedOperations(simState) +} + +// CheckExportSimulation exports the app state and simulation parameters to JSON +// if the export paths are defined. +func CheckExportSimulation( + app App, config simtypes.Config, params simtypes.Params, +) error { + if config.ExportStatePath != "" { + fmt.Println("exporting app state...") + exported, err := app.ExportAppStateAndValidators(false, nil) + if err != nil { + return err + } + + if err := ioutil.WriteFile(config.ExportStatePath, []byte(exported.AppState), 0600); err != nil { + return err + } + } + + if config.ExportParamsPath != "" { + fmt.Println("exporting simulation params...") + paramsBz, err := json.MarshalIndent(params, "", " ") + if err != nil { + return err + } + + if err := ioutil.WriteFile(config.ExportParamsPath, paramsBz, 0600); err != nil { + return err + } + } + return nil +} + +// PrintStats prints the corresponding statistics from the app DB. +func PrintStats(db dbm.DB) { + fmt.Println("\nLevelDB Stats") + fmt.Println(db.Stats()["leveldb.stats"]) + fmt.Println("LevelDB cached block size", db.Stats()["leveldb.cachedblock"]) +} + +// GetSimulationLog unmarshals the KVPair's Value to the corresponding type based on the +// each's module store key and the prefix bytes of the KVPair's key. +func GetSimulationLog(storeName string, sdr sdk.StoreDecoderRegistry, kvAs, kvBs []kv.Pair) (log string) { + for i := 0; i < len(kvAs); i++ { + if len(kvAs[i].Value) == 0 && len(kvBs[i].Value) == 0 { + // skip if the value doesn't have any bytes + continue + } + + decoder, ok := sdr[storeName] + if ok { + log += decoder(kvAs[i], kvBs[i]) + } else { + log += fmt.Sprintf("store A %X => %X\nstore B %X => %X\n", kvAs[i].Key, kvAs[i].Value, kvBs[i].Key, kvBs[i].Value) + } + } + + return log +} diff --git a/x/wasm/ibctesting/simapp/utils_test.go b/x/wasm/ibctesting/simapp/utils_test.go new file mode 100644 index 0000000000..0240c482a5 --- /dev/null +++ b/x/wasm/ibctesting/simapp/utils_test.go @@ -0,0 +1,60 @@ +package simapp + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/std" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/types/module" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func makeCodec(bm module.BasicManager) *codec.LegacyAmino { + cdc := codec.NewLegacyAmino() + + bm.RegisterLegacyAminoCodec(cdc) + std.RegisterLegacyAminoCodec(cdc) + + return cdc +} + +func TestGetSimulationLog(t *testing.T) { + cdc := makeCodec(ModuleBasics) + + decoders := make(sdk.StoreDecoderRegistry) + decoders[authtypes.StoreKey] = func(kvAs, kvBs kv.Pair) string { return "10" } + + tests := []struct { + store string + kvPairs []kv.Pair + expectedLog string + }{ + { + "Empty", + []kv.Pair{{}}, + "", + }, + { + authtypes.StoreKey, + []kv.Pair{{Key: authtypes.GlobalAccountNumberKey, Value: cdc.MustMarshal(uint64(10))}}, + "10", + }, + { + "OtherStore", + []kv.Pair{{Key: []byte("key"), Value: []byte("value")}}, + fmt.Sprintf("store A %X => %X\nstore B %X => %X\n", []byte("key"), []byte("value"), []byte("key"), []byte("value")), + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.store, func(t *testing.T) { + require.Equal(t, tt.expectedLog, GetSimulationLog(tt.store, decoders, tt.kvPairs, tt.kvPairs), tt.store) + }) + } +} diff --git a/x/wasm/ibctesting/solomachine.go b/x/wasm/ibctesting/solomachine.go new file mode 100644 index 0000000000..75d4b58b5a --- /dev/null +++ b/x/wasm/ibctesting/solomachine.go @@ -0,0 +1,319 @@ +package ibctesting + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/crypto/types/multisig" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + commitmenttypes "github.com/cosmos/ibc-go/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/modules/core/24-host" + "github.com/cosmos/ibc-go/modules/core/exported" + solomachinetypes "github.com/cosmos/ibc-go/modules/light-clients/06-solomachine/types" +) + +// Solomachine is a testing helper used to simulate a counterparty +// solo machine client. +type Solomachine struct { + t *testing.T + + cdc codec.BinaryCodec + ClientID string + PrivateKeys []cryptotypes.PrivKey // keys used for signing + PublicKeys []cryptotypes.PubKey // keys used for generating solo machine pub key + PublicKey cryptotypes.PubKey // key used for verification + Sequence uint64 + Time uint64 + Diversifier string +} + +// NewSolomachine returns a new solomachine instance with an `nKeys` amount of +// generated private/public key pairs and a sequence starting at 1. If nKeys +// is greater than 1 then a multisig public key is used. +func NewSolomachine(t *testing.T, cdc codec.BinaryCodec, clientID, diversifier string, nKeys uint64) *Solomachine { + privKeys, pubKeys, pk := GenerateKeys(t, nKeys) + + return &Solomachine{ + t: t, + cdc: cdc, + ClientID: clientID, + PrivateKeys: privKeys, + PublicKeys: pubKeys, + PublicKey: pk, + Sequence: 1, + Time: 10, + Diversifier: diversifier, + } +} + +// GenerateKeys generates a new set of secp256k1 private keys and public keys. +// If the number of keys is greater than one then the public key returned represents +// a multisig public key. The private keys are used for signing, the public +// keys are used for generating the public key and the public key is used for +// solo machine verification. The usage of secp256k1 is entirely arbitrary. +// The key type can be swapped for any key type supported by the PublicKey +// interface, if needed. The same is true for the amino based Multisignature +// public key. +func GenerateKeys(t *testing.T, n uint64) ([]cryptotypes.PrivKey, []cryptotypes.PubKey, cryptotypes.PubKey) { + require.NotEqual(t, uint64(0), n, "generation of zero keys is not allowed") + + privKeys := make([]cryptotypes.PrivKey, n) + pubKeys := make([]cryptotypes.PubKey, n) + for i := uint64(0); i < n; i++ { + privKeys[i] = secp256k1.GenPrivKey() + pubKeys[i] = privKeys[i].PubKey() + } + + var pk cryptotypes.PubKey + if len(privKeys) > 1 { + // generate multi sig pk + pk = kmultisig.NewLegacyAminoPubKey(int(n), pubKeys) + } else { + pk = privKeys[0].PubKey() + } + + return privKeys, pubKeys, pk +} + +// ClientState returns a new solo machine ClientState instance. Default usage does not allow update +// after governance proposal +func (solo *Solomachine) ClientState() *solomachinetypes.ClientState { + return solomachinetypes.NewClientState(solo.Sequence, solo.ConsensusState(), false) +} + +// ConsensusState returns a new solo machine ConsensusState instance +func (solo *Solomachine) ConsensusState() *solomachinetypes.ConsensusState { + publicKey, err := codectypes.NewAnyWithValue(solo.PublicKey) + require.NoError(solo.t, err) + + return &solomachinetypes.ConsensusState{ + PublicKey: publicKey, + Diversifier: solo.Diversifier, + Timestamp: solo.Time, + } +} + +// GetHeight returns an exported.Height with Sequence as RevisionHeight +func (solo *Solomachine) GetHeight() exported.Height { + return clienttypes.NewHeight(0, solo.Sequence) +} + +// CreateHeader generates a new private/public key pair and creates the +// necessary signature to construct a valid solo machine header. +func (solo *Solomachine) CreateHeader() *solomachinetypes.Header { + // generate new private keys and signature for header + newPrivKeys, newPubKeys, newPubKey := GenerateKeys(solo.t, uint64(len(solo.PrivateKeys))) + + publicKey, err := codectypes.NewAnyWithValue(newPubKey) + require.NoError(solo.t, err) + + data := &solomachinetypes.HeaderData{ + NewPubKey: publicKey, + NewDiversifier: solo.Diversifier, + } + + dataBz, err := solo.cdc.Marshal(data) + require.NoError(solo.t, err) + + signBytes := &solomachinetypes.SignBytes{ + Sequence: solo.Sequence, + Timestamp: solo.Time, + Diversifier: solo.Diversifier, + DataType: solomachinetypes.HEADER, + Data: dataBz, + } + + bz, err := solo.cdc.Marshal(signBytes) + require.NoError(solo.t, err) + + sig := solo.GenerateSignature(bz) + + header := &solomachinetypes.Header{ + Sequence: solo.Sequence, + Timestamp: solo.Time, + Signature: sig, + NewPublicKey: publicKey, + NewDiversifier: solo.Diversifier, + } + + // assumes successful header update + solo.Sequence++ + solo.PrivateKeys = newPrivKeys + solo.PublicKeys = newPubKeys + solo.PublicKey = newPubKey + + return header +} + +// CreateMisbehaviour constructs testing misbehaviour for the solo machine client +// by signing over two different data bytes at the same sequence. +func (solo *Solomachine) CreateMisbehaviour() *solomachinetypes.Misbehaviour { + path := solo.GetClientStatePath("counterparty") + dataOne, err := solomachinetypes.ClientStateDataBytes(solo.cdc, path, solo.ClientState()) + require.NoError(solo.t, err) + + path = solo.GetConsensusStatePath("counterparty", clienttypes.NewHeight(0, 1)) + dataTwo, err := solomachinetypes.ConsensusStateDataBytes(solo.cdc, path, solo.ConsensusState()) + require.NoError(solo.t, err) + + signBytes := &solomachinetypes.SignBytes{ + Sequence: solo.Sequence, + Timestamp: solo.Time, + Diversifier: solo.Diversifier, + DataType: solomachinetypes.CLIENT, + Data: dataOne, + } + + bz, err := solo.cdc.Marshal(signBytes) + require.NoError(solo.t, err) + + sig := solo.GenerateSignature(bz) + signatureOne := solomachinetypes.SignatureAndData{ + Signature: sig, + DataType: solomachinetypes.CLIENT, + Data: dataOne, + Timestamp: solo.Time, + } + + // misbehaviour signaturess can have different timestamps + solo.Time++ + + signBytes = &solomachinetypes.SignBytes{ + Sequence: solo.Sequence, + Timestamp: solo.Time, + Diversifier: solo.Diversifier, + DataType: solomachinetypes.CONSENSUS, + Data: dataTwo, + } + + bz, err = solo.cdc.Marshal(signBytes) + require.NoError(solo.t, err) + + sig = solo.GenerateSignature(bz) + signatureTwo := solomachinetypes.SignatureAndData{ + Signature: sig, + DataType: solomachinetypes.CONSENSUS, + Data: dataTwo, + Timestamp: solo.Time, + } + + return &solomachinetypes.Misbehaviour{ + ClientId: solo.ClientID, + Sequence: solo.Sequence, + SignatureOne: &signatureOne, + SignatureTwo: &signatureTwo, + } +} + +// GenerateSignature uses the stored private keys to generate a signature +// over the sign bytes with each key. If the amount of keys is greater than +// 1 then a multisig data type is returned. +func (solo *Solomachine) GenerateSignature(signBytes []byte) []byte { + sigs := make([]signing.SignatureData, len(solo.PrivateKeys)) + for i, key := range solo.PrivateKeys { + sig, err := key.Sign(signBytes) + require.NoError(solo.t, err) + + sigs[i] = &signing.SingleSignatureData{ + Signature: sig, + } + } + + var sigData signing.SignatureData + if len(sigs) == 1 { + // single public key + sigData = sigs[0] + } else { + // generate multi signature data + multiSigData := multisig.NewMultisig(len(sigs)) + for i, sig := range sigs { + multisig.AddSignature(multiSigData, sig, i) + } + + sigData = multiSigData + } + + protoSigData := signing.SignatureDataToProto(sigData) + bz, err := solo.cdc.Marshal(protoSigData) + require.NoError(solo.t, err) + + return bz +} + +// GetClientStatePath returns the commitment path for the client state. +func (solo *Solomachine) GetClientStatePath(counterpartyClientIdentifier string) commitmenttypes.MerklePath { + path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullClientStatePath(counterpartyClientIdentifier))) + require.NoError(solo.t, err) + + return path +} + +// GetConsensusStatePath returns the commitment path for the consensus state. +func (solo *Solomachine) GetConsensusStatePath(counterpartyClientIdentifier string, consensusHeight exported.Height) commitmenttypes.MerklePath { + path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullConsensusStatePath(counterpartyClientIdentifier, consensusHeight))) + require.NoError(solo.t, err) + + return path +} + +// GetConnectionStatePath returns the commitment path for the connection state. +func (solo *Solomachine) GetConnectionStatePath(connID string) commitmenttypes.MerklePath { + connectionPath := commitmenttypes.NewMerklePath(host.ConnectionPath(connID)) + path, err := commitmenttypes.ApplyPrefix(prefix, connectionPath) + require.NoError(solo.t, err) + + return path +} + +// GetChannelStatePath returns the commitment path for that channel state. +func (solo *Solomachine) GetChannelStatePath(portID, channelID string) commitmenttypes.MerklePath { + channelPath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID)) + path, err := commitmenttypes.ApplyPrefix(prefix, channelPath) + require.NoError(solo.t, err) + + return path +} + +// GetPacketCommitmentPath returns the commitment path for a packet commitment. +func (solo *Solomachine) GetPacketCommitmentPath(portID, channelID string) commitmenttypes.MerklePath { + commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, solo.Sequence)) + path, err := commitmenttypes.ApplyPrefix(prefix, commitmentPath) + require.NoError(solo.t, err) + + return path +} + +// GetPacketAcknowledgementPath returns the commitment path for a packet acknowledgement. +func (solo *Solomachine) GetPacketAcknowledgementPath(portID, channelID string) commitmenttypes.MerklePath { + ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, solo.Sequence)) + path, err := commitmenttypes.ApplyPrefix(prefix, ackPath) + require.NoError(solo.t, err) + + return path +} + +// GetPacketReceiptPath returns the commitment path for a packet receipt +// and an absent receipts. +func (solo *Solomachine) GetPacketReceiptPath(portID, channelID string) commitmenttypes.MerklePath { + receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, solo.Sequence)) + path, err := commitmenttypes.ApplyPrefix(prefix, receiptPath) + require.NoError(solo.t, err) + + return path +} + +// GetNextSequenceRecvPath returns the commitment path for the next sequence recv counter. +func (solo *Solomachine) GetNextSequenceRecvPath(portID, channelID string) commitmenttypes.MerklePath { + nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID)) + path, err := commitmenttypes.ApplyPrefix(prefix, nextSequenceRecvPath) + require.NoError(solo.t, err) + + return path +} diff --git a/x/wasm/ibctesting/values.go b/x/wasm/ibctesting/values.go new file mode 100644 index 0000000000..e87b9646a0 --- /dev/null +++ b/x/wasm/ibctesting/values.go @@ -0,0 +1,60 @@ +/* + This file contains the variables, constants, and default values + used in the testing package and commonly defined in tests. +*/ +package ibctesting + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + connectiontypes "github.com/cosmos/ibc-go/modules/core/03-connection/types" + commitmenttypes "github.com/cosmos/ibc-go/modules/core/23-commitment/types" + ibctmtypes "github.com/cosmos/ibc-go/modules/light-clients/07-tendermint/types" + + "github.com/CosmWasm/wasmd/x/wasm/ibctesting/mock" +) + +const ( + FirstClientID = "07-tendermint-0" + FirstChannelID = "channel-0" + FirstConnectionID = "connection-0" + + // Default params constants used to create a TM client + TrustingPeriod time.Duration = time.Hour * 24 * 7 * 2 + UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3 + MaxClockDrift time.Duration = time.Second * 10 + DefaultDelayPeriod uint64 = 0 + + DefaultChannelVersion = ibctransfertypes.Version + InvalidID = "IDisInvalid" + + // Application Ports + TransferPort = ibctransfertypes.ModuleName + MockPort = mock.ModuleName + + // used for testing proposals + Title = "title" + Description = "description" +) + +var ( + DefaultOpenInitVersion *connectiontypes.Version + + // Default params variables used to create a TM client + DefaultTrustLevel ibctmtypes.Fraction = ibctmtypes.DefaultTrustLevel + TestCoin = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) + + UpgradePath = []string{"upgrade", "upgradedIBCState"} + + ConnectionVersion = connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions())[0] + + MockAcknowledgement = mock.MockAcknowledgement.Acknowledgement() + MockPacketData = mock.MockPacketData + MockFailPacketData = mock.MockFailPacketData + MockCanaryCapabilityName = mock.MockCanaryCapabilityName + + prefix = commitmenttypes.NewMerklePrefix([]byte("ibc")) +) diff --git a/x/wasm/ibctesting/wasm.go b/x/wasm/ibctesting/wasm.go index 19010a88c4..7d2a20b99f 100644 --- a/x/wasm/ibctesting/wasm.go +++ b/x/wasm/ibctesting/wasm.go @@ -5,15 +5,14 @@ import ( "compress/gzip" "encoding/json" "fmt" - wasmd "github.com/CosmWasm/wasmd/app" + "io/ioutil" + "strings" + "github.com/CosmWasm/wasmd/x/wasm/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/golang/protobuf/proto" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/rand" - "io/ioutil" - "strings" ) var wasmIdent = []byte("\x00\x61\x73\x6D") @@ -23,9 +22,9 @@ var wasmIdent = []byte("\x00\x61\x73\x6D") // Address is the contract address for this instance. Test should make use of this data and/or use NewIBCContractMockWasmer // for using a contract mock in Go. func (c *TestChain) SeedNewContractInstance() sdk.AccAddress { - pInstResp := c.StoreCode(append(wasmIdent, rand.Bytes(10)...)) + // No longer likes the randomly created wasm, so we just use a test file now + pInstResp := c.StoreCodeFile("./testdata/test.wasm") codeID := pInstResp.CodeID - anyAddressStr := c.SenderAccount.GetAddress().String() initMsg := []byte(fmt.Sprintf(`{"verifier": %q, "beneficiary": %q}`, anyAddressStr, anyAddressStr)) return c.InstantiateContract(codeID, initMsg) @@ -62,13 +61,13 @@ func (c *TestChain) StoreCode(byteCode []byte) types.MsgStoreCodeResponse { return pInstResp } -func (c *TestChain) InstantiateContract(codeID uint64, initMsg []byte) sdk.AccAddress { +func (c *TestChain) InstantiateContract(codeID uint64, msg []byte) sdk.AccAddress { instantiateMsg := &types.MsgInstantiateContract{ Sender: c.SenderAccount.GetAddress().String(), Admin: c.SenderAccount.GetAddress().String(), CodeID: codeID, Label: "ibc-test", - Msg: initMsg, + Msg: msg, Funds: sdk.Coins{TestCoin}, } @@ -127,13 +126,3 @@ func (c *TestChain) parseSDKResultData(r *sdk.Result) sdk.TxMsgData { require.NoError(c.t, proto.Unmarshal(r.Data, &protoResult)) return protoResult } - -// ContractInfo is a helper function to returns the ContractInfo for the given contract address -func (c *TestChain) ContractInfo(contractAddr sdk.AccAddress) *types.ContractInfo { - return c.TestSupport().WasmKeeper().GetContractInfo(c.GetContext(), contractAddr) -} - -// TestSupport provides access to package private keepers. -func (c *TestChain) TestSupport() *wasmd.TestSupport { - return wasmd.NewTestSupport(c.t, c.App) -} diff --git a/x/wasm/keeper/api.go b/x/wasm/keeper/api.go index 44d4ad2dfb..4c4538522f 100644 --- a/x/wasm/keeper/api.go +++ b/x/wasm/keeper/api.go @@ -1,8 +1,6 @@ package keeper import ( - "fmt" - wasmvm "github.com/CosmWasm/wasmvm" wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -28,9 +26,9 @@ var ( ) func humanAddress(canon []byte) (string, uint64, error) { - if len(canon) != sdk.AddrLen { - return "", costHumanize, fmt.Errorf("Expected %d byte address", sdk.AddrLen) - } + // if len(canon) != sdk.AddrLen { + // return "", costHumanize, fmt.Errorf("Expected %d byte address", sdk.AddrLen) + // } return sdk.AccAddress(canon).String(), costHumanize, nil } diff --git a/x/wasm/keeper/genesis_test.go b/x/wasm/keeper/genesis_test.go index 89bb4221c4..f2e6f37be3 100644 --- a/x/wasm/keeper/genesis_test.go +++ b/x/wasm/keeper/genesis_test.go @@ -6,6 +6,12 @@ import ( "encoding/base64" "errors" "fmt" + "io/ioutil" + "math/rand" + "os" + "testing" + "time" + "github.com/CosmWasm/wasmd/x/wasm/types" wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/cosmos/cosmos-sdk/store" @@ -25,11 +31,6 @@ import ( "github.com/tendermint/tendermint/proto/tendermint/crypto" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - "io/ioutil" - "math/rand" - "os" - "testing" - "time" ) const firstCodeID = 1 @@ -472,7 +473,7 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) { ], "contracts": [ { - "contract_address": "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", + "contract_address": "cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5", "contract_info": { "code_id": "1", "creator": "cosmos13x849jzd03vne42ynpj25hn8npjecxqrjghd8x", @@ -529,7 +530,7 @@ func TestImportContractWithCodeHistoryReset(t *testing.T) { assert.Equal(t, expCodeInfo, *gotCodeInfo) // verify contract - contractAddr, _ := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6") + contractAddr, _ := sdk.AccAddressFromBech32("cosmos18vd8fpwxzck93qlwghaj6arh4p7c5n89uzcee5") gotContractInfo := keeper.GetContractInfo(ctx, contractAddr) require.NotNil(t, gotContractInfo) contractCreatorAddr := "cosmos13x849jzd03vne42ynpj25hn8npjecxqrjghd8x" @@ -557,9 +558,9 @@ func TestSupportedGenMsgTypes(t *testing.T) { wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm") require.NoError(t, err) var ( - myAddress sdk.AccAddress = bytes.Repeat([]byte{1}, sdk.AddrLen) - verifierAddress sdk.AccAddress = bytes.Repeat([]byte{2}, sdk.AddrLen) - beneficiaryAddress sdk.AccAddress = bytes.Repeat([]byte{3}, sdk.AddrLen) + myAddress sdk.AccAddress = bytes.Repeat([]byte{1}, 20) + verifierAddress sdk.AccAddress = bytes.Repeat([]byte{2}, 32) + beneficiaryAddress sdk.AccAddress = bytes.Repeat([]byte{3}, 20) ) const denom = "stake" importState := types.GenesisState{ @@ -658,7 +659,7 @@ func setupKeeper(t *testing.T) (*Keeper, sdk.Context, []sdk.StoreKey) { wasmConfig := wasmTypes.DefaultWasmConfig() pk := paramskeeper.NewKeeper(encodingConfig.Marshaler, encodingConfig.Amino, keyParams, tkeyParams) - srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures) + srcKeeper := NewKeeper(encodingConfig.Marshaler, keyWasm, pk.Subspace(wasmTypes.DefaultParamspace), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, nil, tempDir, wasmConfig, SupportedFeatures) return &srcKeeper, ctx, []sdk.StoreKey{keyWasm, keyParams} } diff --git a/x/wasm/keeper/handler_plugin.go b/x/wasm/keeper/handler_plugin.go index de4520b2b1..fc6104e4b3 100644 --- a/x/wasm/keeper/handler_plugin.go +++ b/x/wasm/keeper/handler_plugin.go @@ -6,11 +6,14 @@ import ( "github.com/CosmWasm/wasmd/x/wasm/types" wasmvmtypes "github.com/CosmWasm/wasmvm/types" + "github.com/cosmos/cosmos-sdk/baseapp" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/modules/core/24-host" + + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) // msgEncoder is an extension point to customize encodings @@ -21,12 +24,14 @@ type msgEncoder interface { // SDKMessageHandler can handles messages that can be encoded into sdk.Message types and routed. type SDKMessageHandler struct { - router sdk.Router - encoders msgEncoder + router sdk.Router + msgRouter *baseapp.MsgServiceRouter + encoders msgEncoder } func NewDefaultMessageHandler( router sdk.Router, + msgRouter *baseapp.MsgServiceRouter, channelKeeper types.ChannelKeeper, capabilityKeeper types.CapabilityKeeper, bankKeeper types.Burner, @@ -39,16 +44,18 @@ func NewDefaultMessageHandler( encoders = encoders.Merge(e) } return NewMessageHandlerChain( - NewSDKMessageHandler(router, encoders), + NewSDKMessageHandler(router, msgRouter, encoders), NewIBCRawPacketHandler(channelKeeper, capabilityKeeper), NewBurnCoinMessageHandler(bankKeeper), ) } -func NewSDKMessageHandler(router sdk.Router, encoders msgEncoder) SDKMessageHandler { +func NewSDKMessageHandler( + router sdk.Router, msgRouter *baseapp.MsgServiceRouter, encoders msgEncoder) SDKMessageHandler { return SDKMessageHandler{ - router: router, - encoders: encoders, + router: router, + msgRouter: msgRouter, + encoders: encoders, } } @@ -85,16 +92,33 @@ func (h SDKMessageHandler) handleSdkMessage(ctx sdk.Context, contractAddr sdk.Ad } } - // find the handler and execute it - handler := h.router.Route(ctx, msg.Route()) - if handler == nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, msg.Route()) + if h.msgRouter == nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrPanic, ">>> msgRouter is nil!!!") } - res, err := handler(ctx, msg) - if err != nil { - return nil, err + + if handler := h.msgRouter.Handler(msg); handler != nil { + // ADR 031 request type routing + res, err := handler(ctx, msg) + if err != nil { + return nil, err + } + return res, nil + + } else if legacyMsg, ok := msg.(legacytx.LegacyMsg); ok { + // legacy sdk.Msg routing + handler := h.router.Route(ctx, legacyMsg.Route()) + if handler == nil { + return nil, sdkerrors.Wrapf( + sdkerrors.ErrUnknownRequest, "unrecognized message route: %s; message", legacyMsg.Route()) + } + res, err := handler(ctx, msg) + if err != nil { + return nil, err + } + return res, nil + } - return res, nil + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "can't route message %+v", msg) } // MessageHandlerChain defines a chain of handlers that are called one by one until it can be handled. diff --git a/x/wasm/keeper/handler_plugin_encoders.go b/x/wasm/keeper/handler_plugin_encoders.go index 37412b58f0..27c28fc393 100644 --- a/x/wasm/keeper/handler_plugin_encoders.go +++ b/x/wasm/keeper/handler_plugin_encoders.go @@ -11,10 +11,10 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - ibcclienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + ibcclienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" ) type BankEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.BankMsg) ([]sdk.Msg, error) diff --git a/x/wasm/keeper/handler_plugin_encoders_test.go b/x/wasm/keeper/handler_plugin_encoders_test.go index f8cdb0aa51..b29e0b8bfa 100644 --- a/x/wasm/keeper/handler_plugin_encoders_test.go +++ b/x/wasm/keeper/handler_plugin_encoders_test.go @@ -7,9 +7,9 @@ import ( "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" codectypes "github.com/cosmos/cosmos-sdk/codec/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" "github.com/golang/protobuf/proto" "github.com/stretchr/testify/assert" @@ -29,9 +29,9 @@ func TestEncoding(t *testing.T) { addr3 = RandomAccountAddress(t) invalidAddr = "xrnd1d02kd90n38qvr3qb9qof83fn2d2" ) - valAddr := make(sdk.ValAddress, sdk.AddrLen) + valAddr := make(sdk.ValAddress, 20) valAddr[0] = 12 - valAddr2 := make(sdk.ValAddress, sdk.AddrLen) + valAddr2 := make(sdk.ValAddress, 32) valAddr2[1] = 123 jsonMsg := json.RawMessage(`{"foo": 123}`) diff --git a/x/wasm/keeper/handler_plugin_test.go b/x/wasm/keeper/handler_plugin_test.go index 1e677288d5..3e6d83d202 100644 --- a/x/wasm/keeper/handler_plugin_test.go +++ b/x/wasm/keeper/handler_plugin_test.go @@ -13,9 +13,9 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/modules/core/exported" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -191,11 +191,12 @@ func TestSDKMessageHandlerDispatch(t *testing.T) { t.Run(name, func(t *testing.T) { gotMsg = make([]sdk.Msg, 0) router := baseapp.NewRouter() + msgRouter := baseapp.NewMsgServiceRouter() router.AddRoute(spec.srcRoute) // when ctx := sdk.Context{} - h := NewSDKMessageHandler(router, MessageEncoders{Custom: spec.srcEncoder}) + h := NewSDKMessageHandler(router, msgRouter, MessageEncoders{Custom: spec.srcEncoder}) gotEvents, gotData, gotErr := h.DispatchMsg(ctx, myContractAddr, "myPort", myContractMessage) // then @@ -317,8 +318,6 @@ func TestBurnCoinMessageHandlerIntegration(t *testing.T) { ctx, keepers := CreateDefaultTestInput(t) k := keepers.WasmKeeper - before, err := keepers.BankKeeper.TotalSupply(sdk.WrapSDKContext(ctx), &banktypes.QueryTotalSupplyRequest{}) - require.NoError(t, err) example := InstantiateHackatomExampleContract(t, ctx, keepers) // with deposit of 100 stake specs := map[string]struct { @@ -372,6 +371,9 @@ func TestBurnCoinMessageHandlerIntegration(t *testing.T) { }, 0, nil }} + before, err := keepers.BankKeeper.TotalSupply(sdk.WrapSDKContext(ctx), &banktypes.QueryTotalSupplyRequest{}) + require.NoError(t, err) + // when _, err = k.execute(ctx, example.Contract, example.CreatorAddr, nil, nil) diff --git a/x/wasm/keeper/ibc.go b/x/wasm/keeper/ibc.go index 6e9cac7b0f..8b2df7a87c 100644 --- a/x/wasm/keeper/ibc.go +++ b/x/wasm/keeper/ibc.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" + host "github.com/cosmos/ibc-go/modules/core/24-host" ) // bindIbcPort will reserve the port. diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index bd7bfdf03e..3146ae7891 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -2,7 +2,6 @@ package keeper import ( "bytes" - "crypto/sha256" "encoding/binary" "fmt" "math" @@ -14,10 +13,12 @@ import ( "github.com/CosmWasm/wasmd/x/wasm/types" wasmvm "github.com/CosmWasm/wasmvm" wasmvmtypes "github.com/CosmWasm/wasmvm/types" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" + sdkaddress "github.com/cosmos/cosmos-sdk/types/address" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/tendermint/tendermint/crypto" @@ -59,7 +60,7 @@ type WasmVMResponseHandler interface { // Keeper will have a reference to Wasmer with it's own data directory. type Keeper struct { storeKey sdk.StoreKey - cdc codec.Marshaler + cdc codec.Codec accountKeeper types.AccountKeeper bank CoinTransferrer portKeeper types.PortKeeper @@ -77,7 +78,7 @@ type Keeper struct { // NewKeeper creates a new contract Keeper instance // If customEncoders is non-nil, we can use this to override some of the message handler, especially custom func NewKeeper( - cdc codec.Marshaler, + cdc codec.Codec, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace, accountKeeper types.AccountKeeper, @@ -89,6 +90,7 @@ func NewKeeper( capabilityKeeper types.CapabilityKeeper, portSource types.ICS20TransferPortSource, router sdk.Router, + msgRouter *baseapp.MsgServiceRouter, queryRouter GRPCQueryRouter, homeDir string, wasmConfig types.WasmConfig, @@ -112,7 +114,7 @@ func NewKeeper( bank: NewBankCoinTransferrer(bankKeeper), portKeeper: portKeeper, capabilityKeeper: capabilityKeeper, - messenger: NewDefaultMessageHandler(router, channelKeeper, capabilityKeeper, bankKeeper, cdc, portSource), + messenger: NewDefaultMessageHandler(router, msgRouter, channelKeeper, capabilityKeeper, bankKeeper, cdc, portSource), queryGasLimit: wasmConfig.SmartQueryGasLimit, paramSpace: paramSpace, gasRegister: NewDefaultWasmGasRegister(), @@ -201,7 +203,7 @@ func (k Keeper) create(ctx sdk.Context, creator sdk.AccAddress, wasmCode []byte, func (k Keeper) storeCodeInfo(ctx sdk.Context, codeID uint64, codeInfo types.CodeInfo) { store := ctx.KVStore(k.storeKey) // 0x01 | codeID (uint64) -> ContractInfo - store.Set(types.GetCodeKey(codeID), k.cdc.MustMarshalBinaryBare(&codeInfo)) + store.Set(types.GetCodeKey(codeID), k.cdc.MustMarshal(&codeInfo)) } func (k Keeper) importCode(ctx sdk.Context, codeID uint64, codeInfo types.CodeInfo, wasmCode []byte) error { @@ -223,7 +225,7 @@ func (k Keeper) importCode(ctx sdk.Context, codeID uint64, codeInfo types.CodeIn return sdkerrors.Wrapf(types.ErrDuplicate, "duplicate code: %d", codeID) } // 0x01 | codeID (uint64) -> ContractInfo - store.Set(key, k.cdc.MustMarshalBinaryBare(&codeInfo)) + store.Set(key, k.cdc.MustMarshal(&codeInfo)) return nil } @@ -260,7 +262,7 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A return nil, nil, sdkerrors.Wrap(types.ErrNotFound, "code") } var codeInfo types.CodeInfo - k.cdc.MustUnmarshalBinaryBare(bz, &codeInfo) + k.cdc.MustUnmarshal(bz, &codeInfo) if !authZ.CanInstantiateContract(codeInfo.InstantiateConfig, creator) { return nil, nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "can not instantiate") @@ -556,7 +558,7 @@ func (k Keeper) appendToContractHistory(ctx sdk.Context, contractAddr sdk.AccAdd for _, e := range newEntries { pos++ key := types.GetContractCodeHistoryElementKey(contractAddr, pos) - store.Set(key, k.cdc.MustMarshalBinaryBare(&e)) + store.Set(key, k.cdc.MustMarshal(&e)) } } @@ -566,7 +568,7 @@ func (k Keeper) GetContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress) iter := prefixStore.Iterator(nil, nil) for ; iter.Valid(); iter.Next() { var e types.ContractCodeHistoryEntry - k.cdc.MustUnmarshalBinaryBare(iter.Value(), &e) + k.cdc.MustUnmarshal(iter.Value(), &e) r = append(r, e) } return r @@ -581,7 +583,7 @@ func (k Keeper) getLastContractHistoryEntry(ctx sdk.Context, contractAddr sdk.Ac // all contracts have a history panic(fmt.Sprintf("no history for %s", contractAddr.String())) } - k.cdc.MustUnmarshalBinaryBare(iter.Value(), &r) + k.cdc.MustUnmarshal(iter.Value(), &r) return r } @@ -627,14 +629,14 @@ func (k Keeper) contractInstance(ctx sdk.Context, contractAddress sdk.AccAddress return types.ContractInfo{}, types.CodeInfo{}, prefix.Store{}, sdkerrors.Wrap(types.ErrNotFound, "contract") } var contractInfo types.ContractInfo - k.cdc.MustUnmarshalBinaryBare(contractBz, &contractInfo) + k.cdc.MustUnmarshal(contractBz, &contractInfo) codeInfoBz := store.Get(types.GetCodeKey(contractInfo.CodeID)) if codeInfoBz == nil { return contractInfo, types.CodeInfo{}, prefix.Store{}, sdkerrors.Wrap(types.ErrNotFound, "code info") } var codeInfo types.CodeInfo - k.cdc.MustUnmarshalBinaryBare(codeInfoBz, &codeInfo) + k.cdc.MustUnmarshal(codeInfoBz, &codeInfo) prefixStoreKey := types.GetContractStorePrefix(contractAddress) prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), prefixStoreKey) return contractInfo, codeInfo, prefixStore, nil @@ -647,7 +649,7 @@ func (k Keeper) GetContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) if contractBz == nil { return nil } - k.cdc.MustUnmarshalBinaryBare(contractBz, &contract) + k.cdc.MustUnmarshal(contractBz, &contract) return &contract } @@ -659,7 +661,7 @@ func (k Keeper) HasContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress) // storeContractInfo persists the ContractInfo. No secondary index updated here. func (k Keeper) storeContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress, contract *types.ContractInfo) { store := ctx.KVStore(k.storeKey) - store.Set(types.GetContractAddressKey(contractAddress), k.cdc.MustMarshalBinaryBare(contract)) + store.Set(types.GetContractAddressKey(contractAddress), k.cdc.MustMarshal(contract)) } func (k Keeper) IterateContractInfo(ctx sdk.Context, cb func(sdk.AccAddress, types.ContractInfo) bool) { @@ -667,7 +669,7 @@ func (k Keeper) IterateContractInfo(ctx sdk.Context, cb func(sdk.AccAddress, typ iter := prefixStore.Iterator(nil, nil) for ; iter.Valid(); iter.Next() { var contract types.ContractInfo - k.cdc.MustUnmarshalBinaryBare(iter.Value(), &contract) + k.cdc.MustUnmarshal(iter.Value(), &contract) // cb returns true to stop early if cb(iter.Key(), contract) { break @@ -703,7 +705,7 @@ func (k Keeper) GetCodeInfo(ctx sdk.Context, codeID uint64) *types.CodeInfo { if codeInfoBz == nil { return nil } - k.cdc.MustUnmarshalBinaryBare(codeInfoBz, &codeInfo) + k.cdc.MustUnmarshal(codeInfoBz, &codeInfo) return &codeInfo } @@ -717,7 +719,7 @@ func (k Keeper) IterateCodeInfos(ctx sdk.Context, cb func(uint64, types.CodeInfo iter := prefixStore.Iterator(nil, nil) for ; iter.Valid(); iter.Next() { var c types.CodeInfo - k.cdc.MustUnmarshalBinaryBare(iter.Value(), &c) + k.cdc.MustUnmarshal(iter.Value(), &c) // cb returns true to stop early if cb(binary.BigEndian.Uint64(iter.Key()), c) { return @@ -732,7 +734,7 @@ func (k Keeper) GetByteCode(ctx sdk.Context, codeID uint64) ([]byte, error) { if codeInfoBz == nil { return nil, nil } - k.cdc.MustUnmarshalBinaryBare(codeInfoBz, &codeInfo) + k.cdc.MustUnmarshal(codeInfoBz, &codeInfo) return k.wasmVM.GetCode(codeInfo.CodeHash) } @@ -873,42 +875,7 @@ func BuildContractAddress(codeID, instanceID uint64) sdk.AccAddress { contractID := make([]byte, 16) binary.BigEndian.PutUint64(contractID[:8], codeID) binary.BigEndian.PutUint64(contractID[8:], instanceID) - // 20 bytes to work with Cosmos SDK 0.42 (0.43 pushes for 32 bytes) - // TODO: remove truncate if we update to 0.43 before wasmd 1.0 - return Module(types.ModuleName, contractID)[:20] -} - -// Hash and Module is taken from https://github.com/cosmos/cosmos-sdk/blob/v0.43.0-rc2/types/address/hash.go -// (PR #9088 included in Cosmos SDK 0.43 - can be swapped out for the sdk version when we upgrade) - -// Hash creates a new address from address type and key -func Hash(typ string, key []byte) []byte { - hasher := sha256.New() - _, err := hasher.Write([]byte(typ)) - // the error always nil, it's here only to satisfy the io.Writer interface - assertNil(err) - th := hasher.Sum(nil) - - hasher.Reset() - _, err = hasher.Write(th) - assertNil(err) - _, err = hasher.Write(key) - assertNil(err) - return hasher.Sum(nil) -} - -// Module is a specialized version of a composed address for modules. Each module account -// is constructed from a module name and module account key. -func Module(moduleName string, key []byte) []byte { - mKey := append([]byte(moduleName), 0) - return Hash("module", append(mKey, key...)) -} - -// Also from the 0.43 Cosmos SDK... sigh (sdkerrors.AssertNil) -func assertNil(err error) { - if err != nil { - panic(fmt.Errorf("logic error - this should never happen. %w", err)) - } + return sdkaddress.Module(types.ModuleName, contractID) } // GetNextCodeID reads the next sequence id used for storing wasm code. @@ -1038,7 +1005,7 @@ func NewBankCoinTransferrer(keeper types.BankKeeper) BankCoinTransferrer { func (c BankCoinTransferrer) TransferCoins(parentCtx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { em := sdk.NewEventManager() ctx := parentCtx.WithEventManager(em) - if err := c.keeper.SendEnabledCoins(ctx, amt...); err != nil { + if err := c.keeper.IsSendEnabledCoins(ctx, amt...); err != nil { return err } if c.keeper.BlockedAddr(fromAddr) { diff --git a/x/wasm/keeper/keeper_test.go b/x/wasm/keeper/keeper_test.go index 2473b1f697..3f852d566f 100644 --- a/x/wasm/keeper/keeper_test.go +++ b/x/wasm/keeper/keeper_test.go @@ -90,7 +90,7 @@ func TestCreateInvalidWasmCode(t *testing.T) { func TestCreateStoresInstantiatePermission(t *testing.T) { var ( deposit = sdk.NewCoins(sdk.NewInt64Coin("denom", 100000)) - myAddr sdk.AccAddress = bytes.Repeat([]byte{1}, sdk.AddrLen) + myAddr sdk.AccAddress = bytes.Repeat([]byte{1}, 20) ) specs := map[string]struct { @@ -303,11 +303,11 @@ func TestInstantiate(t *testing.T) { // create with no balance is also legal gotContractAddr, _, err := keepers.ContractKeeper.Instantiate(ctx.WithEventManager(em), codeID, creator, nil, initMsgBz, "demo contract 1", nil) require.NoError(t, err) - require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", gotContractAddr.String()) + require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", gotContractAddr.String()) gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x16e8a), gasAfter-gasBefore) + require.Equal(t, uint64(0x12469), gasAfter-gasBefore) } // ensure it is stored properly @@ -337,8 +337,8 @@ func TestInstantiate(t *testing.T) { func TestInstantiateWithDeposit(t *testing.T) { var ( - bob = bytes.Repeat([]byte{1}, sdk.AddrLen) - fred = bytes.Repeat([]byte{2}, sdk.AddrLen) + bob = bytes.Repeat([]byte{1}, 20) + fred = bytes.Repeat([]byte{2}, 20) deposit = sdk.NewCoins(sdk.NewInt64Coin("denom", 100)) initMsg = HackatomExampleInitMsg{Verifier: fred, Beneficiary: bob} @@ -394,9 +394,9 @@ func TestInstantiateWithDeposit(t *testing.T) { func TestInstantiateWithPermissions(t *testing.T) { var ( deposit = sdk.NewCoins(sdk.NewInt64Coin("denom", 100000)) - myAddr = bytes.Repeat([]byte{1}, sdk.AddrLen) - otherAddr = bytes.Repeat([]byte{2}, sdk.AddrLen) - anyAddr = bytes.Repeat([]byte{3}, sdk.AddrLen) + myAddr = bytes.Repeat([]byte{1}, 20) + otherAddr = bytes.Repeat([]byte{2}, 20) + anyAddr = bytes.Repeat([]byte{3}, 20) ) initMsg := HackatomExampleInitMsg{ @@ -504,7 +504,7 @@ func TestExecute(t *testing.T) { addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit) require.NoError(t, err) - require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", addr.String()) + require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", addr.String()) // ensure bob doesn't exist bobAcct := accKeeper.GetAccount(ctx, bob) @@ -541,7 +541,7 @@ func TestExecute(t *testing.T) { // make sure gas is properly deducted from ctx gasAfter := ctx.GasMeter().GasConsumed() if types.EnableGasVerification { - require.Equal(t, uint64(0x17621), gasAfter-gasBefore) + require.Equal(t, uint64(0x1215a), gasAfter-gasBefore) } // ensure bob now exists and got both payments released bobAcct = accKeeper.GetAccount(ctx, bob) @@ -552,21 +552,21 @@ func TestExecute(t *testing.T) { // ensure contract has updated balance contractAcct = accKeeper.GetAccount(ctx, addr) require.NotNil(t, contractAcct) - assert.Equal(t, sdk.Coins(nil), bankKeeper.GetAllBalances(ctx, contractAcct.GetAddress())) + assert.Equal(t, sdk.Coins{}, bankKeeper.GetAllBalances(ctx, contractAcct.GetAddress())) // and events emitted - require.Len(t, em.Events(), 5) + require.Len(t, em.Events(), 9) expEvt := sdk.NewEvent("execute", sdk.NewAttribute("_contract_address", addr.String())) - assert.Equal(t, expEvt, em.Events()[1]) + assert.Equal(t, expEvt, em.Events()[3]) t.Logf("Duration: %v (%d gas)\n", diff, gasAfter-gasBefore) } func TestExecuteWithDeposit(t *testing.T) { var ( - bob = bytes.Repeat([]byte{1}, sdk.AddrLen) - fred = bytes.Repeat([]byte{2}, sdk.AddrLen) + bob = bytes.Repeat([]byte{1}, 20) + fred = bytes.Repeat([]byte{2}, 20) blockedAddr = authtypes.NewModuleAddress(authtypes.FeeCollectorName) deposit = sdk.NewCoins(sdk.NewInt64Coin("denom", 100)) ) @@ -1045,6 +1045,20 @@ func TestMigrateWithDispatchedMessage(t *testing.T) { {"payout": myPayoutAddr}, }, }, + { + "Type": "coin_spent", + "Attr": []dict{ + {"spender": contractAddr}, + {"amount": "100000denom"}, + }, + }, + { + "Type": "coin_received", + "Attr": []dict{ + {"receiver": myPayoutAddr}, + {"amount": "100000denom"}, + }, + }, { "Type": "transfer", "Attr": []dict{ @@ -1171,7 +1185,7 @@ func TestSudo(t *testing.T) { require.NoError(t, err) addr, _, err := keepers.ContractKeeper.Instantiate(ctx, contractID, creator, nil, initMsgBz, "demo contract 3", deposit) require.NoError(t, err) - require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", addr.String()) + require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", addr.String()) // the community is broke _, _, community := keyPubAddr() @@ -1203,7 +1217,7 @@ func TestSudo(t *testing.T) { balance := bankKeeper.GetBalance(ctx, comAcct.GetAddress(), "denom") assert.Equal(t, sdk.NewInt64Coin("denom", 76543), balance) // and events emitted - require.Len(t, em.Events(), 2) + require.Len(t, em.Events(), 4) expEvt := sdk.NewEvent("sudo", sdk.NewAttribute("_contract_address", addr.String())) assert.Equal(t, expEvt, em.Events()[0]) @@ -1692,12 +1706,12 @@ func TestBuildContractAddress(t *testing.T) { "initial contract": { srcCodeID: 1, srcInstanceID: 1, - expectedAddr: "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", + expectedAddr: "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", }, "demo value": { srcCodeID: 1, srcInstanceID: 100, - expectedAddr: "cosmos1mujpjkwhut9yjw4xueyugc02evfv46y04aervg", + expectedAddr: "cosmos1mujpjkwhut9yjw4xueyugc02evfv46y0dtmnz4lh8xxkkdapym9stu5qm8", }, "both below max": { srcCodeID: math.MaxUint32 - 1, @@ -1710,12 +1724,12 @@ func TestBuildContractAddress(t *testing.T) { "codeID > max u32": { srcCodeID: math.MaxUint32 + 1, srcInstanceID: 17, - expectedAddr: "cosmos1673hrexz4h6s0ft04l96ygq667djzh2nvy7fsu", + expectedAddr: "cosmos1673hrexz4h6s0ft04l96ygq667djzh2nsr335kstjp49x5dk6rpsf5t0le", }, "instanceID > max u32": { srcCodeID: 22, srcInstanceID: math.MaxUint32 + 1, - expectedAddr: "cosmos10q3pgfvmeyy0veekgtqhxujxkhz0vm9z65ckqh", + expectedAddr: "cosmos10q3pgfvmeyy0veekgtqhxujxkhz0vm9zmalqgc7evrhj68q3l62qrdfg4m", }, } for name, spec := range specs { diff --git a/x/wasm/keeper/legacy_querier_test.go b/x/wasm/keeper/legacy_querier_test.go index 256c04602c..cac1902bd0 100644 --- a/x/wasm/keeper/legacy_querier_test.go +++ b/x/wasm/keeper/legacy_querier_test.go @@ -221,7 +221,7 @@ func TestLegacyQueryContractHistory(t *testing.T) { keeper := keepers.WasmKeeper var ( - otherAddr sdk.AccAddress = bytes.Repeat([]byte{0x2}, sdk.AddrLen) + otherAddr sdk.AccAddress = bytes.Repeat([]byte{0x2}, 20) ) specs := map[string]struct { diff --git a/x/wasm/keeper/options_test.go b/x/wasm/keeper/options_test.go index 944fa50e8e..da0d29a897 100644 --- a/x/wasm/keeper/options_test.go +++ b/x/wasm/keeper/options_test.go @@ -1,6 +1,8 @@ package keeper import ( + "testing" + "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" "github.com/CosmWasm/wasmd/x/wasm/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" @@ -9,7 +11,6 @@ import ( stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" ) func TestConstructorOptions(t *testing.T) { @@ -76,7 +77,7 @@ func TestConstructorOptions(t *testing.T) { } for name, spec := range specs { t.Run(name, func(t *testing.T) { - k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, nil, ""), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), SupportedFeatures, spec.srcOpt) + k := NewKeeper(nil, nil, paramtypes.NewSubspace(nil, nil, nil, nil, ""), authkeeper.AccountKeeper{}, nil, stakingkeeper.Keeper{}, distributionkeeper.Keeper{}, nil, nil, nil, nil, nil, nil, nil, "tempDir", types.DefaultWasmConfig(), SupportedFeatures, spec.srcOpt) spec.verify(t, k) }) } diff --git a/x/wasm/keeper/proposal_integration_test.go b/x/wasm/keeper/proposal_integration_test.go index ea83e69fc0..f824e470cb 100644 --- a/x/wasm/keeper/proposal_integration_test.go +++ b/x/wasm/keeper/proposal_integration_test.go @@ -5,11 +5,12 @@ import ( "encoding/hex" "encoding/json" "errors" - "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" - wasmvm "github.com/CosmWasm/wasmvm" "io/ioutil" "testing" + "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" + wasmvm "github.com/CosmWasm/wasmvm" + "github.com/CosmWasm/wasmd/x/wasm/types" sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -73,8 +74,8 @@ func TestInstantiateProposal(t *testing.T) { ) var ( - oneAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, sdk.AddrLen) - otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, sdk.AddrLen) + oneAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, 20) + otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, 20) ) src := types.InstantiateContractProposalFixture(func(p *types.InstantiateContractProposal) { p.CodeID = firstCodeID @@ -94,7 +95,7 @@ func TestInstantiateProposal(t *testing.T) { require.NoError(t, err) // then - contractAddr, err := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6") + contractAddr, err := sdk.AccAddressFromBech32("cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr") require.NoError(t, err) cInfo := wasmKeeper.GetContractInfo(ctx, contractAddr) @@ -136,8 +137,8 @@ func TestMigrateProposal(t *testing.T) { require.NoError(t, wasmKeeper.importCode(ctx, 2, codeInfoFixture, wasmCode)) var ( - anyAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, sdk.AddrLen) - otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, sdk.AddrLen) + anyAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, 20) + otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, 20) contractAddr = BuildContractAddress(1, 1) ) @@ -204,7 +205,7 @@ func TestMigrateProposal(t *testing.T) { func TestAdminProposals(t *testing.T) { var ( - otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, sdk.AddrLen) + otherAddress sdk.AccAddress = bytes.Repeat([]byte{0x2}, 20) contractAddr = BuildContractAddress(1, 1) ) wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm") @@ -295,7 +296,7 @@ func TestUpdateParamsProposal(t *testing.T) { var ( cdc = keepers.WasmKeeper.cdc - myAddress sdk.AccAddress = make([]byte, sdk.AddrLen) + myAddress sdk.AccAddress = make([]byte, 20) oneAddressAccessConfig = types.AccessTypeOnlyAddress.With(myAddress) ) diff --git a/x/wasm/keeper/querier.go b/x/wasm/keeper/querier.go index 2640c34884..d9cd3d2342 100644 --- a/x/wasm/keeper/querier.go +++ b/x/wasm/keeper/querier.go @@ -3,10 +3,11 @@ package keeper import ( "context" "encoding/binary" + "runtime/debug" + "github.com/cosmos/cosmos-sdk/codec" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "runtime/debug" "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/cosmos/cosmos-sdk/store/prefix" @@ -18,14 +19,14 @@ import ( var _ types.QueryServer = &grpcQuerier{} type grpcQuerier struct { - cdc codec.Marshaler + cdc codec.Codec storeKey sdk.StoreKey keeper types.ViewKeeper queryGasLimit sdk.Gas } // NewGrpcQuerier constructor -func NewGrpcQuerier(cdc codec.Marshaler, storeKey sdk.StoreKey, keeper types.ViewKeeper, queryGasLimit sdk.Gas) *grpcQuerier { +func NewGrpcQuerier(cdc codec.Codec, storeKey sdk.StoreKey, keeper types.ViewKeeper, queryGasLimit sdk.Gas) *grpcQuerier { return &grpcQuerier{cdc: cdc, storeKey: storeKey, keeper: keeper, queryGasLimit: queryGasLimit} } @@ -63,7 +64,7 @@ func (q grpcQuerier) ContractHistory(c context.Context, req *types.QueryContract pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { if accumulate { var e types.ContractCodeHistoryEntry - if err := q.cdc.UnmarshalBinaryBare(value, &e); err != nil { + if err := q.cdc.Unmarshal(value, &e); err != nil { return false, err } e.Updated = nil // redact @@ -230,7 +231,7 @@ func (q grpcQuerier) Codes(c context.Context, req *types.QueryCodesRequest) (*ty pageRes, err := query.FilteredPaginate(prefixStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { if accumulate { var c types.CodeInfo - if err := q.cdc.UnmarshalBinaryBare(value, &c); err != nil { + if err := q.cdc.Unmarshal(value, &c); err != nil { return false, err } r = append(r, types.CodeInfoResponse{ diff --git a/x/wasm/keeper/query_plugins.go b/x/wasm/keeper/query_plugins.go index 323f76347b..7f1c60de8b 100644 --- a/x/wasm/keeper/query_plugins.go +++ b/x/wasm/keeper/query_plugins.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/CosmWasm/wasmd/x/wasm/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/x/wasm/keeper/query_plugins_test.go b/x/wasm/keeper/query_plugins_test.go index f3e6364179..57cd852857 100644 --- a/x/wasm/keeper/query_plugins_test.go +++ b/x/wasm/keeper/query_plugins_test.go @@ -7,7 +7,7 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "testing" diff --git a/x/wasm/keeper/recurse_test.go b/x/wasm/keeper/recurse_test.go index 81acbdd41e..0e6be16a13 100644 --- a/x/wasm/keeper/recurse_test.go +++ b/x/wasm/keeper/recurse_test.go @@ -102,7 +102,7 @@ func TestGasCostOnQuery(t *testing.T) { }, } - contractAddr, creator, ctx, keeper := initRecurseContract(t) + contractAddr, _, ctx, keeper := initRecurseContract(t) for name, tc := range cases { t.Run(name, func(t *testing.T) { @@ -129,7 +129,7 @@ func TestGasCostOnQuery(t *testing.T) { err = json.Unmarshal(data, &resp) require.NoError(t, err) if recurse.Work == 0 { - assert.Equal(t, len(resp.Hashed), len(creator.String())) + assert.Equal(t, len(resp.Hashed), len(contractAddr.String())) } else { assert.Equal(t, len(resp.Hashed), 32) } @@ -215,9 +215,14 @@ func TestLimitRecursiveQueryGas(t *testing.T) { const ( // Note: about 100 SDK gas (10k wasmer gas) for each round of sha256 - GasWork2k uint64 = 84103 // = NewContractInstanceCosts + x // we have 6x gas used in cpu than in the instance + //GasWork2k uint64 = 84103 // = NewContractInstanceCosts + x // we have 6x gas used in cpu than in the instance + //GasWork2k uint64 = 273_077 // = NewContractInstanceCosts + x // we have 6x gas used in cpu than in the instance + GasWork2k uint64 = 273_139 // This is overhead for calling into a sub-contract GasReturnHashed uint64 = 24 + // TODO: I'm not sure where cosmwasm team came up with this number...tried to calculate it from gas being used in sub-queries + // didn't line up with anything that was obvious + // GasReturnHashed uint64 = 236 ) cases := map[string]struct { @@ -236,6 +241,21 @@ func TestLimitRecursiveQueryGas(t *testing.T) { expectQueriesFromContract: 0, expectedGas: GasWork2k, }, + // TODO: figure out how this calculation works: GasWork2k + 5*(GasWork2k+GasReturnHashed) - 3 + // "recursion 5, lots of work": { + // gasLimit: 4_000_000, + // msg: Recurse{ + // Depth: 5, + // Work: 2000, + // }, + // expectQueriesFromContract: 5, + // // FIXME: why -3 ... confused a bit by calculations, seems like rounding issues + // expectedGas: GasWork2k + 5*(GasWork2k+GasReturnHashed) - 3, + // }, + // this is where we expect an error... + // it has enough gas to run 4 times and die on the 5th (4th time dispatching to sub-contract) + // however, if we don't charge the cpu gas before sub-dispatching, we can recurse over 20 times + // TODO: figure out how to asset how deep it went "recursion 5, lots of work": { gasLimit: 4_000_000, msg: Recurse{ @@ -249,6 +269,7 @@ func TestLimitRecursiveQueryGas(t *testing.T) { // this is where we expect an error... // it has enough gas to run 4 times and die on the 5th (4th time dispatching to sub-contract) // however, if we don't charge the cpu gas before sub-dispatching, we can recurse over 20 times + // TODO: figure out how to asset how deep it went "deep recursion, should die on 5th level": { gasLimit: 400_000, msg: Recurse{ diff --git a/x/wasm/keeper/reflect_test.go b/x/wasm/keeper/reflect_test.go index c2b1296c69..f461bd7097 100644 --- a/x/wasm/keeper/reflect_test.go +++ b/x/wasm/keeper/reflect_test.go @@ -2,11 +2,12 @@ package keeper import ( "encoding/json" - "github.com/golang/protobuf/proto" "io/ioutil" "strings" "testing" + "github.com/golang/protobuf/proto" + "github.com/CosmWasm/wasmd/x/wasm/types" wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/cosmos/cosmos-sdk/codec" @@ -526,7 +527,7 @@ type reflectCustomMsg struct { // toReflectRawMsg encodes an sdk msg using any type with json encoding. // Then wraps it as an opaque message -func toReflectRawMsg(cdc codec.Marshaler, msg sdk.Msg) (wasmvmtypes.CosmosMsg, error) { +func toReflectRawMsg(cdc codec.Codec, msg sdk.Msg) (wasmvmtypes.CosmosMsg, error) { any, err := codectypes.NewAnyWithValue(msg) if err != nil { return wasmvmtypes.CosmosMsg{}, err @@ -545,7 +546,7 @@ func toReflectRawMsg(cdc codec.Marshaler, msg sdk.Msg) (wasmvmtypes.CosmosMsg, e } // reflectEncoders needs to be registered in test setup to handle custom message callbacks -func reflectEncoders(cdc codec.Marshaler) *MessageEncoders { +func reflectEncoders(cdc codec.Codec) *MessageEncoders { return &MessageEncoders{ Custom: fromReflectRawMsg(cdc), } @@ -553,7 +554,7 @@ func reflectEncoders(cdc codec.Marshaler) *MessageEncoders { // fromReflectRawMsg decodes msg.Data to an sdk.Msg using proto Any and json encoding. // this needs to be registered on the Encoders -func fromReflectRawMsg(cdc codec.Marshaler) CustomEncoder { +func fromReflectRawMsg(cdc codec.Codec) CustomEncoder { return func(_sender sdk.AccAddress, msg json.RawMessage) ([]sdk.Msg, error) { var custom reflectCustomMsg err := json.Unmarshal(msg, &custom) diff --git a/x/wasm/keeper/relay_test.go b/x/wasm/keeper/relay_test.go index c5570553be..a72be9f6e0 100644 --- a/x/wasm/keeper/relay_test.go +++ b/x/wasm/keeper/relay_test.go @@ -79,7 +79,7 @@ func TestOnOpenChannel(t *testing.T) { } require.NoError(t, err) // verify gas consumed - const storageCosts = sdk.Gas(0xa9d) + const storageCosts = sdk.Gas(0xad9) assert.Equal(t, spec.expGas, ctx.GasMeter().GasConsumed()-before-storageCosts) }) } @@ -184,7 +184,7 @@ func TestOnConnectChannel(t *testing.T) { } require.NoError(t, err) // verify gas consumed - const storageCosts = sdk.Gas(0xa9d) + const storageCosts = sdk.Gas(0xad9) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) @@ -294,7 +294,7 @@ func TestOnCloseChannel(t *testing.T) { } require.NoError(t, err) // verify gas consumed - const storageCosts = sdk.Gas(0xa9d) + const storageCosts = sdk.Gas(0xad9) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) @@ -455,7 +455,7 @@ func TestOnRecvPacket(t *testing.T) { require.Equal(t, spec.expAck, gotAck) // verify gas consumed - const storageCosts = sdk.Gas(0xa9d) + const storageCosts = sdk.Gas(0xad9) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) @@ -561,7 +561,7 @@ func TestOnAckPacket(t *testing.T) { } require.NoError(t, err) // verify gas consumed - const storageCosts = sdk.Gas(0xa9d) + const storageCosts = sdk.Gas(0xad9) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) @@ -681,7 +681,7 @@ func TestOnTimeoutPacket(t *testing.T) { } require.NoError(t, err) // verify gas consumed - const storageCosts = sdk.Gas(0xa9d) + const storageCosts = sdk.Gas(0xad9) assert.Equal(t, spec.expContractGas, ctx.GasMeter().GasConsumed()-before-storageCosts) // verify msgs dispatched require.Len(t, *capturedMsgs, len(spec.contractResp.Messages)) diff --git a/x/wasm/keeper/submsg_test.go b/x/wasm/keeper/submsg_test.go index d304048e79..290b3ffbef 100644 --- a/x/wasm/keeper/submsg_test.go +++ b/x/wasm/keeper/submsg_test.go @@ -94,9 +94,23 @@ func TestDispatchSubMsgSuccessCase(t *testing.T) { require.NotNil(t, res.Result.Ok) sub := res.Result.Ok assert.Empty(t, sub.Data) - require.Len(t, sub.Events, 1) + require.Len(t, sub.Events, 3) - transfer := sub.Events[0] + coinSpent := sub.Events[0] + assert.Equal(t, "coin_spent", coinSpent.Type) + assert.Equal(t, wasmvmtypes.EventAttribute{ + Key: "spender", + Value: contractAddr.String(), + }, coinSpent.Attributes[0]) + + coinReceived := sub.Events[1] + assert.Equal(t, "coin_received", coinReceived.Type) + assert.Equal(t, wasmvmtypes.EventAttribute{ + Key: "receiver", + Value: fred.String(), + }, coinReceived.Attributes[0]) + + transfer := sub.Events[2] assert.Equal(t, "transfer", transfer.Type) assert.Equal(t, wasmvmtypes.EventAttribute{ Key: "recipient", @@ -223,7 +237,7 @@ func TestDispatchSubMsgErrorHandling(t *testing.T) { // data field is the raw canonical address // QUESTION: why not types.MsgInstantiateContractResponse? difference between calling Router and Service? - require.Len(t, response.Ok.Data, 20) + require.Len(t, response.Ok.Data, 32) resAddr := sdk.AccAddress(response.Ok.Data) assert.Equal(t, eventAddr, resAddr.String()) } @@ -371,7 +385,7 @@ func TestDispatchSubMsgEncodeToNoSdkMsg(t *testing.T) { Bank: nilEncoder, } - ctx, keepers := CreateTestInput(t, false, ReflectFeatures, WithMessageHandler(NewSDKMessageHandler(nil, customEncoders))) + ctx, keepers := CreateTestInput(t, false, ReflectFeatures, WithMessageHandler(NewSDKMessageHandler(nil, nil, customEncoders))) accKeeper, keeper, bankKeeper := keepers.AccountKeeper, keepers.WasmKeeper, keepers.BankKeeper deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000)) diff --git a/x/wasm/keeper/test_common.go b/x/wasm/keeper/test_common.go index e38cad1757..1baa0c3000 100644 --- a/x/wasm/keeper/test_common.go +++ b/x/wasm/keeper/test_common.go @@ -4,6 +4,9 @@ import ( "encoding/binary" "encoding/json" "fmt" + "io/ioutil" + "time" + "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/cosmos/cosmos-sdk/baseapp" @@ -36,11 +39,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" - ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" "github.com/cosmos/cosmos-sdk/x/mint" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/params" @@ -55,6 +53,13 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/cosmos-sdk/x/upgrade" upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" + upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/cosmos/ibc-go/modules/apps/transfer" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/modules/core" + ibchost "github.com/cosmos/ibc-go/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" @@ -62,8 +67,6 @@ import ( "github.com/tendermint/tendermint/libs/rand" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - "io/ioutil" - "time" ) type TestingT interface { @@ -92,7 +95,7 @@ var ModuleBasics = module.NewBasicManager( transfer.AppModuleBasic{}, ) -func MakeTestCodec(t TestingT) codec.Marshaler { +func MakeTestCodec(t TestingT) codec.Codec { return MakeEncodingConfig(t).Marshaler } @@ -139,6 +142,10 @@ type TestKeepers struct { EncodingConfig params2.EncodingConfig } +type MockVersionSetter struct{} + +func (MockVersionSetter) SetProtocolVersion(uint64) {} + // CreateDefaultTestInput common settings for CreateTestInput func CreateDefaultTestInput(t TestingT) (sdk.Context, TestKeepers) { return CreateTestInput(t, false, "staking") @@ -169,6 +176,7 @@ func createTestInput( keyParams := sdk.NewKVStoreKey(paramstypes.StoreKey) tkeyParams := sdk.NewTransientStoreKey(paramstypes.TStoreKey) keyGov := sdk.NewKVStoreKey(govtypes.StoreKey) + keyUpgrade := storetypes.NewKVStoreKey(upgradetypes.StoreKey) keyIBC := sdk.NewKVStoreKey(ibchost.StoreKey) keyCapability := sdk.NewKVStoreKey(capabilitytypes.StoreKey) keyCapabilityTransient := storetypes.NewMemoryStoreKey(capabilitytypes.MemStoreKey) @@ -206,6 +214,7 @@ func createTestInput( paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(capabilitytypes.ModuleName) + paramsKeeper.Subspace(upgradetypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) maccPerms := map[string][]string{ // module account permissions @@ -242,9 +251,10 @@ func createTestInput( ) bankParams := banktypes.DefaultParams() bankKeeper.SetParams(ctx, bankParams) - bankKeeper.SetSupply(ctx, banktypes.NewSupply(sdk.NewCoins( + err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, sdk.NewCoins( sdk.NewCoin("denom", sdk.NewInt(10000)), - ))) + )) + require.NoError(t, err) stakingSubsp, _ := paramsKeeper.GetSubspace(stakingtypes.ModuleName) stakingKeeper := stakingkeeper.NewKeeper(appCodec, keyStaking, authKeeper, bankKeeper, stakingSubsp) stakingKeeper.SetParams(ctx, TestingStakeParams) @@ -260,9 +270,10 @@ func createTestInput( // set some funds ot pay out validatores, based on code from: // https://github.com/cosmos/cosmos-sdk/blob/fea231556aee4d549d7551a6190389c4328194eb/x/distribution/keeper/keeper_test.go#L50-L57 distrAcc := distKeeper.GetDistributionAccount(ctx) - err := bankKeeper.SetBalances(ctx, distrAcc.GetAddress(), sdk.NewCoins( - sdk.NewCoin("stake", sdk.NewInt(2000000)), - )) + stake := sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(2000000))) + err = bankKeeper.MintCoins(ctx, minttypes.ModuleName, stake) + require.NoError(t, err) + err = bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, distrAcc.GetAddress(), stake) require.NoError(t, err) authKeeper.SetModuleAccount(ctx, distrAcc) capabilityKeeper := capabilitykeeper.NewKeeper(appCodec, keyCapability, keyCapabilityTransient) @@ -271,10 +282,14 @@ func createTestInput( ibcSubsp, _ := paramsKeeper.GetSubspace(ibchost.ModuleName) + skipHeights := make(map[int64]bool) + upgradeKeeper := upgradekeeper.NewKeeper(skipHeights, keyUpgrade, appCodec, tempDir, MockVersionSetter{}) + ibcKeeper := ibckeeper.NewKeeper( - appCodec, keyIBC, ibcSubsp, stakingKeeper, scopedIBCKeeper, + appCodec, keyIBC, ibcSubsp, stakingKeeper, upgradeKeeper, scopedIBCKeeper, ) + // TODO: Remove these routes router := baseapp.NewRouter() bh := bank.NewHandler(bankKeeper) router.AddRoute(sdk.NewRoute(banktypes.RouterKey, bh)) @@ -283,6 +298,9 @@ func createTestInput( dh := distribution.NewHandler(distKeeper) router.AddRoute(sdk.NewRoute(distributiontypes.RouterKey, dh)) + // TODO: Figure out how to register new GRPC style services here + msgRouter := baseapp.NewMsgServiceRouter() + querier := baseapp.NewGRPCQueryRouter() banktypes.RegisterQueryServer(querier, bankKeeper) stakingtypes.RegisterQueryServer(querier, stakingkeeper.Querier{Keeper: stakingKeeper}) @@ -301,6 +319,7 @@ func createTestInput( scopedWasmKeeper, wasmtesting.MockIBCTransferKeeper{}, router, + msgRouter, querier, tempDir, wasmConfig, @@ -606,7 +625,9 @@ func createFakeFundedAccount(t TestingT, ctx sdk.Context, am authkeeper.AccountK func fundAccounts(t TestingT, ctx sdk.Context, am authkeeper.AccountKeeper, bank bankkeeper.Keeper, addr sdk.AccAddress, coins sdk.Coins) { acc := am.NewAccountWithAddress(ctx, addr) am.SetAccount(ctx, acc) - require.NoError(t, bank.SetBalances(ctx, addr, coins)) + err := bank.MintCoins(ctx, minttypes.ModuleName, coins) + require.NoError(t, err) + bank.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) } var keyCounter uint64 = 0 diff --git a/x/wasm/keeper/wasmtesting/mock_keepers.go b/x/wasm/keeper/wasmtesting/mock_keepers.go index 5d9f16cd84..a4bf9be810 100644 --- a/x/wasm/keeper/wasmtesting/mock_keepers.go +++ b/x/wasm/keeper/wasmtesting/mock_keepers.go @@ -4,8 +4,8 @@ import ( "github.com/CosmWasm/wasmd/x/wasm/types" sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/modules/core/exported" ) type MockChannelKeeper struct { diff --git a/x/wasm/module.go b/x/wasm/module.go index aa794d2013..34e7339544 100644 --- a/x/wasm/module.go +++ b/x/wasm/module.go @@ -54,14 +54,14 @@ func (AppModuleBasic) Name() string { // DefaultGenesis returns default genesis state as raw bytes for the wasm // module. -func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { return cdc.MustMarshalJSON(&GenesisState{ Params: DefaultParams(), }) } // ValidateGenesis performs genesis state validation for the wasm module. -func (b AppModuleBasic) ValidateGenesis(marshaler codec.JSONMarshaler, config client.TxEncodingConfig, message json.RawMessage) error { +func (b AppModuleBasic) ValidateGenesis(marshaler codec.JSONCodec, config client.TxEncodingConfig, message json.RawMessage) error { var data GenesisState err := marshaler.UnmarshalJSON(message, &data) if err != nil { @@ -95,13 +95,13 @@ func (b AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) // AppModule implements an application module for the wasm module. type AppModule struct { AppModuleBasic - cdc codec.Marshaler + cdc codec.Codec keeper *Keeper validatorSetSource keeper.ValidatorSetSource } // NewAppModule creates a new AppModule object -func NewAppModule(cdc codec.Marshaler, keeper *Keeper, validatorSetSource keeper.ValidatorSetSource) AppModule { +func NewAppModule(cdc codec.Codec, keeper *Keeper, validatorSetSource keeper.ValidatorSetSource) AppModule { return AppModule{ AppModuleBasic: AppModuleBasic{}, cdc: cdc, @@ -134,7 +134,7 @@ func (AppModule) QuerierRoute() string { // InitGenesis performs genesis initialization for the wasm module. It returns // no validator updates. -func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data json.RawMessage) []abci.ValidatorUpdate { +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { var genesisState GenesisState cdc.MustUnmarshalJSON(data, &genesisState) validators, err := InitGenesis(ctx, am.keeper, genesisState, am.validatorSetSource, am.Route().Handler()) @@ -146,7 +146,7 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data j // ExportGenesis returns the exported genesis state as raw bytes for the wasm // module. -func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { gs := ExportGenesis(ctx, am.keeper) return cdc.MustMarshalJSON(gs) } @@ -219,3 +219,6 @@ func ReadWasmConfig(opts servertypes.AppOptions) (types.WasmConfig, error) { } return cfg, nil } + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/wasm/module_test.go b/x/wasm/module_test.go index 9a6341e135..5c0e677460 100644 --- a/x/wasm/module_test.go +++ b/x/wasm/module_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/dvsekhvalnov/jose2go/base64url" "github.com/stretchr/testify/assert" @@ -176,7 +177,7 @@ func TestHandleInstantiate(t *testing.T) { require.NoError(t, err) contractBech32Addr := parseInitResponse(t, res.Data) - require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr) + require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", contractBech32Addr) // this should be standard x/wasm init event, nothing from contract require.Equal(t, 3, len(res.Events), prettyEvents(res.Events)) require.Equal(t, "message", res.Events[0].Type) @@ -234,15 +235,19 @@ func TestHandleExecute(t *testing.T) { require.NoError(t, err) contractBech32Addr := parseInitResponse(t, res.Data) - require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr) - // this should be standard x/wasm message event, init event, plus a bank send event (2), with no custom contract events - require.Equal(t, 4, len(res.Events), prettyEvents(res.Events)) - require.Equal(t, "message", res.Events[0].Type) + require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", contractBech32Addr) + + require.Equal(t, 6, len(res.Events), prettyEvents(res.Events)) + + assert.Equal(t, "message", res.Events[0].Type) assertAttribute(t, "module", "wasm", res.Events[0].Attributes[0]) - require.Equal(t, "transfer", res.Events[1].Type) - require.Equal(t, "instantiate", res.Events[2].Type) - require.Equal(t, "wasm", res.Events[3].Type) - assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[3].Attributes[0]) + assert.Equal(t, "coin_spent", res.Events[1].Type) + assert.Equal(t, "coin_received", res.Events[2].Type) + assert.Equal(t, "transfer", res.Events[3].Type) + assert.Equal(t, "instantiate", res.Events[4].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[4].Attributes[0]) + assert.Equal(t, "wasm", res.Events[5].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[5].Attributes[0]) // ensure bob doesn't exist bobAcct := data.acctKeeper.GetAccount(data.ctx, bob) @@ -271,34 +276,41 @@ func TestHandleExecute(t *testing.T) { // from https://github.com/CosmWasm/cosmwasm/blob/master/contracts/hackatom/src/contract.rs#L167 assertExecuteResponse(t, res.Data, []byte{0xf0, 0x0b, 0xaa}) - // this should be standard message event, plus x/wasm init event, plus 2 bank send event, plus a special event from the contract - require.Equal(t, 6, len(res.Events), prettyEvents(res.Events)) + require.Equal(t, 10, len(res.Events), prettyEvents(res.Events)) assert.Equal(t, "message", res.Events[0].Type) assertAttribute(t, "module", "wasm", res.Events[0].Attributes[0]) - - require.Equal(t, "transfer", res.Events[1].Type) - require.Len(t, res.Events[1].Attributes, 3) - assertAttribute(t, "recipient", contractBech32Addr, res.Events[1].Attributes[0]) - assertAttribute(t, "sender", fred.String(), res.Events[1].Attributes[1]) - assertAttribute(t, "amount", "5000denom", res.Events[1].Attributes[2]) - - assert.Equal(t, "execute", res.Events[2].Type) + assert.Equal(t, "coin_spent", res.Events[1].Type) + assertAttribute(t, "spender", fred.String(), res.Events[1].Attributes[0]) + assert.Equal(t, "coin_received", res.Events[2].Type) + assertAttribute(t, "receiver", contractBech32Addr, res.Events[2].Attributes[0]) + require.Equal(t, "transfer", res.Events[3].Type) + require.Len(t, res.Events[3].Attributes, 3) + assertAttribute(t, "recipient", contractBech32Addr, res.Events[3].Attributes[0]) + assertAttribute(t, "sender", fred.String(), res.Events[3].Attributes[1]) + assertAttribute(t, "amount", "5000denom", res.Events[3].Attributes[2]) + + assert.Equal(t, "execute", res.Events[4].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[4].Attributes[0]) // custom contract event attribute - assert.Equal(t, "wasm", res.Events[3].Type) - assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[3].Attributes[0]) - assertAttribute(t, "action", "release", res.Events[3].Attributes[1]) + assert.Equal(t, "wasm", res.Events[5].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[5].Attributes[0]) + assertAttribute(t, "action", "release", res.Events[5].Attributes[1]) // custom contract event - assert.Equal(t, "wasm-hackatom", res.Events[4].Type) - assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[4].Attributes[0]) - assertAttribute(t, "action", "release", res.Events[4].Attributes[1]) + assert.Equal(t, "wasm-hackatom", res.Events[6].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[6].Attributes[0]) + assertAttribute(t, "action", "release", res.Events[6].Attributes[1]) + + assert.Equal(t, "coin_spent", res.Events[7].Type) + assertAttribute(t, "spender", contractBech32Addr, res.Events[7].Attributes[0]) + assert.Equal(t, "coin_received", res.Events[8].Type) + assertAttribute(t, "receiver", bob.String(), res.Events[8].Attributes[0]) // second transfer (this without conflicting message) - assert.Equal(t, "transfer", res.Events[5].Type) - assertAttribute(t, "recipient", bob.String(), res.Events[5].Attributes[0]) - assertAttribute(t, "sender", contractBech32Addr, res.Events[5].Attributes[1]) - assertAttribute(t, "amount", "105000denom", res.Events[5].Attributes[2]) - // finally, standard x/wasm tag + assert.Equal(t, "transfer", res.Events[9].Type) + assertAttribute(t, "recipient", bob.String(), res.Events[9].Attributes[0]) + assertAttribute(t, "sender", contractBech32Addr, res.Events[9].Attributes[1]) + assertAttribute(t, "amount", "105000denom", res.Events[9].Attributes[2]) // ensure bob now exists and got both payments released bobAcct = data.acctKeeper.GetAccount(data.ctx, bob) @@ -310,7 +322,7 @@ func TestHandleExecute(t *testing.T) { contractAcct = data.acctKeeper.GetAccount(data.ctx, contractAddr) require.NotNil(t, contractAcct) - assert.Equal(t, sdk.Coins(nil), data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress())) + assert.Equal(t, sdk.Coins{}, data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress())) // ensure all contract state is as after init assertCodeList(t, q, data.ctx, 1) @@ -359,7 +371,7 @@ func TestHandleExecuteEscrow(t *testing.T) { res, err = h(data.ctx, &initCmd) require.NoError(t, err) contractBech32Addr := parseInitResponse(t, res.Data) - require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6", contractBech32Addr) + require.Equal(t, "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr", contractBech32Addr) handleMsg := map[string]interface{}{ "release": map[string]interface{}{}, @@ -388,7 +400,7 @@ func TestHandleExecuteEscrow(t *testing.T) { contractAddr, _ := sdk.AccAddressFromBech32(contractBech32Addr) contractAcct := data.acctKeeper.GetAccount(data.ctx, contractAddr) require.NotNil(t, contractAcct) - assert.Equal(t, sdk.Coins(nil), data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress())) + assert.Equal(t, sdk.Coins{}, data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress())) } func TestReadWasmConfig(t *testing.T) { @@ -575,6 +587,9 @@ func createFakeFundedAccount(t *testing.T, ctx sdk.Context, am authkeeper.Accoun _, _, addr := keyPubAddr() acc := am.NewAccountWithAddress(ctx, addr) am.SetAccount(ctx, acc) - require.NoError(t, bankKeeper.SetBalances(ctx, addr, coins)) + err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, coins) + require.NoError(t, err) + err = bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins) + require.NoError(t, err) return addr } diff --git a/x/wasm/relay_pingpong_test.go b/x/wasm/relay_pingpong_test.go index 305c951859..7ec1410459 100644 --- a/x/wasm/relay_pingpong_test.go +++ b/x/wasm/relay_pingpong_test.go @@ -3,6 +3,8 @@ package wasm_test import ( "encoding/json" "fmt" + "testing" + wasmd "github.com/CosmWasm/wasmd/app" wasmibctesting "github.com/CosmWasm/wasmd/x/wasm/ibctesting" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" @@ -12,12 +14,10 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" ) const ( @@ -27,7 +27,8 @@ const ( var doNotTimeout = clienttypes.NewHeight(1, 1111111) -func TestPinPong(t *testing.T) { +func TestPingPong(t *testing.T) { + wasmibctesting.DefaultTestingAppInit = wasmd.SetupTestingApp pingContract := &player{t: t, actor: ping} pongContract := &player{t: t, actor: pong} @@ -61,16 +62,19 @@ func TestPinPong(t *testing.T) { sourcePortID = wasmkeeper.PortIDForContract(pingContractAddr) counterpartyPortID = wasmkeeper.PortIDForContract(pongContractAddr) ) - clientA, clientB, connA, connB := coordinator.SetupClientConnections(chainA, chainB, ibcexported.Tendermint) - connA.NextChannelVersion = ping - connB.NextChannelVersion = pong - channelA, _ := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartyPortID, channeltypes.UNORDERED) + path := wasmibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = sourcePortID + path.EndpointB.ChannelConfig.PortID = counterpartyPortID + path.EndpointA.ChannelConfig.Version = ping + path.EndpointB.ChannelConfig.Version = pong + + coordinator.Setup(path) const startValue uint64 = 100 const rounds = 3 s := startGame{ - ChannelID: channelA.ID, + ChannelID: path.EndpointA.ChannelID, Value: startValue, } startMsg := &wasmtypes.MsgExecuteContract{ @@ -79,20 +83,45 @@ func TestPinPong(t *testing.T) { Msg: s.GetBytes(), } // send message to chainA - err := coordinator.SendMsg(chainA, chainB, clientB, startMsg) + _, err := chainA.SendMsgs(startMsg) require.NoError(t, err) - t.Log("Duplicate messages are due to check/deliver tx calls") - + var ( + activePlayer = ping + pingBallValue = startValue + ) for i := 1; i <= rounds; i++ { t.Logf("++ round: %d\n", i) - err := coordinator.RelayAndAckPendingPackets(chainA, chainB, clientA, clientB) + ball := NewHit(activePlayer, pingBallValue) + + pkg := channeltypes.NewPacket(ball.GetBytes(), uint64(i*2), + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, doNotTimeout, 0) + ack := ball.BuildAck() + + err = path.EndpointA.SendPacket(pkg) + require.NoError(t, err) + err = path.RelayPacket(pkg, ack.GetBytes()) require.NoError(t, err) // switch side - err = coordinator.RelayAndAckPendingPackets(chainB, chainA, clientB, clientA) + activePlayer = counterParty(activePlayer) + ball = NewHit(activePlayer, uint64(i)) + pkg = channeltypes.NewPacket(ball.GetBytes(), uint64(i*2), + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, doNotTimeout, 0) + ack = ball.BuildAck() + + err = path.EndpointB.SendPacket(pkg) + require.NoError(t, err) + err = path.RelayPacket(pkg, ack.GetBytes()) require.NoError(t, err) + + // switch side for next round + activePlayer = counterParty(activePlayer) + pingBallValue++ } + assert.Equal(t, startValue+rounds, pingContract.QueryState(lastBallSentKey)) assert.Equal(t, uint64(rounds), pingContract.QueryState(lastBallReceivedKey)) assert.Equal(t, uint64(rounds+1), pingContract.QueryState(sentBallsCountKey)) @@ -122,9 +151,6 @@ type player struct { // Contracts finds all connected channels and broadcasts a ping message func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { p.execCalls++ - if p.execCalls%2 == 1 { // skip checkTx step because of no rollback with `chain.GetContext()` - return &wasmvmtypes.Response{}, 0, nil - } // start game var start startGame if err := json.Unmarshal(executeMsg, &start); err != nil { @@ -141,35 +167,33 @@ func (p *player) Execute(code wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmt store.Set(lastBallSentKey, sdk.Uint64ToBigEndian(start.Value)) return &wasmvmtypes.Response{ Messages: []wasmvmtypes.SubMsg{ - {Msg: wasmvmtypes.CosmosMsg{ - IBC: &wasmvmtypes.IBCMsg{ - SendPacket: &wasmvmtypes.SendPacketMsg{ - ChannelID: start.ChannelID, - Data: service.GetBytes(), - Timeout: wasmvmtypes.IBCTimeout{Block: &wasmvmtypes.IBCTimeoutBlock{ - Revision: doNotTimeout.RevisionNumber, - Height: doNotTimeout.RevisionHeight, - }}, + { + ReplyOn: wasmvmtypes.ReplyNever, + Msg: wasmvmtypes.CosmosMsg{ + IBC: &wasmvmtypes.IBCMsg{ + SendPacket: &wasmvmtypes.SendPacketMsg{ + ChannelID: start.ChannelID, + Data: service.GetBytes(), + Timeout: wasmvmtypes.IBCTimeout{Block: &wasmvmtypes.IBCTimeoutBlock{ + Revision: doNotTimeout.RevisionNumber, + Height: doNotTimeout.RevisionHeight, + }}, + }, }, }, }, - ReplyOn: wasmvmtypes.ReplyNever, - }, }, }, 0, nil } // OnIBCChannelOpen ensures to accept only configured version -func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { - if msg.GetChannel().Version != p.actor { - return 0, nil - } +func (p player) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { return 0, nil } // OnIBCChannelConnect persists connection endpoints -func (p player) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - p.storeEndpoint(store, msg.GetChannel()) +func (p player) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + p.storeEndpoint(store, connectedChannelsModel{Our: channel.GetChannel().Endpoint, Their: channel.GetChannel().CounterpartyEndpoint}) return &wasmvmtypes.IBCBasicResponse{}, 0, nil } @@ -198,18 +222,18 @@ func (p player) loadEndpoints(store prefix.Store, channelID string) *connectedCh return nil } -func (p player) storeEndpoint(store wasmvm.KVStore, channel wasmvmtypes.IBCChannel) { +func (p player) storeEndpoint(store wasmvm.KVStore, connectedChannel connectedChannelsModel) { var counterparties []connectedChannelsModel if b := store.Get(ibcEndpointsKey); b != nil { require.NoError(p.t, json.Unmarshal(b, &counterparties)) } - counterparties = append(counterparties, connectedChannelsModel{Our: channel.Endpoint, Their: channel.CounterpartyEndpoint}) + counterparties = append(counterparties, connectedChannel) bz, err := json.Marshal(&counterparties) require.NoError(p.t, err) store.Set(ibcEndpointsKey, bz) } -func (p player) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (p player) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { panic("implement me") } @@ -222,11 +246,10 @@ var ( // store keys ) // IBCPacketReceive receives the hit and serves a response hit via `wasmvmtypes.IBCPacket` -func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { +func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { // parse received data and store - packet := msg.Packet var receivedBall hit - if err := json.Unmarshal(packet.Data, &receivedBall); err != nil { + if err := json.Unmarshal(packet.Packet.Data, &receivedBall); err != nil { return &wasmvmtypes.IBCReceiveResponse{ Acknowledgement: hitAcknowledgement{Error: err.Error()}.GetBytes(), // no hit msg, we stop the game @@ -247,7 +270,7 @@ func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, ms nextValue := p.incrementCounter(lastBallSentKey, store) newHit := NewHit(p.actor, nextValue) respHit := &wasmvmtypes.IBCMsg{SendPacket: &wasmvmtypes.SendPacketMsg{ - ChannelID: packet.Src.ChannelID, + ChannelID: packet.Packet.Src.ChannelID, Data: newHit.GetBytes(), Timeout: wasmvmtypes.IBCTimeout{Block: &wasmvmtypes.IBCTimeoutBlock{ Revision: doNotTimeout.RevisionNumber, @@ -259,20 +282,20 @@ func (p player) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, ms return &wasmvmtypes.IBCReceiveResponse{ Acknowledgement: receivedBall.BuildAck().GetBytes(), - Messages: []wasmvmtypes.SubMsg{{Msg: wasmvmtypes.CosmosMsg{IBC: respHit}, ReplyOn: wasmvmtypes.ReplyNever}}, + Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: respHit}}}, }, 0, nil } // OnIBCPacketAcknowledgement handles the packet acknowledgment frame. Stops the game on an any error -func (p player) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (p player) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packetAck wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { // parse received data and store var sentBall hit - if err := json.Unmarshal(msg.OriginalPacket.Data, &sentBall); err != nil { + if err := json.Unmarshal(packetAck.OriginalPacket.Data, &sentBall); err != nil { return nil, 0, err } var ack hitAcknowledgement - if err := json.Unmarshal(msg.Acknowledgement.Data, &ack); err != nil { + if err := json.Unmarshal(packetAck.Acknowledgement.Data, &ack); err != nil { return nil, 0, err } if ack.Success != nil { @@ -303,7 +326,7 @@ func (p player) incrementCounter(key []byte, store wasmvm.KVStore) uint64 { } func (p player) QueryState(key []byte) uint64 { - raw := wasmd.NewTestSupport(p.t, p.chain.App).WasmKeeper().QueryRaw(p.chain.GetContext(), p.contractAddr, key) + raw := wasmd.IBCTestSupport(p.t, p.chain).WasmKeeper().QueryRaw(p.chain.GetContext(), p.contractAddr, key) return sdk.BigEndianToUint64(raw) } diff --git a/x/wasm/relay_test.go b/x/wasm/relay_test.go index e08c78da9b..51c458ad88 100644 --- a/x/wasm/relay_test.go +++ b/x/wasm/relay_test.go @@ -2,6 +2,9 @@ package wasm_test import ( "encoding/json" + "testing" + "time" + wasmd "github.com/CosmWasm/wasmd/app" "github.com/CosmWasm/wasmd/x/wasm/ibctesting" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" @@ -11,17 +14,15 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" - "time" ) func TestFromIBCTransferToContract(t *testing.T) { + ibctesting.DefaultTestingAppInit = wasmd.SetupTestingApp // scenario: a contract can handle the receiving side of an ics20 transfer myContract := receiverContract{t: t} var ( @@ -34,7 +35,7 @@ func TestFromIBCTransferToContract(t *testing.T) { ) coordinator.CommitBlock(chainA, chainB) myContractAddr := chainB.SeedNewContractInstance() - contractAPortID := chainB.ContractInfo(myContractAddr).IBCPortID + contractAPortID := wasmd.ContractInfo(t, chainB, myContractAddr).IBCPortID myContract.contractAddr = myContractAddr myContract.chain = chainB @@ -43,38 +44,54 @@ func TestFromIBCTransferToContract(t *testing.T) { sourcePortID = "transfer" counterpartPortID = contractAPortID ) - clientA, clientB, connA, connB := coordinator.SetupClientConnections(chainA, chainB, ibcexported.Tendermint) - channelA, channelB := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartPortID, channeltypes.UNORDERED) - originalBalance := wasmd.NewTestSupport(t, chainA.App).BankKeeper().GetBalance(chainA.GetContext(), chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = sourcePortID + path.EndpointB.ChannelConfig.PortID = counterpartPortID + + coordinator.Setup(path) + + originalBalance := wasmd.IBCTestSupport(t, chainA).BankKeeper(). + GetBalance(chainA.GetContext(), chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) // with the channels established, let's do a transfer via sdk transfer coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1)) timeoutHeight := clienttypes.NewHeight(1, 110) - msg := ibctransfertypes.NewMsgTransfer(channelA.PortID, channelA.ID, coinToSendToB, chainA.SenderAccount.GetAddress(), chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) - err := coordinator.SendMsg(chainA, chainB, clientB, msg) + msg := ibctransfertypes.NewMsgTransfer( + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coinToSendToB, + chainA.SenderAccount.GetAddress().String(), chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) + _, err := chainA.SendMsgs(msg) require.NoError(t, err) // when relay to chain B and handle Ack on chain A - fungibleTokenPacket := ibctransfertypes.NewFungibleTokenPacketData(coinToSendToB.Denom, coinToSendToB.Amount.Uint64(), chainA.SenderAccount.GetAddress().String(), chainB.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}).GetBytes() - err = coordinator.RelayPacket(chainA, chainB, clientA, clientB, packet, ack) + fungibleTokenPacket := ibctransfertypes.NewFungibleTokenPacketData( + coinToSendToB.Denom, coinToSendToB.Amount.Uint64(), chainA.SenderAccount.GetAddress().String(), + chainB.SenderAccount.GetAddress().String()) + packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0) + ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}).Acknowledgement() + err = path.RelayPacket(packet, ack) require.NoError(t, err) // then - newBalance := wasmd.NewTestSupport(t, chainA.App).BankKeeper().GetBalance(chainA.GetContext(), chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) + newBalance := wasmd.IBCTestSupport(t, chainA).BankKeeper(). + GetBalance(chainA.GetContext(), chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) assert.Equal(t, originalBalance.Sub(coinToSendToB), newBalance) - voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom(channelB.PortID, channelB.ID, coinToSendToB.Denom)).IBCDenom() - bankKeeperB := wasmd.NewTestSupport(t, chainB.App).BankKeeper() + voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom( + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinToSendToB.Denom)).IBCDenom() + bankKeeperB := wasmd.IBCTestSupport(t, chainB).BankKeeper() chainBBalance := bankKeeperB.GetBalance(chainB.GetContext(), chainB.SenderAccount.GetAddress(), voucherDenom) - // note: the contract is called during check and deliverTX but the context used in the contract does not rollback - // so that we got twice the amount - assert.Equal(t, sdk.Coin{Denom: voucherDenom, Amount: coinToSendToB.Amount.Mul(sdk.NewInt(2))}.String(), chainBBalance.String(), bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress())) + assert.Equal(t, + sdk.Coin{Denom: voucherDenom, Amount: coinToSendToB.Amount}.String(), + chainBBalance.String(), + bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress()), + ) } func TestContractCanUseIBCTransferMsg(t *testing.T) { + ibctesting.DefaultTestingAppInit = wasmd.SetupTestingApp // scenario: a contract can start an ibc transfer via ibctransfertypes.NewMsgTransfer // on an existing connection myContract := &sendViaIBCTransferContract{t: t} @@ -96,13 +113,16 @@ func TestContractCanUseIBCTransferMsg(t *testing.T) { counterpartPortID = ibctransfertypes.ModuleName ) - clientA, clientB, connA, connB := coordinator.SetupClientConnections(chainA, chainB, ibcexported.Tendermint) - channelA, channelB := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartPortID, channeltypes.UNORDERED) + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = sourcePortID + path.EndpointB.ChannelConfig.PortID = counterpartPortID + + coordinator.Setup(path) // send message to chainA receiverAddress := chainB.SenderAccount.GetAddress() - timeoutHeight := clienttypes.NewHeight(0, 110) + //timeoutHeight := clienttypes.NewHeight(0, 110) coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) // start transfer from chainA to chainB @@ -110,28 +130,31 @@ func TestContractCanUseIBCTransferMsg(t *testing.T) { Sender: chainA.SenderAccount.GetAddress().String(), Contract: myContractAddr.String(), Msg: startTransfer{ - ChannelID: channelA.ID, + ChannelID: path.EndpointA.ChannelID, CoinsToSend: coinToSendToB, ReceiverAddr: receiverAddress.String(), }.GetBytes(), } - err := coordinator.SendMsg(chainA, chainB, clientB, startMsg) + _, err := chainA.SendMsgs(startMsg) require.NoError(t, err) // relay send - fungibleTokenPacket := ibctransfertypes.NewFungibleTokenPacketData(coinToSendToB.Denom, coinToSendToB.Amount.Uint64(), myContractAddr.String(), receiverAddress.String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - err = coordinator.RelayPacket(chainA, chainB, clientA, clientB, packet, ack.GetBytes()) + err = coordinator.RelayAndAckPendingPackets(path) require.NoError(t, err) // relay committed - bankKeeperB := wasmd.NewTestSupport(t, chainB.App).BankKeeper() - voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom(channelB.PortID, channelB.ID, coinToSendToB.Denom)).IBCDenom() + bankKeeperB := wasmd.IBCTestSupport(t, chainB).BankKeeper() + voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom( + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinToSendToB.Denom)).IBCDenom() newBalance := bankKeeperB.GetBalance(chainB.GetContext(), receiverAddress, voucherDenom) - assert.Equal(t, sdk.NewCoin(voucherDenom, coinToSendToB.Amount).String(), newBalance.String(), bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress())) + assert.Equal(t, + sdk.NewCoin(voucherDenom, coinToSendToB.Amount).String(), + newBalance.String(), + bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress()), + ) } func TestContractCanEmulateIBCTransferMessage(t *testing.T) { + ibctesting.DefaultTestingAppInit = wasmd.SetupTestingApp // scenario: a contract can be the sending side of an ics20 transfer // on an existing connection myContract := &sendEmulatedIBCTransferContract{t: t} @@ -149,17 +172,19 @@ func TestContractCanEmulateIBCTransferMessage(t *testing.T) { myContractAddr := chainA.SeedNewContractInstance() myContract.contractAddr = myContractAddr.String() var ( - sourcePortID = chainA.ContractInfo(myContractAddr).IBCPortID + sourcePortID = wasmd.ContractInfo(t, chainA, myContractAddr).IBCPortID counterpartPortID = ibctransfertypes.ModuleName ) - clientA, clientB, connA, connB := coordinator.SetupClientConnections(chainA, chainB, ibcexported.Tendermint) - channelA, channelB := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartPortID, channeltypes.UNORDERED) + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = sourcePortID + path.EndpointB.ChannelConfig.PortID = counterpartPortID + + coordinator.Setup(path) // send message to chainA receiverAddress := chainB.SenderAccount.GetAddress() - var timeoutHeight clienttypes.Height timeout := uint64(chainB.LastHeader.Header.Time.Add(time.Hour).UnixNano()) // enough time to not timeout coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) @@ -168,30 +193,33 @@ func TestContractCanEmulateIBCTransferMessage(t *testing.T) { Sender: chainA.SenderAccount.GetAddress().String(), Contract: myContractAddr.String(), Msg: startTransfer{ - ChannelID: channelA.ID, + ChannelID: path.EndpointA.ChannelID, CoinsToSend: coinToSendToB, ReceiverAddr: receiverAddress.String(), - ContractIBCPort: chainA.ContractInfo(myContractAddr).IBCPortID, + ContractIBCPort: wasmd.ContractInfo(t, chainA, myContractAddr).IBCPortID, Timeout: timeout, }.GetBytes(), } - err := coordinator.SendMsg(chainA, chainB, clientB, startMsg) + _, err := chainA.SendMsgs(startMsg) require.NoError(t, err) // relay send - fungibleTokenPacket := ibctransfertypes.NewFungibleTokenPacketData(coinToSendToB.Denom, coinToSendToB.Amount.Uint64(), myContractAddr.String(), receiverAddress.String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, timeout) - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - err = coordinator.RelayPacket(chainA, chainB, clientA, clientB, packet, ack.GetBytes()) + err = coordinator.RelayAndAckPendingPackets(path) require.NoError(t, err) // relay committed - bankKeeperB := wasmd.NewTestSupport(t, chainB.App).BankKeeper() - voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom(channelB.PortID, channelB.ID, coinToSendToB.Denom)).IBCDenom() + bankKeeperB := wasmd.IBCTestSupport(t, chainB).BankKeeper() + voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom( + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinToSendToB.Denom)).IBCDenom() newBalance := bankKeeperB.GetBalance(chainB.GetContext(), receiverAddress, voucherDenom) - assert.Equal(t, sdk.NewCoin(voucherDenom, coinToSendToB.Amount).String(), newBalance.String(), bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress())) + assert.Equal(t, + sdk.NewCoin(voucherDenom, coinToSendToB.Amount).String(), + newBalance.String(), + bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress()), + ) } func TestContractCanEmulateIBCTransferMessageWithTimeout(t *testing.T) { + ibctesting.DefaultTestingAppInit = wasmd.SetupTestingApp // scenario: a contract is the sending side of an ics20 transfer but the packet was not received // on the destination chain within the timeout boundaries myContract := &sendEmulatedIBCTransferContract{t: t} @@ -205,55 +233,76 @@ func TestContractCanEmulateIBCTransferMessageWithTimeout(t *testing.T) { chainA = coordinator.GetChain(ibctesting.GetChainID(0)) chainB = coordinator.GetChain(ibctesting.GetChainID(1)) ) - coordinator.CommitBlock(chainA, chainB) myContractAddr := chainA.SeedNewContractInstance() + coordinator.CommitBlock(chainA, chainB) myContract.contractAddr = myContractAddr.String() var ( - sourcePortID = chainA.ContractInfo(myContractAddr).IBCPortID + sourcePortID = wasmd.ContractInfo(t, chainA, myContractAddr).IBCPortID counterpartPortID = ibctransfertypes.ModuleName ) - clientA, clientB, connA, connB := coordinator.SetupClientConnections(chainA, chainB, ibcexported.Tendermint) - channelA, channelB := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartPortID, channeltypes.UNORDERED) + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = sourcePortID + path.EndpointB.ChannelConfig.PortID = counterpartPortID + + coordinator.Setup(path) // start process by sending message to the contract on chainA receiverAddress := chainB.SenderAccount.GetAddress() coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - timeout := uint64(chainB.LastHeader.Header.Time.Add(time.Nanosecond).UnixNano()) // not enough time + + timeoutTime := chainB.LastHeader.Header.Time.Add(time.Nanosecond) + timeout := uint64(timeoutTime.UnixNano()) // custom payload data to be transfered into a proper ICS20 ibc packet startMsg := &types.MsgExecuteContract{ Sender: chainA.SenderAccount.GetAddress().String(), Contract: myContractAddr.String(), Msg: startTransfer{ - ChannelID: channelA.ID, + ChannelID: path.EndpointA.ChannelID, CoinsToSend: coinToSendToB, ReceiverAddr: receiverAddress.String(), - ContractIBCPort: chainA.ContractInfo(myContractAddr).IBCPortID, + ContractIBCPort: wasmd.ContractInfo(t, chainA, myContractAddr).IBCPortID, Timeout: timeout, }.GetBytes(), } - err := coordinator.SendMsg(chainA, chainB, clientB, startMsg) + _, err := chainA.SendMsgs(startMsg) + require.NoError(t, err) + + // Send packet to chainA + require.Equal(t, 1, len(chainA.PendingSendPackets)) + packet := chainA.PendingSendPackets[0] + packet.Sequence++ + err = path.EndpointA.SendPacket(packet) require.NoError(t, err) - err = coordinator.UpdateClient(chainA, chainB, clientA, ibcexported.Tendermint) + // Need to update chainA's client representing chainB to prove missing ack + err = path.EndpointA.UpdateClient() require.NoError(t, err) // timeout packet send (by the relayer) - fungibleTokenPacketData := ibctransfertypes.NewFungibleTokenPacketData(coinToSendToB.Denom, coinToSendToB.Amount.Uint64(), myContractAddr.String(), receiverAddress.String()) + fungibleTokenPacketData := ibctransfertypes.NewFungibleTokenPacketData( + coinToSendToB.Denom, coinToSendToB.Amount.Uint64(), myContractAddr.String(), receiverAddress.String()) var timeoutHeight clienttypes.Height - packet := channeltypes.NewPacket(fungibleTokenPacketData.GetBytes(), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, timeout) - - err = coordinator.TimeoutPacket(chainA, chainB, clientB, packet) + packet = channeltypes.NewPacket(fungibleTokenPacketData.GetBytes(), 1, + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, timeout) + err = coordinator.TimeoutPacket(path, packet) require.NoError(t, err) // then verify account has no vouchers - bankKeeperB := wasmd.NewTestSupport(t, chainB.App).BankKeeper() - voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom(channelB.PortID, channelB.ID, coinToSendToB.Denom)).IBCDenom() + bankKeeperB := wasmd.IBCTestSupport(t, chainB).BankKeeper() + voucherDenom := ibctransfertypes.ParseDenomTrace(ibctransfertypes.GetPrefixedDenom( + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinToSendToB.Denom)).IBCDenom() newBalance := bankKeeperB.GetBalance(chainB.GetContext(), receiverAddress, voucherDenom) - assert.Equal(t, sdk.NewInt64Coin(voucherDenom, 0).String(), newBalance.String(), bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress())) + assert.Equal(t, + sdk.NewInt64Coin(voucherDenom, 0).String(), + newBalance.String(), + bankKeeperB.GetAllBalances(chainB.GetContext(), chainB.SenderAccount.GetAddress()), + ) } func TestContractHandlesChannelClose(t *testing.T) { + ibctesting.DefaultTestingAppInit = wasmd.SetupTestingApp // scenario: a contract is the sending side of an ics20 transfer but the packet was not received // on the destination chain within the timeout boundaries myContractA := &captureCloseContract{} @@ -276,21 +325,22 @@ func TestContractHandlesChannelClose(t *testing.T) { _ = chainB.SeedNewContractInstance() // skip one instance myContractAddrB := chainB.SeedNewContractInstance() var ( - sourcePortID = chainA.ContractInfo(myContractAddrA).IBCPortID - counterpartPortID = chainB.ContractInfo(myContractAddrB).IBCPortID + sourcePortID = wasmd.ContractInfo(t, chainA, myContractAddrA).IBCPortID + counterpartPortID = wasmd.ContractInfo(t, chainB, myContractAddrB).IBCPortID ) - _, _, connA, connB := coordinator.SetupClientConnections(chainA, chainB, ibcexported.Tendermint) - channelA, channelB := coordinator.CreateChannel(chainA, chainB, connA, connB, sourcePortID, counterpartPortID, channeltypes.UNORDERED) + path := ibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig.PortID = sourcePortID + path.EndpointB.ChannelConfig.PortID = counterpartPortID - err := coordinator.ChanCloseInit(chainA, chainB, channelA) - require.NoError(t, err) - assert.True(t, myContractA.closeCalled) + coordinator.Setup(path) - err = coordinator.UpdateClient(chainB, chainA, channelB.ClientID, ibcexported.Tendermint) - require.NoError(t, err) - err = coordinator.ChanCloseConfirm(chainA, chainB, channelA, channelB) + // close channels + err := path.CloseChannels() require.NoError(t, err) + + // Ensure both contracts were closed + assert.True(t, myContractA.closeCalled) assert.True(t, myContractB.closeCalled) } @@ -302,7 +352,7 @@ type captureCloseContract struct { closeCalled bool } -func (c *captureCloseContract) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (c *captureCloseContract) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { c.closeCalled = true return &wasmvmtypes.IBCBasicResponse{}, 1, nil } @@ -333,7 +383,6 @@ func (s *sendViaIBCTransferContract) Execute(code wasmvm.Checksum, env wasmvmtyp } return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil - return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil } var _ wasmtesting.IBCContractCallbacks = &sendEmulatedIBCTransferContract{} @@ -369,11 +418,9 @@ func (s *sendEmulatedIBCTransferContract) Execute(code wasmvm.Checksum, env wasm return &wasmvmtypes.Response{Messages: []wasmvmtypes.SubMsg{{ReplyOn: wasmvmtypes.ReplyNever, Msg: wasmvmtypes.CosmosMsg{IBC: ibcMsg}}}}, 0, nil } -func (c *sendEmulatedIBCTransferContract) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - packet := msg.Packet - +func (c *sendEmulatedIBCTransferContract) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { var data ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packet.Data, &data); err != nil { + if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packet.Packet.Data, &data); err != nil { return nil, 0, err } @@ -413,43 +460,40 @@ type receiverContract struct { chain *ibctesting.TestChain } -func (c *receiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { - packet := msg.Packet - +func (c *receiverContract) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { var src ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packet.Data, &src); err != nil { + if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packet.Packet.Data, &src); err != nil { return nil, 0, err } // call original ibctransfer keeper to not copy all code into this - ibcPacket := toIBCPacket(packet) + ibcPacket := toIBCPacket(packet.Packet) ctx := c.chain.GetContext() // HACK: please note that this is not reverted after checkTX - err := c.chain.TestSupport().TransferKeeper().OnRecvPacket(ctx, ibcPacket, src) + err := wasmd.IBCTestSupport(c.t, c.chain).TransferKeeper().OnRecvPacket(ctx, ibcPacket, src) if err != nil { return nil, 0, sdkerrors.Wrap(err, "within our smart contract") } var log []wasmvmtypes.EventAttribute // note: all events are under `wasm` event type - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}).GetBytes() + ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}).Acknowledgement() return &wasmvmtypes.IBCReceiveResponse{Acknowledgement: ack, Attributes: log}, 0, nil } -func (c *receiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { - +func (c *receiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, packetAck wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { var data ibctransfertypes.FungibleTokenPacketData - if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(msg.OriginalPacket.Data, &data); err != nil { + if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packetAck.OriginalPacket.Data, &data); err != nil { return nil, 0, err } // call original ibctransfer keeper to not copy all code into this var ack channeltypes.Acknowledgement - if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(msg.Acknowledgement.Data, &ack); err != nil { + if err := ibctransfertypes.ModuleCdc.UnmarshalJSON(packetAck.Acknowledgement.Data, &ack); err != nil { return nil, 0, err } // call original ibctransfer keeper to not copy all code into this ctx := c.chain.GetContext() // HACK: please note that this is not reverted after checkTX - ibcPacket := toIBCPacket(msg.OriginalPacket) - err := c.chain.TestSupport().TransferKeeper().OnAcknowledgementPacket(ctx, ibcPacket, data, ack) + ibcPacket := toIBCPacket(packetAck.OriginalPacket) + err := wasmd.IBCTestSupport(c.t, c.chain).TransferKeeper().OnAcknowledgementPacket(ctx, ibcPacket, data, ack) if err != nil { return nil, 0, sdkerrors.Wrap(err, "within our smart contract") } @@ -460,27 +504,27 @@ func (c *receiverContract) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes. // simple helper struct that implements connection setup methods. type contractStub struct{} -func (s *contractStub) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { +func (s *contractStub) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { return 0, nil } -func (s *contractStub) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { return &wasmvmtypes.IBCBasicResponse{}, 0, nil } -func (s *contractStub) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { panic("implement me") } -func (s *contractStub) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { +func (s *contractStub) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { panic("implement me") } -func (s *contractStub) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { return &wasmvmtypes.IBCBasicResponse{}, 0, nil } -func (s *contractStub) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { +func (s *contractStub) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { panic("implement me") } diff --git a/x/wasm/simulation/params.go b/x/wasm/simulation/params.go index aac662f572..cae932ab32 100644 --- a/x/wasm/simulation/params.go +++ b/x/wasm/simulation/params.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/simulation" ) -func ParamChanges(r *rand.Rand, cdc codec.Marshaler) []simtypes.ParamChange { +func ParamChanges(r *rand.Rand, cdc codec.Codec) []simtypes.ParamChange { params := RandomParams(r) return []simtypes.ParamChange{ simulation.NewSimParamChange(types.ModuleName, string(types.ParamStoreKeyUploadAccess), diff --git a/x/wasm/testdata/test.wasm b/x/wasm/testdata/test.wasm new file mode 100644 index 0000000000..a5c95d0f58 Binary files /dev/null and b/x/wasm/testdata/test.wasm differ diff --git a/x/wasm/types/expected_keepers.go b/x/wasm/types/expected_keepers.go index ed357f7690..f14642bd84 100644 --- a/x/wasm/types/expected_keepers.go +++ b/x/wasm/types/expected_keepers.go @@ -2,14 +2,15 @@ package types import ( "context" + sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + connectiontypes "github.com/cosmos/ibc-go/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/modules/core/exported" ) // BankViewKeeper defines a subset of methods implemented by the cosmos-sdk bank keeper @@ -28,7 +29,10 @@ type Burner interface { type BankKeeper interface { BankViewKeeper Burner - SendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error + + IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool + IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error + BlockedAddr(addr sdk.AccAddress) bool SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error } @@ -68,17 +72,16 @@ type StakingKeeper interface { // ChannelKeeper defines the expected IBC channel keeper type ChannelKeeper interface { - GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) + GetChannel(ctx sdk.Context, portID, channelID string) (channel channeltypes.Channel, found bool) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error - ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error GetAllChannels(ctx sdk.Context) (channels []channeltypes.IdentifiedChannel) IterateChannels(ctx sdk.Context, cb func(channeltypes.IdentifiedChannel) bool) } // ClientKeeper defines the expected IBC client keeper type ClientKeeper interface { - GetClientConsensusState(ctx sdk.Context, clientID string) (connection ibcexported.ConsensusState, found bool) + GetClientConsensusState(ctx sdk.Context, clientID string, height ibcexported.Height) (connection ibcexported.ConsensusState, found bool) } // ConnectionKeeper defines the expected IBC connection keeper diff --git a/x/wasm/types/keys.go b/x/wasm/types/keys.go index fe802f28bc..85513120cc 100644 --- a/x/wasm/types/keys.go +++ b/x/wasm/types/keys.go @@ -57,7 +57,7 @@ func GetContractStorePrefix(addr sdk.AccAddress) []byte { func GetContractByCreatedSecondaryIndexKey(contractAddr sdk.AccAddress, c ContractCodeHistoryEntry) []byte { prefix := GetContractByCodeIDSecondaryIndexPrefix(c.CodeID) prefixLen := len(prefix) - r := make([]byte, prefixLen+AbsoluteTxPositionLen+sdk.AddrLen) + r := make([]byte, prefixLen+AbsoluteTxPositionLen+len(contractAddr)) copy(r[0:], prefix) copy(r[prefixLen:], c.Updated.Bytes()) copy(r[prefixLen+AbsoluteTxPositionLen:], contractAddr) @@ -87,7 +87,7 @@ func GetContractCodeHistoryElementKey(contractAddr sdk.AccAddress, pos uint64) [ // GetContractCodeHistoryElementPrefix returns the key prefix for a contract code history entry: `` func GetContractCodeHistoryElementPrefix(contractAddr sdk.AccAddress) []byte { prefixLen := len(ContractCodeHistoryElementPrefix) - r := make([]byte, prefixLen+sdk.AddrLen) + r := make([]byte, prefixLen+len(contractAddr)) copy(r[0:], ContractCodeHistoryElementPrefix) copy(r[prefixLen:], contractAddr) return r diff --git a/x/wasm/types/keys_test.go b/x/wasm/types/keys_test.go index 95ef74ff16..4b9894d91e 100644 --- a/x/wasm/types/keys_test.go +++ b/x/wasm/types/keys_test.go @@ -4,7 +4,6 @@ import ( "bytes" "testing" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" ) @@ -33,7 +32,7 @@ func TestGetContractByCreatedSecondaryIndexKey(t *testing.T) { CodeID: 1, Updated: &AbsoluteTxPosition{2 + 1<<(8*7), 3 + 1<<(8*7)}, } - addr := bytes.Repeat([]byte{4}, sdk.AddrLen) + addr := bytes.Repeat([]byte{4}, 20) got := GetContractByCreatedSecondaryIndexKey(addr, e) exp := []byte{6, // prefix 0, 0, 0, 0, 0, 0, 0, 1, // codeID diff --git a/x/wasm/types/params_test.go b/x/wasm/types/params_test.go index 21b2443c8b..d970282873 100644 --- a/x/wasm/types/params_test.go +++ b/x/wasm/types/params_test.go @@ -13,7 +13,7 @@ import ( func TestValidateParams(t *testing.T) { var ( - anyAddress sdk.AccAddress = make([]byte, sdk.AddrLen) + anyAddress sdk.AccAddress = make([]byte, 20) invalidAddress = "invalid address" ) diff --git a/x/wasm/types/proposal_test.go b/x/wasm/types/proposal_test.go index 0c8d392cfe..05d172a82a 100644 --- a/x/wasm/types/proposal_test.go +++ b/x/wasm/types/proposal_test.go @@ -95,7 +95,7 @@ func TestValidateProposalCommons(t *testing.T) { func TestValidateStoreCodeProposal(t *testing.T) { var ( - anyAddress sdk.AccAddress = bytes.Repeat([]byte{0x0}, sdk.AddrLen) + anyAddress sdk.AccAddress = bytes.Repeat([]byte{0x0}, 20) invalidAddress = "invalid address" ) @@ -489,7 +489,7 @@ func TestProposalStrings(t *testing.T) { exp: `Migrate Contract Proposal: Title: Foo Description: Bar - Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6 + Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr Code id: 1 Run as: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du Msg "{\"verifier\":\"cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du\"}" @@ -500,7 +500,7 @@ func TestProposalStrings(t *testing.T) { exp: `Update Contract Admin Proposal: Title: Foo Description: Bar - Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6 + Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr New Admin: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du `, }, @@ -509,7 +509,7 @@ func TestProposalStrings(t *testing.T) { exp: `Clear Contract Admin Proposal: Title: Foo Description: Bar - Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6 + Contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr `, }, "pin codes": { @@ -606,7 +606,7 @@ funds: [] src: MigrateContractProposalFixture(), exp: `title: Foo description: Bar -contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6 +contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr code_id: 1 msg: '{"verifier":"cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du"}' run_as: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du @@ -617,14 +617,14 @@ run_as: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du exp: `title: Foo description: Bar new_admin: cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du -contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6 +contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr `, }, "clear admin": { src: ClearAdminProposalFixture(), exp: `title: Foo description: Bar -contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6 +contract: cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr `, }, "pin codes": { diff --git a/x/wasm/types/test_fixtures.go b/x/wasm/types/test_fixtures.go index fc721c7d61..071c8c07ec 100644 --- a/x/wasm/types/test_fixtures.go +++ b/x/wasm/types/test_fixtures.go @@ -160,7 +160,7 @@ func MsgInstantiateContractFixture(mutators ...func(*MsgInstantiateContract)) *M func MsgExecuteContractFixture(mutators ...func(*MsgExecuteContract)) *MsgExecuteContract { const ( anyAddress = "cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du" - firstContractAddress = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + firstContractAddress = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" ) r := &MsgExecuteContract{ Sender: anyAddress, @@ -193,7 +193,7 @@ func StoreCodeProposalFixture(mutators ...func(*StoreCodeProposal)) *StoreCodePr func InstantiateContractProposalFixture(mutators ...func(p *InstantiateContractProposal)) *InstantiateContractProposal { var ( - anyValidAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, sdk.AddrLen) + anyValidAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, 20) initMsg = struct { Verifier sdk.AccAddress `json:"verifier"` @@ -228,7 +228,7 @@ func InstantiateContractProposalFixture(mutators ...func(p *InstantiateContractP func MigrateContractProposalFixture(mutators ...func(p *MigrateContractProposal)) *MigrateContractProposal { var ( - anyValidAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, sdk.AddrLen) + anyValidAddress sdk.AccAddress = bytes.Repeat([]byte{0x1}, 20) migMsg = struct { Verifier sdk.AccAddress `json:"verifier"` @@ -240,7 +240,7 @@ func MigrateContractProposalFixture(mutators ...func(p *MigrateContractProposal) panic(err) } const ( - contractAddr = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + contractAddr = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" anyAddress = "cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du" ) p := &MigrateContractProposal{ @@ -260,7 +260,7 @@ func MigrateContractProposalFixture(mutators ...func(p *MigrateContractProposal) func UpdateAdminProposalFixture(mutators ...func(p *UpdateAdminProposal)) *UpdateAdminProposal { const ( - contractAddr = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + contractAddr = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" anyAddress = "cosmos1qyqszqgpqyqszqgpqyqszqgpqyqszqgpjnp7du" ) @@ -277,7 +277,7 @@ func UpdateAdminProposalFixture(mutators ...func(p *UpdateAdminProposal)) *Updat } func ClearAdminProposalFixture(mutators ...func(p *ClearAdminProposal)) *ClearAdminProposal { - const contractAddr = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhuc53mp6" + const contractAddr = "cosmos14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9s4hmalr" p := &ClearAdminProposal{ Title: "Foo", Description: "Bar", diff --git a/x/wasm/types/tx_test.go b/x/wasm/types/tx_test.go index 1b901a4f5e..d86a11b12b 100644 --- a/x/wasm/types/tx_test.go +++ b/x/wasm/types/tx_test.go @@ -13,9 +13,7 @@ import ( const firstCodeID = 1 func TestStoreCodeValidation(t *testing.T) { - bad, err := sdk.AccAddressFromHex("012345") - require.NoError(t, err) - badAddress := bad.String() + badAddress := "badaddress" // proper address size goodAddress := sdk.AccAddress(make([]byte, 20)).String() @@ -77,9 +75,7 @@ func TestStoreCodeValidation(t *testing.T) { } func TestInstantiateContractValidation(t *testing.T) { - bad, err := sdk.AccAddressFromHex("012345") - require.NoError(t, err) - badAddress := bad.String() + badAddress := "badaddress" // proper address size goodAddress := sdk.AccAddress(make([]byte, 20)).String() @@ -184,9 +180,7 @@ func TestInstantiateContractValidation(t *testing.T) { } func TestExecuteContractValidation(t *testing.T) { - bad, err := sdk.AccAddressFromHex("012345") - require.NoError(t, err) - badAddress := bad.String() + badAddress := "badaddress" // proper address size goodAddress := sdk.AccAddress(make([]byte, 20)).String() @@ -293,9 +287,7 @@ func TestExecuteContractValidation(t *testing.T) { } func TestMsgUpdateAdministrator(t *testing.T) { - bad, err := sdk.AccAddressFromHex("012345") - require.NoError(t, err) - badAddress := bad.String() + badAddress := "badaddress" // proper address size goodAddress := sdk.AccAddress(make([]byte, 20)).String() otherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x1}, 20)).String() @@ -365,9 +357,7 @@ func TestMsgUpdateAdministrator(t *testing.T) { } func TestMsgClearAdministrator(t *testing.T) { - bad, err := sdk.AccAddressFromHex("012345") - require.NoError(t, err) - badAddress := bad.String() + badAddress := "badaddress" // proper address size goodAddress := sdk.AccAddress(make([]byte, 20)).String() anotherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x2}, 20)).String() @@ -416,9 +406,7 @@ func TestMsgClearAdministrator(t *testing.T) { } func TestMsgMigrateContract(t *testing.T) { - bad, err := sdk.AccAddressFromHex("012345") - require.NoError(t, err) - badAddress := bad.String() + badAddress := "badaddress" // proper address size goodAddress := sdk.AccAddress(make([]byte, 20)).String() anotherGoodAddress := sdk.AccAddress(bytes.Repeat([]byte{0x2}, 20)).String() diff --git a/x/wasm/types/types_test.go b/x/wasm/types/types_test.go index e90081c64a..108224a164 100644 --- a/x/wasm/types/types_test.go +++ b/x/wasm/types/types_test.go @@ -2,6 +2,10 @@ package types import ( "context" + "strings" + "testing" + "time" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" @@ -11,9 +15,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/rand" - "strings" - "testing" - "time" ) func TestContractInfoValidateBasic(t *testing.T) { @@ -170,8 +171,8 @@ func TestContractInfoSetExtension(t *testing.T) { } func TestContractInfoMarshalUnmarshal(t *testing.T) { - var myAddr sdk.AccAddress = rand.Bytes(sdk.AddrLen) - var myOtherAddr sdk.AccAddress = rand.Bytes(sdk.AddrLen) + var myAddr sdk.AccAddress = rand.Bytes(20) + var myOtherAddr sdk.AccAddress = rand.Bytes(20) var anyPos = AbsoluteTxPosition{BlockHeight: 1, TxIndex: 2} anyTime := time.Now().UTC() @@ -196,11 +197,11 @@ func TestContractInfoMarshalUnmarshal(t *testing.T) { govtypes.RegisterInterfaces(interfaceRegistry) // when encode - bz, err := marshaler.MarshalBinaryBare(&src) + bz, err := marshaler.Marshal(&src) require.NoError(t, err) // and decode var dest ContractInfo - err = marshaler.UnmarshalBinaryBare(bz, &dest) + err = marshaler.Unmarshal(bz, &dest) // then require.NoError(t, err) assert.Equal(t, src, dest) @@ -291,7 +292,7 @@ func TestContractInfoReadExtension(t *testing.T) { func TestNewEnv(t *testing.T) { myTime := time.Unix(0, 1619700924259075000) t.Logf("++ unix: %d", myTime.UnixNano()) - var myContractAddr sdk.AccAddress = randBytes(sdk.AddrLen) + var myContractAddr sdk.AccAddress = randBytes(20) specs := map[string]struct { srcCtx sdk.Context exp wasmvmtypes.Env diff --git a/x/wasm/wasmtesting/coin_transferrer.go b/x/wasm/wasmtesting/coin_transferrer.go new file mode 100644 index 0000000000..497ecc747f --- /dev/null +++ b/x/wasm/wasmtesting/coin_transferrer.go @@ -0,0 +1,14 @@ +package wasmtesting + +import sdk "github.com/cosmos/cosmos-sdk/types" + +type MockCoinTransferrer struct { + TransferCoinsFn func(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error +} + +func (m *MockCoinTransferrer) TransferCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { + if m.TransferCoinsFn == nil { + panic("not expected to be called") + } + return m.TransferCoinsFn(ctx, fromAddr, toAddr, amt) +} diff --git a/x/wasm/wasmtesting/messenger.go b/x/wasm/wasmtesting/messenger.go new file mode 100644 index 0000000000..ae964011d7 --- /dev/null +++ b/x/wasm/wasmtesting/messenger.go @@ -0,0 +1,35 @@ +package wasmtesting + +import ( + "errors" + + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MockMessageHandler struct { + DispatchMsgFn func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) +} + +func (m *MockMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + return m.DispatchMsgFn(ctx, contractAddr, contractIBCPortID, msg) +} + +func NewCapturingMessageHandler() (*MockMessageHandler, *[]wasmvmtypes.CosmosMsg) { + var messages []wasmvmtypes.CosmosMsg + return &MockMessageHandler{ + DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + messages = append(messages, msg) + // return one data item so that this doesn't cause an error in submessage processing (it takes the first element from data) + return nil, [][]byte{{1}}, nil + }, + }, &messages +} + +func NewErroringMessageHandler() *MockMessageHandler { + return &MockMessageHandler{ + DispatchMsgFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + return nil, nil, errors.New("test, ignore") + }, + } +} diff --git a/x/wasm/wasmtesting/mock_engine.go b/x/wasm/wasmtesting/mock_engine.go new file mode 100644 index 0000000000..1a100f2d8d --- /dev/null +++ b/x/wasm/wasmtesting/mock_engine.go @@ -0,0 +1,343 @@ +package wasmtesting + +import ( + "bytes" + "crypto/sha256" + + "github.com/CosmWasm/wasmd/x/wasm/types" + wasmvm "github.com/CosmWasm/wasmvm" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/tendermint/tendermint/libs/rand" +) + +var _ types.WasmerEngine = &MockWasmer{} + +// MockWasmer implements types.WasmerEngine for testing purpose. One or multiple messages can be stubbed. +// Without a stub function a panic is thrown. +type MockWasmer struct { + CreateFn func(codeID wasmvm.WasmCode) (wasmvm.Checksum, error) + AnalyzeCodeFn func(codeID wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) + InstantiateFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) + ExecuteFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) + QueryFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) ([]byte, uint64, error) + MigrateFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) + SudoFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) + ReplyFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) + GetCodeFn func(codeID wasmvm.Checksum) (wasmvm.WasmCode, error) + CleanupFn func() + IBCChannelOpenFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (uint64, error) + IBCChannelConnectFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCChannelCloseFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCPacketReceiveFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCReceiveResponse, uint64, error) + IBCPacketAckFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCPacketTimeoutFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.IBCBasicResponse, uint64, error) + PinFn func(checksum wasmvm.Checksum) error + UnpinFn func(checksum wasmvm.Checksum) error + GetMetricsFn func() (*wasmvmtypes.Metrics, error) +} + +func (m *MockWasmer) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (uint64, error) { + if m.IBCChannelOpenFn == nil { + panic("not supposed to be called!") + } + return m.IBCChannelOpenFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCChannelConnectFn == nil { + panic("not supposed to be called!") + } + return m.IBCChannelConnectFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCChannelCloseFn == nil { + panic("not supposed to be called!") + } + return m.IBCChannelCloseFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResponse, uint64, error) { + if m.IBCPacketReceiveFn == nil { + panic("not supposed to be called!") + } + return m.IBCPacketReceiveFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCPacketAckFn == nil { + panic("not supposed to be called!") + } + return m.IBCPacketAckFn(codeID, env, ack, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCPacketTimeoutFn == nil { + panic("not supposed to be called!") + } + return m.IBCPacketTimeoutFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) Create(codeID wasmvm.WasmCode) (wasmvm.Checksum, error) { + if m.CreateFn == nil { + panic("not supposed to be called!") + } + return m.CreateFn(codeID) +} + +func (m *MockWasmer) AnalyzeCode(codeID wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) { + if m.AnalyzeCodeFn == nil { + panic("not supposed to be called!") + } + return m.AnalyzeCodeFn(codeID) +} + +func (m *MockWasmer) Instantiate(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + if m.InstantiateFn == nil { + panic("not supposed to be called!") + } + return m.InstantiateFn(codeID, env, info, initMsg, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) Execute(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + if m.ExecuteFn == nil { + panic("not supposed to be called!") + } + return m.ExecuteFn(codeID, env, info, executeMsg, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) Query(codeID wasmvm.Checksum, env wasmvmtypes.Env, queryMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) ([]byte, uint64, error) { + if m.QueryFn == nil { + panic("not supposed to be called!") + } + return m.QueryFn(codeID, env, queryMsg, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) Migrate(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + if m.MigrateFn == nil { + panic("not supposed to be called!") + } + return m.MigrateFn(codeID, env, migrateMsg, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) Sudo(codeID wasmvm.Checksum, env wasmvmtypes.Env, sudoMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + if m.SudoFn == nil { + panic("not supposed to be called!") + } + return m.SudoFn(codeID, env, sudoMsg, store, goapi, querier, gasMeter, gasLimit) + +} + +func (m *MockWasmer) Reply(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) { + if m.ReplyFn == nil { + panic("not supposed to be called!") + } + return m.ReplyFn(codeID, env, reply, store, goapi, querier, gasMeter, gasLimit) +} + +func (m *MockWasmer) GetCode(codeID wasmvm.Checksum) (wasmvm.WasmCode, error) { + if m.GetCodeFn == nil { + panic("not supposed to be called!") + } + return m.GetCodeFn(codeID) +} + +func (m *MockWasmer) Cleanup() { + if m.CleanupFn == nil { + panic("not supposed to be called!") + } + m.CleanupFn() +} + +func (m *MockWasmer) Pin(checksum wasmvm.Checksum) error { + if m.PinFn == nil { + panic("not supposed to be called!") + } + return m.PinFn(checksum) +} + +func (m *MockWasmer) Unpin(checksum wasmvm.Checksum) error { + if m.UnpinFn == nil { + panic("not supposed to be called!") + } + return m.UnpinFn(checksum) +} + +func (m *MockWasmer) GetMetrics() (*wasmvmtypes.Metrics, error) { + if m.GetMetricsFn == nil { + panic("not expected to be called") + } + return m.GetMetricsFn() +} + +var AlwaysPanicMockWasmer = &MockWasmer{} + +// SelfCallingInstMockWasmer prepares a Wasmer mock that calls itself on instantiation. +func SelfCallingInstMockWasmer(executeCalled *bool) *MockWasmer { + return &MockWasmer{ + + CreateFn: func(code wasmvm.WasmCode) (wasmvm.Checksum, error) { + anyCodeID := bytes.Repeat([]byte{0x1}, 32) + return anyCodeID, nil + }, + InstantiateFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, initMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { + return &wasmvmtypes.Response{ + Messages: []wasmvmtypes.SubMsg{ + {Msg: wasmvmtypes.CosmosMsg{ + Wasm: &wasmvmtypes.WasmMsg{ + Execute: &wasmvmtypes.ExecuteMsg{ContractAddr: env.Contract.Address, Msg: []byte(`{}`)}}}, + }, + }, + }, 1, nil + }, + AnalyzeCodeFn: WithoutIBCAnalyzeFn, + ExecuteFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, info wasmvmtypes.MessageInfo, executeMsg []byte, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64) (*wasmvmtypes.Response, uint64, error) { + *executeCalled = true + return &wasmvmtypes.Response{}, 1, nil + }, + } +} + +// IBCContractCallbacks defines the methods from wasmvm to interact with the wasm contract. +// A mock contract would implement the interface to fully simulate a wasm contract's behaviour. +type IBCContractCallbacks interface { + IBCChannelOpen( + codeID wasmvm.Checksum, + env wasmvmtypes.Env, + channel wasmvmtypes.IBCChannelOpenMsg, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + ) (uint64, error) + + IBCChannelConnect( + codeID wasmvm.Checksum, + env wasmvmtypes.Env, + channel wasmvmtypes.IBCChannelConnectMsg, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + ) (*wasmvmtypes.IBCBasicResponse, uint64, error) + + IBCChannelClose( + codeID wasmvm.Checksum, + env wasmvmtypes.Env, + channel wasmvmtypes.IBCChannelCloseMsg, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + ) (*wasmvmtypes.IBCBasicResponse, uint64, error) + + IBCPacketReceive( + codeID wasmvm.Checksum, + env wasmvmtypes.Env, + packet wasmvmtypes.IBCPacketReceiveMsg, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + ) (*wasmvmtypes.IBCReceiveResponse, uint64, error) + + IBCPacketAck( + codeID wasmvm.Checksum, + env wasmvmtypes.Env, + ack wasmvmtypes.IBCPacketAckMsg, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + ) (*wasmvmtypes.IBCBasicResponse, uint64, error) + + IBCPacketTimeout( + codeID wasmvm.Checksum, + env wasmvmtypes.Env, + packet wasmvmtypes.IBCPacketTimeoutMsg, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + ) (*wasmvmtypes.IBCBasicResponse, uint64, error) +} + +type contractExecutable interface { + Execute( + codeID wasmvm.Checksum, + env wasmvmtypes.Env, + info wasmvmtypes.MessageInfo, + executeMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + ) (*wasmvmtypes.Response, uint64, error) +} + +//MakeInstantiable adds some noop functions to not fail when contract is used for instantiation +func MakeInstantiable(m *MockWasmer) { + m.CreateFn = HashOnlyCreateFn + m.InstantiateFn = NoOpInstantiateFn + m.AnalyzeCodeFn = WithoutIBCAnalyzeFn +} + +//MakeIBCInstantiable adds some noop functions to not fail when contract is used for instantiation +func MakeIBCInstantiable(m *MockWasmer) { + MakeInstantiable(m) + m.AnalyzeCodeFn = HasIBCAnalyzeFn +} + +// NewIBCContractMockWasmer prepares a mocked wasm_engine for testing with an IBC contract test type. +// It is safe to use the mock with store code and instantiate functions in keeper as is also prepared +// with stubs. Execute is optional. When implemented by the Go test contract then it can be used with +// the mock. +func NewIBCContractMockWasmer(c IBCContractCallbacks) *MockWasmer { + m := &MockWasmer{ + IBCChannelOpenFn: c.IBCChannelOpen, + IBCChannelConnectFn: c.IBCChannelConnect, + IBCChannelCloseFn: c.IBCChannelClose, + IBCPacketReceiveFn: c.IBCPacketReceive, + IBCPacketAckFn: c.IBCPacketAck, + IBCPacketTimeoutFn: c.IBCPacketTimeout, + } + MakeIBCInstantiable(m) + if e, ok := c.(contractExecutable); ok { // optional function + m.ExecuteFn = e.Execute + } + return m +} + +func HashOnlyCreateFn(code wasmvm.WasmCode) (wasmvm.Checksum, error) { + if code == nil { + return nil, sdkerrors.Wrap(types.ErrInvalid, "wasm code must not be nil") + } + hash := sha256.Sum256(code) + return hash[:], nil +} + +func NoOpInstantiateFn(wasmvm.Checksum, wasmvmtypes.Env, wasmvmtypes.MessageInfo, []byte, wasmvm.KVStore, wasmvm.GoAPI, wasmvm.Querier, wasmvm.GasMeter, uint64) (*wasmvmtypes.Response, uint64, error) { + return &wasmvmtypes.Response{}, 0, nil +} + +func NoOpCreateFn(_ wasmvm.WasmCode) (wasmvm.Checksum, error) { + return rand.Bytes(32), nil +} + +func HasIBCAnalyzeFn(wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) { + return &wasmvmtypes.AnalysisReport{ + HasIBCEntryPoints: true, + }, nil +} + +func WithoutIBCAnalyzeFn(wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) { + return &wasmvmtypes.AnalysisReport{}, nil +} diff --git a/x/wasm/wasmtesting/mock_keepers.go b/x/wasm/wasmtesting/mock_keepers.go new file mode 100644 index 0000000000..a4bf9be810 --- /dev/null +++ b/x/wasm/wasmtesting/mock_keepers.go @@ -0,0 +1,111 @@ +package wasmtesting + +import ( + "github.com/CosmWasm/wasmd/x/wasm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/modules/core/exported" +) + +type MockChannelKeeper struct { + GetChannelFn func(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) + GetNextSequenceSendFn func(ctx sdk.Context, portID, channelID string) (uint64, bool) + SendPacketFn func(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error + ChanCloseInitFn func(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error + GetAllChannelsFn func(ctx sdk.Context) []channeltypes.IdentifiedChannel + IterateChannelsFn func(ctx sdk.Context, cb func(channeltypes.IdentifiedChannel) bool) +} + +func (m *MockChannelKeeper) GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) { + if m.GetChannelFn == nil { + panic("not supposed to be called!") + } + return m.GetChannelFn(ctx, srcPort, srcChan) +} + +func (m *MockChannelKeeper) GetAllChannels(ctx sdk.Context) []channeltypes.IdentifiedChannel { + if m.GetAllChannelsFn == nil { + panic("not supposed to be called!") + } + return m.GetAllChannelsFn(ctx) +} + +func (m *MockChannelKeeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { + if m.GetNextSequenceSendFn == nil { + panic("not supposed to be called!") + } + return m.GetNextSequenceSendFn(ctx, portID, channelID) +} + +func (m *MockChannelKeeper) SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { + if m.SendPacketFn == nil { + panic("not supposed to be called!") + } + return m.SendPacketFn(ctx, channelCap, packet) +} + +func (m *MockChannelKeeper) ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error { + if m.ChanCloseInitFn == nil { + panic("not supposed to be called!") + } + return m.ChanCloseInitFn(ctx, portID, channelID, chanCap) +} + +func (m *MockChannelKeeper) IterateChannels(ctx sdk.Context, cb func(channeltypes.IdentifiedChannel) bool) { + if m.IterateChannelsFn == nil { + panic("not expected to be called") + } + m.IterateChannelsFn(ctx, cb) +} + +func MockChannelKeeperIterator(s []channeltypes.IdentifiedChannel) func(ctx sdk.Context, cb func(channeltypes.IdentifiedChannel) bool) { + return func(ctx sdk.Context, cb func(channeltypes.IdentifiedChannel) bool) { + for _, channel := range s { + stop := cb(channel) + if stop { + break + } + } + } +} + +type MockCapabilityKeeper struct { + GetCapabilityFn func(ctx sdk.Context, name string) (*capabilitytypes.Capability, bool) + ClaimCapabilityFn func(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error + AuthenticateCapabilityFn func(ctx sdk.Context, capability *capabilitytypes.Capability, name string) bool +} + +func (m MockCapabilityKeeper) GetCapability(ctx sdk.Context, name string) (*capabilitytypes.Capability, bool) { + if m.GetCapabilityFn == nil { + panic("not supposed to be called!") + } + return m.GetCapabilityFn(ctx, name) +} + +func (m MockCapabilityKeeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error { + if m.ClaimCapabilityFn == nil { + panic("not supposed to be called!") + } + return m.ClaimCapabilityFn(ctx, cap, name) +} + +func (m MockCapabilityKeeper) AuthenticateCapability(ctx sdk.Context, capability *capabilitytypes.Capability, name string) bool { + if m.AuthenticateCapabilityFn == nil { + panic("not supposed to be called!") + } + return m.AuthenticateCapabilityFn(ctx, capability, name) +} + +var _ types.ICS20TransferPortSource = &MockIBCTransferKeeper{} + +type MockIBCTransferKeeper struct { + GetPortFn func(ctx sdk.Context) string +} + +func (m MockIBCTransferKeeper) GetPort(ctx sdk.Context) string { + if m.GetPortFn == nil { + panic("not expected to be called") + } + return m.GetPortFn(ctx) +} diff --git a/x/wasm/wasmtesting/msg_dispatcher.go b/x/wasm/wasmtesting/msg_dispatcher.go new file mode 100644 index 0000000000..b05d25dfc8 --- /dev/null +++ b/x/wasm/wasmtesting/msg_dispatcher.go @@ -0,0 +1,25 @@ +package wasmtesting + +import ( + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MockMsgDispatcher struct { + DispatchMessagesFn func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error + DispatchSubmessagesFn func(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) +} + +func (m MockMsgDispatcher) DispatchMessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.CosmosMsg) error { + if m.DispatchMessagesFn == nil { + panic("not expected to be called") + } + return m.DispatchMessagesFn(ctx, contractAddr, ibcPort, msgs) +} + +func (m MockMsgDispatcher) DispatchSubmessages(ctx sdk.Context, contractAddr sdk.AccAddress, ibcPort string, msgs []wasmvmtypes.SubMsg) ([]byte, error) { + if m.DispatchSubmessagesFn == nil { + panic("not expected to be called") + } + return m.DispatchSubmessagesFn(ctx, contractAddr, ibcPort, msgs) +} diff --git a/x/wasm/wasmtesting/query_handler.go b/x/wasm/wasmtesting/query_handler.go new file mode 100644 index 0000000000..52cf97d31f --- /dev/null +++ b/x/wasm/wasmtesting/query_handler.go @@ -0,0 +1,17 @@ +package wasmtesting + +import ( + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MockQueryHandler struct { + HandleQueryFn func(ctx sdk.Context, request wasmvmtypes.QueryRequest, caller sdk.AccAddress) ([]byte, error) +} + +func (m *MockQueryHandler) HandleQuery(ctx sdk.Context, caller sdk.AccAddress, request wasmvmtypes.QueryRequest) ([]byte, error) { + if m.HandleQueryFn == nil { + panic("not expected to be called") + } + return m.HandleQueryFn(ctx, request, caller) +} diff --git a/x/wasm/wasmtesting/store.go b/x/wasm/wasmtesting/store.go new file mode 100644 index 0000000000..6548c8bae2 --- /dev/null +++ b/x/wasm/wasmtesting/store.go @@ -0,0 +1,26 @@ +package wasmtesting + +import ( + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// MockCommitMultiStore mock with a CacheMultiStore to capture commits +type MockCommitMultiStore struct { + sdk.CommitMultiStore + Committed []bool +} + +func (m *MockCommitMultiStore) CacheMultiStore() storetypes.CacheMultiStore { + m.Committed = append(m.Committed, false) + return &mockCMS{m, &m.Committed[len(m.Committed)-1]} +} + +type mockCMS struct { + sdk.CommitMultiStore + committed *bool +} + +func (m *mockCMS) Write() { + *m.committed = true +}