Merge branch 'master' into gov_split_vote_weighted_vote

This commit is contained in:
Sunny Aggarwal 2021-02-12 11:07:27 -05:00 committed by GitHub
commit 47f7502e72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 713 additions and 129 deletions

View File

@ -24,7 +24,7 @@ jobs:
make build-docs LEDGER_ENABLED=false
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
uses: JamesIves/github-pages-deploy-action@4.0.0
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages

View File

@ -67,6 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue
* (server) [\#8481](https://github.com/cosmos/cosmos-sdk/pull/8481) Don't create
files when running `{appd} tendermint show-*` subcommands
* (x/staking) [\#8546](https://github.com/cosmos/cosmos-sdk/pull/8546) Fix caching bug where concurrent calls to GetValidator could cause a node to crash
## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19

View File

@ -87,7 +87,7 @@ software and restore to their latest snapshot before restarting their nodes.
1) If your chain is using IBC, make sure to add IBC initial genesis state to the genesis file. You can use the following command to add IBC initial genesis state to the genesis file.
```shell
cat new_v040_genesis.json | jq '.app_state |= . + {"ibc":{"client_genesis":{"clients":[],"clients_consensus":[],"create_localhost":false},"connection_genesis":{"connections":[],"client_connection_paths":[]},"channel_genesis":{"channels":[],"acknowledgements":[],"commitments":[],"receipts":[],"send_sequences":[],"recv_sequences":[],"ack_sequences":[]}},"transfer":{"port_id":"transfer","denom_traces":[],"params":{"send_enabled":false,"receive_enabled":false}},"capability":{"index":"1","owners":[]}}' > new_v040_genesis.json
cat new_v040_genesis.json | jq '.app_state |= . + {"ibc":{"client_genesis":{"clients":[],"clients_consensus":[],"create_localhost":false},"connection_genesis":{"connections":[],"client_connection_paths":[]},"channel_genesis":{"channels":[],"acknowledgements":[],"commitments":[],"receipts":[],"send_sequences":[],"recv_sequences":[],"ack_sequences":[]}},"transfer":{"port_id":"transfer","denom_traces":[],"params":{"send_enabled":false,"receive_enabled":false}},"capability":{"index":"1","owners":[]}}' > tmp_genesis.json && mv tmp_genesis.json new_v040_genesis.json
```
**Note:** This would add IBC state with IBC's `send_enabled: false` and `receive_enabled: false`. Make sure to update them to `true` in the above command if are planning to enable IBC transactions with chain upgrade. Otherwise you can do it via a governance proposal.

View File

@ -1,10 +1,6 @@
# Cosmosvisor Quick Start
`cosmovisor` is a small process manager around Cosmos SDK binaries that uses the upgrade module to allow
for smooth and configurable management of upgrading binaries as a live chain is upgraded, and can be
used to simplify validator operations while doing upgrades or to make syncing a full node for genesis
simple. The `cosmovisor` program monitors the stdout of Cosmos SDK application's executable to look for
messages from the upgrade module indicating a pending or required upgrade and act appropriately.
`cosmovisor` is a small process manager around Cosmos SDK binaries that monitors the governance module via stdout to see if there's a chain upgrade proposal coming in. If it see a proposal that gets approved it can be run manually or automatically to download the new code, stop the node, run the migration script, replace the node binary, and start with the new genesis file.
## Installation

6
go.mod
View File

@ -38,7 +38,7 @@ require (
github.com/rs/zerolog v1.20.0
github.com/spf13/afero v1.3.4 // indirect
github.com/spf13/cast v1.3.1
github.com/spf13/cobra v1.1.1
github.com/spf13/cobra v1.1.3
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
@ -47,8 +47,8 @@ require (
github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15
github.com/tendermint/go-amino v0.16.0
github.com/tendermint/tendermint v0.34.3
github.com/tendermint/tm-db v0.6.3
github.com/tendermint/tendermint v0.34.4
github.com/tendermint/tm-db v0.6.4
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f
google.golang.org/grpc v1.35.0

10
go.sum
View File

@ -599,6 +599,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4=
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@ -627,6 +629,8 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
@ -673,11 +677,13 @@ github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM
github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4=
github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg=
github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
github.com/tendermint/tendermint v0.34.3 h1:9yEsf3WO5VAwPVwrmM+RffDMiijmNfWaBwNttHm0q5w=
github.com/tendermint/tendermint v0.34.3/go.mod h1:h57vnXeOlrdvvNFCqPBSaOrpOivl+2swWEtlUAqStYE=
github.com/tendermint/tendermint v0.34.4 h1:E7qkvFGx27d8ugVLiAY2iWP6DL5cep3l/mpTaWKHyBA=
github.com/tendermint/tendermint v0.34.4/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss=
github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI=
github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg=
github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8=
github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ=
github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw=
github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=

View File

@ -198,6 +198,9 @@ type SimApp struct {
// simulation manager
sm *module.SimulationManager
// the configurator
configurator module.Configurator
}
func init() {
@ -393,7 +396,8 @@ func NewSimApp(
app.mm.RegisterInvariants(&app.CrisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
app.mm.RegisterServices(module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()))
app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter())
app.mm.RegisterServices(app.configurator)
// add test gRPC service for testing gRPC queries in isolation
testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{})
@ -598,6 +602,28 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) {
tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry)
}
// RunMigrations performs in-place store migrations for all modules. This
// function MUST be only called by x/upgrade UpgradeHandler.
//
// `migrateFromVersions` is a map of moduleName to fromVersion (unit64), where
// fromVersion denotes the version from which we should migrate the module, the
// target version being the module's latest ConsensusVersion.
//
// Example:
// cfg := module.NewConfigurator(...)
// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan) {
// err := app.RunMigrations(ctx, module.MigrationMap{
// "bank": 1, // Migrate x/bank from v1 to current x/bank's ConsensusVersion
// "staking": 8, // Migrate x/staking from v8 to current x/staking's ConsensusVersion
// })
// if err != nil {
// panic(err)
// }
// })
func (app *SimApp) RunMigrations(ctx sdk.Context, migrateFromVersions module.MigrationMap) error {
return app.mm.RunMigrations(ctx, app.configurator, migrateFromVersions)
}
// RegisterSwaggerAPI registers swagger route with API Server
func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) {
statikFS, err := fs.New()

View File

@ -6,10 +6,13 @@ import (
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
)
func TestSimAppExportAndBlockedAddrs(t *testing.T) {
@ -45,3 +48,87 @@ func TestGetMaccPerms(t *testing.T) {
dup := GetMaccPerms()
require.Equal(t, maccPerms, dup, "duplicated module account permissions differed from actual module account permissions")
}
func TestRunMigrations(t *testing.T) {
db := dbm.NewMemDB()
encCfg := MakeTestEncodingConfig()
app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{})
// Create a new configurator for the purpose of this test.
app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter())
testCases := []struct {
name string
moduleName string
forVersion uint64
expRegErr bool // errors while registering migration
expRegErrMsg string
expRunErr bool // errors while running migration
expRunErrMsg string
expCalled int
}{
{
"cannot register migration for version 0",
"bank", 0,
true, "module migration versions should start at 1: invalid version", false, "", 0,
},
{
"throws error on RunMigrations if no migration registered for bank",
"", 1,
false, "", true, "no migrations found for module bank: not found", 0,
},
{
"can register and run migration handler for x/bank",
"bank", 1,
false, "", false, "", 1,
},
{
"cannot register migration handler for same module & forVersion",
"bank", 1,
true, "another migration for module bank and version 1 already exists: internal logic error", false, "", 0,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var err error
// Since it's very hard to test actual in-place store migrations in
// tests (due to the difficulty of maintaing multiple versions of a
// module), we're just testing here that the migration logic is
// called.
called := 0
if tc.moduleName != "" {
// Register migration for module from version `forVersion` to `forVersion+1`.
err = app.configurator.RegisterMigration(tc.moduleName, tc.forVersion, func(sdk.Context) error {
called++
return nil
})
if tc.expRegErr {
require.EqualError(t, err, tc.expRegErrMsg)
return
}
}
require.NoError(t, err)
err = app.RunMigrations(
app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}),
module.MigrationMap{
"auth": 1, "authz": 1, "bank": 1, "staking": 1, "mint": 1, "distribution": 1,
"slashing": 1, "gov": 1, "params": 1, "ibc": 1, "upgrade": 1, "vesting": 1,
"feegrant": 1, "transfer": 1, "evidence": 1, "crisis": 1, "genutil": 1, "capability": 1,
},
)
if tc.expRunErr {
require.EqualError(t, err, tc.expRunErrMsg)
} else {
require.NoError(t, err)
require.Equal(t, tc.expCalled, called)
}
})
}
}

