Merge branch 'master' into gov_split_vote_weighted_vote
This commit is contained in:
commit
47f7502e72
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
6
go.mod
@ -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
10
go.sum
@ -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=
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
25
testutil/context.go
Normal 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
|
||||
}
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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).
|
||||
|
||||
4
x/auth/legacy/v040/store.go
Normal file
4
x/auth/legacy/v040/store.go
Normal file
@ -0,0 +1,4 @@
|
||||
package v040
|
||||
|
||||
// AddrLen defines a valid address length
|
||||
const AddrLen = 20
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -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
|
||||
|
||||
37
x/authz/spec/01_concepts.md
Normal file
37
x/authz/spec/01_concepts.md
Normal 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
14
x/authz/spec/02_state.md
Normal 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
|
||||
42
x/authz/spec/03_messages.md
Normal file
42
x/authz/spec/03_messages.md
Normal 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
28
x/authz/spec/04_events.md
Normal 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
26
x/authz/spec/README.md
Normal 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)
|
||||
|
||||
20
x/bank/keeper/migrations.go
Normal file
20
x/bank/keeper/migrations.go
Normal 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)
|
||||
}
|
||||
47
x/bank/legacy/v040/keys.go
Normal file
47
x/bank/legacy/v040/keys.go
Normal 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)
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package v040
|
||||
|
||||
const (
|
||||
ModuleName = "bank"
|
||||
)
|
||||
50
x/bank/legacy/v042/keys.go
Normal file
50
x/bank/legacy/v042/keys.go
Normal 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)...)
|
||||
}
|
||||
38
x/bank/legacy/v042/store.go
Normal file
38
x/bank/legacy/v042/store.go
Normal 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
|
||||
}
|
||||
36
x/bank/legacy/v042/store_test.go
Normal file
36
x/bank/legacy/v042/store_test.go
Normal 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))
|
||||
}
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -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)`
|
||||
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -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) {
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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) {}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
29
x/staking/keeper/validator_bench_test.go
Normal file
29
x/staking/keeper/validator_bench_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user