diff --git a/app/app.go b/app/app.go index afe378dc..8cb0de71 100644 --- a/app/app.go +++ b/app/app.go @@ -6,6 +6,7 @@ import ( "github.com/confio/tgrade/x/globalfee" "github.com/confio/tgrade/x/poe" poekeeper "github.com/confio/tgrade/x/poe/keeper" + poestakingadapter "github.com/confio/tgrade/x/poe/stakingadapter" "github.com/confio/tgrade/x/twasm" twasmkeeper "github.com/confio/tgrade/x/twasm/keeper" "github.com/cosmos/cosmos-sdk/baseapp" @@ -40,7 +41,6 @@ import ( 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" @@ -64,11 +64,6 @@ import ( 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" @@ -129,7 +124,7 @@ var ( poe.AppModuleBasic{}, bank.AppModuleBasic{}, capability.AppModuleBasic{}, - staking.AppModuleBasic{}, + //staking.AppModuleBasic{}, mint.AppModuleBasic{}, distr.AppModuleBasic{}, gov.NewAppModuleBasic( @@ -139,7 +134,6 @@ var ( params.AppModuleBasic{}, twasm.AppModuleBasic{}, crisis.AppModuleBasic{}, - slashing.AppModuleBasic{}, ibc.AppModuleBasic{}, upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, @@ -190,10 +184,7 @@ type TgradeApp struct { 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 @@ -228,8 +219,8 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bApp.SetInterfaceRegistry(interfaceRegistry) keys := sdk.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, - minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, + authtypes.StoreKey, banktypes.StoreKey, + minttypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, wasm.StoreKey, poe.StoreKey, @@ -258,6 +249,7 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest scopedIBCKeeper := app.capabilityKeeper.ScopeToModule(ibchost.ModuleName) scopedTransferKeeper := app.capabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName) scopedWasmKeeper := app.capabilityKeeper.ScopeToModule(twasm.ModuleName) + stakingKeeper := poestakingadapter.StakingAdapter{} // add keepers app.accountKeeper = authkeeper.NewAccountKeeper( @@ -266,34 +258,18 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest 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, + 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.upgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath) - // 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, scopedIBCKeeper, + appCodec, keys[ibchost.StoreKey], app.getSubspace(ibchost.ModuleName), stakingKeeper, scopedIBCKeeper, ) twasmConfig, err := twasm.ReadWasmConfig(appOpts) @@ -305,7 +281,6 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest 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(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.ibcKeeper.ClientKeeper)) @@ -321,9 +296,10 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest ibcRouter := porttypes.NewRouter() ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) + slashingAdapter := poestakingadapter.SlashingAdapter{} // create evidence keeper with router evidenceKeeper := evidencekeeper.NewKeeper( - appCodec, keys[evidencetypes.StoreKey], &app.stakingKeeper, app.slashingKeeper, + appCodec, keys[evidencetypes.StoreKey], stakingKeeper, slashingAdapter, ) app.evidenceKeeper = *evidenceKeeper @@ -335,7 +311,7 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // if we want to allow any custom callbacks supportedFeatures := "staking,stargate" - stakingAdapter := poekeeper.NewStakingAdapter(&app.poeKeeper, app.twasmKeeper.GetContractKeeper()) + stakingAdapter := stakingKeeper app.twasmKeeper = twasmkeeper.NewKeeper( appCodec, keys[twasm.StoreKey], @@ -369,7 +345,7 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest app.getSubspace(govtypes.ModuleName), app.accountKeeper, app.bankKeeper, - &stakingKeeper, + stakingKeeper, govRouter, ) @@ -391,11 +367,8 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest crisis.NewAppModule(&app.crisisKeeper, skipGenesisInvariants), 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), - twasm.NewAppModule(appCodec, &app.twasmKeeper, app.stakingKeeper), + twasm.NewAppModule(appCodec, &app.twasmKeeper, stakingKeeper), evidence.NewAppModule(app.evidenceKeeper), ibc.NewAppModule(app.ibcKeeper), params.NewAppModule(app.paramsKeeper), @@ -422,8 +395,8 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // wasm module should be a the end as it can call other modules functionality direct or via message dispatching during // genesis phase. For example bank transfer, auth account check, staking, ... app.mm.SetOrderInitGenesis( - capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, - slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, + capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, + govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, ibchost.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, // wasm after ibc transfer twasm.ModuleName, @@ -448,11 +421,8 @@ func NewTgradeApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest capability.NewAppModule(appCodec, *app.capabilityKeeper), 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), - twasm.NewAppModule(appCodec, &app.twasmKeeper, app.stakingKeeper), + twasm.NewAppModule(appCodec, &app.twasmKeeper, stakingKeeper), evidence.NewAppModule(app.evidenceKeeper), ibc.NewAppModule(app.ibcKeeper), transferModule, @@ -623,10 +593,7 @@ func initParamsKeeper(appCodec codec.BinaryMarshaler, legacyAmino *codec.LegacyA 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) diff --git a/app/app_test.go b/app/app_test.go index 36826864..02ab4f7a 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -22,6 +22,7 @@ import ( var emptyWasmOpts []wasm.Option = nil func TestTgradeExport(t *testing.T) { + t.Skip("Alex, this is not implemented") db := db.NewMemDB() gapp := NewTgradeApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, EmptyBaseAppOptions{}, emptyWasmOpts) genesisState := NewDefaultGenesisState() diff --git a/app/export.go b/app/export.go index 33f3231e..291e9f6f 100644 --- a/app/export.go +++ b/app/export.go @@ -1,16 +1,7 @@ package app 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 @@ -18,176 +9,177 @@ import ( func (app *TgradeApp) 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 + panic("Alex, not implemented") + //// 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 *TgradeApp) 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(iter.Key()[1:]) - 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 - }, - ) -} +//func (app *TgradeApp) 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(iter.Key()[1:]) +// 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/app/test_access.go b/app/test_access.go index 56711696..ff502863 100644 --- a/app/test_access.go +++ b/app/test_access.go @@ -9,7 +9,6 @@ import ( 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" ) type TestSupport struct { @@ -44,10 +43,6 @@ func (s TestSupport) ScopedTransferKeeper() capabilitykeeper.ScopedKeeper { return s.app.scopedTransferKeeper } -func (s TestSupport) StakingKeeper() stakingkeeper.Keeper { - return s.app.stakingKeeper -} - func (s TestSupport) BankKeeper() bankkeeper.Keeper { return s.app.bankKeeper } diff --git a/app/test_helpers.go b/app/test_helpers.go index 5ce7be0d..199be0e6 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -228,49 +228,49 @@ func createIncrementalAccounts(accNum int) []sdk.AccAddress { } // AddTestAddrsFromPubKeys adds the addresses into the TgradeApp providing only the public keys. -func AddTestAddrsFromPubKeys(app *TgradeApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt sdk.Int) { - initCoins := sdk.NewCoins(sdk.NewCoin(app.stakingKeeper.BondDenom(ctx), accAmt)) - - setTotalSupply(app, ctx, accAmt, len(pubKeys)) - - // fill all the addresses with some coins, set the loose pool tokens simultaneously - for _, pubKey := range pubKeys { - saveAccount(app, ctx, sdk.AccAddress(pubKey.Address()), initCoins) - } -} - -// setTotalSupply provides the total supply based on accAmt * totalAccounts. -func setTotalSupply(app *TgradeApp, 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...))) -} +//func AddTestAddrsFromPubKeys(app *TgradeApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt sdk.Int) { +// initCoins := sdk.NewCoins(sdk.NewCoin(app.stakingKeeper.BondDenom(ctx), accAmt)) +// +// setTotalSupply(app, ctx, accAmt, len(pubKeys)) +// +// // fill all the addresses with some coins, set the loose pool tokens simultaneously +// for _, pubKey := range pubKeys { +// saveAccount(app, ctx, sdk.AccAddress(pubKey.Address()), initCoins) +// } +//} +// +//// setTotalSupply provides the total supply based on accAmt * totalAccounts. +//func setTotalSupply(app *TgradeApp, 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...))) +//} // AddTestAddrs constructs and returns accNum amount of accounts with an // initial balance of accAmt in random order -func AddTestAddrs(app *TgradeApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress { - return addTestAddrs(app, ctx, accNum, accAmt, createRandomAccounts) -} +//func AddTestAddrs(app *TgradeApp, 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 *TgradeApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress { - return addTestAddrs(app, ctx, accNum, accAmt, createIncrementalAccounts) -} - -func addTestAddrs(app *TgradeApp, 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)) - setTotalSupply(app, ctx, accAmt, accNum) - - // fill all the addresses with some coins, set the loose pool tokens simultaneously - for _, addr := range testAddrs { - saveAccount(app, ctx, addr, initCoins) - } - - return testAddrs -} +//func AddTestAddrsIncremental(app *TgradeApp, ctx sdk.Context, accNum int, accAmt sdk.Int) []sdk.AccAddress { +// return addTestAddrs(app, ctx, accNum, accAmt, createIncrementalAccounts) +//} + +//func addTestAddrs(app *TgradeApp, 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)) +// setTotalSupply(app, ctx, accAmt, accNum) +// +// // fill all the addresses with some coins, set the loose pool tokens simultaneously +// for _, addr := range testAddrs { +// saveAccount(app, ctx, addr, initCoins) +// } +// +// return testAddrs +//} // saveAccount saves the provided account into the TgradeApp with balance based on initCoins. func saveAccount(app *TgradeApp, ctx sdk.Context, addr sdk.AccAddress, initCoins sdk.Coins) { diff --git a/docs/proto/proto-docs.md b/docs/proto/proto-docs.md index 88c93b81..79870bfc 100644 --- a/docs/proto/proto-docs.md +++ b/docs/proto/proto-docs.md @@ -25,6 +25,8 @@ - [confio/poe/v1beta1/query.proto](#confio/poe/v1beta1/query.proto) - [QueryContractAddressRequest](#confio.poe.v1beta1.QueryContractAddressRequest) - [QueryContractAddressResponse](#confio.poe.v1beta1.QueryContractAddressResponse) + - [QueryUnbondingPeriodRequest](#confio.poe.v1beta1.QueryUnbondingPeriodRequest) + - [QueryUnbondingPeriodResponse](#confio.poe.v1beta1.QueryUnbondingPeriodResponse) - [Query](#confio.poe.v1beta1.Query) @@ -152,7 +154,7 @@ Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `MinimumGasPrices` | [QueryMinimumGasPricesRequest](#confio.globalfee.v1beta1.QueryMinimumGasPricesRequest) | [QueryMinimumGasPricesResponse](#confio.globalfee.v1beta1.QueryMinimumGasPricesResponse) | | GET|/globalfee/v1beta1/minimum_gas_prices| +| `MinimumGasPrices` | [QueryMinimumGasPricesRequest](#confio.globalfee.v1beta1.QueryMinimumGasPricesRequest) | [QueryMinimumGasPricesResponse](#confio.globalfee.v1beta1.QueryMinimumGasPricesResponse) | | GET|/tgrade/globalfee/v1beta1/minimum_gas_prices| @@ -295,6 +297,34 @@ Query/ContractAddress RPC method. + + + +### QueryUnbondingPeriodRequest +QueryUnbondingPeriodRequest is request type for the Query/UnbondingPeriod RPC +method + + + + + + + + +### QueryUnbondingPeriodResponse +QueryUnbondingPeriodResponse is response type for the Query/UnbondingPeriod +RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `time` | [google.protobuf.Duration](#google.protobuf.Duration) | | Time is the time that must pass | +| `height` | [uint64](#uint64) | | Height is the number of blocks that must pass | + + + + + @@ -309,7 +339,10 @@ Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ContractAddress` | [QueryContractAddressRequest](#confio.poe.v1beta1.QueryContractAddressRequest) | [QueryContractAddressResponse](#confio.poe.v1beta1.QueryContractAddressResponse) | | GET|/poe/v1beta1/contract/{contract_type}| +| `ContractAddress` | [QueryContractAddressRequest](#confio.poe.v1beta1.QueryContractAddressRequest) | [QueryContractAddressResponse](#confio.poe.v1beta1.QueryContractAddressResponse) | ContractAddress queries the address for one of the PoE contracts | GET|/tgrade/poe/v1beta1/contract/{contract_type}| +| `Validators` | [.cosmos.staking.v1beta1.QueryValidatorsRequest](#cosmos.staking.v1beta1.QueryValidatorsRequest) | [.cosmos.staking.v1beta1.QueryValidatorsResponse](#cosmos.staking.v1beta1.QueryValidatorsResponse) | Validators queries all validators that match the given status. | GET|/tgrade/poe/v1beta1/validators| +| `Validator` | [.cosmos.staking.v1beta1.QueryValidatorRequest](#cosmos.staking.v1beta1.QueryValidatorRequest) | [.cosmos.staking.v1beta1.QueryValidatorResponse](#cosmos.staking.v1beta1.QueryValidatorResponse) | Validator queries validator info for given validator address. | GET|/tgrade/poe/v1beta1/validators/{validator_addr}| +| `UnbondingPeriod` | [QueryUnbondingPeriodRequest](#confio.poe.v1beta1.QueryUnbondingPeriodRequest) | [QueryUnbondingPeriodResponse](#confio.poe.v1beta1.QueryUnbondingPeriodResponse) | Validator queries validator info for given validator address. | GET|/tgrade/poe/v1beta1/staking/unbonding| @@ -607,8 +640,8 @@ Query provides defines the gRPC querier service | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `PrivilegedContracts` | [QueryPrivilegedContractsRequest](#confio.twasm.v1beta1.QueryPrivilegedContractsRequest) | [QueryPrivilegedContractsResponse](#confio.twasm.v1beta1.QueryPrivilegedContractsResponse) | PrivilegedContracts returns all privileged contracts | GET|/twasm/v1beta1/contracts/privileged| -| `ContractsByPrivilegeType` | [QueryContractsByPrivilegeTypeRequest](#confio.twasm.v1beta1.QueryContractsByPrivilegeTypeRequest) | [QueryContractsByPrivilegeTypeResponse](#confio.twasm.v1beta1.QueryContractsByPrivilegeTypeResponse) | ContractsByPrivilegeType returns all contracts that have registered for the privilege type | GET|/twasm/v1beta1/contracts/privilege/{privilege_type}| +| `PrivilegedContracts` | [QueryPrivilegedContractsRequest](#confio.twasm.v1beta1.QueryPrivilegedContractsRequest) | [QueryPrivilegedContractsResponse](#confio.twasm.v1beta1.QueryPrivilegedContractsResponse) | PrivilegedContracts returns all privileged contracts | GET|/tgrade/twasm/v1beta1/contracts/privileged| +| `ContractsByPrivilegeType` | [QueryContractsByPrivilegeTypeRequest](#confio.twasm.v1beta1.QueryContractsByPrivilegeTypeRequest) | [QueryContractsByPrivilegeTypeResponse](#confio.twasm.v1beta1.QueryContractsByPrivilegeTypeResponse) | ContractsByPrivilegeType returns all contracts that have registered for the privilege type | GET|/tgrade/twasm/v1beta1/contracts/privilege/{privilege_type}| diff --git a/go.mod b/go.mod index 104415ed..2d816b5c 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/tidwall/sjson v1.1.6 google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c google.golang.org/grpc v1.38.0 + google.golang.org/protobuf v1.26.0 // indirect gopkg.in/yaml.v2 v2.4.0 ) diff --git a/proto/confio/globalfee/v1beta1/query.proto b/proto/confio/globalfee/v1beta1/query.proto index 0a623cc0..2d4025be 100644 --- a/proto/confio/globalfee/v1beta1/query.proto +++ b/proto/confio/globalfee/v1beta1/query.proto @@ -11,7 +11,8 @@ option go_package = "github.com/confio/tgrade/x/globalfee/types"; service Query { rpc MinimumGasPrices(QueryMinimumGasPricesRequest) returns (QueryMinimumGasPricesResponse) { - option (google.api.http).get = "/globalfee/v1beta1/minimum_gas_prices"; + option (google.api.http).get = + "/tgrade/globalfee/v1beta1/minimum_gas_prices"; } } diff --git a/proto/confio/poe/v1beta1/poe.proto b/proto/confio/poe/v1beta1/poe.proto index 31fab3ac..c8474aed 100644 --- a/proto/confio/poe/v1beta1/poe.proto +++ b/proto/confio/poe/v1beta1/poe.proto @@ -2,8 +2,13 @@ syntax = "proto3"; package confio.poe.v1beta1; import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "cosmos_proto/cosmos.proto"; import "cosmos/base/v1beta1/coin.proto"; -import "cosmwasm/wasm/v1beta1/genesis.proto"; +import "cosmos/staking/v1beta1/staking.proto"; +import "tendermint/types/types.proto"; option go_package = "github.com/confio/tgrade/x/poe/types"; diff --git a/proto/confio/poe/v1beta1/query.proto b/proto/confio/poe/v1beta1/query.proto index 1d3528df..b427fad5 100644 --- a/proto/confio/poe/v1beta1/query.proto +++ b/proto/confio/poe/v1beta1/query.proto @@ -3,16 +3,39 @@ package confio.poe.v1beta1; import "cosmos/base/query/v1beta1/pagination.proto"; import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; import "google/api/annotations.proto"; import "confio/poe/v1beta1/poe.proto"; +import "cosmos/staking/v1beta1/staking.proto"; +import "cosmos/staking/v1beta1/query.proto"; option go_package = "github.com/confio/tgrade/x/poe/types"; // Query defines the gRPC querier service. service Query { + // ContractAddress queries the address for one of the PoE contracts rpc ContractAddress(QueryContractAddressRequest) returns (QueryContractAddressResponse) { - option (google.api.http).get = "/poe/v1beta1/contract/{contract_type}"; + option (google.api.http).get = + "/tgrade/poe/v1beta1/contract/{contract_type}"; + } + + // Validators queries all validators that match the given status. + rpc Validators(cosmos.staking.v1beta1.QueryValidatorsRequest) + returns (cosmos.staking.v1beta1.QueryValidatorsResponse) { + option (google.api.http).get = "/tgrade/poe/v1beta1/validators"; + } + + // Validator queries validator info for given validator address. + rpc Validator(cosmos.staking.v1beta1.QueryValidatorRequest) + returns (cosmos.staking.v1beta1.QueryValidatorResponse) { + option (google.api.http).get = + "/tgrade/poe/v1beta1/validators/{validator_addr}"; + } + // Validator queries validator info for given validator address. + rpc UnbondingPeriod(QueryUnbondingPeriodRequest) + returns (QueryUnbondingPeriodResponse) { + option (google.api.http).get = "/tgrade/poe/v1beta1/staking/unbonding"; } } @@ -28,4 +51,18 @@ message QueryContractAddressRequest { // QueryContractAddressRequest is the response type for the // Query/ContractAddress RPC method. -message QueryContractAddressResponse { string address = 1; } \ No newline at end of file +message QueryContractAddressResponse { string address = 1; } + +// QueryUnbondingPeriodRequest is request type for the Query/UnbondingPeriod RPC +// method +message QueryUnbondingPeriodRequest {} + +// QueryUnbondingPeriodResponse is response type for the Query/UnbondingPeriod +// RPC method +message QueryUnbondingPeriodResponse { + // Time is the time that must pass + google.protobuf.Duration time = 1 + [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true ]; + // Height is the number of blocks that must pass + uint64 height = 2; +} diff --git a/proto/confio/twasm/v1beta1/query.proto b/proto/confio/twasm/v1beta1/query.proto index 40798bbb..b368a6da 100644 --- a/proto/confio/twasm/v1beta1/query.proto +++ b/proto/confio/twasm/v1beta1/query.proto @@ -14,14 +14,14 @@ service Query { // PrivilegedContracts returns all privileged contracts rpc PrivilegedContracts(QueryPrivilegedContractsRequest) returns (QueryPrivilegedContractsResponse) { - option (google.api.http).get = "/twasm/v1beta1/contracts/privileged"; + option (google.api.http).get = "/tgrade/twasm/v1beta1/contracts/privileged"; } // ContractsByPrivilegeType returns all contracts that have registered for the // privilege type rpc ContractsByPrivilegeType(QueryContractsByPrivilegeTypeRequest) returns (QueryContractsByPrivilegeTypeResponse) { option (google.api.http).get = - "/twasm/v1beta1/contracts/privilege/{privilege_type}"; + "/tgrade/twasm/v1beta1/contracts/privilege/{privilege_type}"; } } diff --git a/testing/README.md b/testing/README.md index a6c6a2c2..00ef4c46 100644 --- a/testing/README.md +++ b/testing/README.md @@ -1,12 +1,26 @@ # Testing -Test framework for system tests. Uses: - +Test framework for system tests. +Starts and interacts with a (multi node) blockchain in Go. +Supports +* CLI +* Servers +* Events +* RPC + +Uses: +* testify * gjson - +* sjson Server and client side are executed on the host machine -## Execute a single test +## Developer +### Test strategy +System tests cover the full stack via cli and a running (multi node) network. They are more expensive (in terms of time/ cpu) +to run compared to unit or integration tests. +Therefore, we focus on the **critical path** and do not cover every condition. + +### Execute a single test ```sh go test -tags system_test -count=1 -v ./testing --run TestSmokeTest -verbose diff --git a/testing/cli.go b/testing/cli.go index a42ef528..4b571a3c 100644 --- a/testing/cli.go +++ b/testing/cli.go @@ -140,6 +140,11 @@ func (c TgradeCli) QueryTotalSupply(denom string) int64 { return gjson.Get(raw, "amount").Int() } +// QueryValidator queries the validator for the given operator address. Returns json response +func (c TgradeCli) QueryValidator(addr string) string { + return c.CustomQuery("q", "poe", "validator", addr) +} + // RequireTxSuccess require the received response to contain the success code func RequireTxSuccess(t *testing.T, got string) { t.Helper() diff --git a/testing/poe_test.go b/testing/poe_test.go index 6c81654b..63295525 100644 --- a/testing/poe_test.go +++ b/testing/poe_test.go @@ -91,6 +91,46 @@ func TestProofOfEngagementSetup(t *testing.T) { } } assert.True(t, distributed, "no tokens distributed") + + // And when moniker updated + myAddr := cli.GetKeyAddr("node0") + txResult := cli.CustomCommand("tx", "poe", "edit-validator", "--moniker=newMoniker", "--from=node0") + RequireTxSuccess(t, txResult) + qResult = cli.QueryValidator(myAddr) + assert.Equal(t, "newMoniker", gjson.Get(qResult, "description.moniker").String()) +} + +func TestPoEQueries(t *testing.T) { + sut.ResetChain(t) + cli := NewTgradeCli(t, sut, verbose) + sut.StartChain(t) + specs := map[string]struct { + query []string + assert func(t *testing.T, qResult string) + }{ + "unbonding period": { + query: []string{"q", "poe", "unbonding-period"}, + assert: func(t *testing.T, qResult string) { + gotTime := gjson.Get(qResult, "time").String() + assert.Equal(t, "1814400s", gotTime) + }, + }, + "validators": { + query: []string{"q", "poe", "validators"}, + assert: func(t *testing.T, qResult string) { + gotValidators := gjson.Get(qResult, "validators").Array() + assert.Greater(t, len(gotValidators), 0, gotValidators) + assert.NotEmpty(t, gjson.Get(gotValidators[0].String(), "description.moniker"), "moniker") + }, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + qResult := cli.CustomQuery(spec.query...) + spec.assert(t, qResult) + t.Logf(qResult) + }) + } } func assertValidatorsUpdated(t *testing.T, sortedMember []testingcontracts.TG4Member, stakedAmounts []uint64, expValidators int) { diff --git a/x/globalfee/types/query.pb.go b/x/globalfee/types/query.pb.go index 2ab619a2..55ded6a1 100644 --- a/x/globalfee/types/query.pb.go +++ b/x/globalfee/types/query.pb.go @@ -125,32 +125,32 @@ func init() { } var fileDescriptor_1265df7e439588bb = []byte{ - // 385 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x3f, 0x8f, 0xd3, 0x30, - 0x18, 0xc6, 0x63, 0x10, 0x0c, 0x61, 0xa9, 0x22, 0x86, 0x52, 0x05, 0x07, 0x45, 0x20, 0x10, 0x50, - 0x5b, 0x2d, 0x12, 0x48, 0x8c, 0xa5, 0x12, 0x13, 0x12, 0x74, 0x64, 0xa9, 0x9c, 0xd4, 0x35, 0x16, - 0xb1, 0xdf, 0x34, 0x76, 0x10, 0x59, 0xf9, 0x04, 0x48, 0x7c, 0x0b, 0x46, 0xe6, 0x7e, 0x80, 0x8e, - 0x95, 0x58, 0x6e, 0xca, 0x9d, 0xda, 0x9b, 0x6e, 0xbc, 0x4f, 0x70, 0x6a, 0xd2, 0xde, 0x9f, 0xf6, - 0x7a, 0xd2, 0x4d, 0xb6, 0xf4, 0xfc, 0x5e, 0x3f, 0x7a, 0x1e, 0xbf, 0xee, 0xd3, 0x18, 0xf4, 0x58, - 0x02, 0x15, 0x09, 0x44, 0x2c, 0x19, 0x73, 0x4e, 0x7f, 0x74, 0x22, 0x6e, 0x59, 0x87, 0x4e, 0x72, - 0x9e, 0x15, 0x24, 0xcd, 0xc0, 0x82, 0xd7, 0xac, 0x29, 0x72, 0x4e, 0x91, 0x35, 0xd5, 0x7a, 0x28, - 0x40, 0x40, 0x05, 0xd1, 0xd5, 0xad, 0xe6, 0x5b, 0xbe, 0x00, 0x10, 0x09, 0xa7, 0x2c, 0x95, 0x94, - 0x69, 0x0d, 0x96, 0x59, 0x09, 0xda, 0xac, 0x55, 0x1c, 0x83, 0x51, 0x60, 0x68, 0xc4, 0xcc, 0x85, - 0x5d, 0x0c, 0x52, 0xd7, 0x7a, 0x88, 0x5d, 0xff, 0xcb, 0xca, 0xfc, 0x93, 0xd4, 0x52, 0xe5, 0xea, - 0x23, 0x33, 0x9f, 0x33, 0x19, 0x73, 0x33, 0xe0, 0x93, 0x9c, 0x1b, 0x1b, 0x96, 0xc8, 0x7d, 0xbc, - 0x07, 0x30, 0x29, 0x68, 0xc3, 0xbd, 0x29, 0x72, 0x3d, 0x55, 0x8b, 0x43, 0xc1, 0xcc, 0x30, 0xad, - 0xe4, 0x26, 0x7a, 0x72, 0xf7, 0xc5, 0x83, 0xae, 0x4f, 0x6a, 0x7f, 0xb2, 0xf2, 0xdf, 0x04, 0x21, - 0x7d, 0x1e, 0x7f, 0x00, 0xa9, 0x7b, 0xe9, 0xac, 0x0c, 0x9c, 0x93, 0x32, 0xf0, 0x77, 0xe7, 0x5f, - 0x83, 0x92, 0x96, 0xab, 0xd4, 0x16, 0xa7, 0x65, 0xf0, 0xa8, 0x60, 0x2a, 0x79, 0x1f, 0xee, 0x52, - 0xe1, 0xdf, 0xc3, 0xe0, 0x95, 0x90, 0xf6, 0x5b, 0x1e, 0x91, 0x18, 0x14, 0x5d, 0x87, 0xad, 0x8f, - 0xb6, 0x19, 0x7d, 0xa7, 0xb6, 0x48, 0xb9, 0xd9, 0x18, 0x9a, 0x41, 0x43, 0x6d, 0xc5, 0xe8, 0x4e, - 0x91, 0x7b, 0xaf, 0x0a, 0xe8, 0xfd, 0x43, 0x6e, 0x63, 0x3b, 0xa5, 0xf7, 0x96, 0xec, 0xfb, 0x0e, - 0x72, 0x53, 0x6f, 0xad, 0x77, 0xb7, 0x9e, 0xab, 0xeb, 0x0c, 0xdb, 0xbf, 0xfe, 0x1f, 0xff, 0xb9, - 0xf3, 0xdc, 0x7b, 0x76, 0xcd, 0x9a, 0xec, 0x16, 0xd0, 0xeb, 0xcf, 0x16, 0x18, 0xcd, 0x17, 0x18, - 0x1d, 0x2d, 0x30, 0xfa, 0xbd, 0xc4, 0xce, 0x7c, 0x89, 0x9d, 0x83, 0x25, 0x76, 0xbe, 0xbe, 0xbc, - 0xd2, 0x4b, 0xb5, 0x78, 0x56, 0x64, 0x6c, 0xc4, 0xe9, 0xcf, 0x4b, 0x4f, 0x57, 0xfd, 0x44, 0xf7, - 0xab, 0x65, 0x78, 0x73, 0x16, 0x00, 0x00, 0xff, 0xff, 0xac, 0xad, 0x86, 0x40, 0xa2, 0x02, 0x00, - 0x00, + // 388 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x4f, 0x8b, 0xd3, 0x40, + 0x18, 0xc6, 0x33, 0x8a, 0x1e, 0xe2, 0xa5, 0x04, 0x0f, 0xb5, 0xc4, 0x89, 0x04, 0x0f, 0xa2, 0x75, + 0x86, 0x56, 0x51, 0xf0, 0x58, 0x0b, 0x9e, 0x04, 0xed, 0xd1, 0x4b, 0x99, 0xa4, 0xd3, 0x71, 0x30, + 0x33, 0x6f, 0x9a, 0x99, 0x88, 0xb9, 0xfa, 0x09, 0x04, 0xbf, 0x85, 0xdf, 0x40, 0xf0, 0xe6, 0xa5, + 0xc7, 0x82, 0x17, 0x4f, 0xd9, 0xa5, 0xdd, 0xd3, 0x1e, 0xf7, 0x13, 0x2c, 0x4d, 0xd2, 0xfd, 0xd3, + 0x6e, 0x17, 0xf6, 0x94, 0xc0, 0xf3, 0x7b, 0xdf, 0x87, 0xe7, 0x99, 0xd7, 0x7d, 0x1c, 0x83, 0x9e, + 0x4a, 0xa0, 0x22, 0x81, 0x88, 0x25, 0x53, 0xce, 0xe9, 0xd7, 0x5e, 0xc4, 0x2d, 0xeb, 0xd1, 0x59, + 0xce, 0xb3, 0x82, 0xa4, 0x19, 0x58, 0xf0, 0xda, 0x35, 0x45, 0xce, 0x28, 0xd2, 0x50, 0x9d, 0xfb, + 0x02, 0x04, 0x54, 0x10, 0x5d, 0xff, 0xd5, 0x7c, 0xc7, 0x17, 0x00, 0x22, 0xe1, 0x94, 0xa5, 0x92, + 0x32, 0xad, 0xc1, 0x32, 0x2b, 0x41, 0x9b, 0x46, 0xc5, 0x31, 0x18, 0x05, 0x86, 0x46, 0xcc, 0x9c, + 0xdb, 0xc5, 0x20, 0x75, 0xad, 0x87, 0xd8, 0xf5, 0x3f, 0xae, 0xcd, 0xdf, 0x4b, 0x2d, 0x55, 0xae, + 0xde, 0x31, 0xf3, 0x21, 0x93, 0x31, 0x37, 0x23, 0x3e, 0xcb, 0xb9, 0xb1, 0x61, 0x89, 0xdc, 0x87, + 0x7b, 0x00, 0x93, 0x82, 0x36, 0xdc, 0xfb, 0x83, 0x5c, 0x4f, 0xd5, 0xe2, 0x58, 0x30, 0x33, 0x4e, + 0x2b, 0xb9, 0x8d, 0x1e, 0xdd, 0x7e, 0x72, 0xaf, 0xef, 0x93, 0xda, 0x9f, 0xac, 0xfd, 0x37, 0x41, + 0xc8, 0x90, 0xc7, 0x6f, 0x41, 0xea, 0x41, 0x3a, 0x2f, 0x03, 0xe7, 0xb8, 0x0c, 0xfc, 0xdd, 0xf9, + 0x2e, 0x28, 0x69, 0xb9, 0x4a, 0x6d, 0x71, 0x52, 0x06, 0x0f, 0x0a, 0xa6, 0x92, 0x37, 0xe1, 0x2e, + 0x15, 0xfe, 0x3a, 0x08, 0x9e, 0x09, 0x69, 0x3f, 0xe7, 0x11, 0x89, 0x41, 0xd1, 0x26, 0x6c, 0xfd, + 0x79, 0x6e, 0x26, 0x5f, 0xa8, 0x2d, 0x52, 0x6e, 0x36, 0x86, 0x66, 0xd4, 0x52, 0x5b, 0x31, 0xfa, + 0x7f, 0x91, 0x7b, 0xa7, 0x0a, 0xe8, 0xfd, 0x46, 0x6e, 0x6b, 0x3b, 0xa5, 0xf7, 0x8a, 0xec, 0x7b, + 0x0e, 0x72, 0x5d, 0x6f, 0x9d, 0xd7, 0x37, 0x9e, 0xab, 0xeb, 0x0c, 0x5f, 0x7e, 0xff, 0x77, 0xf4, + 0xf3, 0x16, 0xf1, 0xba, 0xd4, 0x8a, 0x8c, 0x4d, 0xf8, 0x15, 0xd7, 0xb2, 0xdb, 0xc3, 0x60, 0x38, + 0x5f, 0x62, 0xb4, 0x58, 0x62, 0x74, 0xb8, 0xc4, 0xe8, 0xc7, 0x0a, 0x3b, 0x8b, 0x15, 0x76, 0xfe, + 0xaf, 0xb0, 0xf3, 0xe9, 0xe9, 0xa5, 0x7a, 0xaa, 0xfb, 0x6b, 0x16, 0x7f, 0xbb, 0xb0, 0xba, 0xaa, + 0x29, 0xba, 0x5b, 0xdd, 0xc4, 0x8b, 0xd3, 0x00, 0x00, 0x00, 0xff, 0xff, 0xef, 0x81, 0x03, 0xd0, + 0xa9, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/globalfee/types/query.pb.gw.go b/x/globalfee/types/query.pb.gw.go index dc5421ee..f6c1a56a 100644 --- a/x/globalfee/types/query.pb.gw.go +++ b/x/globalfee/types/query.pb.gw.go @@ -140,7 +140,7 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_MinimumGasPrices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"globalfee", "v1beta1", "minimum_gas_prices"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_MinimumGasPrices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"tgrade", "globalfee", "v1beta1", "minimum_gas_prices"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( diff --git a/x/poe/abci.go b/x/poe/abci.go index 65477302..9f231cf0 100644 --- a/x/poe/abci.go +++ b/x/poe/abci.go @@ -12,7 +12,7 @@ import ( ) type abciKeeper interface { - contract.Sudoer + types.Sudoer IteratePrivilegedContractsByType(ctx sdk.Context, privilegeType twasmtypes.PrivilegeType, cb func(prio uint8, contractAddr sdk.AccAddress) bool) } diff --git a/x/poe/bootstrap.go b/x/poe/bootstrap.go index f62c6f01..31240ad7 100644 --- a/x/poe/bootstrap.go +++ b/x/poe/bootstrap.go @@ -27,8 +27,8 @@ var ( contractVersion []byte ) -// clearEmbeddedContracts release memory -func clearEmbeddedContracts() { +// ClearEmbeddedContracts release memory +func ClearEmbeddedContracts() { tg4Group = nil tg4Stake = nil tg4Mixer = nil @@ -127,7 +127,7 @@ func bootstrapPoEContracts(ctx sdk.Context, k wasmtypes.ContractOpsKeeper, tk tw MaxValidators: 100, EpochLength: 1, EpochReward: sdk.NewCoin(gs.BondDenom, sdk.OneInt()), - InitialKeys: []contract.ValsetInitKey{}, + InitialKeys: []contract.Validator{}, } codeID, err = k.Create(ctx, creator, tgValset, &wasmtypes.AllowEverybody) if err != nil { diff --git a/x/poe/client/cli/query.go b/x/poe/client/cli/query.go index c86f97de..a3d8589e 100644 --- a/x/poe/client/cli/query.go +++ b/x/poe/client/cli/query.go @@ -6,6 +6,9 @@ import ( "github.com/confio/tgrade/x/poe/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/spf13/cobra" flag "github.com/spf13/pflag" "sort" @@ -22,6 +25,9 @@ func GetQueryCmd() *cobra.Command { } queryCmd.AddCommand( GetCmdShowPoEContract(), + GetCmdQueryValidators(), + GetCmdQueryValidator(), + GetCmdQueryUnbondingPeriod(), ) return queryCmd } @@ -61,6 +67,117 @@ func GetCmdShowPoEContract() *cobra.Command { return cmd } +func GetCmdQueryUnbondingPeriod() *cobra.Command { + cmd := &cobra.Command{ + Use: "unbonding-period", + Short: "Query the global unbonding period", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.UnbondingPeriod( + cmd.Context(), + &types.QueryUnbondingPeriodRequest{}, + ) + if err != nil { + return err + } + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +// GetCmdQueryValidators implements the query all validators command. +func GetCmdQueryValidators() *cobra.Command { + cmd := &cobra.Command{ + Use: "validators", + Short: "Query for all validators", + Args: cobra.NoArgs, + Long: strings.TrimSpace( + fmt.Sprintf(`Query details about all validators on a network. + +Example: +$ %s query staking validators +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + _ = pageReq // todo (Alex): support pagination + result, err := queryClient.Validators(cmd.Context(), &stakingtypes.QueryValidatorsRequest{ + // Leaving status empty on purpose to query all validators. + //Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(result) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + // flags.AddPaginationFlagsToCmd(cmd, "validators") + return cmd +} + +// GetCmdQueryValidator implements the validator query command. +func GetCmdQueryValidator() *cobra.Command { + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "validator [operator-addr]", + Short: "Query a validator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query details about an individual validator. + +Example: +$ %s query poe validator %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + addr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + params := &stakingtypes.QueryValidatorRequest{ValidatorAddr: addr.String()} + res, err := queryClient.Validator(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Validator) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + func allPoEContractTypes() string { r := make([]string, 0, len(types.PoEContractType_name)-1) for _, v := range types.PoEContractType_name { diff --git a/x/poe/client/cli/staking_query.go_txt b/x/poe/client/cli/staking_query.go_txt new file mode 100644 index 00000000..1e8b0a5c --- /dev/null +++ b/x/poe/client/cli/staking_query.go_txt @@ -0,0 +1,748 @@ +package cli + +import ( + "context" + "fmt" + "strconv" + "strings" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + stakingQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the staking module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + stakingQueryCmd.AddCommand( + GetCmdQueryDelegation(), + GetCmdQueryDelegations(), + GetCmdQueryUnbondingDelegation(), + GetCmdQueryUnbondingDelegations(), + GetCmdQueryRedelegation(), + GetCmdQueryRedelegations(), + GetCmdQueryValidator(), + GetCmdQueryValidators(), + GetCmdQueryValidatorDelegations(), + GetCmdQueryValidatorUnbondingDelegations(), + GetCmdQueryValidatorRedelegations(), + GetCmdQueryHistoricalInfo(), + GetCmdQueryParams(), + GetCmdQueryPool(), + ) + + return stakingQueryCmd +} + +// GetCmdQueryValidator implements the validator query command. +func GetCmdQueryValidator() *cobra.Command { + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "validator [validator-addr]", + Short: "Query a validator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query details about an individual validator. + +Example: +$ %s query staking validator %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + addr, err := sdk.ValAddressFromBech32(args[0]) + if err != nil { + return err + } + + params := &types.QueryValidatorRequest{ValidatorAddr: addr.String()} + res, err := queryClient.Validator(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Validator) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryValidators implements the query all validators command. +func GetCmdQueryValidators() *cobra.Command { + cmd := &cobra.Command{ + Use: "validators", + Short: "Query for all validators", + Args: cobra.NoArgs, + Long: strings.TrimSpace( + fmt.Sprintf(`Query details about all validators on a network. + +Example: +$ %s query staking validators +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + result, err := queryClient.Validators(context.Background(), &types.QueryValidatorsRequest{ + // Leaving status empty on purpose to query all validators. + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(result) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "validators") + + return cmd +} + +// GetCmdQueryValidatorUnbondingDelegations implements the query all unbonding delegatations from a validator command. +func GetCmdQueryValidatorUnbondingDelegations() *cobra.Command { + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "unbonding-delegations-from [validator-addr]", + Short: "Query all unbonding delegatations from a validator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query delegations that are unbonding _from_ a validator. + +Example: +$ %s query staking unbonding-delegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + valAddr, err := sdk.ValAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + params := &types.QueryValidatorUnbondingDelegationsRequest{ + ValidatorAddr: valAddr.String(), + Pagination: pageReq, + } + + res, err := queryClient.ValidatorUnbondingDelegations(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "unbonding delegations") + + return cmd +} + +// GetCmdQueryValidatorRedelegations implements the query all redelegatations +// from a validator command. +func GetCmdQueryValidatorRedelegations() *cobra.Command { + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "redelegations-from [validator-addr]", + Short: "Query all outgoing redelegatations from a validator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query delegations that are redelegating _from_ a validator. + +Example: +$ %s query staking redelegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + valSrcAddr, err := sdk.ValAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + params := &types.QueryRedelegationsRequest{ + SrcValidatorAddr: valSrcAddr.String(), + Pagination: pageReq, + } + + res, err := queryClient.Redelegations(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "validator redelegations") + + return cmd +} + +// GetCmdQueryDelegation the query delegation command. +func GetCmdQueryDelegation() *cobra.Command { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "delegation [delegator-addr] [validator-addr]", + Short: "Query a delegation based on address and validator address", + Long: strings.TrimSpace( + fmt.Sprintf(`Query delegations for an individual delegator on an individual validator. + +Example: +$ %s query staking delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + delAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + valAddr, err := sdk.ValAddressFromBech32(args[1]) + if err != nil { + return err + } + + params := &types.QueryDelegationRequest{ + DelegatorAddr: delAddr.String(), + ValidatorAddr: valAddr.String(), + } + + res, err := queryClient.Delegation(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res.DelegationResponse) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryDelegations implements the command to query all the delegations +// made from one delegator. +func GetCmdQueryDelegations() *cobra.Command { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + + cmd := &cobra.Command{ + Use: "delegations [delegator-addr]", + Short: "Query all delegations made by one delegator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query delegations for an individual delegator on all validators. + +Example: +$ %s query staking delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +`, + version.AppName, bech32PrefixAccAddr, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + delAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + params := &types.QueryDelegatorDelegationsRequest{ + DelegatorAddr: delAddr.String(), + Pagination: pageReq, + } + + res, err := queryClient.DelegatorDelegations(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "delegations") + + return cmd +} + +// GetCmdQueryValidatorDelegations implements the command to query all the +// delegations to a specific validator. +func GetCmdQueryValidatorDelegations() *cobra.Command { + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "delegations-to [validator-addr]", + Short: "Query all delegations made to one validator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query delegations on an individual validator. + +Example: +$ %s query staking delegations-to %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + valAddr, err := sdk.ValAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + params := &types.QueryValidatorDelegationsRequest{ + ValidatorAddr: valAddr.String(), + Pagination: pageReq, + } + + res, err := queryClient.ValidatorDelegations(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "validator delegations") + + return cmd +} + +// GetCmdQueryUnbondingDelegation implements the command to query a single +// unbonding-delegation record. +func GetCmdQueryUnbondingDelegation() *cobra.Command { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "unbonding-delegation [delegator-addr] [validator-addr]", + Short: "Query an unbonding-delegation record based on delegator and validator address", + Long: strings.TrimSpace( + fmt.Sprintf(`Query unbonding delegations for an individual delegator on an individual validator. + +Example: +$ %s query staking unbonding-delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + valAddr, err := sdk.ValAddressFromBech32(args[1]) + if err != nil { + return err + } + + delAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + params := &types.QueryUnbondingDelegationRequest{ + DelegatorAddr: delAddr.String(), + ValidatorAddr: valAddr.String(), + } + + res, err := queryClient.UnbondingDelegation(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Unbond) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryUnbondingDelegations implements the command to query all the +// unbonding-delegation records for a delegator. +func GetCmdQueryUnbondingDelegations() *cobra.Command { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + + cmd := &cobra.Command{ + Use: "unbonding-delegations [delegator-addr]", + Short: "Query all unbonding-delegations records for one delegator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query unbonding delegations for an individual delegator. + +Example: +$ %s query staking unbonding-delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +`, + version.AppName, bech32PrefixAccAddr, + ), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + delegatorAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + params := &types.QueryDelegatorUnbondingDelegationsRequest{ + DelegatorAddr: delegatorAddr.String(), + Pagination: pageReq, + } + + res, err := queryClient.DelegatorUnbondingDelegations(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "unbonding delegations") + + return cmd +} + +// GetCmdQueryRedelegation implements the command to query a single +// redelegation record. +func GetCmdQueryRedelegation() *cobra.Command { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() + + cmd := &cobra.Command{ + Use: "redelegation [delegator-addr] [src-validator-addr] [dst-validator-addr]", + Short: "Query a redelegation record based on delegator and a source and destination validator address", + Long: strings.TrimSpace( + fmt.Sprintf(`Query a redelegation record for an individual delegator between a source and destination validator. + +Example: +$ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj +`, + version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr, bech32PrefixValAddr, + ), + ), + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + delAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + valSrcAddr, err := sdk.ValAddressFromBech32(args[1]) + if err != nil { + return err + } + + valDstAddr, err := sdk.ValAddressFromBech32(args[2]) + if err != nil { + return err + } + + params := &types.QueryRedelegationsRequest{ + DelegatorAddr: delAddr.String(), + DstValidatorAddr: valDstAddr.String(), + SrcValidatorAddr: valSrcAddr.String(), + } + + res, err := queryClient.Redelegations(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryRedelegations implements the command to query all the +// redelegation records for a delegator. +func GetCmdQueryRedelegations() *cobra.Command { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + + cmd := &cobra.Command{ + Use: "redelegations [delegator-addr]", + Args: cobra.ExactArgs(1), + Short: "Query all redelegations records for one delegator", + Long: strings.TrimSpace( + fmt.Sprintf(`Query all redelegation records for an individual delegator. + +Example: +$ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p +`, + version.AppName, bech32PrefixAccAddr, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + delAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + params := &types.QueryRedelegationsRequest{ + DelegatorAddr: delAddr.String(), + Pagination: pageReq, + } + + res, err := queryClient.Redelegations(context.Background(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "delegator redelegations") + + return cmd +} + +// GetCmdQueryHistoricalInfo implements the historical info query command +func GetCmdQueryHistoricalInfo() *cobra.Command { + cmd := &cobra.Command{ + Use: "historical-info [height]", + Args: cobra.ExactArgs(1), + Short: "Query historical info at given height", + Long: strings.TrimSpace( + fmt.Sprintf(`Query historical info at given height. + +Example: +$ %s query staking historical-info 5 +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + height, err := strconv.ParseInt(args[0], 10, 64) + if err != nil || height < 0 { + return fmt.Errorf("height argument provided must be a non-negative-integer: %v", err) + } + + params := &types.QueryHistoricalInfoRequest{Height: height} + res, err := queryClient.HistoricalInfo(context.Background(), params) + + if err != nil { + return err + } + + return clientCtx.PrintProto(res.Hist) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryPool implements the pool query command. +func GetCmdQueryPool() *cobra.Command { + cmd := &cobra.Command{ + Use: "pool", + Args: cobra.NoArgs, + Short: "Query the current staking pool values", + Long: strings.TrimSpace( + fmt.Sprintf(`Query values for amounts stored in the staking pool. + +Example: +$ %s query staking pool +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Pool(context.Background(), &types.QueryPoolRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Pool) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryParams implements the params query command. +func GetCmdQueryParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Args: cobra.NoArgs, + Short: "Query the current staking parameters information", + Long: strings.TrimSpace( + fmt.Sprintf(`Query values set as staking parameters. + +Example: +$ %s query staking params +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Params) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/poe/client/cli/tx.go b/x/poe/client/cli/tx.go index 023edde9..1fad717b 100644 --- a/x/poe/client/cli/tx.go +++ b/x/poe/client/cli/tx.go @@ -34,6 +34,7 @@ func NewTxCmd() *cobra.Command { poeTxCmd.AddCommand( NewCreateValidatorCmd(), + NewEditValidatorCmd(), ) return poeTxCmd @@ -140,17 +141,45 @@ func NewBuildCreateValidatorMsg(clientCtx client.Context, txf tx.Factory, fs *fl return txf, msg, nil } +func NewEditValidatorCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "edit-validator", + Short: "edit an existing validator account", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + valAddr := clientCtx.GetFromAddress() + moniker, _ := cmd.Flags().GetString(FlagMoniker) + identity, _ := cmd.Flags().GetString(FlagIdentity) + website, _ := cmd.Flags().GetString(FlagWebsite) + security, _ := cmd.Flags().GetString(FlagSecurityContact) + details, _ := cmd.Flags().GetString(FlagDetails) + description := stakingtypes.NewDescription(moniker, identity, website, security, details) + + msg := types.NewMsgUpdateValidator(valAddr, description) + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().AddFlagSet(flagSetValidatorDescription(stakingtypes.DoNotModifyDesc)) + flags.AddTxFlagsToCmd(cmd) + return cmd +} + // CreateValidatorMsgFlagSet Return the flagset, particular flags, and a description of defaults // this is anticipated to be used with the gen-tx func CreateValidatorMsgFlagSet(ipDefault string) (fs *flag.FlagSet, defaultsDesc string) { fsCreateValidator := flag.NewFlagSet("", flag.ContinueOnError) fsCreateValidator.String(FlagIP, ipDefault, "The node's public IP") fsCreateValidator.String(FlagNodeID, "", "The node's NodeID") - fsCreateValidator.String(FlagMoniker, "", "The validator's (optional) moniker") - fsCreateValidator.String(FlagWebsite, "", "The validator's (optional) website") - fsCreateValidator.String(FlagSecurityContact, "", "The validator's (optional) security contact email") - fsCreateValidator.String(FlagDetails, "", "The validator's (optional) details") - fsCreateValidator.String(FlagIdentity, "", "The (optional) identity signature (ex. UPort or Keybase)") + + fsCreateValidator.AddFlagSet(flagSetValidatorDescription("")) fsCreateValidator.AddFlagSet(FlagSetAmount()) fsCreateValidator.AddFlagSet(FlagSetPublicKey()) @@ -159,6 +188,16 @@ func CreateValidatorMsgFlagSet(ipDefault string) (fs *flag.FlagSet, defaultsDesc return fsCreateValidator, defaultsDesc } +func flagSetValidatorDescription(defaultValue string) *flag.FlagSet { + fs := flag.NewFlagSet("", flag.ContinueOnError) + fs.String(FlagMoniker, defaultValue, "The validator's name") + fs.String(FlagIdentity, defaultValue, "The (optional) identity signature (ex. UPort or Keybase)") + fs.String(FlagWebsite, defaultValue, "The validator's (optional) website") + fs.String(FlagSecurityContact, defaultValue, "The validator's (optional) security contact email") + fs.String(FlagDetails, defaultValue, "The validator's (optional) details") + return fs +} + type TxCreateValidatorConfig struct { ChainID string NodeID string diff --git a/x/poe/contract/README.md b/x/poe/contract/README.md index b447ef1b..ff88e6ca 100644 --- a/x/poe/contract/README.md +++ b/x/poe/contract/README.md @@ -1,8 +1,19 @@ # Contracts -Tgrade smart contracts +Tgrade smart contracts. See https://github.com/confio/tgrade-contracts for source code and details. -## Download new artifacts +## Developers +### Test strategy +**Contract interactions (query/ updates)** should be covered by **integration tests** that talk to the real contract(s) +We need to ensure that things work as expected but also to provide ["consumer driven contracts"](https://martinfowler.com/articles/consumerDrivenContracts.html) +in code that couple both worlds to be stable. +Though there are use cases that would also be covered by system tests like create-validator or end block callback. In this +case we have enough confidence. + +Pure Go code should be unit tested only + + +### Download new artifacts **Requires a github access token** Example to download contract for tag `v0.1.3` diff --git a/x/poe/contract/contractio.go b/x/poe/contract/contractio.go index 997d1015..881ede66 100644 --- a/x/poe/contract/contractio.go +++ b/x/poe/contract/contractio.go @@ -11,18 +11,8 @@ import ( "github.com/tendermint/tendermint/proto/tendermint/crypto" ) -// Sudoer with access to sudo method -type Sudoer interface { - Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte) ([]byte, error) -} - -// Executor with access to excute method -type Executor interface { - Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) ([]byte, error) -} - // RegisterValidator calls valset contract to register a new validator key and address -func RegisterValidator(ctx sdk.Context, contractAddr sdk.AccAddress, pk cryptotypes.PubKey, delegatorAddress sdk.AccAddress, description stakingtypes.Description, k Executor) error { +func RegisterValidator(ctx sdk.Context, contractAddr sdk.AccAddress, pk cryptotypes.PubKey, delegatorAddress sdk.AccAddress, description stakingtypes.Description, k types.Executor) error { pub, err := NewValidatorPubkey(pk) if err != nil { return err @@ -43,7 +33,7 @@ func RegisterValidator(ctx sdk.Context, contractAddr sdk.AccAddress, pk cryptoty } // UpdateValidator calls valset contract to change validator's metadata -func UpdateValidator(ctx sdk.Context, contractAddr sdk.AccAddress, delegatorAddress sdk.AccAddress, description stakingtypes.Description, k Executor) error { +func UpdateValidator(ctx sdk.Context, contractAddr sdk.AccAddress, delegatorAddress sdk.AccAddress, description stakingtypes.Description, k types.Executor) error { metadata := MetadataFromDescription(description) updateValidator := TG4ValsetExecute{ UpdateMetadata: &metadata, @@ -58,7 +48,7 @@ func UpdateValidator(ctx sdk.Context, contractAddr sdk.AccAddress, delegatorAddr } // CallEndBlockWithValidatorUpdate calls valset contract for a validator diff -func CallEndBlockWithValidatorUpdate(ctx sdk.Context, contractAddr sdk.AccAddress, k Sudoer) ([]abci.ValidatorUpdate, error) { +func CallEndBlockWithValidatorUpdate(ctx sdk.Context, contractAddr sdk.AccAddress, k types.Sudoer) ([]abci.ValidatorUpdate, error) { sudoMsg := ValidatorUpdateSudoMsg{EndWithValidatorUpdate: &struct{}{}} msgBz, err := json.Marshal(sudoMsg) if err != nil { @@ -82,7 +72,7 @@ func CallEndBlockWithValidatorUpdate(ctx sdk.Context, contractAddr sdk.AccAddres result := make([]abci.ValidatorUpdate, len(contractResult.Diffs)) for i, v := range contractResult.Diffs { - pub, err := getPubKey(v.PubKey) + pub, err := convertToTendermintPubKey(v.PubKey) if err != nil { return nil, err } @@ -94,7 +84,7 @@ func CallEndBlockWithValidatorUpdate(ctx sdk.Context, contractAddr sdk.AccAddres return result, nil } -func getPubKey(key ValidatorPubkey) (crypto.PublicKey, error) { +func convertToTendermintPubKey(key ValidatorPubkey) (crypto.PublicKey, error) { switch { case key.Ed25519 != nil: return crypto.PublicKey{ @@ -114,7 +104,7 @@ func getPubKey(key ValidatorPubkey) (crypto.PublicKey, error) { } // BondTokens sends given amount to the staking contract to increase the bonded amount for the delegator -func BondTokens(ctx sdk.Context, contractAddr sdk.AccAddress, delegatorAddress sdk.AccAddress, amount sdk.Coins, k Executor) error { +func BondTokens(ctx sdk.Context, contractAddr sdk.AccAddress, delegatorAddress sdk.AccAddress, amount sdk.Coins, k types.Executor) error { bondStake := TG4StakeExecute{ Bond: &struct{}{}, } diff --git a/x/poe/contract/contractio_test.go b/x/poe/contract/contractio_test.go index 323cb323..e50d8c0d 100644 --- a/x/poe/contract/contractio_test.go +++ b/x/poe/contract/contractio_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -func TestGetPubKey(t *testing.T) { +func TestConvertToTendermintPubKey(t *testing.T) { var ( ed25519pubkeybz = ed25519.GenPrivKey().PubKey().Bytes() secp256k1pubkeybz = secp256k1.GenPrivKey().PubKey().Bytes() @@ -39,7 +39,7 @@ func TestGetPubKey(t *testing.T) { }} for name, spec := range specs { t.Run(name, func(t *testing.T) { - gotRes, gotErr := getPubKey(spec.src) + gotRes, gotErr := convertToTendermintPubKey(spec.src) if spec.expErr { require.Error(t, gotErr) return diff --git a/x/poe/contract/download_releases.sh b/x/poe/contract/download_releases.sh index ceb30d60..ee475738 100755 --- a/x/poe/contract/download_releases.sh +++ b/x/poe/contract/download_releases.sh @@ -20,5 +20,6 @@ for contract in tg4_group tgrade_gov_reflect tgrade_valset tg4_mixer tg4_stake; # download the artifact curl -LJO -H 'Accept: application/octet-stream' -H "Authorization: token $GITHUB_API_TOKEN" "$asset_url" done + rm -f version.txt echo "$tag" >version.txt diff --git a/x/poe/contract/msg.go b/x/poe/contract/msg.go index 3dcf37e2..4d127840 100644 --- a/x/poe/contract/msg.go +++ b/x/poe/contract/msg.go @@ -101,20 +101,20 @@ func (m TG4StakeExecute) Json(t *testing.T) string { // ValsetInitMsg Valset contract init message // See https://github.com/confio/tgrade-contracts/tree/main/contracts/tgrade-valset type ValsetInitMsg struct { - Membership string `json:"membership"` - MinWeight int `json:"min_weight"` - MaxValidators int `json:"max_validators"` - EpochLength int `json:"epoch_length"` - EpochReward sdk.Coin `json:"epoch_reward"` - InitialKeys []ValsetInitKey `json:"initial_keys"` - Scaling int `json:"scaling,omitempty"` + Membership string `json:"membership"` + MinWeight int `json:"min_weight"` + MaxValidators int `json:"max_validators"` + EpochLength int `json:"epoch_length"` + EpochReward sdk.Coin `json:"epoch_reward"` + InitialKeys []Validator `json:"initial_keys"` + Scaling int `json:"scaling,omitempty"` } func (m ValsetInitMsg) Json(t *testing.T) string { return asJson(t, m) } -type ValsetInitKey struct { +type Validator struct { Operator string `json:"operator"` ValidatorPubkey ValidatorPubkey `json:"validator_pubkey"` } diff --git a/x/poe/contract/query.go b/x/poe/contract/query.go index 0e30f146..7e4bed9f 100644 --- a/x/poe/contract/query.go +++ b/x/poe/contract/query.go @@ -2,8 +2,14 @@ package contract import ( "encoding/json" - twasmkeeper "github.com/confio/tgrade/x/twasm/keeper" + "github.com/confio/tgrade/x/poe/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptosecp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // ValsetQuery will create many queries for the valset contract @@ -54,6 +60,34 @@ type OperatorResponse struct { Metadata ValidatorMetadata `json:"metadata"` } +func (v OperatorResponse) ToValidator() (stakingtypes.Validator, error) { + pubKey, err := toCosmosPubKey(v.Pubkey) + if err != nil { + return stakingtypes.Validator{}, sdkerrors.Wrap(err, "convert to cosmos key") + } + any, err := codectypes.NewAnyWithValue(pubKey) + if err != nil { + return stakingtypes.Validator{}, sdkerrors.Wrap(err, "convert to any type") + } + + return stakingtypes.Validator{ + OperatorAddress: v.Operator, + ConsensusPubkey: any, + Description: v.Metadata.ToDescription(), + }, nil +} + +func toCosmosPubKey(key ValidatorPubkey) (cryptotypes.PubKey, error) { + switch { + case key.Ed25519 != nil: + return &ed25519.PubKey{Key: key.Ed25519}, nil + case key.Secp256k1 != nil: + return &cryptosecp256k1.PubKey{Key: key.Secp256k1}, nil + default: + return nil, types.ErrValidatorPubKeyTypeNotSupported + } +} + type ValidatorInfo struct { Operator string `json:"operator"` ValidatorPubkey ValidatorPubkey `json:"validator_pubkey"` @@ -74,42 +108,42 @@ type ListActiveValidatorsResponse struct { type SimulateActiveValidatorsResponse = ListActiveValidatorsResponse -func QueryValsetConfig(ctx sdk.Context, k *twasmkeeper.Keeper, valset sdk.AccAddress) (*ValsetConfigResponse, error) { +func QueryValsetConfig(ctx sdk.Context, k types.SmartQuerier, valset sdk.AccAddress) (*ValsetConfigResponse, error) { query := ValsetQuery{Config: &struct{}{}} var response ValsetConfigResponse err := doQuery(ctx, k, valset, query, &response) return &response, err } -func QueryValsetEpoch(ctx sdk.Context, k *twasmkeeper.Keeper, valset sdk.AccAddress) (*ValsetEpochResponse, error) { +func QueryValsetEpoch(ctx sdk.Context, k types.SmartQuerier, valset sdk.AccAddress) (*ValsetEpochResponse, error) { query := ValsetQuery{Epoch: &struct{}{}} var response ValsetEpochResponse err := doQuery(ctx, k, valset, query, &response) return &response, err } -func QueryValidator(ctx sdk.Context, k *twasmkeeper.Keeper, valset sdk.AccAddress, operator sdk.AccAddress) (*OperatorResponse, error) { +func QueryValidator(ctx sdk.Context, k types.SmartQuerier, valset sdk.AccAddress, operator sdk.AccAddress) (*OperatorResponse, error) { query := ValsetQuery{Validator: &ValidatorQuery{Operator: operator.String()}} var response ValidatorResponse err := doQuery(ctx, k, valset, query, &response) return response.Validator, err } -func ListValidators(ctx sdk.Context, k *twasmkeeper.Keeper, valset sdk.AccAddress) ([]OperatorResponse, error) { +func ListValidators(ctx sdk.Context, k types.SmartQuerier, valset sdk.AccAddress) ([]OperatorResponse, error) { query := ValsetQuery{ListValidators: &ListValidatorsQuery{Limit: 30}} var response ListValidatorsResponse err := doQuery(ctx, k, valset, query, &response) return response.Validators, err } -func ListActiveValidators(ctx sdk.Context, k *twasmkeeper.Keeper, valset sdk.AccAddress) ([]ValidatorInfo, error) { +func ListActiveValidators(ctx sdk.Context, k types.SmartQuerier, valset sdk.AccAddress) ([]ValidatorInfo, error) { query := ValsetQuery{ListActiveValidators: &struct{}{}} var response ListActiveValidatorsResponse err := doQuery(ctx, k, valset, query, &response) return response.Validators, err } -func SimulateActiveValidators(ctx sdk.Context, k *twasmkeeper.Keeper, valset sdk.AccAddress) ([]ValidatorInfo, error) { +func SimulateActiveValidators(ctx sdk.Context, k types.SmartQuerier, valset sdk.AccAddress) ([]ValidatorInfo, error) { query := ValsetQuery{SimulateActiveValidators: &struct{}{}} var response ListActiveValidatorsResponse err := doQuery(ctx, k, valset, query, &response) @@ -158,14 +192,14 @@ type TG4TotalWeightResponse struct { Weight int `json:"weight"` } -func QueryTG4MembersByWeight(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.AccAddress) ([]TG4Member, error) { +func QueryTG4MembersByWeight(ctx sdk.Context, k types.SmartQuerier, tg4Addr sdk.AccAddress) ([]TG4Member, error) { query := TG4Query{ListMembersByWeight: &ListMembersByWeightQuery{Limit: 30}} var response TG4MemberListResponse err := doQuery(ctx, k, tg4Addr, query, &response) return response.Members, err } -func QueryTG4Members(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.AccAddress) ([]TG4Member, error) { +func QueryTG4Members(ctx sdk.Context, k types.SmartQuerier, tg4Addr sdk.AccAddress) ([]TG4Member, error) { query := TG4Query{ListMembers: &ListMembersQuery{Limit: 30}} var response TG4MemberListResponse err := doQuery(ctx, k, tg4Addr, query, &response) @@ -173,7 +207,7 @@ func QueryTG4Members(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.AccAddr } // QueryTG4Member returns the weight of this member. (nil, nil) means not present, (&0, nil) means member with no votes -func QueryTG4Member(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.AccAddress, member sdk.AccAddress) (*int, error) { +func QueryTG4Member(ctx sdk.Context, k types.SmartQuerier, tg4Addr sdk.AccAddress, member sdk.AccAddress) (*int, error) { query := TG4Query{Member: &MemberQuery{Addr: member.String()}} var response TG4MemberResponse err := doQuery(ctx, k, tg4Addr, query, &response) @@ -181,7 +215,7 @@ func QueryTG4Member(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.AccAddre } // QueryTG4TotalWeight returns the weight of this member. (nil, nil) means not present -func QueryTG4TotalWeight(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.AccAddress) (int, error) { +func QueryTG4TotalWeight(ctx sdk.Context, k types.SmartQuerier, tg4Addr sdk.AccAddress) (int, error) { query := TG4Query{TotalWeight: &struct{}{}} var response TG4TotalWeightResponse err := doQuery(ctx, k, tg4Addr, query, &response) @@ -189,7 +223,7 @@ func QueryTG4TotalWeight(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.Acc } // QueryTG4Admin returns admin of this contract, if any. Will return nil, err if no admin -func QueryTG4Admin(ctx sdk.Context, k *twasmkeeper.Keeper, tg4Addr sdk.AccAddress) (sdk.AccAddress, error) { +func QueryTG4Admin(ctx sdk.Context, k types.SmartQuerier, tg4Addr sdk.AccAddress) (sdk.AccAddress, error) { query := TG4Query{Admin: &struct{}{}} var response TG4AdminResponse err := doQuery(ctx, k, tg4Addr, query, &response) @@ -220,14 +254,14 @@ type Duration struct { Time int `json:"time,omitempty"` } -func QueryStakingUnbondingPeriod(ctx sdk.Context, k *twasmkeeper.Keeper, stakeAddr sdk.AccAddress) (Duration, error) { +func QueryStakingUnbondingPeriod(ctx sdk.Context, k types.SmartQuerier, stakeAddr sdk.AccAddress) (Duration, error) { query := TG4StakeQuery{UnbondingPeriod: &struct{}{}} var response UnbondingPeriodResponse err := doQuery(ctx, k, stakeAddr, query, &response) return response.UnbondingPeriod, err } -func doQuery(ctx sdk.Context, k *twasmkeeper.Keeper, contractAddr sdk.AccAddress, query interface{}, result interface{}) error { +func doQuery(ctx sdk.Context, k types.SmartQuerier, contractAddr sdk.AccAddress, query interface{}, result interface{}) error { bz, err := json.Marshal(query) if err != nil { return err diff --git a/x/poe/contract/query_integration_test.go b/x/poe/contract/query_integration_test.go new file mode 100644 index 00000000..5ed651ed --- /dev/null +++ b/x/poe/contract/query_integration_test.go @@ -0,0 +1,182 @@ +package contract_test + +import ( + "encoding/json" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/confio/tgrade/x/poe" + "github.com/confio/tgrade/x/poe/contract" + "github.com/confio/tgrade/x/poe/keeper" + "github.com/confio/tgrade/x/poe/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + fuzz "github.com/google/gofuzz" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/rand" + "sort" + "testing" +) + +func TestListValidators(t *testing.T) { + // setup contracts and seed some data + ctx, example := keeper.CreateDefaultTestInput(t) + deliverTXFn := unAuthorizedDeliverTXFn(t, ctx, example.PoEKeeper, example.TWasmKeeper.GetContractKeeper(), example.EncodingConfig.TxConfig.TxDecoder()) + module := poe.NewAppModule(example.PoEKeeper, example.TWasmKeeper, deliverTXFn, example.EncodingConfig.TxConfig, example.TWasmKeeper.GetContractKeeper()) + + mutator, expValidators := withRandomValidators(t, ctx, example, 3) + gs := types.GenesisStateFixture(mutator) + genesisBz := example.EncodingConfig.Marshaler.MustMarshalJSON(&gs) + module.InitGenesis(ctx, example.EncodingConfig.Marshaler, genesisBz) + + // when + contractAddr, err := example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeValset) + require.NoError(t, err) + vals, err := contract.ListValidators(ctx, example.TWasmKeeper, contractAddr) + + // then + require.NoError(t, err) + sort.Slice(expValidators, func(i, j int) bool { + return expValidators[i].OperatorAddress < expValidators[j].OperatorAddress + }) + gotValidators := make([]stakingtypes.Validator, len(vals)) + for i, v := range vals { + gotValidators[i], err = v.ToValidator() + require.NoError(t, err) + } + assert.Equal(t, expValidators, gotValidators) +} + +func TestGetValidator(t *testing.T) { + // setup contracts and seed some data + ctx, example := keeper.CreateDefaultTestInput(t) + deliverTXFn := unAuthorizedDeliverTXFn(t, ctx, example.PoEKeeper, example.TWasmKeeper.GetContractKeeper(), example.EncodingConfig.TxConfig.TxDecoder()) + module := poe.NewAppModule(example.PoEKeeper, example.TWasmKeeper, deliverTXFn, example.EncodingConfig.TxConfig, example.TWasmKeeper.GetContractKeeper()) + + mutator, expValidators := withRandomValidators(t, ctx, example, 2) + gs := types.GenesisStateFixture(mutator) + genesisBz := example.EncodingConfig.Marshaler.MustMarshalJSON(&gs) + module.InitGenesis(ctx, example.EncodingConfig.Marshaler, genesisBz) + + specs := map[string]struct { + operatorAddr string + expVal stakingtypes.Validator + expEmpty bool + }{ + "query one validator": { + operatorAddr: expValidators[0].OperatorAddress, + expVal: expValidators[0], + }, + "query other validator": { + operatorAddr: expValidators[1].OperatorAddress, + expVal: expValidators[1], + }, + "query with unknown address": { + operatorAddr: sdk.AccAddress(rand.Bytes(sdk.AddrLen)).String(), + expEmpty: true, + }, + "query with invalid address": { + operatorAddr: "not an address", + expEmpty: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + contractAddr, err := example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeValset) + require.NoError(t, err) + opAddr, _ := sdk.AccAddressFromBech32(spec.operatorAddr) + + // when + val, err := contract.QueryValidator(ctx, example.TWasmKeeper, contractAddr, opAddr) + + // then + if spec.expEmpty { + assert.Nil(t, val) + return + } + gotVal, err := val.ToValidator() + require.NoError(t, err) + assert.Equal(t, spec.expVal, gotVal) + }) + } + +} +func TestQueryUnbondingPeriod(t *testing.T) { + // setup contracts and seed some data + ctx, example := keeper.CreateDefaultTestInput(t) + deliverTXFn := unAuthorizedDeliverTXFn(t, ctx, example.PoEKeeper, example.TWasmKeeper.GetContractKeeper(), example.EncodingConfig.TxConfig.TxDecoder()) + module := poe.NewAppModule(example.PoEKeeper, example.TWasmKeeper, deliverTXFn, example.EncodingConfig.TxConfig, example.TWasmKeeper.GetContractKeeper()) + + mutator, _ := withRandomValidators(t, ctx, example, 1) + gs := types.GenesisStateFixture(mutator) + genesisBz := example.EncodingConfig.Marshaler.MustMarshalJSON(&gs) + module.InitGenesis(ctx, example.EncodingConfig.Marshaler, genesisBz) + + contractAddr, err := example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeStaking) + require.NoError(t, err) + // when + res, err := contract.QueryStakingUnbondingPeriod(ctx, example.TWasmKeeper, contractAddr) + + // then + + configuredTime := 21 * 24 * 60 * 60 // in bootstrap + assert.Equal(t, contract.Duration{Time: configuredTime}, res) +} + +// unAuthorizedDeliverTXFn applies the TX without ante handler checks for testing purpose +func unAuthorizedDeliverTXFn(t *testing.T, ctx sdk.Context, k keeper.Keeper, contractKeeper wasmtypes.ContractOpsKeeper, txDecoder sdk.TxDecoder) func(tx abci.RequestDeliverTx) abci.ResponseDeliverTx { + t.Helper() + h := poe.NewHandler(k, contractKeeper, nil) + return func(tx abci.RequestDeliverTx) abci.ResponseDeliverTx { + genTx, err := txDecoder(tx.GetTx()) + require.NoError(t, err) + msgs := genTx.GetMsgs() + require.Len(t, msgs, 1) + msg := msgs[0].(*types.MsgCreateValidator) + _, err = h(ctx, msg) + require.NoError(t, err) + t.Logf("+++ create validator: %s\n", msg.DelegatorAddress) + return abci.ResponseDeliverTx{} + } +} + +// return genesis mutator that adds the given mumber of validators to the genesis +func withRandomValidators(t *testing.T, ctx sdk.Context, example keeper.TestKeepers, numValidators int) (func(m *types.GenesisState), []stakingtypes.Validator) { + collectValidators := make([]stakingtypes.Validator, numValidators) + return func(m *types.GenesisState) { + f := fuzz.New() + m.GenTxs = make([]json.RawMessage, numValidators) + m.Engagement = make([]types.TG4Member, numValidators) + for i := 0; i < numValidators; i++ { + var ( // power * engagement must be less than 10^18 (constraint is in the contract) + power uint16 + engagement uint16 + desc stakingtypes.Description + ) + f.NilChance(0).Fuzz(&power) // must be > 0 so that staked amount is > 0 + f.Fuzz(&engagement) + for len(desc.Moniker) < 3 { // ensure min length is met + f.Fuzz(&desc) + } + + genTx, opAddr, pubKey := types.RandomGenTX(t, uint32(power), func(m *types.MsgCreateValidator) { + m.Description = desc + }) + any, err := codectypes.NewAnyWithValue(pubKey) + require.NoError(t, err) + stakedAmount := sdk.TokensFromConsensusPower(int64(power)).Uint64() + collectValidators[i] = stakingtypes.Validator{ + OperatorAddress: opAddr.String(), + ConsensusPubkey: any, + Description: desc, + } + m.GenTxs[i] = genTx + m.Engagement[i] = types.TG4Member{Address: opAddr.String(), Weight: uint64(engagement)} + example.AccountKeeper.NewAccountWithAddress(ctx, opAddr) + example.BankKeeper.SetBalances(ctx, opAddr, sdk.NewCoins( + sdk.NewCoin(types.DefaultBondDenom, sdk.NewIntFromUint64(stakedAmount)), + )) + } + }, collectValidators +} diff --git a/x/poe/handler.go b/x/poe/handler.go index 83e05181..3aac3ea6 100644 --- a/x/poe/handler.go +++ b/x/poe/handler.go @@ -9,8 +9,8 @@ import ( ) // NewHandler constructor -func NewHandler(k keeper.ContractSource, contractKeeper wasmtypes.ContractOpsKeeper) sdk.Handler { - return newHandler(keeper.NewMsgServerImpl(k, contractKeeper)) +func NewHandler(k keeper.ContractSource, contractKeeper wasmtypes.ContractOpsKeeper, q types.SmartQuerier) sdk.Handler { + return newHandler(keeper.NewMsgServerImpl(k, contractKeeper, q)) } // internal constructor for testing @@ -22,7 +22,9 @@ func newHandler(msgServer types.MsgServer) sdk.Handler { case *types.MsgCreateValidator: res, err := msgServer.CreateValidator(sdk.WrapSDKContext(ctx), msg) return sdk.WrapServiceResult(ctx, res, err) - + case *types.MsgUpdateValidator: + res, err := msgServer.UpdateValidator(sdk.WrapSDKContext(ctx), msg) + return sdk.WrapServiceResult(ctx, res, err) default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg) } diff --git a/x/poe/handler_test.go b/x/poe/handler_test.go index eb48db15..ed28ce2f 100644 --- a/x/poe/handler_test.go +++ b/x/poe/handler_test.go @@ -40,7 +40,7 @@ func TestHandler(t *testing.T) { Type: "foo", }}}, }, - "error returned": { + "MsgCreateValidator error returned": { src: types.MsgCreateValidatorFixture(), mock: MsgServerMock{ CreateValidatorFn: func(ctx context.Context, validator *types.MsgCreateValidator) (*types.MsgCreateValidatorResponse, error) { @@ -49,6 +49,24 @@ func TestHandler(t *testing.T) { }, expErr: sdkerrors.ErrInvalidAddress, }, + "MsgUpdateValidator": { + src: types.MsgUpdateValidatorFixture(), + mock: MsgServerMock{ + UpdateValidatorFn: func(ctx context.Context, validator *types.MsgUpdateValidator) (*types.MsgUpdateValidatorResponse, error) { + return &types.MsgUpdateValidatorResponse{}, nil + }, + }, + expResult: &sdk.Result{Data: []byte{}, Events: []abcitypes.Event{}}, + }, + "MsgUpdateValidator error returned": { + src: types.MsgUpdateValidatorFixture(), + mock: MsgServerMock{ + UpdateValidatorFn: func(ctx context.Context, validator *types.MsgUpdateValidator) (*types.MsgUpdateValidatorResponse, error) { + return nil, sdkerrors.ErrInvalidAddress + }, + }, + expErr: sdkerrors.ErrInvalidAddress, + }, "unknown message": { src: &banktypes.MsgSend{}, expErr: sdkerrors.ErrUnknownRequest, diff --git a/x/poe/keeper/grpc_query.go b/x/poe/keeper/grpc_query.go new file mode 100644 index 00000000..63f453ba --- /dev/null +++ b/x/poe/keeper/grpc_query.go @@ -0,0 +1,134 @@ +package keeper + +import ( + "context" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/confio/tgrade/x/poe/contract" + "github.com/confio/tgrade/x/poe/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "time" +) + +var _ types.QueryServer = &grpcQuerier{} + +type grpcQuerier struct { + keeper ContractSource + contractQuerier types.SmartQuerier +} + +// NewGrpcQuerier constructor +func NewGrpcQuerier(keeper ContractSource, contractQuerier types.SmartQuerier) *grpcQuerier { + return &grpcQuerier{keeper: keeper, contractQuerier: contractQuerier} +} + +// ContractAddress query PoE contract address for given type +func (g grpcQuerier) ContractAddress(c context.Context, request *types.QueryContractAddressRequest) (*types.QueryContractAddressResponse, error) { + addr, err := g.keeper.GetPoEContractAddress(sdk.UnwrapSDKContext(c), request.ContractType) + switch { + case wasmtypes.ErrNotFound.Is(err): + return nil, status.Error(codes.NotFound, err.Error()) + case err != nil: + return nil, status.Error(codes.Internal, err.Error()) + } + return &types.QueryContractAddressResponse{Address: addr.String()}, nil +} + +// Validators query all validators +func (g grpcQuerier) Validators(c context.Context, request *stakingtypes.QueryValidatorsRequest) (*stakingtypes.QueryValidatorsResponse, error) { + if request == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + addr, err := g.keeper.GetPoEContractAddress(ctx, types.PoEContractTypeValset) + switch { + case wasmtypes.ErrNotFound.Is(err): + return nil, status.Error(codes.NotFound, err.Error()) + case err != nil: + return nil, status.Error(codes.Internal, err.Error()) + } + if request.Pagination != nil { + return nil, status.Error(codes.Unimplemented, "pagination not supported, yet") + } + + valsRsp, err := contract.ListValidators(ctx, g.contractQuerier, addr) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + vals := make([]stakingtypes.Validator, len(valsRsp)) + for i, v := range valsRsp { + vals[i], err = v.ToValidator() + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + } + return &stakingtypes.QueryValidatorsResponse{ + Validators: vals, + }, nil +} + +// Validator queries validator info for given validator address +func (g grpcQuerier) Validator(c context.Context, req *stakingtypes.QueryValidatorRequest) (*stakingtypes.QueryValidatorResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + if req.ValidatorAddr == "" { + return nil, status.Error(codes.InvalidArgument, "validator address cannot be empty") + } + + opAddr, err := sdk.AccAddressFromBech32(req.ValidatorAddr) + if err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(c) + contractAddr, err := g.keeper.GetPoEContractAddress(ctx, types.PoEContractTypeValset) + switch { + case wasmtypes.ErrNotFound.Is(err): + return nil, status.Error(codes.NotFound, err.Error()) + case err != nil: + return nil, status.Error(codes.Internal, err.Error()) + } + + valRsp, err := contract.QueryValidator(ctx, g.contractQuerier, contractAddr, opAddr) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + if valRsp == nil { + return nil, status.Errorf(codes.NotFound, "validator %s not found", req.ValidatorAddr) + } + val, err := valRsp.ToValidator() + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return &stakingtypes.QueryValidatorResponse{Validator: val}, nil +} + +// UnbondingPeriod query the global unbonding period +func (g grpcQuerier) UnbondingPeriod(c context.Context, request *types.QueryUnbondingPeriodRequest) (*types.QueryUnbondingPeriodResponse, error) { + if request == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + ctx := sdk.UnwrapSDKContext(c) + contractAddr, err := g.keeper.GetPoEContractAddress(ctx, types.PoEContractTypeStaking) + switch { + case wasmtypes.ErrNotFound.Is(err): + return nil, status.Error(codes.NotFound, err.Error()) + case err != nil: + return nil, status.Error(codes.Internal, err.Error()) + } + + rsp, err := contract.QueryStakingUnbondingPeriod(ctx, g.contractQuerier, contractAddr) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + return &types.QueryUnbondingPeriodResponse{ + Height: uint64(rsp.Height), + Time: time.Duration(rsp.Time) * time.Second, + }, nil +} diff --git a/x/poe/keeper/grpc_query_test.go b/x/poe/keeper/grpc_query_test.go new file mode 100644 index 00000000..4b64b27b --- /dev/null +++ b/x/poe/keeper/grpc_query_test.go @@ -0,0 +1,296 @@ +package keeper + +import ( + "context" + "encoding/json" + "errors" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/confio/tgrade/x/poe/contract" + "github.com/confio/tgrade/x/poe/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/rand" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "testing" + "time" +) + +func TestQueryContractAddress(t *testing.T) { + var myContractAddr sdk.AccAddress = rand.Bytes(sdk.AddrLen) + specs := map[string]struct { + srcMsg types.QueryContractAddressRequest + mockFn func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) + expResult *types.QueryContractAddressResponse + expErrCode codes.Code + }{ + "return address": { + srcMsg: types.QueryContractAddressRequest{ContractType: types.PoEContractTypeMixer}, + mockFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { + return myContractAddr, nil + }, + expResult: &types.QueryContractAddressResponse{ + Address: myContractAddr.String(), + }, + }, + "not found": { + srcMsg: types.QueryContractAddressRequest{ContractType: types.PoEContractTypeMixer}, + mockFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { + return nil, wasmtypes.ErrNotFound + }, + expErrCode: codes.NotFound, + }, + "other error": { + srcMsg: types.QueryContractAddressRequest{ContractType: types.PoEContractTypeMixer}, + mockFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { + return nil, errors.New("testing") + }, + expErrCode: codes.Internal, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + q := NewGrpcQuerier(ContractSourceMock{GetPoEContractAddressFn: spec.mockFn}, nil) + ctx := sdk.Context{}.WithContext(context.Background()) + gotRes, gotErr := q.ContractAddress(sdk.WrapSDKContext(ctx), &spec.srcMsg) + if spec.expErrCode != 0 { + require.Error(t, gotErr) + assert.Equal(t, spec.expErrCode, status.Code(gotErr)) + return + } + require.NoError(t, gotErr) + assert.Equal(t, spec.expResult, gotRes) + }) + } +} + +func TestQueryValidators(t *testing.T) { + var myValsetContract sdk.AccAddress = rand.Bytes(sdk.AddrLen) + contractSource := newContractSourceMock(t, myValsetContract, nil) + + pubKey := ed25519.GenPrivKey().PubKey() + expValidator := types.ValidatorFixtureFixture(func(m *stakingtypes.Validator) { + pkAny, _ := codectypes.NewAnyWithValue(pubKey) + m.ConsensusPubkey = pkAny + }) + + querier := SmartQuerierMock{func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return json.Marshal(contract.ListValidatorsResponse{Validators: []contract.OperatorResponse{ + { + Operator: expValidator.OperatorAddress, + Pubkey: contract.ValidatorPubkey{Ed25519: pubKey.Bytes()}, + Metadata: contract.MetadataFromDescription(expValidator.Description), + }, + }}) + }} + specs := map[string]struct { + src *stakingtypes.QueryValidatorsRequest + querier types.SmartQuerier + exp *stakingtypes.QueryValidatorsResponse + expErr bool + }{ + "all good": { + src: &stakingtypes.QueryValidatorsRequest{}, + querier: querier, + exp: &stakingtypes.QueryValidatorsResponse{ + Validators: []stakingtypes.Validator{expValidator}, + }, + }, + "nil request": { + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + t.Fatalf("not expected to be called") + return nil, nil + }}, + expErr: true, + }, + "empty result": { + src: &stakingtypes.QueryValidatorsRequest{}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + r := contract.ListValidatorsResponse{} + return json.Marshal(r) + }}, + exp: &stakingtypes.QueryValidatorsResponse{ + Validators: []stakingtypes.Validator{}, + }, + }, + "nil result": { + src: &stakingtypes.QueryValidatorsRequest{}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return nil, nil + }}, + expErr: true, + }, + "contract returns error": { + src: &stakingtypes.QueryValidatorsRequest{}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return nil, errors.New("testing") + }}, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + ctx := sdk.WrapSDKContext(sdk.Context{}.WithContext(context.Background())) + + // when + s := NewGrpcQuerier(contractSource, spec.querier) + gotRes, gotErr := s.Validators(ctx, spec.src) + + // then + if spec.expErr { + assert.Error(t, gotErr) + return + } + require.NoError(t, gotErr) + assert.Equal(t, spec.exp, gotRes) + }) + } +} + +func TestQueryValidator(t *testing.T) { + var myValsetContract sdk.AccAddress = rand.Bytes(sdk.AddrLen) + var myOperator sdk.AccAddress = rand.Bytes(sdk.AddrLen) + + contractSource := newContractSourceMock(t, myValsetContract, nil) + + pubKey := ed25519.GenPrivKey().PubKey() + expValidator := types.ValidatorFixtureFixture(func(m *stakingtypes.Validator) { + pkAny, _ := codectypes.NewAnyWithValue(pubKey) + m.ConsensusPubkey = pkAny + }) + + querier := SmartQuerierMock{func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return json.Marshal(contract.ValidatorResponse{Validator: &contract.OperatorResponse{ + Operator: expValidator.OperatorAddress, + Pubkey: contract.ValidatorPubkey{Ed25519: pubKey.Bytes()}, + Metadata: contract.MetadataFromDescription(expValidator.Description), + }}) + }} + specs := map[string]struct { + src *stakingtypes.QueryValidatorRequest + querier types.SmartQuerier + exp *stakingtypes.QueryValidatorResponse + expErr bool + }{ + "all good": { + src: &stakingtypes.QueryValidatorRequest{ValidatorAddr: myOperator.String()}, + querier: querier, + exp: &stakingtypes.QueryValidatorResponse{ + Validator: expValidator, + }, + }, + "nil request": { + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + t.Fatalf("not expected to be called") + return nil, nil + }}, + expErr: true, + }, + "empty address": { + src: &stakingtypes.QueryValidatorRequest{}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + t.Fatalf("not expected to be called") + return nil, nil + }}, + expErr: true, + }, + "not found": { + src: &stakingtypes.QueryValidatorRequest{ValidatorAddr: myOperator.String()}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return nil, nil + }}, + expErr: true, + }, + "contract returns error": { + src: &stakingtypes.QueryValidatorRequest{ValidatorAddr: myOperator.String()}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return nil, errors.New("testing") + }}, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + ctx := sdk.WrapSDKContext(sdk.Context{}.WithContext(context.Background())) + + // when + s := NewGrpcQuerier(contractSource, spec.querier) + gotRes, gotErr := s.Validator(ctx, spec.src) + + // then + if spec.expErr { + assert.Error(t, gotErr) + return + } + require.NoError(t, gotErr) + assert.Equal(t, spec.exp, gotRes) + }) + } +} + +func TestQueryUnbondingPeriod(t *testing.T) { + var myStakingContract sdk.AccAddress = rand.Bytes(sdk.AddrLen) + contractSource := newContractSourceMock(t, nil, myStakingContract) + + specs := map[string]struct { + src *types.QueryUnbondingPeriodRequest + querier types.SmartQuerier + exp *types.QueryUnbondingPeriodResponse + expErr bool + }{ + "all good": { + src: &types.QueryUnbondingPeriodRequest{}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return json.Marshal(contract.UnbondingPeriodResponse{ + UnbondingPeriod: contract.Duration{Time: 1, Height: 2}, + }) + }}, + exp: &types.QueryUnbondingPeriodResponse{ + Time: time.Second, + Height: 2, + }, + }, + "nil request": { + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + t.Fatalf("not expected to be called") + return nil, nil + }}, + expErr: true, + }, + "contract returns nil": { + src: &types.QueryUnbondingPeriodRequest{}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return nil, nil + }}, + expErr: true, + }, + "contract returns error": { + src: &types.QueryUnbondingPeriodRequest{}, + querier: SmartQuerierMock{QuerySmartFn: func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return nil, errors.New("testing") + }}, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + ctx := sdk.WrapSDKContext(sdk.Context{}.WithContext(context.Background())) + + // when + s := NewGrpcQuerier(contractSource, spec.querier) + gotRes, gotErr := s.UnbondingPeriod(ctx, spec.src) + + // then + if spec.expErr { + assert.Error(t, gotErr) + return + } + require.NoError(t, gotErr) + assert.Equal(t, spec.exp, gotRes) + }) + } +} diff --git a/x/poe/keeper/keeper.go b/x/poe/keeper/keeper.go index cddb2d7f..49c7398b 100644 --- a/x/poe/keeper/keeper.go +++ b/x/poe/keeper/keeper.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/tendermint/tendermint/libs/log" ) @@ -16,6 +17,7 @@ type Keeper struct { storeKey sdk.StoreKey } +// NewKeeper constructor func NewKeeper(marshaler codec.Marshaler, key sdk.StoreKey) Keeper { return Keeper{marshaler: marshaler, storeKey: key} } @@ -62,6 +64,11 @@ func (k Keeper) GetPoESystemAdminAddress(ctx sdk.Context) sdk.AccAddress { return store.Get(types.SystemAdminPrefix) } +func (k Keeper) GetLastValidators(ctx sdk.Context) []stakingtypes.Validator { + panic("implement") + return nil +} + func ModuleLogger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) } diff --git a/x/poe/keeper/msg_server.go b/x/poe/keeper/msg_server.go index 06327149..4aaf4133 100644 --- a/x/poe/keeper/msg_server.go +++ b/x/poe/keeper/msg_server.go @@ -20,12 +20,13 @@ type ContractSource interface { type msgServer struct { contractSource ContractSource contractKeeper wasmtypes.ContractOpsKeeper + smartQuerier types.SmartQuerier } // NewMsgServerImpl returns an implementation of the bank MsgServer interface // for the provided Keeper. -func NewMsgServerImpl(poeKeeper ContractSource, contractKeeper wasmtypes.ContractOpsKeeper) types.MsgServer { - return &msgServer{contractSource: poeKeeper, contractKeeper: contractKeeper} +func NewMsgServerImpl(poeKeeper ContractSource, contractKeeper wasmtypes.ContractOpsKeeper, q types.SmartQuerier) types.MsgServer { + return &msgServer{contractSource: poeKeeper, contractKeeper: contractKeeper, smartQuerier: q} } var _ types.MsgServer = msgServer{} @@ -98,7 +99,7 @@ func (m msgServer) UpdateValidator(goCtx context.Context, msg *types.MsgUpdateVa ctx := sdk.UnwrapSDKContext(goCtx) if _, err := msg.Description.EnsureLength(); err != nil { - return nil, err + return nil, sdkerrors.Wrap(err, "description") } contractAddr, err := m.contractSource.GetPoEContractAddress(ctx, types.PoEContractTypeValset) @@ -110,7 +111,24 @@ func (m msgServer) UpdateValidator(goCtx context.Context, msg *types.MsgUpdateVa return nil, sdkerrors.Wrap(err, "delegator address") } - err = contract.UpdateValidator(ctx, contractAddr, delegatorAddress, msg.Description, m.contractKeeper) + // client sends a diff. we need to query the old description and merge it + current, err := contract.QueryValidator(ctx, m.smartQuerier, contractAddr, delegatorAddress) + if err != nil { + return nil, sdkerrors.Wrap(err, "query current description") + } + if current == nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownAddress, "operator") + } + validator, err := current.ToValidator() + if err != nil { + return nil, sdkerrors.Wrap(err, "to validator") + } + newDescr, err := validator.Description.UpdateDescription(msg.Description) + if err != nil { + return nil, sdkerrors.Wrap(err, "merge description") + } + // do the update + err = contract.UpdateValidator(ctx, contractAddr, delegatorAddress, newDescr, m.contractKeeper) if err != nil { return nil, sdkerrors.Wrap(err, "update validator") } diff --git a/x/poe/keeper/msg_server_test.go b/x/poe/keeper/msg_server_test.go index 3af92753..eef1faad 100644 --- a/x/poe/keeper/msg_server_test.go +++ b/x/poe/keeper/msg_server_test.go @@ -2,6 +2,8 @@ package keeper import ( "context" + "encoding/json" + "github.com/confio/tgrade/x/poe/contract" "github.com/confio/tgrade/x/poe/types" wasmtesting "github.com/confio/tgrade/x/twasm/testing" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -12,8 +14,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/libs/rand" types1 "github.com/tendermint/tendermint/proto/tendermint/types" + "strings" "testing" ) @@ -21,6 +25,9 @@ func TestCreateValidator(t *testing.T) { var myValsetContract sdk.AccAddress = rand.Bytes(sdk.AddrLen) var myStakingContract sdk.AccAddress = rand.Bytes(sdk.AddrLen) var myDelegatorAddr sdk.AccAddress = rand.Bytes(sdk.AddrLen) + + contractSource := newContractSourceMock(t, myValsetContract, myStakingContract) + specs := map[string]struct { src *types.MsgCreateValidator expErr *sdkerrors.Error @@ -46,19 +53,6 @@ func TestCreateValidator(t *testing.T) { } for name, spec := range specs { t.Run(name, func(t *testing.T) { - cm := ContractSourceMock{ - GetPoEContractAddressFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { - switch ctype { - case types.PoEContractTypeValset: - return myValsetContract, nil - case types.PoEContractTypeStaking: - return myStakingContract, nil - default: - t.Fatalf("unexpected type: %s", ctype) - return nil, nil - } - }, - } fn, execs := wasmtesting.CaptureExecuteFn() km := &wasmtesting.ContractOpsKeeperMock{ ExecuteFn: fn, @@ -68,7 +62,7 @@ func TestCreateValidator(t *testing.T) { Validator: &types1.ValidatorParams{PubKeyTypes: []string{"ed25519"}}})) // when - s := NewMsgServerImpl(cm, km) + s := NewMsgServerImpl(contractSource, km, nil) gotRes, gotErr := s.CreateValidator(ctx, spec.src) // then @@ -79,7 +73,7 @@ func TestCreateValidator(t *testing.T) { } require.NoError(t, gotErr) // and contract called - assert.Len(t, *execs, 2) + require.Len(t, *execs, 2) assert.Equal(t, myValsetContract, (*execs)[0].ContractAddress) assert.Equal(t, myDelegatorAddr, (*execs)[0].Caller) assert.Nil(t, (*execs)[0].Coins) @@ -94,5 +88,213 @@ func TestCreateValidator(t *testing.T) { assert.Equal(t, types.EventTypeCreateValidator, em.Events()[1].Type) }) } +} + +func TestUpdateValidator(t *testing.T) { + var myValsetContract sdk.AccAddress = rand.Bytes(sdk.AddrLen) + var myStakingContract sdk.AccAddress = rand.Bytes(sdk.AddrLen) + var myOperatorAddr sdk.AccAddress = rand.Bytes(sdk.AddrLen) + + contractSource := newContractSourceMock(t, myValsetContract, myStakingContract) + + desc := contract.MetadataFromDescription(stakingtypes.Description{ + Moniker: "myMoniker", + Identity: "myIdentity", + Website: "https://example.com", + SecurityContact: "myContact", + Details: "myDetails", + }) + querier := SmartQuerierMock{func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + return json.Marshal(contract.ValidatorResponse{Validator: &contract.OperatorResponse{ + Operator: RandomAddress(t).String(), + Pubkey: contract.ValidatorPubkey{Ed25519: ed25519.GenPrivKey().PubKey().Bytes()}, + Metadata: desc, + }}) + }} + specs := map[string]struct { + src *types.MsgUpdateValidator + exp *contract.ValidatorMetadata + expErr *sdkerrors.Error + }{ + "update all": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.DelegatorAddress = myOperatorAddr.String() + m.Description = stakingtypes.NewDescription( + "otherMoniker", + "otherIdentity", + "https://otherWebsite", + "otherContact", + "otherDetails", + ) + }, + ), + exp: &contract.ValidatorMetadata{ + Moniker: "otherMoniker", + Identity: "otherIdentity", + Website: "https://otherWebsite", + SecurityContact: "otherContact", + Details: "otherDetails", + }, + }, + "partial update: moniker": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.DelegatorAddress = myOperatorAddr.String() + m.Description = stakingtypes.NewDescription( + "otherMoniker", + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + ) + }, + ), + exp: &contract.ValidatorMetadata{ + Moniker: "otherMoniker", + Identity: "myIdentity", + Website: "https://example.com", + SecurityContact: "myContact", + Details: "myDetails", + }, + }, + "partial update: Identity": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.DelegatorAddress = myOperatorAddr.String() + m.Description = stakingtypes.NewDescription( + stakingtypes.DoNotModifyDesc, + "otherIdentity", + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + ) + }, + ), + exp: &contract.ValidatorMetadata{ + Moniker: "myMoniker", + Identity: "otherIdentity", + Website: "https://example.com", + SecurityContact: "myContact", + Details: "myDetails", + }, + }, + "partial update: Website": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.DelegatorAddress = myOperatorAddr.String() + m.Description = stakingtypes.NewDescription( + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + "otherWebsite", + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + ) + }, + ), + exp: &contract.ValidatorMetadata{ + Moniker: "myMoniker", + Identity: "myIdentity", + Website: "otherWebsite", + SecurityContact: "myContact", + Details: "myDetails", + }, + }, + "partial update: Details": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.DelegatorAddress = myOperatorAddr.String() + m.Description = stakingtypes.NewDescription( + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + "otherDetails", + ) + }, + ), + exp: &contract.ValidatorMetadata{ + Moniker: "myMoniker", + Identity: "myIdentity", + Website: "https://example.com", + SecurityContact: "myContact", + Details: "otherDetails", + }, + }, + "partial update: SecurityContact": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.DelegatorAddress = myOperatorAddr.String() + m.Description = stakingtypes.NewDescription( + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + "otherContact", + stakingtypes.DoNotModifyDesc, + ) + }, + ), + exp: &contract.ValidatorMetadata{ + Moniker: "myMoniker", + Identity: "myIdentity", + Website: "https://example.com", + SecurityContact: "otherContact", + Details: "myDetails", + }, + }, + "set empty values": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.DelegatorAddress = myOperatorAddr.String() + m.Description = stakingtypes.NewDescription("otherMoniker", "", "", "", "") + }, + ), + exp: &contract.ValidatorMetadata{Moniker: "otherMoniker"}, + }, + "invalid description": { + src: types.MsgUpdateValidatorFixture( + func(m *types.MsgUpdateValidator) { + m.Description.Moniker = strings.Repeat("x", 71) + }, + ), + expErr: sdkerrors.ErrInvalidRequest, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + fn, execs := wasmtesting.CaptureExecuteFn() + km := &wasmtesting.ContractOpsKeeperMock{ + ExecuteFn: fn, + } + em := sdk.NewEventManager() + ctx := sdk.WrapSDKContext(sdk.Context{}.WithContext(context.Background()).WithEventManager(em)) + + // when + s := NewMsgServerImpl(contractSource, km, querier) + gotRes, gotErr := s.UpdateValidator(ctx, spec.src) + + // then + if spec.expErr != nil { + require.True(t, spec.expErr.Is(gotErr), "exp %v but got %#+v", spec.expErr, gotErr) + assert.Nil(t, gotRes) + return + } + require.NoError(t, gotErr) + // and contract called + assert.Len(t, *execs, 1) + assert.Equal(t, myValsetContract, (*execs)[0].ContractAddress) + assert.Equal(t, myOperatorAddr, (*execs)[0].Caller) + // ensure we pass the right data + var op contract.TG4ValsetExecute + require.NoError(t, json.Unmarshal((*execs)[0].Msg, &op)) + assert.Equal(t, spec.exp, op.UpdateMetadata) + assert.Nil(t, (*execs)[0].Coins) + // and events emitted + require.NoError(t, gotErr) + require.Len(t, em.Events(), 2) + assert.Equal(t, sdk.EventTypeMessage, em.Events()[0].Type) + assert.Equal(t, types.EventTypeUpdateValidator, em.Events()[1].Type) + }) + } } diff --git a/x/poe/keeper/querier.go b/x/poe/keeper/querier.go deleted file mode 100644 index b059644c..00000000 --- a/x/poe/keeper/querier.go +++ /dev/null @@ -1,33 +0,0 @@ -package keeper - -import ( - "context" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/confio/tgrade/x/poe/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -var _ types.QueryServer = &grpcQuerier{} - -type grpcQuerier struct { - keeper ContractSource -} - -// NewGrpcQuerier constructor -func NewGrpcQuerier(keeper ContractSource) *grpcQuerier { - return &grpcQuerier{keeper: keeper} -} - -// ContractAddress query PoE contract address for given type -func (g grpcQuerier) ContractAddress(c context.Context, request *types.QueryContractAddressRequest) (*types.QueryContractAddressResponse, error) { - addr, err := g.keeper.GetPoEContractAddress(sdk.UnwrapSDKContext(c), request.ContractType) - switch { - case wasmtypes.ErrNotFound.Is(err): - return nil, status.Error(codes.NotFound, err.Error()) - case err != nil: - return nil, status.Error(codes.Internal, err.Error()) - } - return &types.QueryContractAddressResponse{Address: addr.String()}, nil -} diff --git a/x/poe/keeper/querier_test.go b/x/poe/keeper/querier_test.go deleted file mode 100644 index 4d0f2be6..00000000 --- a/x/poe/keeper/querier_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package keeper - -import ( - "context" - "errors" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/confio/tgrade/x/poe/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/libs/rand" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "testing" -) - -func TestQueryContractAddress(t *testing.T) { - var myContractAddr sdk.AccAddress = rand.Bytes(sdk.AddrLen) - specs := map[string]struct { - srcMsg types.QueryContractAddressRequest - mockFn func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) - expResult *types.QueryContractAddressResponse - expErrCode codes.Code - }{ - "return address": { - srcMsg: types.QueryContractAddressRequest{ContractType: types.PoEContractTypeMixer}, - mockFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { - return myContractAddr, nil - }, - expResult: &types.QueryContractAddressResponse{ - Address: myContractAddr.String(), - }, - }, - "not found": { - srcMsg: types.QueryContractAddressRequest{ContractType: types.PoEContractTypeMixer}, - mockFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { - return nil, wasmtypes.ErrNotFound - }, - expErrCode: codes.NotFound, - }, - "other error": { - srcMsg: types.QueryContractAddressRequest{ContractType: types.PoEContractTypeMixer}, - mockFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { - return nil, errors.New("testing") - }, - expErrCode: codes.Internal, - }, - } - for name, spec := range specs { - t.Run(name, func(t *testing.T) { - q := NewGrpcQuerier(ContractSourceMock{GetPoEContractAddressFn: spec.mockFn}) - ctx := sdk.Context{}.WithContext(context.Background()) - gotRes, gotErr := q.ContractAddress(sdk.WrapSDKContext(ctx), &spec.srcMsg) - if spec.expErrCode != 0 { - require.Error(t, gotErr) - assert.Equal(t, spec.expErrCode, status.Code(gotErr)) - return - } - require.NoError(t, gotErr) - assert.Equal(t, spec.expResult, gotRes) - }) - } - -} diff --git a/x/poe/keeper/staking.go b/x/poe/keeper/staking.go deleted file mode 100644 index 029a7c50..00000000 --- a/x/poe/keeper/staking.go +++ /dev/null @@ -1,52 +0,0 @@ -package keeper - -import ( - "context" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/distribution/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -// StakingAdapter connect to POE contract - -var _ wasmtypes.StakingKeeper = &StakingAdapter{} -var _ wasmtypes.DistributionKeeper = &StakingAdapter{} - -type StakingAdapter struct { - k *Keeper - contractKeeper wasmtypes.ContractOpsKeeper -} - -func NewStakingAdapter(k *Keeper, contractKeeper wasmtypes.ContractOpsKeeper) StakingAdapter { - return StakingAdapter{k: k, contractKeeper: contractKeeper} - -} - -func (s StakingAdapter) BondDenom(ctx sdk.Context) (res string) { - panic("implement me") // TODO (Alex): can be satisfied by contract -} - -func (s StakingAdapter) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) { - panic("implement me") // TODO (Alex): can be satisfied by contract -} - -func (s StakingAdapter) GetBondedValidatorsByPower(ctx sdk.Context) []stakingtypes.Validator { - panic("implement me") // TODO (Alex): can be satisfied by contract -} - -func (s StakingAdapter) GetAllDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress) []stakingtypes.Delegation { - return nil -} - -func (s StakingAdapter) GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (delegation stakingtypes.Delegation, found bool) { - return -} - -func (s StakingAdapter) HasReceivingRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) bool { - return false -} - -func (s StakingAdapter) DelegationRewards(c context.Context, req *types.QueryDelegationRewardsRequest) (*types.QueryDelegationRewardsResponse, error) { - return nil, nil -} diff --git a/x/poe/keeper/test_common.go b/x/poe/keeper/test_common.go index 21277f5e..8c67ea90 100644 --- a/x/poe/keeper/test_common.go +++ b/x/poe/keeper/test_common.go @@ -4,6 +4,7 @@ import ( "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" "github.com/CosmWasm/wasmd/x/wasm/keeper/wasmtesting" + "github.com/confio/tgrade/x/poe/stakingadapter" "github.com/confio/tgrade/x/poe/types" "github.com/confio/tgrade/x/twasm" twasmkeeper "github.com/confio/tgrade/x/twasm/keeper" @@ -41,8 +42,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/params" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" - slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/cosmos-sdk/x/upgrade" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" @@ -142,23 +141,18 @@ func createTestInput( paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, keyParams, tkeyParams) paramsKeeper.Subspace(authtypes.ModuleName) paramsKeeper.Subspace(banktypes.ModuleName) - paramsKeeper.Subspace(stakingtypes.ModuleName) paramsKeeper.Subspace(minttypes.ModuleName) paramsKeeper.Subspace(distributiontypes.ModuleName) - paramsKeeper.Subspace(slashingtypes.ModuleName) paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(capabilitytypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) maccPerms := map[string][]string{ // module account permissions - authtypes.FeeCollectorName: nil, - distributiontypes.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}, + authtypes.FeeCollectorName: nil, + minttypes.ModuleName: {authtypes.Minter}, + govtypes.ModuleName: {authtypes.Burner}, + ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, } authSubsp, _ := paramsKeeper.GetSubspace(authtypes.ModuleName) authKeeper := authkeeper.NewAccountKeeper( @@ -204,7 +198,7 @@ func createTestInput( querier := baseapp.NewGRPCQueryRouter() banktypes.RegisterQueryServer(querier, bankKeeper) - stakingAdapter := NewStakingAdapter(nil, nil) + stakingAdapter := stakingadapter.NewStakingAdapter(nil, nil) twasmSubspace := paramsKeeper.Subspace(twasmtypes.DefaultParamspace) twasmKeeper := twasmkeeper.NewKeeper( appCodec, diff --git a/x/poe/keeper/test_mocks.go b/x/poe/keeper/test_mocks.go index 79a818ad..693ee4bb 100644 --- a/x/poe/keeper/test_mocks.go +++ b/x/poe/keeper/test_mocks.go @@ -3,6 +3,7 @@ package keeper import ( "github.com/confio/tgrade/x/poe/types" sdk "github.com/cosmos/cosmos-sdk/types" + "testing" ) var _ ContractSource = ContractSourceMock{} @@ -63,3 +64,40 @@ func CaptureSetPoEContractAddressFn() (func(ctx sdk.Context, ctype types.PoECont r = append(r, CapturedPoEContractAddress{Ctype: ctype, ContractAddr: contractAddr}) }, &r } + +var _ types.SmartQuerier = SmartQuerierMock{} + +// SmartQuerierMock Mock queries to a contract +type SmartQuerierMock struct { + QuerySmartFn func(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) +} + +func (m SmartQuerierMock) QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) { + if m.QuerySmartFn == nil { + panic("not expected to be called") + } + return m.QuerySmartFn(ctx, contractAddr, req) +} + +// return matching type or fail +func newContractSourceMock(t *testing.T, myValsetContract sdk.AccAddress, myStakingContract sdk.AccAddress) ContractSourceMock { + return ContractSourceMock{ + GetPoEContractAddressFn: func(ctx sdk.Context, ctype types.PoEContractType) (sdk.AccAddress, error) { + switch ctype { + case types.PoEContractTypeValset: + if myValsetContract == nil { + t.Fatalf("unexpected call to %s", types.PoEContractTypeValset) + } + return myValsetContract, nil + case types.PoEContractTypeStaking: + if myStakingContract == nil { + t.Fatalf("unexpected call to %s", types.PoEContractTypeValset) + } + return myStakingContract, nil + default: + t.Fatalf("unexpected type: %s", ctype) + return nil, nil + } + }, + } +} diff --git a/x/poe/module.go b/x/poe/module.go index bd3e8722..0239047e 100644 --- a/x/poe/module.go +++ b/x/poe/module.go @@ -16,10 +16,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/gorilla/mux" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/spf13/cobra" abci "github.com/tendermint/tendermint/abci/types" + "sync" ) var ( @@ -44,6 +47,8 @@ func (AppModuleBasic) RegisterLegacyAminoCodec(amino *codec.LegacyAmino) { // RegisterInterfaces registers the module's interface types func (b AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { types.RegisterInterfaces(registry) + slashingtypes.RegisterInterfaces(registry) + stakingtypes.RegisterInterfaces(registry) } // DefaultGenesis returns default genesis state as raw bytes for the genutil @@ -90,13 +95,14 @@ type AppModule struct { twasmKeeper twasmKeeper contractKeeper wasmtypes.ContractOpsKeeper poeKeeper keeper.Keeper + doOnce sync.Once } // twasmKeeper subset of keeper to decouple from twasm module type twasmKeeper interface { abciKeeper - QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) - Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte) ([]byte, error) + types.SmartQuerier + types.Sudoer SetPrivileged(ctx sdk.Context, contractAddr sdk.AccAddress) error HasPrivilegedContract(ctx sdk.Context, contractAddr sdk.AccAddress, privilegeType twasmtypes.PrivilegeType) (bool, error) } @@ -123,7 +129,7 @@ func (am AppModule) RegisterInvariants(registry sdk.InvariantRegistry) { } func (am AppModule) Route() sdk.Route { - return sdk.NewRoute(types.RouterKey, NewHandler(am.poeKeeper, am.contractKeeper)) + return sdk.NewRoute(types.RouterKey, NewHandler(am.poeKeeper, am.contractKeeper, am.twasmKeeper)) } func (am AppModule) QuerierRoute() string { @@ -135,21 +141,21 @@ func (am AppModule) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier { } func (am AppModule) RegisterServices(cfg module.Configurator) { - types.RegisterQueryServer(cfg.QueryServer(), keeper.NewGrpcQuerier(am.poeKeeper)) - types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.poeKeeper, am.contractKeeper)) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewGrpcQuerier(am.poeKeeper, am.twasmKeeper)) + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.poeKeeper, am.contractKeeper, am.twasmKeeper)) } func (am AppModule) BeginBlock(context sdk.Context, block abci.RequestBeginBlock) { } func (am AppModule) EndBlock(context sdk.Context, block abci.RequestEndBlock) []abci.ValidatorUpdate { + am.doOnce.Do(ClearEmbeddedContracts) // release memory return EndBlocker(context, am.twasmKeeper) } // InitGenesis performs genesis initialization for the genutil module. It returns // no validator updates. func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data json.RawMessage) []abci.ValidatorUpdate { - defer clearEmbeddedContracts() var genesisState types.GenesisState cdc.MustUnmarshalJSON(data, &genesisState) if len(genesisState.GenTxs) == 0 { diff --git a/x/poe/module_test.go b/x/poe/module_test.go index 7f7a7cae..1081e0ac 100644 --- a/x/poe/module_test.go +++ b/x/poe/module_test.go @@ -18,6 +18,60 @@ import ( "testing" ) +func TestInitGenesis(t *testing.T) { + // scenario: + // setup some genTX with random staking value + // add the operators to the engagement group + // when init genesis is executed + // then validators should be found in valset diff + // and contracts state as expected + ctx, example := keeper.CreateDefaultTestInput(t) + ctx = ctx.WithBlockHeight(0) + deliverTXFn := unAuthorizedDeliverTXFn(t, ctx, example.PoEKeeper, example.TWasmKeeper.GetContractKeeper(), example.EncodingConfig.TxConfig.TxDecoder()) + app := NewAppModule(example.PoEKeeper, example.TWasmKeeper, deliverTXFn, example.EncodingConfig.TxConfig, example.TWasmKeeper.GetContractKeeper()) + + const numValidators = 15 + mutator, myValidators := withRandomValidators(t, ctx, example, numValidators) + gs := types.GenesisStateFixture(mutator) + + // when + genesisBz := example.EncodingConfig.Marshaler.MustMarshalJSON(&gs) + gotValset := app.InitGenesis(ctx, example.EncodingConfig.Marshaler, genesisBz) + + // then valset diff matches + assert.Equal(t, valsetAsMap(myValidators.expValidatorSet()), valsetAsMap(gotValset)) // compare unordered + + // and engagement group is setup as expected + addr, err := example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeEngagement) + require.NoError(t, err) + gotMembers := queryAllMembers(t, ctx, example.TWasmKeeper, addr) + assert.Equal(t, myValidators.expEngagementGroup(), gotMembers) + + // and staking group setup as expected + addr, err = example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeStaking) + gotMembers = queryAllMembers(t, ctx, example.TWasmKeeper, addr) + assert.Equal(t, myValidators.expStakingGroup(), gotMembers) + + // and valset config + addr, err = example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeValset) + require.NoError(t, err) + + gotValsetConfig, err := contract.QueryValsetConfig(ctx, example.TWasmKeeper, addr) + require.NoError(t, err) + + mixerAddr, err := example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeMixer) + require.NoError(t, err) + + expConfig := &contract.ValsetConfigResponse{ + Membership: mixerAddr.String(), + MinWeight: 1, + MaxValidators: 100, + Scaling: 0, + } + assert.Equal(t, expConfig, gotValsetConfig) + +} + type validators []validator type validator struct { @@ -72,86 +126,37 @@ func (v validators) expStakingGroup() []contract.TG4Member { return contract.SortByWeightDesc(r) } -func TestInitGenesis(t *testing.T) { - // scenario: - // setup some genTX with random staking value - // add the operators to the engagement group - // when init genesis is executed - // then validators should be found in valset diff - // and contracts state as expected - ctx, example := keeper.CreateDefaultTestInput(t) - ctx = ctx.WithBlockHeight(0) - deliverTXFn := unAuthorizedDeliverTXFn(t, ctx, example.PoEKeeper, example.TWasmKeeper.GetContractKeeper(), example.EncodingConfig.TxConfig.TxDecoder()) - app := NewAppModule(example.PoEKeeper, example.TWasmKeeper, deliverTXFn, example.EncodingConfig.TxConfig, example.TWasmKeeper.GetContractKeeper()) - - const numValidators = 15 - myValidators := make(validators, numValidators) - gs := types.GenesisStateFixture( - func(m *types.GenesisState) { - f := fuzz.New() - m.GenTxs = make([]json.RawMessage, numValidators) - m.Engagement = make([]types.TG4Member, numValidators) - for i := 0; i < numValidators; i++ { - var ( // power * engagement must be less than 10^18 (constraint is in the contract) - power uint16 - engagement uint16 - ) - f.NilChance(0).Fuzz(&power) // must be > 0 so that staked amount is > 0 - f.Fuzz(&engagement) - - genTx, opAddr, pubKey := types.RandomGenTX(t, uint32(power)) - myValidators[i] = validator{ - operatorAddr: opAddr, - pubKey: pubKey, - stakedAmount: sdk.TokensFromConsensusPower(int64(power)).Uint64(), - engagement: uint64(engagement), - } - m.GenTxs[i] = genTx - m.Engagement[i] = types.TG4Member{Address: opAddr.String(), Weight: uint64(engagement)} - example.AccountKeeper.NewAccountWithAddress(ctx, opAddr) - example.BankKeeper.SetBalances(ctx, opAddr, sdk.NewCoins( - sdk.NewCoin(types.DefaultBondDenom, sdk.NewIntFromUint64(myValidators[i].stakedAmount)), - )) +// return genesis mutator that adds the given mumber of validators to the genesis +func withRandomValidators(t *testing.T, ctx sdk.Context, example keeper.TestKeepers, numValidators int) (func(m *types.GenesisState), validators) { + collectValidators := make(validators, numValidators) + return func(m *types.GenesisState) { + f := fuzz.New() + m.GenTxs = make([]json.RawMessage, numValidators) + m.Engagement = make([]types.TG4Member, numValidators) + for i := 0; i < numValidators; i++ { + var ( // power * engagement must be less than 10^18 (constraint is in the contract) + power uint16 + engagement uint16 + ) + f.NilChance(0).Fuzz(&power) // must be > 0 so that staked amount is > 0 + f.Fuzz(&engagement) + + genTx, opAddr, pubKey := types.RandomGenTX(t, uint32(power)) + stakedAmount := sdk.TokensFromConsensusPower(int64(power)).Uint64() + collectValidators[i] = validator{ + operatorAddr: opAddr, + pubKey: pubKey, + stakedAmount: stakedAmount, + engagement: uint64(engagement), } - }, - ) - - // when - genesisBz := example.EncodingConfig.Marshaler.MustMarshalJSON(&gs) - gotValset := app.InitGenesis(ctx, example.EncodingConfig.Marshaler, genesisBz) - - // then valset diff matches - assert.Equal(t, valsetAsMap(myValidators.expValidatorSet()), valsetAsMap(gotValset)) // compare unordered - - // and engagement group is setup as expected - addr, err := example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeEngagement) - require.NoError(t, err) - gotMembers := queryAllMembers(t, ctx, example.TWasmKeeper, addr) - assert.Equal(t, myValidators.expEngagementGroup(), gotMembers) - - // and staking group setup as expected - addr, err = example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeStaking) - gotMembers = queryAllMembers(t, ctx, example.TWasmKeeper, addr) - assert.Equal(t, myValidators.expStakingGroup(), gotMembers) - - // and valset config - addr, err = example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeValset) - require.NoError(t, err) - - gotValsetConfig, err := contract.QueryValsetConfig(ctx, example.TWasmKeeper, addr) - require.NoError(t, err) - - mixerAddr, err := example.PoEKeeper.GetPoEContractAddress(ctx, types.PoEContractTypeMixer) - require.NoError(t, err) - - expConfig := &contract.ValsetConfigResponse{ - Membership: mixerAddr.String(), - MinWeight: 1, - MaxValidators: 100, - Scaling: 0, - } - assert.Equal(t, expConfig, gotValsetConfig) - + m.GenTxs[i] = genTx + m.Engagement[i] = types.TG4Member{Address: opAddr.String(), Weight: uint64(engagement)} + example.AccountKeeper.NewAccountWithAddress(ctx, opAddr) + example.BankKeeper.SetBalances(ctx, opAddr, sdk.NewCoins( + sdk.NewCoin(types.DefaultBondDenom, sdk.NewIntFromUint64(stakedAmount)), + )) + } + }, collectValidators } func queryAllMembers(t *testing.T, ctx sdk.Context, k *twasmkeeper.Keeper, addr sdk.AccAddress) []contract.TG4Member { @@ -163,7 +168,7 @@ func queryAllMembers(t *testing.T, ctx sdk.Context, k *twasmkeeper.Keeper, addr // unAuthorizedDeliverTXFn applies the TX without ante handler checks for testing purpose func unAuthorizedDeliverTXFn(t *testing.T, ctx sdk.Context, k keeper.Keeper, contractKeeper wasmtypes.ContractOpsKeeper, txDecoder sdk.TxDecoder) func(tx abci.RequestDeliverTx) abci.ResponseDeliverTx { t.Helper() - h := NewHandler(k, contractKeeper) + h := NewHandler(k, contractKeeper, nil) return func(tx abci.RequestDeliverTx) abci.ResponseDeliverTx { genTx, err := txDecoder(tx.GetTx()) require.NoError(t, err) diff --git a/x/poe/stakingadapter/keeper.go b/x/poe/stakingadapter/keeper.go new file mode 100644 index 00000000..6d4ab9cb --- /dev/null +++ b/x/poe/stakingadapter/keeper.go @@ -0,0 +1,133 @@ +package stakingadapter + +import ( + "context" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "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" + ibccoretypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + abci "github.com/tendermint/tendermint/abci/types" + "time" +) + +// StakingAdapter connect to POE contract + +var _ wasmtypes.StakingKeeper = &StakingAdapter{} +var _ wasmtypes.DistributionKeeper = &StakingAdapter{} +var _ wasmkeeper.ValidatorSetSource = &StakingAdapter{} +var _ ibccoretypes.StakingKeeper = &StakingAdapter{} +var _ evidencetypes.StakingKeeper = &StakingAdapter{} +var _ slashingtypes.StakingKeeper = &StakingAdapter{} +var _ minttypes.StakingKeeper = &StakingAdapter{} +var _ govtypes.StakingKeeper = &StakingAdapter{} + +type poeKeeper interface{} + +type StakingAdapter struct { + k poeKeeper + contractKeeper wasmtypes.ContractOpsKeeper +} + +func NewStakingAdapter(k poeKeeper, contractKeeper wasmtypes.ContractOpsKeeper) StakingAdapter { + return StakingAdapter{k: k, contractKeeper: contractKeeper} + +} + +func (s StakingAdapter) BondDenom(ctx sdk.Context) (res string) { + panic("implement me") // TODO (Alex): can be satisfied by contract +} + +func (s StakingAdapter) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) { + panic("implement me") // TODO (Alex): can be satisfied by contract +} + +func (s StakingAdapter) GetBondedValidatorsByPower(ctx sdk.Context) []stakingtypes.Validator { + panic("implement me") // TODO (Alex): can be satisfied by contract +} + +func (s StakingAdapter) GetAllDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress) []stakingtypes.Delegation { + return nil +} + +func (s StakingAdapter) GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (delegation stakingtypes.Delegation, found bool) { + return +} + +func (s StakingAdapter) HasReceivingRedelegation(ctx sdk.Context, delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) bool { + return false +} + +func (s StakingAdapter) DelegationRewards(c context.Context, req *types.QueryDelegationRewardsRequest) (*types.QueryDelegationRewardsResponse, error) { + return nil, nil +} + +func (s StakingAdapter) GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool) { + panic("implement me") +} + +func (s StakingAdapter) UnbondingTime(ctx sdk.Context) time.Duration { + panic("implement me") +} + +func (s StakingAdapter) ValidatorByConsAddr(ctx sdk.Context, address sdk.ConsAddress) stakingtypes.ValidatorI { + panic("implement me") +} + +func (s StakingAdapter) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []abci.ValidatorUpdate, err error) { + ctx.Logger().Error("NOT IMPLEMENTED") + return nil, nil +} + +func (s StakingAdapter) IterateValidators(ctx sdk.Context, f func(index int64, validator stakingtypes.ValidatorI) (stop bool)) { + panic("implement me") +} + +func (s StakingAdapter) Validator(ctx sdk.Context, address sdk.ValAddress) stakingtypes.ValidatorI { + panic("implement me") +} + +func (s StakingAdapter) Slash(ctx sdk.Context, address sdk.ConsAddress, i int64, i2 int64, dec sdk.Dec) { + panic("implement me") +} + +func (s StakingAdapter) Jail(ctx sdk.Context, address sdk.ConsAddress) { + panic("implement me") +} + +func (s StakingAdapter) Unjail(ctx sdk.Context, address sdk.ConsAddress) { + panic("implement me") +} + +func (s StakingAdapter) Delegation(ctx sdk.Context, address sdk.AccAddress, address2 sdk.ValAddress) stakingtypes.DelegationI { + panic("implement me") +} + +func (s StakingAdapter) MaxValidators(ctx sdk.Context) uint32 { + panic("implement me") +} + +func (s StakingAdapter) StakingTokenSupply(ctx sdk.Context) sdk.Int { + panic("implement me") +} + +func (s StakingAdapter) BondedRatio(ctx sdk.Context) sdk.Dec { + panic("implement me") +} + +func (s2 StakingAdapter) IterateBondedValidatorsByPower(s sdk.Context, f func(index int64, validator stakingtypes.ValidatorI) (stop bool)) { + panic("implement me") +} + +func (s2 StakingAdapter) TotalBondedTokens(s sdk.Context) sdk.Int { + panic("implement me") +} + +func (s2 StakingAdapter) IterateDelegations(ctx sdk.Context, delegator sdk.AccAddress, fn func(index int64, delegation stakingtypes.DelegationI) (stop bool)) { + panic("implement me") +} diff --git a/x/poe/stakingadapter/slashing.go b/x/poe/stakingadapter/slashing.go new file mode 100644 index 00000000..cc252723 --- /dev/null +++ b/x/poe/stakingadapter/slashing.go @@ -0,0 +1,44 @@ +package stakingadapter + +import ( + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + "time" +) + +var _ evidencetypes.SlashingKeeper = &SlashingAdapter{} + +type SlashingAdapter struct{} + +func (s SlashingAdapter) GetPubkey(context sdk.Context, address cryptotypes.Address) (cryptotypes.PubKey, error) { + panic("implement me") +} + +func (s SlashingAdapter) IsTombstoned(context sdk.Context, address sdk.ConsAddress) bool { + panic("implement me") +} + +func (s SlashingAdapter) HasValidatorSigningInfo(context sdk.Context, address sdk.ConsAddress) bool { + panic("implement me") +} + +func (s SlashingAdapter) Tombstone(context sdk.Context, address sdk.ConsAddress) { + panic("implement me") +} + +func (s SlashingAdapter) Slash(context sdk.Context, address sdk.ConsAddress, dec sdk.Dec, i int64, i2 int64) { + panic("implement me") +} + +func (s SlashingAdapter) SlashFractionDoubleSign(context sdk.Context) sdk.Dec { + panic("implement me") +} + +func (s SlashingAdapter) Jail(context sdk.Context, address sdk.ConsAddress) { + panic("implement me") +} + +func (s SlashingAdapter) JailUntil(context sdk.Context, address sdk.ConsAddress, time time.Time) { + panic("implement me") +} diff --git a/x/poe/types/codec.go b/x/poe/types/codec.go index 913f7762..fd5cc954 100644 --- a/x/poe/types/codec.go +++ b/x/poe/types/codec.go @@ -12,12 +12,14 @@ import ( // on the provided LegacyAmino codec. These types are used for Amino JSON serialization. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterConcrete(&MsgCreateValidator{}, "tgrade/MsgCreateValidator", nil) + cdc.RegisterConcrete(&MsgUpdateValidator{}, "tgrade/MsgUpdateValidator", nil) } // RegisterInterfaces registers the x/poe interfaces types with the interface registry func RegisterInterfaces(registry types.InterfaceRegistry) { registry.RegisterImplementations((*sdk.Msg)(nil), &MsgCreateValidator{}, + &MsgUpdateValidator{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/poe/types/expected_keepers.go b/x/poe/types/expected_keepers.go new file mode 100644 index 00000000..87d9f7b8 --- /dev/null +++ b/x/poe/types/expected_keepers.go @@ -0,0 +1,17 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +type SmartQuerier interface { + QuerySmart(ctx sdk.Context, contractAddr sdk.AccAddress, req []byte) ([]byte, error) +} + +// Sudoer with access to sudo method +type Sudoer interface { + Sudo(ctx sdk.Context, contractAddress sdk.AccAddress, msg []byte) ([]byte, error) +} + +// Executor with access to excute method +type Executor interface { + Execute(ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins) ([]byte, error) +} diff --git a/x/poe/types/msg.go b/x/poe/types/msg.go index 7441ca05..74b9312d 100644 --- a/x/poe/types/msg.go +++ b/x/poe/types/msg.go @@ -142,15 +142,19 @@ func (msg MsgUpdateValidator) GetSignBytes() []byte { // ValidateBasic implements the sdk.Msg interface. func (msg MsgUpdateValidator) ValidateBasic() error { // note that unmarshaling from bech32 ensures either empty or valid - delAddr, err := sdk.AccAddressFromBech32(msg.DelegatorAddress) + _, err := sdk.AccAddressFromBech32(msg.DelegatorAddress) if err != nil { return err } - if delAddr.Empty() { - return stakingtypes.ErrEmptyDelegatorAddr - } - if msg.Description == (stakingtypes.Description{}) { + if msg.Description == (stakingtypes.Description{}) || + msg.Description == stakingtypes.NewDescription( + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + ) { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "empty description") } diff --git a/x/poe/types/msg_test.go b/x/poe/types/msg_test.go index afc3261f..73671688 100644 --- a/x/poe/types/msg_test.go +++ b/x/poe/types/msg_test.go @@ -1,13 +1,13 @@ -package types_test +package types import ( - "github.com/confio/tgrade/x/poe/types" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/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" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/bech32" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/stretchr/testify/require" "testing" @@ -25,7 +25,7 @@ var ( func TestMsgDecode(t *testing.T) { registry := codectypes.NewInterfaceRegistry() cryptocodec.RegisterInterfaces(registry) - types.RegisterInterfaces(registry) + RegisterInterfaces(registry) cdc := codec.NewProtoCodec(registry) // firstly we start testing the pubkey serialization @@ -39,7 +39,7 @@ func TestMsgDecode(t *testing.T) { // now let's try to serialize the whole message - msg, err := types.NewMsgCreateValidator(valAddr1, pk1, coinPos, stakingtypes.Description{}) + msg, err := NewMsgCreateValidator(valAddr1, pk1, coinPos, stakingtypes.Description{}) require.NoError(t, err) msgSerialized, err := cdc.MarshalInterface(msg) require.NoError(t, err) @@ -47,7 +47,7 @@ func TestMsgDecode(t *testing.T) { var msgUnmarshaled sdk.Msg err = cdc.UnmarshalInterface(msgSerialized, &msgUnmarshaled) require.NoError(t, err) - msg2, ok := msgUnmarshaled.(*types.MsgCreateValidator) + msg2, ok := msgUnmarshaled.(*MsgCreateValidator) require.True(t, ok) require.True(t, msg.Value.IsEqual(msg2.Value)) require.True(t, msg.Pubkey.Equal(msg2.Pubkey)) @@ -74,7 +74,7 @@ func TestMsgCreateValidator(t *testing.T) { for _, tc := range tests { description := stakingtypes.NewDescription(tc.moniker, tc.identity, tc.website, tc.securityContact, tc.details) - msg, err := types.NewMsgCreateValidator(tc.delegatorAddr, tc.pubkey, tc.bond, description) + msg, err := NewMsgCreateValidator(tc.delegatorAddr, tc.pubkey, tc.bond, description) require.NoError(t, err) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name) @@ -83,3 +83,56 @@ func TestMsgCreateValidator(t *testing.T) { } } } + +func TestMsgUpdateValidatorValidateBasic(t *testing.T) { + specs := map[string]struct { + src *MsgUpdateValidator + expErr bool + }{ + "all good": { + src: MsgUpdateValidatorFixture(), + }, + "empty description": { + src: MsgUpdateValidatorFixture(func(m *MsgUpdateValidator) { + m.Description = stakingtypes.Description{} + }), + expErr: true, + }, + "do not modify description": { + src: MsgUpdateValidatorFixture(func(m *MsgUpdateValidator) { + m.Description = stakingtypes.NewDescription( + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + stakingtypes.DoNotModifyDesc, + ) + }), + expErr: true, + }, + "invalid address": { + src: MsgUpdateValidatorFixture(func(m *MsgUpdateValidator) { + m.DelegatorAddress = "notAValidAddress" + }), + expErr: true, + }, + "empty address": { + src: MsgUpdateValidatorFixture(func(m *MsgUpdateValidator) { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + bech32Addr, _ := bech32.ConvertAndEncode(bech32PrefixAccAddr, []byte{}) + m.DelegatorAddress = bech32Addr + }), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + gotErr := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, gotErr) + return + } + require.NoError(t, gotErr) + }) + } +} diff --git a/x/poe/types/poe.pb.go b/x/poe/types/poe.pb.go index 37f5e9bc..50867892 100644 --- a/x/poe/types/poe.pb.go +++ b/x/poe/types/poe.pb.go @@ -5,10 +5,15 @@ package types import ( fmt "fmt" - _ "github.com/CosmWasm/wasmd/x/wasm/types" + _ "github.com/cosmos/cosmos-sdk/codec/types" _ "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/x/staking/types" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-proto" + _ "github.com/tendermint/tendermint/proto/tendermint/types" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/timestamppb" math "math" ) @@ -65,27 +70,30 @@ func init() { func init() { proto.RegisterFile("confio/poe/v1beta1/poe.proto", fileDescriptor_df6d9ea68813554a) } var fileDescriptor_df6d9ea68813554a = []byte{ - // 344 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0xd1, 0x41, 0x4b, 0xf3, 0x30, - 0x18, 0xc0, 0xf1, 0xf6, 0x7d, 0xf7, 0xee, 0xc5, 0x5c, 0x2c, 0x65, 0xca, 0x16, 0x66, 0x28, 0x4c, - 0x11, 0x14, 0x57, 0x86, 0x77, 0x61, 0xba, 0x38, 0x86, 0xae, 0x88, 0xeb, 0x86, 0x78, 0x4b, 0xbb, - 0x2c, 0x16, 0x6d, 0x52, 0x9a, 0xa8, 0xdb, 0x37, 0x90, 0x9e, 0xfc, 0x02, 0x3d, 0xf9, 0x65, 0x3c, - 0xee, 0xe8, 0x51, 0xb6, 0x8b, 0x1f, 0x43, 0xda, 0x4d, 0x84, 0x5e, 0xc2, 0x43, 0xfe, 0x3f, 0x72, - 0xc8, 0x03, 0xea, 0xbe, 0xe0, 0x93, 0x40, 0xd8, 0x91, 0xa0, 0xf6, 0x53, 0xcb, 0xa3, 0x8a, 0xb4, - 0xb2, 0xb9, 0x19, 0xc5, 0x42, 0x09, 0xd3, 0x5c, 0xd5, 0x66, 0x76, 0xb3, 0xae, 0xb0, 0xc2, 0x04, - 0x13, 0x79, 0xb6, 0xb3, 0x69, 0x25, 0x21, 0xf2, 0x85, 0x0c, 0x85, 0xb4, 0x3d, 0x22, 0x7f, 0x1f, - 0xf2, 0x45, 0xc0, 0xd7, 0xbd, 0x91, 0xf5, 0x67, 0x22, 0x43, 0x3b, 0x3f, 0x7e, 0x04, 0xa3, 0x9c, - 0xca, 0x40, 0xae, 0xd0, 0xc1, 0x97, 0x0e, 0x36, 0xaf, 0x04, 0x3e, 0x13, 0x5c, 0xc5, 0xc4, 0x57, - 0xee, 0x2c, 0xa2, 0xe6, 0x21, 0xd8, 0x18, 0x3a, 0x1d, 0x7c, 0xde, 0x73, 0x70, 0xc7, 0xd0, 0x60, - 0x3d, 0x49, 0xad, 0x6a, 0xc1, 0x0c, 0xf9, 0x98, 0x4e, 0x02, 0x4e, 0xc7, 0xe6, 0x3e, 0xf8, 0x3f, - 0x70, 0xdb, 0x17, 0x3d, 0xa7, 0x6b, 0xe8, 0x10, 0x26, 0xa9, 0xb5, 0x5d, 0xa0, 0x03, 0x45, 0xee, - 0x03, 0xce, 0xcc, 0x3d, 0x50, 0x1e, 0xb5, 0x2f, 0x07, 0xd8, 0x35, 0xfe, 0xc0, 0x5a, 0x92, 0x5a, - 0x5b, 0x05, 0x37, 0x22, 0x0f, 0x92, 0x2a, 0xf3, 0x08, 0x00, 0xec, 0x74, 0xdb, 0x5d, 0xdc, 0xc7, - 0x8e, 0x6b, 0xfc, 0x85, 0x3b, 0x49, 0x6a, 0xd5, 0x0a, 0x14, 0x73, 0x46, 0x18, 0x0d, 0x29, 0x57, - 0x66, 0x03, 0xfc, 0xeb, 0xf7, 0x6e, 0xf0, 0xb5, 0x51, 0x82, 0xd5, 0x24, 0xb5, 0x2a, 0x05, 0xd9, - 0x0f, 0xa6, 0x34, 0x86, 0xa5, 0x97, 0x37, 0xa4, 0x9d, 0x9e, 0xbc, 0x2f, 0x90, 0x3e, 0x5f, 0x20, - 0xfd, 0x73, 0x81, 0xf4, 0xd7, 0x25, 0xd2, 0xe6, 0x4b, 0xa4, 0x7d, 0x2c, 0x91, 0x76, 0xbb, 0xcb, - 0x02, 0x75, 0xf7, 0xe8, 0x35, 0x7d, 0x11, 0xda, 0xeb, 0xe5, 0x28, 0x16, 0x93, 0x31, 0xb5, 0xa7, - 0xf9, 0x96, 0xd4, 0x2c, 0xa2, 0xd2, 0x2b, 0xe7, 0x3f, 0x76, 0xfc, 0x1d, 0x00, 0x00, 0xff, 0xff, - 0xbe, 0xff, 0xa2, 0xc5, 0xc0, 0x01, 0x00, 0x00, + // 397 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x92, 0x41, 0x8b, 0xd3, 0x40, + 0x14, 0xc7, 0x13, 0x5d, 0x57, 0x9c, 0x8b, 0x21, 0xac, 0xb2, 0x1d, 0xea, 0x18, 0x70, 0x45, 0x50, + 0xec, 0xb0, 0x78, 0x17, 0xaa, 0x3b, 0x96, 0xa2, 0x0d, 0x62, 0xd3, 0x22, 0x5e, 0x64, 0x92, 0x4c, + 0xc7, 0xc1, 0x66, 0x5e, 0x48, 0xa6, 0xd2, 0x7e, 0x03, 0xc9, 0xc9, 0x2f, 0x90, 0x93, 0x5f, 0xc6, + 0x63, 0x8f, 0x1e, 0xa5, 0xbd, 0xf8, 0x31, 0xa4, 0x99, 0xd4, 0x85, 0x5c, 0xc2, 0xfb, 0xe7, 0xf7, + 0xe3, 0xcd, 0xe3, 0xf1, 0x50, 0x3f, 0x01, 0xbd, 0x50, 0x40, 0x73, 0x10, 0xf4, 0xdb, 0x65, 0x2c, + 0x0c, 0xbf, 0x3c, 0xd4, 0x83, 0xbc, 0x00, 0x03, 0xbe, 0x6f, 0xe9, 0xe0, 0xf0, 0xa7, 0xa5, 0xf8, + 0x4c, 0x82, 0x84, 0x06, 0xd3, 0x43, 0x65, 0x4d, 0xdc, 0x93, 0x00, 0x72, 0x29, 0x68, 0x93, 0xe2, + 0xd5, 0x82, 0x72, 0xbd, 0x69, 0x11, 0xe9, 0xa2, 0x74, 0x55, 0x70, 0xa3, 0x40, 0xb7, 0xfc, 0x61, + 0x97, 0x1b, 0x95, 0x89, 0xd2, 0xf0, 0x2c, 0x3f, 0xf6, 0x4e, 0xa0, 0xcc, 0xa0, 0xfc, 0x6c, 0x1f, + 0xb5, 0xe1, 0xd8, 0xdb, 0x26, 0x1a, 0xf3, 0xf2, 0x7a, 0xfe, 0x04, 0xd4, 0xb1, 0xf7, 0x45, 0xcb, + 0x4b, 0xc3, 0xbf, 0x2a, 0x2d, 0xff, 0x2b, 0x6d, 0x6e, 0xad, 0xbe, 0x11, 0x3a, 0x15, 0x45, 0xa6, + 0xb4, 0xa1, 0x66, 0x93, 0x8b, 0xd2, 0x7e, 0x2d, 0x7d, 0xfa, 0xd7, 0x45, 0x77, 0xdf, 0x03, 0x7b, + 0x0d, 0xda, 0x14, 0x3c, 0x31, 0xd1, 0x26, 0x17, 0xfe, 0x33, 0x74, 0x67, 0x16, 0x5e, 0xb1, 0x37, + 0xe3, 0x90, 0x5d, 0x79, 0x0e, 0xee, 0x57, 0x75, 0x70, 0xde, 0x71, 0x66, 0x3a, 0x15, 0x0b, 0xa5, + 0x45, 0xea, 0x3f, 0x41, 0xb7, 0xa7, 0xd1, 0xf0, 0xed, 0x38, 0x1c, 0x79, 0x2e, 0xc6, 0x55, 0x1d, + 0xdc, 0xef, 0xa8, 0x53, 0x3b, 0x8d, 0xff, 0x18, 0x9d, 0xce, 0x87, 0xef, 0xa6, 0x2c, 0xf2, 0x6e, + 0xe0, 0x5e, 0x55, 0x07, 0xf7, 0x3a, 0xde, 0x9c, 0x2f, 0x4b, 0x61, 0xfc, 0xe7, 0x08, 0xb1, 0x70, + 0x34, 0x1c, 0xb1, 0x09, 0x0b, 0x23, 0xef, 0x26, 0x7e, 0x50, 0xd5, 0x41, 0xaf, 0xa3, 0x32, 0x2d, + 0xb9, 0x14, 0x99, 0xd0, 0xc6, 0x7f, 0x84, 0x6e, 0x4d, 0xc6, 0x1f, 0xd9, 0x07, 0xef, 0x04, 0x9f, + 0x57, 0x75, 0x70, 0xd6, 0x31, 0x27, 0x6a, 0x2d, 0x0a, 0x7c, 0xf2, 0xfd, 0x27, 0x71, 0x5e, 0xbd, + 0xfc, 0xb5, 0x23, 0xee, 0x76, 0x47, 0xdc, 0x3f, 0x3b, 0xe2, 0xfe, 0xd8, 0x13, 0x67, 0xbb, 0x27, + 0xce, 0xef, 0x3d, 0x71, 0x3e, 0x5d, 0x48, 0x65, 0xbe, 0xac, 0xe2, 0x41, 0x02, 0x19, 0x6d, 0x4f, + 0xc6, 0xc8, 0x82, 0xa7, 0x82, 0xae, 0x9b, 0xdb, 0x69, 0x16, 0x16, 0x9f, 0x36, 0x1b, 0x7b, 0xf1, + 0x2f, 0x00, 0x00, 0xff, 0xff, 0x40, 0xba, 0x2a, 0x86, 0x56, 0x02, 0x00, 0x00, } diff --git a/x/poe/types/query.pb.go b/x/poe/types/query.pb.go index 5675b16b..d6c31924 100644 --- a/x/poe/types/query.pb.go +++ b/x/poe/types/query.pb.go @@ -7,22 +7,27 @@ import ( context "context" fmt "fmt" _ "github.com/cosmos/cosmos-sdk/types/query" + types "github.com/cosmos/cosmos-sdk/x/staking/types" _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + _ "google.golang.org/protobuf/types/known/durationpb" io "io" math "math" math_bits "math/bits" + time "time" ) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +var _ = time.Kitchen // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -116,37 +121,147 @@ func (m *QueryContractAddressResponse) GetAddress() string { return "" } +// QueryUnbondingPeriodRequest is request type for the Query/UnbondingPeriod RPC +// method +type QueryUnbondingPeriodRequest struct { +} + +func (m *QueryUnbondingPeriodRequest) Reset() { *m = QueryUnbondingPeriodRequest{} } +func (m *QueryUnbondingPeriodRequest) String() string { return proto.CompactTextString(m) } +func (*QueryUnbondingPeriodRequest) ProtoMessage() {} +func (*QueryUnbondingPeriodRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_55a2242dcc0e0cfb, []int{2} +} +func (m *QueryUnbondingPeriodRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUnbondingPeriodRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUnbondingPeriodRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUnbondingPeriodRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUnbondingPeriodRequest.Merge(m, src) +} +func (m *QueryUnbondingPeriodRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryUnbondingPeriodRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUnbondingPeriodRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUnbondingPeriodRequest proto.InternalMessageInfo + +// QueryUnbondingPeriodResponse is response type for the Query/UnbondingPeriod +// RPC method +type QueryUnbondingPeriodResponse struct { + // Time is the time that must pass + Time time.Duration `protobuf:"bytes,1,opt,name=time,proto3,stdduration" json:"time"` + // Height is the number of blocks that must pass + Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` +} + +func (m *QueryUnbondingPeriodResponse) Reset() { *m = QueryUnbondingPeriodResponse{} } +func (m *QueryUnbondingPeriodResponse) String() string { return proto.CompactTextString(m) } +func (*QueryUnbondingPeriodResponse) ProtoMessage() {} +func (*QueryUnbondingPeriodResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_55a2242dcc0e0cfb, []int{3} +} +func (m *QueryUnbondingPeriodResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUnbondingPeriodResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUnbondingPeriodResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryUnbondingPeriodResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUnbondingPeriodResponse.Merge(m, src) +} +func (m *QueryUnbondingPeriodResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryUnbondingPeriodResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUnbondingPeriodResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUnbondingPeriodResponse proto.InternalMessageInfo + +func (m *QueryUnbondingPeriodResponse) GetTime() time.Duration { + if m != nil { + return m.Time + } + return 0 +} + +func (m *QueryUnbondingPeriodResponse) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + func init() { proto.RegisterType((*QueryContractAddressRequest)(nil), "confio.poe.v1beta1.QueryContractAddressRequest") proto.RegisterType((*QueryContractAddressResponse)(nil), "confio.poe.v1beta1.QueryContractAddressResponse") + proto.RegisterType((*QueryUnbondingPeriodRequest)(nil), "confio.poe.v1beta1.QueryUnbondingPeriodRequest") + proto.RegisterType((*QueryUnbondingPeriodResponse)(nil), "confio.poe.v1beta1.QueryUnbondingPeriodResponse") } func init() { proto.RegisterFile("confio/poe/v1beta1/query.proto", fileDescriptor_55a2242dcc0e0cfb) } var fileDescriptor_55a2242dcc0e0cfb = []byte{ - // 349 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xce, 0xcf, 0x4b, - 0xcb, 0xcc, 0xd7, 0x2f, 0xc8, 0x4f, 0xd5, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, - 0x2c, 0x4d, 0x2d, 0xaa, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x82, 0xc8, 0xeb, 0x15, - 0xe4, 0xa7, 0xea, 0x41, 0xe5, 0xa5, 0xb4, 0x92, 0xf3, 0x8b, 0x73, 0xf3, 0x8b, 0xf5, 0x93, 0x12, - 0x8b, 0x53, 0x21, 0x8a, 0xe1, 0x5a, 0x0b, 0x12, 0xd3, 0x33, 0xf3, 0x12, 0x4b, 0x32, 0xf3, 0xf3, - 0x20, 0xfa, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x2a, 0x2a, 0x93, - 0x9e, 0x9f, 0x9f, 0x9e, 0x93, 0xaa, 0x9f, 0x58, 0x90, 0xa9, 0x9f, 0x98, 0x97, 0x97, 0x5f, 0x02, - 0xd6, 0x52, 0x0c, 0x93, 0xc5, 0xe2, 0x26, 0x90, 0xfd, 0x60, 0x59, 0xa5, 0x42, 0x2e, 0xe9, 0x40, - 0x90, 0x9d, 0xce, 0xf9, 0x79, 0x25, 0x45, 0x89, 0xc9, 0x25, 0x8e, 0x29, 0x29, 0x45, 0xa9, 0xc5, - 0xc5, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x1e, 0x5c, 0xbc, 0xc9, 0x50, 0x99, 0xf8, - 0x92, 0xca, 0x82, 0x54, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x3e, 0x23, 0x65, 0x3d, 0x4c, 0x8f, 0xe8, - 0x05, 0xe4, 0xbb, 0xc2, 0x4c, 0x09, 0xa9, 0x2c, 0x48, 0x0d, 0xe2, 0x49, 0x46, 0xe2, 0x59, 0x71, - 0x74, 0x2c, 0x90, 0x67, 0x78, 0xb1, 0x40, 0x9e, 0x41, 0xc9, 0x82, 0x4b, 0x06, 0xbb, 0x95, 0xc5, - 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x12, 0x5c, 0xec, 0x89, 0x10, 0x21, 0xb0, 0x6d, 0x9c, 0x41, - 0x30, 0xae, 0xd1, 0x5a, 0x46, 0x2e, 0x56, 0xb0, 0x56, 0xa1, 0xc5, 0x8c, 0x5c, 0xfc, 0x68, 0xfa, - 0x85, 0xf4, 0xb1, 0x39, 0x0a, 0x8f, 0xe7, 0xa4, 0x0c, 0x88, 0xd7, 0x00, 0x71, 0x9a, 0x92, 0x6e, - 0xd3, 0xe5, 0x27, 0x93, 0x99, 0xd4, 0x85, 0x54, 0x51, 0x42, 0x13, 0xe6, 0x4f, 0xfd, 0x6a, 0x94, - 0xb0, 0xaa, 0x75, 0xb2, 0x3b, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, - 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x95, - 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x68, 0xfc, 0x94, 0xa4, 0x17, - 0x25, 0xa6, 0xa4, 0xea, 0x57, 0x80, 0x8d, 0x06, 0xe9, 0x2f, 0x4e, 0x62, 0x03, 0xc7, 0x91, 0x31, - 0x20, 0x00, 0x00, 0xff, 0xff, 0x7f, 0xbd, 0x07, 0x6a, 0x57, 0x02, 0x00, 0x00, + // 569 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0x4f, 0x6b, 0x13, 0x4f, + 0x18, 0xc7, 0x77, 0x4b, 0xdb, 0x5f, 0x3b, 0x3f, 0xb5, 0x30, 0x88, 0xc4, 0x58, 0x37, 0x61, 0xad, + 0x5a, 0xc4, 0xce, 0x98, 0x28, 0x54, 0x3c, 0x08, 0x56, 0x05, 0x8f, 0x35, 0xa8, 0x07, 0x2f, 0x65, + 0x76, 0x77, 0xba, 0x59, 0x6c, 0xe6, 0xd9, 0xec, 0xcc, 0x16, 0x43, 0xe9, 0xc5, 0x93, 0x47, 0x41, + 0x84, 0x1e, 0x0b, 0xde, 0x7c, 0x25, 0x3d, 0x16, 0xbc, 0x78, 0x52, 0x49, 0x3c, 0xf8, 0x32, 0x64, + 0x67, 0x67, 0xd3, 0xa4, 0xdd, 0x86, 0xdc, 0xe6, 0xd9, 0xe7, 0xdf, 0x67, 0x9e, 0xe7, 0x3b, 0x8b, + 0x1c, 0x1f, 0xc4, 0x76, 0x04, 0x34, 0x06, 0x4e, 0x77, 0x1b, 0x1e, 0x57, 0xac, 0x41, 0xbb, 0x29, + 0x4f, 0x7a, 0x24, 0x4e, 0x40, 0x01, 0xc6, 0xb9, 0x9f, 0xc4, 0xc0, 0x89, 0xf1, 0x57, 0xef, 0xf8, + 0x20, 0x3b, 0x20, 0xa9, 0xc7, 0x24, 0xcf, 0x83, 0x87, 0xa9, 0x31, 0x0b, 0x23, 0xc1, 0x54, 0x04, + 0x22, 0xcf, 0xaf, 0x5e, 0x0e, 0x21, 0x04, 0x7d, 0xa4, 0xd9, 0xc9, 0x7c, 0x75, 0x42, 0x80, 0x70, + 0x87, 0x53, 0x6d, 0x79, 0xe9, 0x36, 0x0d, 0xd2, 0x64, 0x34, 0x6b, 0xd9, 0xf8, 0x59, 0x1c, 0x51, + 0x26, 0x04, 0x28, 0xed, 0x94, 0x85, 0xb7, 0x84, 0x39, 0xe3, 0xcb, 0xbd, 0x2b, 0x86, 0x4e, 0x2a, + 0xf6, 0x2e, 0x12, 0xe1, 0x30, 0xc2, 0xd8, 0x26, 0xca, 0x3d, 0x27, 0x6a, 0xe4, 0xee, 0x6e, 0x17, + 0x5d, 0x7b, 0x99, 0x99, 0x4f, 0x41, 0xa8, 0x84, 0xf9, 0xea, 0x49, 0x10, 0x24, 0x5c, 0xca, 0x16, + 0xef, 0xa6, 0x5c, 0x2a, 0xfc, 0x02, 0x5d, 0xf4, 0x8d, 0x67, 0x4b, 0xf5, 0x62, 0x5e, 0xb1, 0xeb, + 0xf6, 0xea, 0xa5, 0xe6, 0x0d, 0x72, 0x76, 0x64, 0x64, 0x13, 0x9e, 0x17, 0x55, 0x5e, 0xf5, 0x62, + 0xde, 0xba, 0xe0, 0x8f, 0x58, 0x8f, 0x16, 0x3e, 0x1e, 0xd6, 0xac, 0xbf, 0x87, 0x35, 0xcb, 0x7d, + 0x88, 0x96, 0xcb, 0x5b, 0xca, 0x18, 0x84, 0xe4, 0xb8, 0x82, 0xfe, 0x63, 0xf9, 0x27, 0xdd, 0x6d, + 0xb1, 0x55, 0x98, 0xee, 0x75, 0x03, 0xfb, 0x5a, 0x78, 0x20, 0x82, 0x48, 0x84, 0x9b, 0x3c, 0x89, + 0x20, 0x30, 0xb0, 0x2e, 0x98, 0xc2, 0x67, 0xdc, 0xa6, 0xf0, 0x3a, 0x9a, 0x55, 0x51, 0x27, 0xbf, + 0xc3, 0xff, 0xcd, 0xab, 0x24, 0x5f, 0x00, 0x29, 0x16, 0x44, 0x9e, 0x99, 0x05, 0x6d, 0x2c, 0x1c, + 0xfd, 0xac, 0x59, 0x07, 0xbf, 0x6a, 0x76, 0x4b, 0x27, 0xe0, 0x2b, 0x68, 0xbe, 0xcd, 0xa3, 0xb0, + 0xad, 0x2a, 0x33, 0x75, 0x7b, 0x75, 0xb6, 0x65, 0xac, 0xe6, 0xc1, 0x1c, 0x9a, 0xd3, 0x1d, 0xf1, + 0x37, 0x1b, 0x2d, 0x9d, 0xba, 0x0f, 0xa6, 0x65, 0x43, 0x9a, 0x30, 0xec, 0xea, 0xbd, 0xe9, 0x13, + 0xf2, 0x1b, 0xb9, 0x0f, 0x3e, 0x7c, 0xff, 0xf3, 0x79, 0x86, 0xe0, 0xbb, 0x54, 0x85, 0x09, 0x0b, + 0xf8, 0x98, 0x5c, 0x8a, 0xf1, 0xd3, 0xbd, 0xb1, 0x15, 0xee, 0xe3, 0x2f, 0x36, 0x42, 0x6f, 0xd8, + 0x4e, 0x14, 0x30, 0x05, 0x89, 0xc4, 0x84, 0xe4, 0x3a, 0x21, 0x85, 0x7a, 0xc6, 0x5a, 0x9f, 0x04, + 0x16, 0x98, 0x74, 0xea, 0x78, 0x43, 0x79, 0x4b, 0x53, 0xd6, 0xb1, 0x53, 0x46, 0xb9, 0x7b, 0x02, + 0xf2, 0xd5, 0x46, 0x8b, 0xc3, 0x74, 0xbc, 0x36, 0x5d, 0x9b, 0x82, 0x8a, 0x4c, 0x1b, 0x6e, 0xa0, + 0xd6, 0x35, 0x54, 0x03, 0xd3, 0xc9, 0x50, 0x74, 0x6f, 0x78, 0xde, 0xca, 0x64, 0xb8, 0x9f, 0x51, + 0x2e, 0x9d, 0x52, 0xd8, 0x84, 0x55, 0x97, 0x4b, 0x75, 0xc2, 0xaa, 0xcf, 0x11, 0xaf, 0xbb, 0xa6, + 0x79, 0x6f, 0xe3, 0x9b, 0x65, 0xbc, 0xc5, 0x0b, 0x4f, 0x8b, 0xe4, 0x8d, 0xc7, 0x47, 0x7d, 0xc7, + 0x3e, 0xee, 0x3b, 0xf6, 0xef, 0xbe, 0x63, 0x7f, 0x1a, 0x38, 0xd6, 0xf1, 0xc0, 0xb1, 0x7e, 0x0c, + 0x1c, 0xeb, 0xed, 0x4a, 0x18, 0xa9, 0x76, 0xea, 0x11, 0x1f, 0x3a, 0xd4, 0xfc, 0x64, 0x4c, 0xc5, + 0xf7, 0xba, 0x66, 0xa6, 0x11, 0xe9, 0xcd, 0xeb, 0x57, 0x71, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x4f, 0xe2, 0xc9, 0x54, 0x3c, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -161,7 +276,14 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { + // ContractAddress queries the address for one of the PoE contracts ContractAddress(ctx context.Context, in *QueryContractAddressRequest, opts ...grpc.CallOption) (*QueryContractAddressResponse, error) + // Validators queries all validators that match the given status. + Validators(ctx context.Context, in *types.QueryValidatorsRequest, opts ...grpc.CallOption) (*types.QueryValidatorsResponse, error) + // Validator queries validator info for given validator address. + Validator(ctx context.Context, in *types.QueryValidatorRequest, opts ...grpc.CallOption) (*types.QueryValidatorResponse, error) + // Validator queries validator info for given validator address. + UnbondingPeriod(ctx context.Context, in *QueryUnbondingPeriodRequest, opts ...grpc.CallOption) (*QueryUnbondingPeriodResponse, error) } type queryClient struct { @@ -181,9 +303,43 @@ func (c *queryClient) ContractAddress(ctx context.Context, in *QueryContractAddr return out, nil } +func (c *queryClient) Validators(ctx context.Context, in *types.QueryValidatorsRequest, opts ...grpc.CallOption) (*types.QueryValidatorsResponse, error) { + out := new(types.QueryValidatorsResponse) + err := c.cc.Invoke(ctx, "/confio.poe.v1beta1.Query/Validators", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Validator(ctx context.Context, in *types.QueryValidatorRequest, opts ...grpc.CallOption) (*types.QueryValidatorResponse, error) { + out := new(types.QueryValidatorResponse) + err := c.cc.Invoke(ctx, "/confio.poe.v1beta1.Query/Validator", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) UnbondingPeriod(ctx context.Context, in *QueryUnbondingPeriodRequest, opts ...grpc.CallOption) (*QueryUnbondingPeriodResponse, error) { + out := new(QueryUnbondingPeriodResponse) + err := c.cc.Invoke(ctx, "/confio.poe.v1beta1.Query/UnbondingPeriod", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { + // ContractAddress queries the address for one of the PoE contracts ContractAddress(context.Context, *QueryContractAddressRequest) (*QueryContractAddressResponse, error) + // Validators queries all validators that match the given status. + Validators(context.Context, *types.QueryValidatorsRequest) (*types.QueryValidatorsResponse, error) + // Validator queries validator info for given validator address. + Validator(context.Context, *types.QueryValidatorRequest) (*types.QueryValidatorResponse, error) + // Validator queries validator info for given validator address. + UnbondingPeriod(context.Context, *QueryUnbondingPeriodRequest) (*QueryUnbondingPeriodResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -193,6 +349,15 @@ type UnimplementedQueryServer struct { func (*UnimplementedQueryServer) ContractAddress(ctx context.Context, req *QueryContractAddressRequest) (*QueryContractAddressResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ContractAddress not implemented") } +func (*UnimplementedQueryServer) Validators(ctx context.Context, req *types.QueryValidatorsRequest) (*types.QueryValidatorsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Validators not implemented") +} +func (*UnimplementedQueryServer) Validator(ctx context.Context, req *types.QueryValidatorRequest) (*types.QueryValidatorResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Validator not implemented") +} +func (*UnimplementedQueryServer) UnbondingPeriod(ctx context.Context, req *QueryUnbondingPeriodRequest) (*QueryUnbondingPeriodResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UnbondingPeriod not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -216,6 +381,60 @@ func _Query_ContractAddress_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Query_Validators_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(types.QueryValidatorsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Validators(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/confio.poe.v1beta1.Query/Validators", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Validators(ctx, req.(*types.QueryValidatorsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Validator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(types.QueryValidatorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Validator(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/confio.poe.v1beta1.Query/Validator", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Validator(ctx, req.(*types.QueryValidatorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_UnbondingPeriod_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryUnbondingPeriodRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UnbondingPeriod(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/confio.poe.v1beta1.Query/UnbondingPeriod", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UnbondingPeriod(ctx, req.(*QueryUnbondingPeriodRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "confio.poe.v1beta1.Query", HandlerType: (*QueryServer)(nil), @@ -224,6 +443,18 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "ContractAddress", Handler: _Query_ContractAddress_Handler, }, + { + MethodName: "Validators", + Handler: _Query_Validators_Handler, + }, + { + MethodName: "Validator", + Handler: _Query_Validator_Handler, + }, + { + MethodName: "UnbondingPeriod", + Handler: _Query_UnbondingPeriod_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "confio/poe/v1beta1/query.proto", @@ -287,6 +518,65 @@ func (m *QueryContractAddressResponse) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *QueryUnbondingPeriodRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUnbondingPeriodRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUnbondingPeriodRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryUnbondingPeriodResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryUnbondingPeriodResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUnbondingPeriodResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Height != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + n1, err1 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.Time):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintQuery(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -323,6 +613,29 @@ func (m *QueryContractAddressResponse) Size() (n int) { return n } +func (m *QueryUnbondingPeriodRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryUnbondingPeriodResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.Time) + n += 1 + l + sovQuery(uint64(l)) + if m.Height != 0 { + n += 1 + sovQuery(uint64(m.Height)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -480,6 +793,158 @@ func (m *QueryContractAddressResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryUnbondingPeriodRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUnbondingPeriodRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUnbondingPeriodRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUnbondingPeriodResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryUnbondingPeriodResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUnbondingPeriodResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/poe/types/query.pb.gw.go b/x/poe/types/query.pb.gw.go index 6f192e05..39e156dc 100644 --- a/x/poe/types/query.pb.gw.go +++ b/x/poe/types/query.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + types_3 "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" @@ -91,6 +92,114 @@ func local_request_Query_ContractAddress_0(ctx context.Context, marshaler runtim } +var ( + filter_Query_Validators_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Validators_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq types_3.QueryValidatorsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Validators_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Validators(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Validators_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq types_3.QueryValidatorsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Validators_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Validators(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq types_3.QueryValidatorRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := client.Validator(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Validator_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq types_3.QueryValidatorRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["validator_addr"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "validator_addr") + } + + protoReq.ValidatorAddr, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "validator_addr", err) + } + + msg, err := server.Validator(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_UnbondingPeriod_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnbondingPeriodRequest + var metadata runtime.ServerMetadata + + msg, err := client.UnbondingPeriod(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UnbondingPeriod_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUnbondingPeriodRequest + var metadata runtime.ServerMetadata + + msg, err := server.UnbondingPeriod(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -117,6 +226,66 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_Validators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Validators_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Validators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Validator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Validator_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Validator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UnbondingPeriod_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_UnbondingPeriod_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UnbondingPeriod_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -178,13 +347,85 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_Validators_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Validators_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Validators_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Validator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Validator_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Validator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_UnbondingPeriod_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_UnbondingPeriod_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_UnbondingPeriod_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } var ( - pattern_Query_ContractAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"poe", "v1beta1", "contract", "contract_type"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ContractAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"tgrade", "poe", "v1beta1", "contract", "contract_type"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Validators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"tgrade", "poe", "v1beta1", "validators"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Validator_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"tgrade", "poe", "v1beta1", "validators", "validator_addr"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_UnbondingPeriod_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"tgrade", "poe", "v1beta1", "staking", "unbonding"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( forward_Query_ContractAddress_0 = runtime.ForwardResponseMessage + + forward_Query_Validators_0 = runtime.ForwardResponseMessage + + forward_Query_Validator_0 = runtime.ForwardResponseMessage + + forward_Query_UnbondingPeriod_0 = runtime.ForwardResponseMessage ) diff --git a/x/poe/types/test_common.go b/x/poe/types/test_common.go index 6a3b5bc9..fe99ba21 100644 --- a/x/poe/types/test_common.go +++ b/x/poe/types/test_common.go @@ -44,7 +44,7 @@ func RandomAccAddress() sdk.AccAddress { } // RandomGenTX returns a signed genesis tx -func RandomGenTX(t *testing.T, power uint32) (json.RawMessage, sdk.AccAddress, cryptotypes.PubKey) { +func RandomGenTX(t *testing.T, power uint32, mutators ...func(*MsgCreateValidator)) (json.RawMessage, sdk.AccAddress, cryptotypes.PubKey) { t.Helper() nodeConfig := cfg.TestConfig() nodeConfig.RootDir = t.TempDir() @@ -70,6 +70,9 @@ func RandomGenTX(t *testing.T, power uint32) (json.RawMessage, sdk.AccAddress, c stakingtypes.NewDescription("testing", "", "", "", ""), ) require.NoError(t, err) + for _, m := range mutators { + m(createValMsg) + } txConfig := MakeEncodingConfig(t).TxConfig txBuilder := txConfig.NewTxBuilder() err = txBuilder.SetMsgs(createValMsg) diff --git a/x/poe/types/test_fixtures.go b/x/poe/types/test_fixtures.go index 377800e9..e35c87b1 100644 --- a/x/poe/types/test_fixtures.go +++ b/x/poe/types/test_fixtures.go @@ -1,6 +1,8 @@ package types import ( + "fmt" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -20,6 +22,16 @@ func MsgCreateValidatorFixture(mutators ...func(m *MsgCreateValidator)) *MsgCrea return r } +func MsgUpdateValidatorFixture(mutators ...func(m *MsgUpdateValidator)) *MsgUpdateValidator { + desc := stakingtypes.NewDescription("other-name", "foo", "http://example.com", "bar", "my details") + + r := NewMsgUpdateValidator(RandomAccAddress(), desc) + for _, m := range mutators { + m(r) + } + return r +} + func GenesisStateFixture(mutators ...func(m *GenesisState)) GenesisState { r := DefaultGenesisState() r.Engagement = []TG4Member{{ @@ -32,3 +44,27 @@ func GenesisStateFixture(mutators ...func(m *GenesisState)) GenesisState { } return r } + +func ValidatorFixtureFixture(mutators ...func(m *stakingtypes.Validator)) stakingtypes.Validator { + pkAny, err := codectypes.NewAnyWithValue(ed25519.GenPrivKey().PubKey()) + if err != nil { + panic(fmt.Sprintf("failed to encode any type: %s", err.Error())) + } + desc := stakingtypes.Description{ + Moniker: "myMoniker", + Identity: "myIdentity", + Website: "https://example.com", + SecurityContact: "myContact", + Details: "myDetails", + } + r := stakingtypes.Validator{ + OperatorAddress: RandomAccAddress().String(), + ConsensusPubkey: pkAny, + Description: desc, + } + + for _, m := range mutators { + m(&r) + } + return r +} diff --git a/x/twasm/keeper/keeper.go b/x/twasm/keeper/keeper.go index 2b3a75b4..fe8ee82b 100644 --- a/x/twasm/keeper/keeper.go +++ b/x/twasm/keeper/keeper.go @@ -5,6 +5,7 @@ import ( "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/confio/tgrade/x/twasm/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -53,6 +54,13 @@ func NewKeeper( // configure wasm keeper via options var handlerChain wasmkeeper.Messenger = wasmkeeper.NewMessageHandlerChain( + // disable staking messages + wasmkeeper.MessageHandlerFunc(func(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + if msg.Staking != nil { + return nil, nil, sdkerrors.Wrap(wasmtypes.ErrExecuteFailed, "not supported, yet") + } + return nil, nil, wasmtypes.ErrUnknownMsg + }), wasmkeeper.NewDefaultMessageHandler( router, channelKeeper, @@ -64,7 +72,11 @@ func NewKeeper( // append our custom message handler NewTgradeHandler(cdc, &result, bankKeeper, govRouter), ) - var queryPlugins wasmkeeper.WasmVMQueryHandler = wasmkeeper.DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, channelKeeper, queryRouter, &result.Keeper) + queryPlugins := wasmkeeper.DefaultQueryPlugins(bankKeeper, stakingKeeper, distKeeper, channelKeeper, queryRouter, &result.Keeper) + // disable staking queries + queryPlugins.Staking = func(ctx sdk.Context, request *wasmvmtypes.StakingQuery) ([]byte, error) { + return nil, wasmvmtypes.UnsupportedRequest{Kind: "not supported, yet"} + } opts = append([]wasm.Option{ wasmkeeper.WithMessageHandler(handlerChain), diff --git a/x/twasm/types/query.pb.go b/x/twasm/types/query.pb.go index 049f57a8..585bdac4 100644 --- a/x/twasm/types/query.pb.go +++ b/x/twasm/types/query.pb.go @@ -219,7 +219,7 @@ func init() { func init() { proto.RegisterFile("confio/twasm/v1beta1/query.proto", fileDescriptor_1dcfe179625ad95e) } var fileDescriptor_1dcfe179625ad95e = []byte{ - // 400 bytes of a gzipped FileDescriptorProto + // 404 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x48, 0xce, 0xcf, 0x4b, 0xcb, 0xcc, 0xd7, 0x2f, 0x29, 0x4f, 0x2c, 0xce, 0xd5, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0x2c, 0x4d, 0x2d, 0xaa, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x81, 0xa8, @@ -235,16 +235,17 @@ var fileDescriptor_1dcfe179625ad95e = []byte{ 0x01, 0x25, 0x5f, 0x2e, 0x15, 0xb0, 0x09, 0x70, 0x7d, 0x4e, 0x08, 0xc3, 0x42, 0x2a, 0x0b, 0x52, 0xa1, 0x36, 0x09, 0xa9, 0x72, 0xf1, 0x15, 0xc0, 0xc4, 0xe3, 0x41, 0xfe, 0x95, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0xe2, 0x2d, 0x40, 0x56, 0xad, 0xe4, 0xca, 0xa5, 0x4a, 0xc0, 0x38, 0x62, 0x5c, - 0x65, 0xd4, 0xc7, 0xcc, 0xc5, 0x0a, 0x36, 0x47, 0x68, 0x23, 0x23, 0x97, 0x30, 0x16, 0xdf, 0x09, - 0x99, 0xea, 0x61, 0x8b, 0x36, 0x3d, 0x02, 0x01, 0x26, 0x65, 0x46, 0xaa, 0x36, 0x88, 0x73, 0x95, - 0xb4, 0x9b, 0x2e, 0x3f, 0x99, 0xcc, 0xa4, 0x2a, 0xa4, 0x8c, 0x96, 0x90, 0xe0, 0x4e, 0xd6, 0x87, - 0x87, 0x43, 0x8a, 0xd0, 0x05, 0x46, 0x2e, 0x09, 0x5c, 0x01, 0x20, 0x64, 0x85, 0xc7, 0x05, 0x04, - 0x22, 0x41, 0xca, 0x9a, 0x2c, 0xbd, 0x50, 0x2f, 0x58, 0x83, 0xbd, 0x60, 0x2a, 0x64, 0x4c, 0xd8, - 0x0b, 0xfa, 0xd5, 0xa8, 0x71, 0x5d, 0xeb, 0xe4, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, - 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, - 0x72, 0x0c, 0x51, 0x6a, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xb0, - 0xbc, 0x96, 0x5e, 0x94, 0x98, 0x92, 0xaa, 0x5f, 0x01, 0xb5, 0x08, 0x9c, 0x3b, 0x92, 0xd8, 0xc0, - 0x89, 0xda, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x58, 0xb8, 0xa3, 0xa1, 0x91, 0x03, 0x00, 0x00, + 0x65, 0x34, 0x87, 0x99, 0x8b, 0x15, 0x6c, 0x8e, 0xd0, 0x0e, 0x46, 0x2e, 0x61, 0x2c, 0xbe, 0x13, + 0x32, 0xd5, 0xc3, 0x16, 0x6d, 0x7a, 0x04, 0x02, 0x4c, 0xca, 0x8c, 0x54, 0x6d, 0x10, 0xe7, 0x2a, + 0x19, 0x35, 0x5d, 0x7e, 0x32, 0x99, 0x49, 0x47, 0x48, 0x4b, 0xbf, 0x24, 0xbd, 0x28, 0x31, 0x25, + 0x15, 0x2d, 0x3d, 0xc1, 0x5d, 0xae, 0x0f, 0x0f, 0x8e, 0x14, 0xa1, 0xeb, 0x8c, 0x5c, 0x12, 0xb8, + 0xc2, 0x41, 0xc8, 0x0a, 0x8f, 0x43, 0x08, 0xc4, 0x85, 0x94, 0x35, 0x59, 0x7a, 0xa1, 0x3e, 0x71, + 0x02, 0xfb, 0xc4, 0x46, 0xc8, 0x8a, 0x68, 0x9f, 0xe8, 0x57, 0xa3, 0xc6, 0x7c, 0xad, 0x93, 0xc3, + 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, + 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0xa9, 0xa5, 0x67, 0x96, 0x64, 0x94, + 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0xc3, 0x72, 0x1e, 0xc4, 0x9a, 0x0a, 0xa8, 0x45, 0xe0, 0xbc, + 0x92, 0xc4, 0x06, 0x4e, 0xe2, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb8, 0xce, 0xbd, 0x3e, + 0x9f, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/twasm/types/query.pb.gw.go b/x/twasm/types/query.pb.gw.go index 3e35d684..f16d0638 100644 --- a/x/twasm/types/query.pb.gw.go +++ b/x/twasm/types/query.pb.gw.go @@ -234,9 +234,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_PrivilegedContracts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"twasm", "v1beta1", "contracts", "privileged"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_PrivilegedContracts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"tgrade", "twasm", "v1beta1", "contracts", "privileged"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_ContractsByPrivilegeType_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"twasm", "v1beta1", "contracts", "privilege", "privilege_type"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ContractsByPrivilegeType_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"tgrade", "twasm", "v1beta1", "contracts", "privilege", "privilege_type"}, "", runtime.AssumeColonVerbOpt(true))) ) var (