View File

@ -492,6 +492,9 @@ func (m *MockAppModule) ExportGenesis(arg0 types0.Context, arg1 codec.JSONMarsha
return ret0
}
// ConsensusVersion mocks base method
func (m *MockAppModule) ConsensusVersion() uint64 { return 1 }
// ExportGenesis indicates an expected call of ExportGenesis
func (mr *MockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()

25
testutil/context.go Normal file
View File

@ -0,0 +1,25 @@
package testutil
import (
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// DefaultContext creates a sdk.Context with a fresh MemDB that can be used in tests.
func DefaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db)
err := cms.LoadLatestVersion()
if err != nil {
panic(err)
}
ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger())
return ctx
}

View File

@ -8,13 +8,11 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/store"
"github.com/cosmos/cosmos-sdk/tests/mocks"
"github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/types"
)
@ -26,15 +24,6 @@ func TestContextTestSuite(t *testing.T) {
suite.Run(t, new(contextTestSuite))
}
func (s *contextTestSuite) defaultContext(key types.StoreKey) types.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(key, types.StoreTypeIAVL, db)
s.Require().NoError(cms.LoadLatestVersion())
ctx := types.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger())
return ctx
}
func (s *contextTestSuite) TestCacheContext() {
key := types.NewKVStoreKey(s.T().Name() + "_TestCacheContext")
k1 := []byte("hello")
@ -42,7 +31,7 @@ func (s *contextTestSuite) TestCacheContext() {
k2 := []byte("key")
v2 := []byte("value")
ctx := s.defaultContext(key)
ctx := testutil.DefaultContext(key, types.NewTransientStoreKey("transient_"+s.T().Name()))
store := ctx.KVStore(key)
store.Set(k1, v1)
s.Require().Equal(v1, store.Get(k1))
@ -64,7 +53,7 @@ func (s *contextTestSuite) TestCacheContext() {
func (s *contextTestSuite) TestLogContext() {
key := types.NewKVStoreKey(s.T().Name())
ctx := s.defaultContext(key)
ctx := testutil.DefaultContext(key, types.NewTransientStoreKey("transient_"+s.T().Name()))
ctrl := gomock.NewController(s.T())
s.T().Cleanup(ctrl.Finish)

View File

@ -1,6 +1,11 @@
package module
import "github.com/gogo/protobuf/grpc"
import (
"github.com/gogo/protobuf/grpc"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// Configurator provides the hooks to allow modules to configure and register
// their services in the RegisterServices method. It is designed to eventually
@ -15,16 +20,34 @@ type Configurator interface {
// QueryServer returns a grpc.Server instance which allows registering services
// that will be exposed as gRPC services as well as ABCI query handlers.
QueryServer() grpc.Server
// RegisterMigration registers an in-place store migration for a module. The
// handler is a migration script to perform in-place migrations from version
// `forVersion` to version `forVersion+1`.
//
// EACH TIME a module's ConsensusVersion increments, a new migration MUST
// be registered using this function. If a migration handler is missing for
// a particular function, the upgrade logic (see RunMigrations function)
// will panic. If the ConsensusVersion bump does not introduce any store
// changes, then a no-op function must be registered here.
RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error
}
type configurator struct {
msgServer grpc.Server
queryServer grpc.Server
// migrations is a map of moduleName -> forVersion -> migration script handler
migrations map[string]map[uint64]MigrationHandler
}
// NewConfigurator returns a new Configurator instance
func NewConfigurator(msgServer grpc.Server, queryServer grpc.Server) Configurator {
return configurator{msgServer: msgServer, queryServer: queryServer}
return configurator{
msgServer: msgServer,
queryServer: queryServer,
migrations: map[string]map[uint64]MigrationHandler{},
}
}
var _ Configurator = configurator{}
@ -38,3 +61,51 @@ func (c configurator) MsgServer() grpc.Server {
func (c configurator) QueryServer() grpc.Server {
return c.queryServer
}
// RegisterMigration implements the Configurator.RegisterMigration method
func (c configurator) RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error {
if forVersion == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "module migration versions should start at 1")
}
if c.migrations[moduleName] == nil {
c.migrations[moduleName] = map[uint64]MigrationHandler{}
}
if c.migrations[moduleName][forVersion] != nil {
return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, forVersion)
}
c.migrations[moduleName][forVersion] = handler
return nil
}
// runModuleMigrations runs all in-place store migrations for one given module from a
// version to another version.
func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error {
// No-op if toVersion is the initial version.
if toVersion <= 1 {
return nil
}
moduleMigrationsMap, found := c.migrations[moduleName]
if !found {
return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migrations found for module %s", moduleName)
}
// Run in-place migrations for the module sequentially until toVersion.
for i := fromVersion; i < toVersion; i++ {
migrateFn, found := moduleMigrationsMap[i]
if !found {
return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1)
}
err := migrateFn(ctx)
if err != nil {
return err
}
}
return nil
}

View File

@ -40,6 +40,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
//__________________________________________________________________________________________
@ -174,6 +175,12 @@ type AppModule interface {
// RegisterServices allows a module to register services
RegisterServices(Configurator)
// ConsensusVersion is a sequence number for state-breaking change of the
// module. It should be incremented on each consensus-breaking change
// introduced by the module. To avoid wrong/empty versions, the initial version
// should be set to 1.
ConsensusVersion() uint64
// ABCI
BeginBlock(sdk.Context, abci.RequestBeginBlock)
EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate
@ -208,6 +215,9 @@ func (gam GenesisOnlyAppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Que
// RegisterServices registers all services.
func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns an empty module begin-block
func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {}
@ -328,6 +338,30 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st
return genesisData
}
// MigrationHandler is the migration function that each module registers.
type MigrationHandler func(store sdk.Context) error
// MigrationMap is a map of moduleName -> version, where version denotes the
// version from which we should perform the migration for each module.
type MigrationMap map[string]uint64
// RunMigrations performs in-place store migrations for all modules.
func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrateFromVersions MigrationMap) error {
c, ok := cfg.(configurator)
if !ok {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg)
}
for moduleName, module := range m.Modules {
err := c.runModuleMigrations(ctx, moduleName, migrateFromVersions[moduleName], module.ConsensusVersion())
if err != nil {
return err
}
}
return nil
}
// BeginBlock performs begin block functionality for all modules. It creates a
// child context with an event manager to aggregate events emitted from all
// modules.

View File

@ -8,7 +8,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/query"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
@ -32,7 +31,7 @@ func (s *paginationTestSuite) TestFilteredPaginations() {
acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
app.AccountKeeper.SetAccount(ctx, acc1)
s.Require().NoError(app.BankKeeper.SetBalances(ctx, addr1, balances))
store := ctx.KVStore(app.GetKey(authtypes.StoreKey))
store := ctx.KVStore(app.GetKey(types.StoreKey))
// verify pagination with limit > total values
pageReq := &query.PageRequest{Key: nil, Limit: 5, CountTotal: true}
@ -110,7 +109,7 @@ func ExampleFilteredPaginate() {
}
pageReq := &query.PageRequest{Key: nil, Limit: 1, CountTotal: true}
store := ctx.KVStore(app.GetKey(authtypes.StoreKey))
store := ctx.KVStore(app.GetKey(types.StoreKey))
balancesStore := prefix.NewStore(store, types.BalancesPrefix)
accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1))

View File

@ -19,9 +19,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/query"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
@ -192,7 +189,7 @@ func ExamplePaginate() {
pageReq := &query.PageRequest{Key: nil, Limit: 1, CountTotal: true}
request := types.NewQueryAllBalancesRequest(addr1, pageReq)
balResult := sdk.NewCoins()
authStore := ctx.KVStore(app.GetKey(authtypes.StoreKey))
authStore := ctx.KVStore(app.GetKey(types.StoreKey))
balancesStore := prefix.NewStore(authStore, types.BalancesPrefix)
accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1))
pageRes, err := query.Paginate(accountStore, request.Pagination, func(key []byte, value []byte) error {
@ -222,20 +219,5 @@ func setupTest() (*simapp.SimApp, sdk.Context, codec.Marshaler) {
ms.LoadLatestVersion()
maccPerms := simapp.GetMaccPerms()
maccPerms[holder] = nil
maccPerms[authtypes.Burner] = []string{authtypes.Burner}
maccPerms[authtypes.Minter] = []string{authtypes.Minter}
maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking}
maccPerms[randomPerm] = []string{"random"}
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, app.GetKey(authtypes.StoreKey), app.GetSubspace(authtypes.ModuleName),
authtypes.ProtoBaseAccount, maccPerms,
)
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec, app.GetKey(authtypes.StoreKey), app.AccountKeeper,
app.GetSubspace(types.ModuleName), make(map[string]bool),
)
return app, ctx, appCodec
}

View File

@ -8,6 +8,7 @@ parent:
Here are some production-grade modules that can be used in Cosmos SDK applications, along with their respective documentation:
- [Auth](auth/spec/README.md) - Authentication of accounts and transactions for Cosmos SDK application.
- [Authz](authz/spec/README.md) - Authorization for accounts to perform actions on behalf of other accounts.
- [Bank](bank/spec/README.md) - Token transfer functionalities.
- [Capability](capability/spec/README.md) - Object capability implementation.
- [Crisis](crisis/spec/README.md) - Halting the blockchain under certain circumstances (e.g. if an invariant is broken).

View File

@ -0,0 +1,4 @@
package v040
// AddrLen defines a valid address length
const AddrLen = 20

View File

@ -147,6 +147,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns the begin blocker for the auth module.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -127,3 +127,6 @@ func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Valid
func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.RawMessage {
return am.DefaultGenesis(cdc)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }

View File

@ -152,6 +152,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {}
// EndBlock does nothing

View File

@ -0,0 +1,37 @@
<!--
order: 1
-->
# Concepts
## Authorization
Any concrete type of authorization defined in the `x/authz` module must fulfill the `Authorization` interface outlined below. Authorizations determine exactly what privileges are granted. They are extensible and can be defined for any Msg service method even outside of the module where the Msg method is defined. Authorizations use the new `ServiceMsg` type from [ADR 031](../../../architecture/adr-031-msg-service.md).
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/x/authz/types/authorizations.go#L15-L24
## Built-in Authorizations
Cosmos-SDK `x/authz` module comes with following authorization types
### SendAuthorization
`SendAuthorization` implements `Authorization` interface for the `cosmos.bank.v1beta1.Msg/Send` ServiceMsg, that takes a `SpendLimit` and updates it down to zero.
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/authz.proto#L12-L19
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/x/authz/types/send_authorization.go#L23-L45
- `spent_limit` keeps track of how many coins left in the authorization.
### GenericAuthorization
`GenericAuthorization` implements the `Authorization` interface, that gives unrestricted permission to execute the provided ServiceMsg on behalf of granter's account.
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/authz.proto#L21-L30
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/x/authz/types/generic_authorization.go#L20-L28
- `method_name` holds ServiceMsg type.

14
x/authz/spec/02_state.md Normal file
View File

@ -0,0 +1,14 @@
<!--
order: 2
-->
# State
## AuthorizationGrant
Authorizations are identified by combining granter address (the address bytes of the granter), grantee address (the address bytes of the grantee) and ServiceMsg type (its method name).
- AuthorizationGrant: `0x01 | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes | msgType_bytes-> ProtocolBuffer(AuthorizationGrant)`
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/authz.proto#L32-L37

View File

@ -0,0 +1,42 @@
<!--
order: 3
-->
# Messages
In this section we describe the processing of messages for the authz module.
## Msg/GrantAuthorization
An authorization-grant is created using the `MsgGrantAuthorization` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/tx.proto#L27-L35
This message is expected to fail if:
- both granter & grantee have same address.
- provided `Expiration` time less than current unix timestamp.
- provided `Authorization` is not implemented.
## Msg/RevokeAuthorization
An allowed authorization can be removed with `MsgRevokeAuthorization` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/tx.proto#L53-L59
This message is expected to fail if:
- both granter & grantee have same address.
- provided `MethodName` is empty.
## Msg/ExecAuthorizedRequest
When a grantee wants to execute transaction on behalf of a granter, it must send MsgExecAuthorizedRequest.
+++ https://github.com/cosmos/cosmos-sdk/blob/c95de9c4177442dee4c69d96917efc955b5d19d9/proto/cosmos/authz/v1beta1/tx.proto#L42-L48
This message is expected to fail if:
- authorization not implemented for the provided msg.
- grantee don't have permission to run transaction.
- if granted authorization is expired.

28
x/authz/spec/04_events.md Normal file
View File

@ -0,0 +1,28 @@
<!--
order: 4
-->
# Events
The authz module emits the following events:
## Keeper
### GrantAuthorization
| Type | Attribute Key | Attribute Value |
|----------------------|-------------------|--------------------|
| grant-authorization | module | authz |
| grant-authorization | grant-type | {msgType} |
| grant-authorization | granter | {granterAddress} |
| grant-authorization | grantee | {granteeAddress} |
### RevokeAuthorization
| Type | Attribute Key | Attribute Value |
|----------------------|-------------------|--------------------|
| revoke-authorization | module | authz |
| revoke-authorization | grant-type | {msgType} |
| revoke-authorization | granter | {granterAddress} |
| revoke-authorization | grantee | {granteeAddress} |

26
x/authz/spec/README.md Normal file
View File

@ -0,0 +1,26 @@
<!--
order: 0
title: Authz Overview
parent:
title: "authz"
-->
# `authz`
## Contents
## Abstract
`x/authz` is an implementation of a Cosmos SDK module, per [ADR 30](../../../architecture/adr-030-authz-module.md), that allows
granting arbitrary privileges from one account (the granter) to another account (the grantee). Authorizations must be granted for a particular Msg service method one by one using an implementation of the `Authorization` interface.
1. **[Concept](01_concepts.md)**
- [Authorization](01_concepts.md#Authorization)
- [Built-in Authorizations](01_concepts.md#Built-in-Authorization)
2. **[State](02_state.md)**
3. **[Messages](03_messages.md)**
- [Msg/GrantAuthorization](03_messages.md#MsgGrantAuthorization)
- [Msg/RevokeAuthorization](03_messages.md#MsgRevokeAuthorization)
- [Msg/ExecAuthorized](03_messages.md#MsgExecAuthorized)
4. **[Events](04_events.md)**
- [Keeper](04_events.md#Keeper)

View File

@ -0,0 +1,20 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v042 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042"
)
// MigrationKeeper is an interface that the keeper implements for handling
// in-place store migrations.
type MigrationKeeper interface {
// Migrate1 migrates the store from version 1 to 2.
Migrate1(ctx sdk.Context) error
}
var _ MigrationKeeper = (*BaseKeeper)(nil)
// Migrate1 implements MigrationKeeper.Migrate1 method.
func (keeper BaseKeeper) Migrate1(ctx sdk.Context) error {
return v042.MigrateStore(ctx, keeper.storeKey)
}

View File

@ -0,0 +1,47 @@
package v040
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
)
const (
// ModuleName defines the module name
ModuleName = "bank"
// StoreKey defines the primary module store key
StoreKey = ModuleName
// RouterKey defines the module's message routing key
RouterKey = ModuleName
// QuerierRoute defines the module's query routing key
QuerierRoute = ModuleName
)
// KVStore keys
var (
BalancesPrefix = []byte("balances")
SupplyKey = []byte{0x00}
DenomMetadataPrefix = []byte{0x1}
)
// DenomMetadataKey returns the denomination metadata key.
func DenomMetadataKey(denom string) []byte {
d := []byte(denom)
return append(DenomMetadataPrefix, d...)
}
// AddressFromBalancesStore returns an account address from a balances prefix
// store. The key must not contain the perfix BalancesPrefix as the prefix store
// iterator discards the actual prefix.
func AddressFromBalancesStore(key []byte) sdk.AccAddress {
addr := key[:v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic(fmt.Sprintf("unexpected account address key length; got: %d, expected: %d", len(addr), v040auth.AddrLen))
}
return sdk.AccAddress(addr)
}

View File

@ -1,5 +0,0 @@
package v040
const (
ModuleName = "bank"
)

View File

@ -0,0 +1,50 @@
package v042
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
)
const (
// ModuleName defines the module name
ModuleName = "bank"
// StoreKey defines the primary module store key
StoreKey = ModuleName
// RouterKey defines the module's message routing key
RouterKey = ModuleName
// QuerierRoute defines the module's query routing key
QuerierRoute = ModuleName
)
// KVStore keys
var (
// BalancesPrefix is the for the account balances store. We use a byte
// (instead of say `[]]byte("balances")` to save some disk space).
BalancesPrefix = []byte{0x02}
SupplyKey = []byte{0x00}
DenomMetadataPrefix = []byte{0x1}
)
// DenomMetadataKey returns the denomination metadata key.
func DenomMetadataKey(denom string) []byte {
d := []byte(denom)
return append(DenomMetadataPrefix, d...)
}
// AddressFromBalancesStore returns an account address from a balances prefix
// store. The key must not contain the perfix BalancesPrefix as the prefix store
// iterator discards the actual prefix.
func AddressFromBalancesStore(key []byte) sdk.AccAddress {
addrLen := key[0]
addr := key[1 : addrLen+1]
return sdk.AccAddress(addr)
}
// CreateAccountBalancesPrefix creates the prefix for an account's balances.
func CreateAccountBalancesPrefix(addr []byte) []byte {
return append(BalancesPrefix, address.MustLengthPrefix(addr)...)
}

View File

@ -0,0 +1,38 @@
package v042
import (
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040"
)
// MigrateStore performs in-place store migrations from v0.40 to v0.42. The
// migration includes:
//
// - Change addresses to be length-prefixed.
// - Change balances prefix to 1 byte
func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error {
store := ctx.KVStore(storeKey)
// old key is of format:
// prefix ("balances") || addrBytes (20 bytes) || denomBytes
// new key is of format
// prefix (0x02) || addrLen (1 byte) || addrBytes || denomBytes
oldStore := prefix.NewStore(store, v040bank.BalancesPrefix)
oldStoreIter := oldStore.Iterator(nil, nil)
defer oldStoreIter.Close()
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key())
denom := oldStoreIter.Key()[v040auth.AddrLen:]
newStoreKey := append(CreateAccountBalancesPrefix(addr), denom...)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
return nil
}

View File

@ -0,0 +1,36 @@
package v042_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
v040bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v040"
v042bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042"
)
func TestStoreMigration(t *testing.T) {
bankKey := sdk.NewKVStoreKey("bank")
ctx := testutil.DefaultContext(bankKey, sdk.NewTransientStoreKey("transient_test"))
store := ctx.KVStore(bankKey)
_, _, addr := testdata.KeyTestPubAddr()
denom := []byte("foo")
value := []byte("bar")
oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...)
store.Set(oldKey, value)
err := v042bank.MigrateStore(ctx, bankKey)
require.NoError(t, err)
newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...)
// -7 because we replaced "balances" with 0x02,
// +1 because we added length-prefix to address.
require.Equal(t, len(oldKey)-7+1, len(newKey))
require.Nil(t, store.Get(oldKey))
require.Equal(t, value, store.Get(newKey))
}

View File

@ -100,6 +100,9 @@ type AppModule struct {
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
cfg.RegisterMigration(types.ModuleName, 0, func(ctx sdk.Context) error {
return am.keeper.(keeper.MigrationKeeper).Migrate1(ctx)
})
}
// NewAppModule creates a new AppModule object
@ -151,6 +154,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 2 }
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -7,5 +7,5 @@ order: 1
The `x/bank` module keeps state of two primary objects, account balances and the
total supply of all balances.
- Balances: `[]byte("balances") | []byte(address) / []byte(balance.Denom) -> ProtocolBuffer(balance)`
- Supply: `0x0 -> ProtocolBuffer(Supply)`
- Balances: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)`

View File

@ -136,6 +136,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(genState)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock executes all ABCI BeginBlock logic respective to the capability module.
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -158,6 +158,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -161,6 +161,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns the begin blocker for the distribution module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper)

View File

@ -175,6 +175,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(ExportGenesis(ctx, am.keeper))
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock executes all ABCI BeginBlock logic respective to the evidence module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper)

View File

@ -167,6 +167,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns the begin blocker for the feegrant module.
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -110,3 +110,6 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data j
func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.RawMessage {
return am.DefaultGenesis(cdc)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }

View File

@ -177,6 +177,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -145,6 +145,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock implements the AppModule interface
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
}

View File

@ -1,6 +1,7 @@
package keeper
import (
"bytes"
"context"
"fmt"
"sort"
@ -159,7 +160,7 @@ func (q Keeper) ConsensusStates(c context.Context, req *types.QueryConsensusStat
pageRes, err := query.FilteredPaginate(store, req.Pagination, func(key, value []byte, accumulate bool) (bool, error) {
// filter any metadata stored under consensus state key
if strings.Contains(string(key), "/") {
if bytes.Contains(key, []byte("/")) {
return false, nil
}

View File

@ -156,6 +156,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(ExportGenesis(ctx, *am.keeper))
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns the begin blocker for the ibc module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
ibcclient.BeginBlocker(ctx, am.keeper.ClientKeeper)

View File

@ -146,6 +146,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns the begin blocker for the mint module.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlocker(ctx, am.keeper)

View File

@ -1,14 +1,9 @@
package keeper_test
import (
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
)
@ -18,7 +13,7 @@ func testComponents() (*codec.LegacyAmino, sdk.Context, sdk.StoreKey, sdk.StoreK
legacyAmino := createTestCodec()
mkey := sdk.NewKVStoreKey("test")
tkey := sdk.NewTransientStoreKey("transient_test")
ctx := defaultContext(mkey, tkey)
ctx := testutil.DefaultContext(mkey, tkey)
keeper := paramskeeper.NewKeeper(marshaler, legacyAmino, mkey, tkey)
return legacyAmino, ctx, mkey, tkey, keeper
@ -37,16 +32,3 @@ func createTestCodec() *codec.LegacyAmino {
cdc.RegisterConcrete(invalid{}, "test/invalid", nil)
return cdc
}
func defaultContext(key sdk.StoreKey, tkey sdk.StoreKey) sdk.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db)
cms.MountStoreWithDB(tkey, sdk.StoreTypeTransient, db)
err := cms.LoadLatestVersion()
if err != nil {
panic(err)
}
ctx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger())
return ctx
}

View File

@ -139,6 +139,9 @@ func (am AppModule) ExportGenesis(_ sdk.Context, _ codec.JSONMarshaler) json.Raw
return nil
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -159,6 +159,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns the begin blocker for the slashing module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, req, am.keeper)

View File

@ -12,8 +12,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
const aminoCacheSize = 500
// Implements ValidatorSet interface
var _ types.ValidatorSet = Keeper{}
@ -28,7 +26,6 @@ type Keeper struct {
bankKeeper types.BankKeeper
hooks types.StakingHooks
paramstore paramtypes.Subspace
validatorCache map[string]cachedValidator
validatorCacheList *list.List
}
@ -58,7 +55,6 @@ func NewKeeper(
bankKeeper: bk,
paramstore: ps,
hooks: nil,
validatorCache: make(map[string]cachedValidator, aminoCacheSize),
validatorCacheList: list.New(),
}
}

View File

@ -10,22 +10,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
// Cache the amino decoding of validators, as it can be the case that repeated slashing calls
// cause many calls to GetValidator, which were shown to throttle the state machine in our
// simulation. Note this is quite biased though, as the simulator does more slashes than a
// live chain should, however we require the slashing to be fast as noone pays gas for it.
type cachedValidator struct {
val types.Validator
marshalled string // marshalled amino bytes for the validator object (not operator address)
}
func newCachedValidator(val types.Validator, marshalled string) cachedValidator {
return cachedValidator{
val: val,
marshalled: marshalled,
}
}
// get a single validator
func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator types.Validator, found bool) {
store := ctx.KVStore(k.storeKey)
@ -35,30 +19,7 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty
return validator, false
}
// If these amino encoded bytes are in the cache, return the cached validator
strValue := string(value)
if val, ok := k.validatorCache[strValue]; ok {
valToReturn := val.val
// Doesn't mutate the cache's value
valToReturn.OperatorAddress = addr.String()
return valToReturn, true
}
// amino bytes weren't found in cache, so amino unmarshal and add it to the cache
validator = types.MustUnmarshalValidator(k.cdc, value)
cachedVal := newCachedValidator(validator, strValue)
k.validatorCache[strValue] = newCachedValidator(validator, strValue)
k.validatorCacheList.PushBack(cachedVal)
// if the cache is too big, pop off the last element from it
if k.validatorCacheList.Len() > aminoCacheSize {
valToRemove := k.validatorCacheList.Remove(k.validatorCacheList.Front()).(cachedValidator)
delete(k.validatorCache, valToRemove.marshalled)
}
validator = types.MustUnmarshalValidator(k.cdc, value)
return validator, true
}

View File

@ -0,0 +1,29 @@
package keeper_test
import "testing"
func BenchmarkGetValidator(b *testing.B) {
// 900 is the max number we are allowed to use in order to avoid simapp.CreateTestPubKeys
// panic: encoding/hex: odd length hex string
var powersNumber = 900
var totalPower int64 = 0
var powers = make([]int64, powersNumber)
for i := range powers {
powers[i] = int64(i)
totalPower += int64(i)
}
app, ctx, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers)
for _, validator := range vals {
app.StakingKeeper.SetValidator(ctx, validator)
}
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, addr := range valAddrs {
_, _ = app.StakingKeeper.GetValidator(ctx, addr)
}
}
}

View File

@ -19,13 +19,13 @@ import (
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
func newMonikerValidator(t *testing.T, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator {
func newMonikerValidator(t testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator {
v, err := types.NewValidator(operator, pubKey, types.Description{Moniker: moniker})
require.NoError(t, err)
return v
}
func bootstrapValidatorTest(t *testing.T, power int64, numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) {
func bootstrapValidatorTest(t testing.TB, power int64, numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) {
_, app, ctx := createTestInput()
addrDels, addrVals := generateAddresses(app, ctx, numAddrs)
@ -43,12 +43,13 @@ func bootstrapValidatorTest(t *testing.T, power int64, numAddrs int) (*simapp.Si
return app, ctx, addrDels, addrVals
}
func initValidators(t *testing.T, power int64, numAddrs int, powers []int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) {
app, ctx, addrs, valAddrs := bootstrapValidatorTest(t, 1000, 20)
func initValidators(t testing.TB, power int64, numAddrs int, powers []int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) {
app, ctx, addrs, valAddrs := bootstrapValidatorTest(t, power, numAddrs)
pks := simapp.CreateTestPubKeys(numAddrs)
vs := make([]types.Validator, len(powers))
for i, power := range powers {
vs[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i])
vs[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), pks[i])
tokens := sdk.TokensFromConsensusPower(power)
vs[i], _ = vs[i].AddTokensFromDel(tokens)
}

View File

@ -157,6 +157,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
return cdc.MustMarshalJSON(gs)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock returns the begin blocker for the staking module.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {
BeginBlocker(ctx, am.keeper)

View File

@ -11,7 +11,7 @@ import (
)
// NewValidator is a testing helper method to create validators in tests
func NewValidator(t *testing.T, operator sdk.ValAddress, pubKey cryptotypes.PubKey) types.Validator {
func NewValidator(t testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey) types.Validator {
v, err := types.NewValidator(operator, pubKey, types.Description{})
require.NoError(t, err)
return v

View File

@ -120,6 +120,9 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONMarshaler) json.R
return am.DefaultGenesis(cdc)
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
// BeginBlock calls the upgrade module hooks
//
// CONTRACT: this is registered in BeginBlocker *before* all other modules' BeginBlock functions