x{stake,slash,gov,distrib} In-place Store Migrations (#8504)

* Add 1st version of migrate

* Put migration logic into Configurator

* add test to bank store migration

* add test for configurator

* Error if no migration found

* Remove RunMigrations from Configurator interface

* Update spec

* Rename folders

* copy-paste from keys.go

* Fix nil map

* rename function

* Update simapp/app.go

Co-authored-by: Robert Zaremba <robert@zaremba.ch>

* Update simapp/app_test.go

Co-authored-by: Robert Zaremba <robert@zaremba.ch>

* Adderss reviews

* Fix tests

* Update testutil/context.go

Co-authored-by: Robert Zaremba <robert@zaremba.ch>

* Update docs for ConsensusVersion

* Rename to forVersion

* Fix tests

* Check error early

* Return 1 for intiial version

* Use MigrationKeeper

* Fix test

* Revert adding marshaler to Configurator

* Godoc updates

* Update docs

* Add distrib legacy folder

* Add tests for distrib migration

* Add gov migrations

* Copy paste whole keys file

* Add gov migrations

* Add staking

* Fix staking tests

* Update spec and module.go

* Update to latest changes

* Update migration scripts

* capability to 1

* Fix tests

* Add package godoc

* Remove whitespace

* Remove global

* Use Migrator

* Remove 042 keys files

* Fix build

* Unlambda

* Rename to Migrate1to2

Co-authored-by: Robert Zaremba <robert@zaremba.ch>
This commit is contained in:
Amaury 2021-02-25 11:43:31 +01:00 committed by GitHub
parent eeb3eabdc6
commit ba74a7c737
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1588 additions and 115 deletions

View File

@ -11,8 +11,27 @@ import (
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
"github.com/cosmos/cosmos-sdk/x/authz"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/capability"
"github.com/cosmos/cosmos-sdk/x/crisis"
"github.com/cosmos/cosmos-sdk/x/distribution"
"github.com/cosmos/cosmos-sdk/x/evidence"
feegrant "github.com/cosmos/cosmos-sdk/x/feegrant"
"github.com/cosmos/cosmos-sdk/x/genutil"
"github.com/cosmos/cosmos-sdk/x/gov"
transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer"
ibc "github.com/cosmos/cosmos-sdk/x/ibc/core"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/params"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/upgrade"
)
func TestSimAppExportAndBlockedAddrs(t *testing.T) {
@ -52,11 +71,33 @@ func TestGetMaccPerms(t *testing.T) {
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{})
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{})
// Create a new configurator for the purpose of this test.
// Create a new baseapp and configurator for the purpose of this test.
bApp := baseapp.NewBaseApp(appName, logger, db, encCfg.TxConfig.TxDecoder())
bApp.SetCommitMultiStoreTracer(nil)
bApp.SetInterfaceRegistry(encCfg.InterfaceRegistry)
app.BaseApp = bApp
app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter())
// We register all modules on the Configurator, except x/bank. x/bank will
// serve as the test subject on which we run the migration tests.
//
// The loop below is the same as calling `RegisterServices` on
// ModuleManager, except that we skip x/bank.
for _, module := range app.mm.Modules {
if module.Name() == banktypes.ModuleName {
continue
}
module.RegisterServices(app.configurator)
}
// Initialize the chain
app.InitChain(abci.RequestInitChain{})
app.Commit()
testCases := []struct {
name string
moduleName string
@ -115,12 +156,30 @@ func TestRunMigrations(t *testing.T) {
}
require.NoError(t, err)
// Run migrations only for bank. That's why we put the initial
// version for bank as 1, and for all other modules, we put as
// their latest ConsensusVersion.
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,
"bank": 1,
"auth": auth.AppModule{}.ConsensusVersion(),
"authz": authz.AppModule{}.ConsensusVersion(),
"staking": staking.AppModule{}.ConsensusVersion(),
"mint": mint.AppModule{}.ConsensusVersion(),
"distribution": distribution.AppModule{}.ConsensusVersion(),
"slashing": slashing.AppModule{}.ConsensusVersion(),
"gov": gov.AppModule{}.ConsensusVersion(),
"params": params.AppModule{}.ConsensusVersion(),
"ibc": ibc.AppModule{}.ConsensusVersion(),
"upgrade": upgrade.AppModule{}.ConsensusVersion(),
"vesting": vesting.AppModule{}.ConsensusVersion(),
"feegrant": feegrant.AppModule{}.ConsensusVersion(),
"transfer": transfer.AppModule{}.ConsensusVersion(),
"evidence": evidence.AppModule{}.ConsensusVersion(),
"crisis": crisis.AppModule{}.ConsensusVersion(),
"genutil": genutil.AppModule{}.ConsensusVersion(),
"capability": capability.AppModule{}.ConsensusVersion(),
},
)
if tc.expRunErr {

View File

@ -331,7 +331,7 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st
}
// MigrationHandler is the migration function that each module registers.
type MigrationHandler func(store sdk.Context) error
type MigrationHandler func(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.

View File

@ -5,16 +5,17 @@ import (
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
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper BaseKeeper
}
var _ MigrationKeeper = (*BaseKeeper)(nil)
// Migrate1 implements MigrationKeeper.Migrate1 method.
func (keeper BaseKeeper) Migrate1(ctx sdk.Context) error {
return v042.MigrateStore(ctx, keeper.storeKey)
// NewMigrator returns a new Migrator.
func NewMigrator(keeper BaseKeeper) Migrator {
return Migrator{keeper: keeper}
}
// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v042.MigrateStore(ctx, m.keeper.storeKey)
}

View File

@ -1,3 +1,5 @@
// Package v040 is copy-pasted from:
// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/bank/types/key.go
package v040
import (

View File

@ -1,50 +0,0 @@
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

@ -5,6 +5,7 @@ import (
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"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
// MigrateStore performs in-place store migrations from v0.40 to v0.42. The
@ -27,7 +28,7 @@ func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error {
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key())
denom := oldStoreIter.Key()[v040auth.AddrLen:]
newStoreKey := append(CreateAccountBalancesPrefix(addr), denom...)
newStoreKey := append(types.CreateAccountBalancesPrefix(addr), denom...)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())

View File

@ -10,6 +10,7 @@ import (
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"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
func TestStoreMigration(t *testing.T) {
@ -27,7 +28,7 @@ func TestStoreMigration(t *testing.T) {
err := v042bank.MigrateStore(ctx, bankKey)
require.NoError(t, err)
newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...)
newKey := append(types.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))

View File

@ -98,9 +98,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)
})
m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper))
cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2)
}
// NewAppModule creates a new AppModule object

View File

@ -0,0 +1,21 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v042 "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042"
)
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper Keeper
}
// NewMigrator returns a new Migrator.
func NewMigrator(keeper Keeper) Migrator {
return Migrator{keeper: keeper}
}
// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v042.MigrateStore(ctx, m.keeper.storeKey)
}

View File

@ -0,0 +1,196 @@
// Package v040 is copy-pasted from:
// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/distribution/types/keys.go
package v040
import (
"encoding/binary"
sdk "github.com/cosmos/cosmos-sdk/types"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
)
const (
// ModuleName is the module name constant used in many places
ModuleName = "distribution"
// StoreKey is the store key string for distribution
StoreKey = ModuleName
// RouterKey is the message route for distribution
RouterKey = ModuleName
// QuerierRoute is the querier route for distribution
QuerierRoute = ModuleName
)
// Keys for distribution store
// Items are stored with the following key: values
//
// - 0x00<proposalID_Bytes>: FeePol
//
// - 0x01: sdk.ConsAddress
//
// - 0x02<valAddr_Bytes>: ValidatorOutstandingRewards
//
// - 0x03<accAddr_Bytes>: sdk.AccAddress
//
// - 0x04<valAddr_Bytes><accAddr_Bytes>: DelegatorStartingInfo
//
// - 0x05<valAddr_Bytes><period_Bytes>: ValidatorHistoricalRewards
//
// - 0x06<valAddr_Bytes>: ValidatorCurrentRewards
//
// - 0x07<valAddr_Bytes>: ValidatorCurrentRewards
//
// - 0x08<valAddr_Bytes><height>: ValidatorSlashEvent
var (
FeePoolKey = []byte{0x00} // key for global distribution state
ProposerKey = []byte{0x01} // key for the proposer operator address
ValidatorOutstandingRewardsPrefix = []byte{0x02} // key for outstanding rewards
DelegatorWithdrawAddrPrefix = []byte{0x03} // key for delegator withdraw address
DelegatorStartingInfoPrefix = []byte{0x04} // key for delegator starting info
ValidatorHistoricalRewardsPrefix = []byte{0x05} // key for historical validators rewards / stake
ValidatorCurrentRewardsPrefix = []byte{0x06} // key for current validator rewards
ValidatorAccumulatedCommissionPrefix = []byte{0x07} // key for accumulated validator commission
ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction
)
// gets an address from a validator's outstanding rewards key
func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) {
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
return sdk.ValAddress(addr)
}
// gets an address from a delegator's withdraw info key
func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) {
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
return sdk.AccAddress(addr)
}
// gets the addresses from a delegator starting info key
func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) {
addr := key[1 : 1+v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
valAddr = sdk.ValAddress(addr)
addr = key[1+v040auth.AddrLen:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
delAddr = sdk.AccAddress(addr)
return
}
// gets the address & period from a validator's historical rewards key
func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) {
addr := key[1 : 1+v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
valAddr = sdk.ValAddress(addr)
b := key[1+v040auth.AddrLen:]
if len(b) != 8 {
panic("unexpected key length")
}
period = binary.LittleEndian.Uint64(b)
return
}
// gets the address from a validator's current rewards key
func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) {
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
return sdk.ValAddress(addr)
}
// gets the address from a validator's accumulated commission key
func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) {
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
return sdk.ValAddress(addr)
}
// gets the height from a validator's slash event key
func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) {
addr := key[1 : 1+v040auth.AddrLen]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
valAddr = sdk.ValAddress(addr)
startB := 1 + v040auth.AddrLen
b := key[startB : startB+8] // the next 8 bytes represent the height
height = binary.BigEndian.Uint64(b)
return
}
// gets the outstanding rewards key for a validator
func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte {
return append(ValidatorOutstandingRewardsPrefix, valAddr.Bytes()...)
}
// gets the key for a delegator's withdraw addr
func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte {
return append(DelegatorWithdrawAddrPrefix, delAddr.Bytes()...)
}
// gets the key for a delegator's starting info
func GetDelegatorStartingInfoKey(v sdk.ValAddress, d sdk.AccAddress) []byte {
return append(append(DelegatorStartingInfoPrefix, v.Bytes()...), d.Bytes()...)
}
// gets the prefix key for a validator's historical rewards
func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte {
return append(ValidatorHistoricalRewardsPrefix, v.Bytes()...)
}
// gets the key for a validator's historical rewards
func GetValidatorHistoricalRewardsKey(v sdk.ValAddress, k uint64) []byte {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, k)
return append(append(ValidatorHistoricalRewardsPrefix, v.Bytes()...), b...)
}
// gets the key for a validator's current rewards
func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte {
return append(ValidatorCurrentRewardsPrefix, v.Bytes()...)
}
// gets the key for a validator's current commission
func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte {
return append(ValidatorAccumulatedCommissionPrefix, v.Bytes()...)
}
// gets the prefix key for a validator's slash fractions
func GetValidatorSlashEventPrefix(v sdk.ValAddress) []byte {
return append(ValidatorSlashEventPrefix, v.Bytes()...)
}
// gets the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height)
func GetValidatorSlashEventKeyPrefix(v sdk.ValAddress, height uint64) []byte {
heightBz := make([]byte, 8)
binary.BigEndian.PutUint64(heightBz, height)
return append(
ValidatorSlashEventPrefix,
append(v.Bytes(), heightBz...)...,
)
}
// gets the key for a validator's slash fraction
func GetValidatorSlashEventKey(v sdk.ValAddress, height, period uint64) []byte {
periodBz := make([]byte, 8)
binary.BigEndian.PutUint64(periodBz, period)
prefix := GetValidatorSlashEventKeyPrefix(v, height)
return append(prefix, periodBz...)
}

View File

@ -1,6 +0,0 @@
package v040
// Default parameter values
const (
ModuleName = "distribution"
)

View File

@ -0,0 +1,70 @@
package v042
import (
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
)
// MigratePrefixAddress is a helper function that migrates all keys of format:
// prefix_bytes | address_bytes
// into format:
// prefix_bytes | address_len (1 byte) | address_bytes
func MigratePrefixAddress(store sdk.KVStore, prefixBz []byte) {
oldStore := prefix.NewStore(store, prefixBz)
oldStoreIter := oldStore.Iterator(nil, nil)
defer oldStoreIter.Close()
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
addr := oldStoreIter.Key()
newStoreKey := append(prefixBz, address.MustLengthPrefix(addr)...)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
}
// MigratePrefixAddressBytes is a helper function that migrates all keys of format:
// prefix_bytes | address_bytes | arbitrary_bytes
// into format:
// prefix_bytes | address_len (1 byte) | address_bytes | arbitrary_bytes
func MigratePrefixAddressBytes(store sdk.KVStore, prefixBz []byte) {
oldStore := prefix.NewStore(store, prefixBz)
oldStoreIter := oldStore.Iterator(nil, nil)
defer oldStoreIter.Close()
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
addr := oldStoreIter.Key()[:v040auth.AddrLen]
endBz := oldStoreIter.Key()[v040auth.AddrLen:]
newStoreKey := append(append(prefixBz, address.MustLengthPrefix(addr)...), endBz...)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
}
// MigratePrefixAddressAddress is a helper function that migrates all keys of format:
// prefix_bytes | address_1_bytes | address_2_bytes
// into format:
// prefix_bytes | address_1_len (1 byte) | address_1_bytes | address_2_len (1 byte) | address_2_bytes
func MigratePrefixAddressAddress(store sdk.KVStore, prefixBz []byte) {
oldStore := prefix.NewStore(store, prefixBz)
oldStoreIter := oldStore.Iterator(nil, nil)
defer oldStoreIter.Close()
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
addr1 := oldStoreIter.Key()[:v040auth.AddrLen]
addr2 := oldStoreIter.Key()[v040auth.AddrLen:]
newStoreKey := append(append(prefixBz, address.MustLengthPrefix(addr1)...), address.MustLengthPrefix(addr2)...)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
}

View File

@ -0,0 +1,23 @@
package v042
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040"
)
// MigrateStore performs in-place store migrations from v0.40 to v0.42. The
// migration includes:
//
// - Change addresses to be length-prefixed.
func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error {
store := ctx.KVStore(storeKey)
MigratePrefixAddress(store, v040distribution.ValidatorOutstandingRewardsPrefix)
MigratePrefixAddress(store, v040distribution.DelegatorWithdrawAddrPrefix)
MigratePrefixAddressAddress(store, v040distribution.DelegatorStartingInfoPrefix)
MigratePrefixAddressBytes(store, v040distribution.ValidatorHistoricalRewardsPrefix)
MigratePrefixAddress(store, v040distribution.ValidatorCurrentRewardsPrefix)
MigratePrefixAddress(store, v040distribution.ValidatorAccumulatedCommissionPrefix)
MigratePrefixAddressBytes(store, v040distribution.ValidatorSlashEventPrefix)
return nil
}

View File

@ -0,0 +1,99 @@
package v042_test
import (
"bytes"
"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"
v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040"
v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042"
"github.com/cosmos/cosmos-sdk/x/distribution/types"
)
func TestStoreMigration(t *testing.T) {
distributionKey := sdk.NewKVStoreKey("distribution")
ctx := testutil.DefaultContext(distributionKey, sdk.NewTransientStoreKey("transient_test"))
store := ctx.KVStore(distributionKey)
_, _, addr1 := testdata.KeyTestPubAddr()
valAddr := sdk.ValAddress(addr1)
_, _, addr2 := testdata.KeyTestPubAddr()
// Use dummy value for all keys.
value := []byte("foo")
testCases := []struct {
name string
oldKey []byte
newKey []byte
}{
{
"FeePoolKey",
v040distribution.FeePoolKey,
types.FeePoolKey,
},
{
"ProposerKey",
v040distribution.ProposerKey,
types.ProposerKey,
},
{
"ValidatorOutstandingRewards",
v040distribution.GetValidatorOutstandingRewardsKey(valAddr),
types.GetValidatorOutstandingRewardsKey(valAddr),
},
{
"DelegatorWithdrawAddr",
v040distribution.GetDelegatorWithdrawAddrKey(addr2),
types.GetDelegatorWithdrawAddrKey(addr2),
},
{
"DelegatorStartingInfo",
v040distribution.GetDelegatorStartingInfoKey(valAddr, addr2),
types.GetDelegatorStartingInfoKey(valAddr, addr2),
},
{
"ValidatorHistoricalRewards",
v040distribution.GetValidatorHistoricalRewardsKey(valAddr, 6),
types.GetValidatorHistoricalRewardsKey(valAddr, 6),
},
{
"ValidatorCurrentRewards",
v040distribution.GetValidatorCurrentRewardsKey(valAddr),
types.GetValidatorCurrentRewardsKey(valAddr),
},
{
"ValidatorAccumulatedCommission",
v040distribution.GetValidatorAccumulatedCommissionKey(valAddr),
types.GetValidatorAccumulatedCommissionKey(valAddr),
},
{
"ValidatorSlashEvent",
v040distribution.GetValidatorSlashEventKey(valAddr, 6, 8),
types.GetValidatorSlashEventKey(valAddr, 6, 8),
},
}
// Set all the old keys to the store
for _, tc := range testCases {
store.Set(tc.oldKey, value)
}
// Run migrations.
err := v042distribution.MigrateStore(ctx, distributionKey)
require.NoError(t, err)
// Make sure the new keys are set and old keys are deleted.
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if bytes.Compare(tc.oldKey, tc.newKey) != 0 {
require.Nil(t, store.Get(tc.oldKey))
}
require.Equal(t, value, store.Get(tc.newKey))
})
}
}

View File

@ -141,6 +141,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
m := keeper.NewMigrator(am.keeper)
cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2)
}
// InitGenesis performs genesis initialization for the distribution module. It returns
@ -160,7 +163,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
func (AppModule) ConsensusVersion() uint64 { return 2 }
// BeginBlock returns the begin blocker for the distribution module.
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {

View File

@ -15,7 +15,7 @@ for fractions of coins to be received from operations like inflation.
When coins are distributed from the pool they are truncated back to
`sdk.Coins` which are non-decimal.
- FeePool: `0x00 -> ProtocolBuffer(FeePool)`
- FeePool: `0x00 -> ProtocolBuffer(FeePool)`
```go
// coins with decimal
@ -33,12 +33,12 @@ type DecCoin struct {
Validator distribution information for the relevant validator is updated each time:
1. delegation amount to a validator is updated,
2. a validator successfully proposes a block and receives a reward,
3. any delegator withdraws from a validator, or
4. the validator withdraws it's commission.
1. delegation amount to a validator is updated,
2. a validator successfully proposes a block and receives a reward,
3. any delegator withdraws from a validator, or
4. the validator withdraws it's commission.
- ValidatorDistInfo: `0x02 | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)`
- ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)`
```go
type ValidatorDistInfo struct {
@ -56,7 +56,7 @@ properties change (aka bonded tokens etc.) its properties will remain constant
and the delegator's _accumulation_ factor can be calculated passively knowing
only the height of the last withdrawal and its current properties.
- DelegationDistInfo: `0x02 | DelegatorAddr | ValOperatorAddr -> ProtocolBuffer(delegatorDist)`
- DelegationDistInfo: `0x02 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(delegatorDist)`
```go
type DelegationDistInfo struct {

View File

@ -0,0 +1,21 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v042 "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042"
)
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper Keeper
}
// NewMigrator returns a new Migrator.
func NewMigrator(keeper Keeper) Migrator {
return Migrator{keeper: keeper}
}
// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v042.MigrateStore(ctx, m.keeper.storeKey)
}

167
x/gov/legacy/v040/keys.go Normal file
View File

@ -0,0 +1,167 @@
// Package v040 is copy-pasted from:
// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/gov/types/keys.go
package v040
import (
"encoding/binary"
"fmt"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
)
const (
// ModuleName is the name of the module
ModuleName = "gov"
// StoreKey is the store key string for gov
StoreKey = ModuleName
// RouterKey is the message route for gov
RouterKey = ModuleName
// QuerierRoute is the querier route for gov
QuerierRoute = ModuleName
)
// Keys for governance store
// Items are stored with the following key: values
//
// - 0x00<proposalID_Bytes>: Proposal
//
// - 0x01<endTime_Bytes><proposalID_Bytes>: activeProposalID
//
// - 0x02<endTime_Bytes><proposalID_Bytes>: inactiveProposalID
//
// - 0x03: nextProposalID
//
// - 0x10<proposalID_Bytes><depositorAddr_Bytes>: Deposit
//
// - 0x20<proposalID_Bytes><voterAddr_Bytes>: Voter
var (
ProposalsKeyPrefix = []byte{0x00}
ActiveProposalQueuePrefix = []byte{0x01}
InactiveProposalQueuePrefix = []byte{0x02}
ProposalIDKey = []byte{0x03}
DepositsKeyPrefix = []byte{0x10}
VotesKeyPrefix = []byte{0x20}
)
var lenTime = len(sdk.FormatTimeBytes(time.Now()))
// GetProposalIDBytes returns the byte representation of the proposalID
func GetProposalIDBytes(proposalID uint64) (proposalIDBz []byte) {
proposalIDBz = make([]byte, 8)
binary.BigEndian.PutUint64(proposalIDBz, proposalID)
return
}
// GetProposalIDFromBytes returns proposalID in uint64 format from a byte array
func GetProposalIDFromBytes(bz []byte) (proposalID uint64) {
return binary.BigEndian.Uint64(bz)
}
// ProposalKey gets a specific proposal from the store
func ProposalKey(proposalID uint64) []byte {
return append(ProposalsKeyPrefix, GetProposalIDBytes(proposalID)...)
}
// ActiveProposalByTimeKey gets the active proposal queue key by endTime
func ActiveProposalByTimeKey(endTime time.Time) []byte {
return append(ActiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...)
}
// ActiveProposalQueueKey returns the key for a proposalID in the activeProposalQueue
func ActiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte {
return append(ActiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...)
}
// InactiveProposalByTimeKey gets the inactive proposal queue key by endTime
func InactiveProposalByTimeKey(endTime time.Time) []byte {
return append(InactiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...)
}
// InactiveProposalQueueKey returns the key for a proposalID in the inactiveProposalQueue
func InactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte {
return append(InactiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...)
}
// DepositsKey gets the first part of the deposits key based on the proposalID
func DepositsKey(proposalID uint64) []byte {
return append(DepositsKeyPrefix, GetProposalIDBytes(proposalID)...)
}
// DepositKey key of a specific deposit from the store
func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte {
return append(DepositsKey(proposalID), depositorAddr.Bytes()...)
}
// VotesKey gets the first part of the votes key based on the proposalID
func VotesKey(proposalID uint64) []byte {
return append(VotesKeyPrefix, GetProposalIDBytes(proposalID)...)
}
// VoteKey key of a specific vote from the store
func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte {
return append(VotesKey(proposalID), voterAddr.Bytes()...)
}
// Split keys function; used for iterators
// SplitProposalKey split the proposal key and returns the proposal id
func SplitProposalKey(key []byte) (proposalID uint64) {
if len(key[1:]) != 8 {
panic(fmt.Sprintf("unexpected key length (%d ≠ 8)", len(key[1:])))
}
return GetProposalIDFromBytes(key[1:])
}
// SplitActiveProposalQueueKey split the active proposal key and returns the proposal id and endTime
func SplitActiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) {
return splitKeyWithTime(key)
}
// SplitInactiveProposalQueueKey split the inactive proposal key and returns the proposal id and endTime
func SplitInactiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) {
return splitKeyWithTime(key)
}
// SplitKeyDeposit split the deposits key and returns the proposal id and depositor address
func SplitKeyDeposit(key []byte) (proposalID uint64, depositorAddr sdk.AccAddress) {
return splitKeyWithAddress(key)
}
// SplitKeyVote split the votes key and returns the proposal id and voter address
func SplitKeyVote(key []byte) (proposalID uint64, voterAddr sdk.AccAddress) {
return splitKeyWithAddress(key)
}
// private functions
func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) {
if len(key[1:]) != 8+lenTime {
panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key[1:]), lenTime+8))
}
endTime, err := sdk.ParseTimeBytes(key[1 : 1+lenTime])
if err != nil {
panic(err)
}
proposalID = GetProposalIDFromBytes(key[1+lenTime:])
return
}
func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) {
if len(key[1:]) != 8+v040auth.AddrLen {
panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key), 8+v040auth.AddrLen))
}
proposalID = GetProposalIDFromBytes(key[1:9])
addr = sdk.AccAddress(key[9:])
return
}

View File

@ -1,6 +0,0 @@
package v040
// Default parameter values
const (
ModuleName = "gov"
)

View File

@ -0,0 +1,43 @@
package v042
import (
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040"
)
const proposalIDLen = 8
// migratePrefixProposalAddress is a helper function that migrates all keys of format:
// <prefix_bytes><proposal_id (8 bytes)><address_bytes>
// into format:
// <prefix_bytes><proposal_id (8 bytes)><address_len (1 byte)><address_bytes>
func migratePrefixProposalAddress(store sdk.KVStore, prefixBz []byte) {
oldStore := prefix.NewStore(store, prefixBz)
oldStoreIter := oldStore.Iterator(nil, nil)
defer oldStoreIter.Close()
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
proposalID := oldStoreIter.Key()[:proposalIDLen]
addr := oldStoreIter.Key()[proposalIDLen:]
newStoreKey := append(append(prefixBz, proposalID...), address.MustLengthPrefix(addr)...)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
}
// MigrateStore performs in-place store migrations from v0.40 to v0.42. The
// migration includes:
//
// - Change addresses to be length-prefixed.
func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error {
store := ctx.KVStore(storeKey)
migratePrefixProposalAddress(store, v040gov.DepositsKeyPrefix)
migratePrefixProposalAddress(store, v040gov.VotesKeyPrefix)
return nil
}

View File

@ -0,0 +1,85 @@
package v042_test
import (
"bytes"
"testing"
"time"
"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"
v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040"
v042gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042"
"github.com/cosmos/cosmos-sdk/x/gov/types"
)
func TestStoreMigration(t *testing.T) {
govKey := sdk.NewKVStoreKey("gov")
ctx := testutil.DefaultContext(govKey, sdk.NewTransientStoreKey("transient_test"))
store := ctx.KVStore(govKey)
_, _, addr1 := testdata.KeyTestPubAddr()
proposalID := uint64(6)
now := time.Now()
// Use dummy value for all keys.
value := []byte("foo")
testCases := []struct {
name string
oldKey []byte
newKey []byte
}{
{
"ProposalKey",
v040gov.ProposalKey(proposalID),
types.ProposalKey(proposalID),
},
{
"ActiveProposalQueue",
v040gov.ActiveProposalQueueKey(proposalID, now),
types.ActiveProposalQueueKey(proposalID, now),
},
{
"InactiveProposalQueue",
v040gov.InactiveProposalQueueKey(proposalID, now),
types.InactiveProposalQueueKey(proposalID, now),
},
{
"ProposalIDKey",
v040gov.ProposalIDKey,
types.ProposalIDKey,
},
{
"DepositKey",
v040gov.DepositKey(proposalID, addr1),
types.DepositKey(proposalID, addr1),
},
{
"VotesKeyPrefix",
v040gov.VoteKey(proposalID, addr1),
types.VoteKey(proposalID, addr1),
},
}
// Set all the old keys to the store
for _, tc := range testCases {
store.Set(tc.oldKey, value)
}
// Run migrations.
err := v042gov.MigrateStore(ctx, govKey)
require.NoError(t, err)
// Make sure the new keys are set and old keys are deleted.
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if bytes.Compare(tc.oldKey, tc.newKey) != 0 {
require.Nil(t, store.Get(tc.oldKey))
}
require.Equal(t, value, store.Get(tc.newKey))
})
}
}

View File

@ -157,6 +157,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
m := keeper.NewMigrator(am.keeper)
cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2)
}
// InitGenesis performs genesis initialization for the gov module. It returns
@ -176,7 +179,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
func (AppModule) ConsensusVersion() uint64 { return 2 }
// BeginBlock performs a no-op.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

View File

@ -0,0 +1,21 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v042 "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042"
)
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper Keeper
}
// NewMigrator returns a new Migrator.
func NewMigrator(keeper Keeper) Migrator {
return Migrator{keeper: keeper}
}
// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v042.MigrateStore(ctx, m.keeper.storeKey)
}

View File

@ -0,0 +1,69 @@
// Package v040 is copy-pasted from:
// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/slashing/types/keys.go
package v040
import (
"encoding/binary"
sdk "github.com/cosmos/cosmos-sdk/types"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
)
const (
// ModuleName is the name of the module
ModuleName = "slashing"
// StoreKey is the store key string for slashing
StoreKey = ModuleName
// RouterKey is the message route for slashing
RouterKey = ModuleName
// QuerierRoute is the querier route for slashing
QuerierRoute = ModuleName
)
// Keys for slashing store
// Items are stored with the following key: values
//
// - 0x01<consAddress_Bytes>: ValidatorSigningInfo
//
// - 0x02<consAddress_Bytes><period_Bytes>: bool
//
// - 0x03<accAddr_Bytes>: crypto.PubKey
var (
ValidatorSigningInfoKeyPrefix = []byte{0x01} // Prefix for signing info
ValidatorMissedBlockBitArrayKeyPrefix = []byte{0x02} // Prefix for missed block bit array
AddrPubkeyRelationKeyPrefix = []byte{0x03} // Prefix for address-pubkey relation
)
// ValidatorSigningInfoKey - stored by *Consensus* address (not operator address)
func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte {
return append(ValidatorSigningInfoKeyPrefix, v.Bytes()...)
}
// ValidatorSigningInfoAddress - extract the address from a validator signing info key
func ValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) {
addr := key[1:]
if len(addr) != v040auth.AddrLen {
panic("unexpected key length")
}
return sdk.ConsAddress(addr)
}
// ValidatorMissedBlockBitArrayPrefixKey - stored by *Consensus* address (not operator address)
func ValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte {
return append(ValidatorMissedBlockBitArrayKeyPrefix, v.Bytes()...)
}
// ValidatorMissedBlockBitArrayKey - stored by *Consensus* address (not operator address)
func ValidatorMissedBlockBitArrayKey(v sdk.ConsAddress, i int64) []byte {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(i))
return append(ValidatorMissedBlockBitArrayPrefixKey(v), b...)
}
// AddrPubkeyRelationKey gets pubkey relation key used to get the pubkey from the address
func AddrPubkeyRelationKey(address []byte) []byte {
return append(AddrPubkeyRelationKeyPrefix, address...)
}

View File

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

View File

@ -0,0 +1,20 @@
package v042
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042"
v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040"
)
// MigrateStore performs in-place store migrations from v0.40 to v0.42. The
// migration includes:
//
// - Change addresses to be length-prefixed.
func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error {
store := ctx.KVStore(storeKey)
v042distribution.MigratePrefixAddress(store, v040slashing.ValidatorSigningInfoKeyPrefix)
v042distribution.MigratePrefixAddressBytes(store, v040slashing.ValidatorMissedBlockBitArrayKeyPrefix)
v042distribution.MigratePrefixAddress(store, v040slashing.AddrPubkeyRelationKeyPrefix)
return nil
}

View File

@ -0,0 +1,68 @@
package v042_test
import (
"bytes"
"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"
v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040"
v042slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042"
"github.com/cosmos/cosmos-sdk/x/slashing/types"
)
func TestStoreMigration(t *testing.T) {
slashingKey := sdk.NewKVStoreKey("slashing")
ctx := testutil.DefaultContext(slashingKey, sdk.NewTransientStoreKey("transient_test"))
store := ctx.KVStore(slashingKey)
_, _, addr1 := testdata.KeyTestPubAddr()
consAddr := sdk.ConsAddress(addr1)
// Use dummy value for all keys.
value := []byte("foo")
testCases := []struct {
name string
oldKey []byte
newKey []byte
}{
{
"ValidatorSigningInfoKey",
v040slashing.ValidatorSigningInfoKey(consAddr),
types.ValidatorSigningInfoKey(consAddr),
},
{
"ValidatorMissedBlockBitArrayKey",
v040slashing.ValidatorMissedBlockBitArrayKey(consAddr, 2),
types.ValidatorMissedBlockBitArrayKey(consAddr, 2),
},
{
"AddrPubkeyRelationKey",
v040slashing.AddrPubkeyRelationKey(consAddr),
types.AddrPubkeyRelationKey(consAddr),
},
}
// Set all the old keys to the store
for _, tc := range testCases {
store.Set(tc.oldKey, value)
}
// Run migrations.
err := v042slashing.MigrateStore(ctx, slashingKey)
require.NoError(t, err)
// Make sure the new keys are set and old keys are deleted.
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if bytes.Compare(tc.oldKey, tc.newKey) != 0 {
require.Nil(t, store.Get(tc.oldKey))
}
require.Equal(t, value, store.Get(tc.newKey))
})
}
}

View File

@ -139,6 +139,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
m := keeper.NewMigrator(am.keeper)
cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2)
}
// InitGenesis performs genesis initialization for the slashing module. It returns

View File

@ -27,8 +27,8 @@ number of blocks by being automatically jailed, potentially slashed, and unbonde
Information about validator's liveness activity is tracked through `ValidatorSigningInfo`.
It is indexed in the store as follows:
- ValidatorSigningInfo: ` 0x01 | ConsAddress -> ProtocolBuffer(ValSigningInfo)`
- MissedBlocksBitArray: ` 0x02 | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` (varint is a number encoding format)
- ValidatorSigningInfo: ` 0x01 | ConsAddrLen (1 byte) | ConsAddress -> ProtocolBuffer(ValSigningInfo)`
- MissedBlocksBitArray: ` 0x02 | ConsAddrLen (1 byte) | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` (varint is a number encoding format)
The first mapping allows us to easily lookup the recent signing info for a
validator based on the validator's consensus address.

View File

@ -0,0 +1,21 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v042 "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042"
)
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper Keeper
}
// NewMigrator returns a new Migrator.
func NewMigrator(keeper Keeper) Migrator {
return Migrator{keeper: keeper}
}
// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v042.MigrateStore(ctx, m.keeper.storeKey)
}

View File

@ -0,0 +1,330 @@
// Package v040 is copy-pasted from:
// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/staking/types/keys.go
package v040
import (
"bytes"
"encoding/binary"
"fmt"
"strconv"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
const (
// ModuleName is the name of the staking module
ModuleName = "staking"
// StoreKey is the string store representation
StoreKey = ModuleName
// QuerierRoute is the querier route for the staking module
QuerierRoute = ModuleName
// RouterKey is the msg router key for the staking module
RouterKey = ModuleName
)
var (
// Keys for store prefixes
// Last* values are constant during a block.
LastValidatorPowerKey = []byte{0x11} // prefix for each key to a validator index, for bonded validators
LastTotalPowerKey = []byte{0x12} // prefix for the total power
ValidatorsKey = []byte{0x21} // prefix for each key to a validator
ValidatorsByConsAddrKey = []byte{0x22} // prefix for each key to a validator index, by pubkey
ValidatorsByPowerIndexKey = []byte{0x23} // prefix for each key to a validator index, sorted by power
DelegationKey = []byte{0x31} // key for a delegation
UnbondingDelegationKey = []byte{0x32} // key for an unbonding-delegation
UnbondingDelegationByValIndexKey = []byte{0x33} // prefix for each key for an unbonding-delegation, by validator operator
RedelegationKey = []byte{0x34} // key for a redelegation
RedelegationByValSrcIndexKey = []byte{0x35} // prefix for each key for an redelegation, by source validator operator
RedelegationByValDstIndexKey = []byte{0x36} // prefix for each key for an redelegation, by destination validator operator
UnbondingQueueKey = []byte{0x41} // prefix for the timestamps in unbonding queue
RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue
ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue
HistoricalInfoKey = []byte{0x50} // prefix for the historical info
)
// gets the key for the validator with address
// VALUE: staking/Validator
func GetValidatorKey(operatorAddr sdk.ValAddress) []byte {
return append(ValidatorsKey, operatorAddr.Bytes()...)
}
// gets the key for the validator with pubkey
// VALUE: validator operator address ([]byte)
func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte {
return append(ValidatorsByConsAddrKey, addr.Bytes()...)
}
// Get the validator operator address from LastValidatorPowerKey
func AddressFromLastValidatorPowerKey(key []byte) []byte {
return key[1:] // remove prefix bytes
}
// get the validator by power index.
// Power index is the key used in the power-store, and represents the relative
// power ranking of the validator.
// VALUE: validator operator address ([]byte)
func GetValidatorsByPowerIndexKey(validator types.Validator) []byte {
// NOTE the address doesn't need to be stored because counter bytes must always be different
// NOTE the larger values are of higher value
consensusPower := sdk.TokensToConsensusPower(validator.Tokens)
consensusPowerBytes := make([]byte, 8)
binary.BigEndian.PutUint64(consensusPowerBytes, uint64(consensusPower))
powerBytes := consensusPowerBytes
powerBytesLen := len(powerBytes) // 8
// key is of format prefix || powerbytes || addrBytes
key := make([]byte, 1+powerBytesLen+v040auth.AddrLen)
key[0] = ValidatorsByPowerIndexKey[0]
copy(key[1:powerBytesLen+1], powerBytes)
addr, err := sdk.ValAddressFromBech32(validator.OperatorAddress)
if err != nil {
panic(err)
}
operAddrInvr := sdk.CopyBytes(addr)
for i, b := range operAddrInvr {
operAddrInvr[i] = ^b
}
copy(key[powerBytesLen+1:], operAddrInvr)
return key
}
// get the bonded validator index key for an operator address
func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte {
return append(LastValidatorPowerKey, operator...)
}
// parse the validators operator address from power rank key
func ParseValidatorPowerRankKey(key []byte) (operAddr []byte) {
powerBytesLen := 8
if len(key) != 1+powerBytesLen+v040auth.AddrLen {
panic("Invalid validator power rank key length")
}
operAddr = sdk.CopyBytes(key[powerBytesLen+1:])
for i, b := range operAddr {
operAddr[i] = ^b
}
return operAddr
}
// GetValidatorQueueKey returns the prefix key used for getting a set of unbonding
// validators whose unbonding completion occurs at the given time and height.
func GetValidatorQueueKey(timestamp time.Time, height int64) []byte {
heightBz := sdk.Uint64ToBigEndian(uint64(height))
timeBz := sdk.FormatTimeBytes(timestamp)
timeBzL := len(timeBz)
prefixL := len(ValidatorQueueKey)
bz := make([]byte, prefixL+8+timeBzL+8)
// copy the prefix
copy(bz[:prefixL], ValidatorQueueKey)
// copy the encoded time bytes length
copy(bz[prefixL:prefixL+8], sdk.Uint64ToBigEndian(uint64(timeBzL)))
// copy the encoded time bytes
copy(bz[prefixL+8:prefixL+8+timeBzL], timeBz)
// copy the encoded height
copy(bz[prefixL+8+timeBzL:], heightBz)
return bz
}
// ParseValidatorQueueKey returns the encoded time and height from a key created
// from GetValidatorQueueKey.
func ParseValidatorQueueKey(bz []byte) (time.Time, int64, error) {
prefixL := len(ValidatorQueueKey)
if prefix := bz[:prefixL]; !bytes.Equal(prefix, ValidatorQueueKey) {
return time.Time{}, 0, fmt.Errorf("invalid prefix; expected: %X, got: %X", ValidatorQueueKey, prefix)
}
timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8])
ts, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)])
if err != nil {
return time.Time{}, 0, err
}
height := sdk.BigEndianToUint64(bz[prefixL+8+int(timeBzL):])
return ts, int64(height), nil
}
// gets the key for delegator bond with validator
// VALUE: staking/Delegation
func GetDelegationKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(GetDelegationsKey(delAddr), valAddr.Bytes()...)
}
// gets the prefix for a delegator for all validators
func GetDelegationsKey(delAddr sdk.AccAddress) []byte {
return append(DelegationKey, delAddr.Bytes()...)
}
// gets the key for an unbonding delegation by delegator and validator addr
// VALUE: staking/UnbondingDelegation
func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(
GetUBDsKey(delAddr.Bytes()),
valAddr.Bytes()...)
}
// gets the index-key for an unbonding delegation, stored by validator-index
// VALUE: none (key rearrangement used)
func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte {
return append(GetUBDsByValIndexKey(valAddr), delAddr.Bytes()...)
}
// rearranges the ValIndexKey to get the UBDKey
func GetUBDKeyFromValIndexKey(indexKey []byte) []byte {
addrs := indexKey[1:] // remove prefix bytes
if len(addrs) != 2*v040auth.AddrLen {
panic("unexpected key length")
}
valAddr := addrs[:v040auth.AddrLen]
delAddr := addrs[v040auth.AddrLen:]
return GetUBDKey(delAddr, valAddr)
}
// gets the prefix for all unbonding delegations from a delegator
func GetUBDsKey(delAddr sdk.AccAddress) []byte {
return append(UnbondingDelegationKey, delAddr.Bytes()...)
}
// gets the prefix keyspace for the indexes of unbonding delegations for a validator
func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte {
return append(UnbondingDelegationByValIndexKey, valAddr.Bytes()...)
}
// gets the prefix for all unbonding delegations from a delegator
func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte {
bz := sdk.FormatTimeBytes(timestamp)
return append(UnbondingQueueKey, bz...)
}
// GetREDKey returns a key prefix for indexing a redelegation from a delegator
// and source validator to a destination validator.
func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
key := make([]byte, 1+v040auth.AddrLen*3)
copy(key[0:v040auth.AddrLen+1], GetREDsKey(delAddr.Bytes()))
copy(key[v040auth.AddrLen+1:2*v040auth.AddrLen+1], valSrcAddr.Bytes())
copy(key[2*v040auth.AddrLen+1:3*v040auth.AddrLen+1], valDstAddr.Bytes())
return key
}
// gets the index-key for a redelegation, stored by source-validator-index
// VALUE: none (key rearrangement used)
func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
REDSFromValsSrcKey := GetREDsFromValSrcIndexKey(valSrcAddr)
offset := len(REDSFromValsSrcKey)
// key is of the form REDSFromValsSrcKey || delAddr || valDstAddr
key := make([]byte, len(REDSFromValsSrcKey)+2*v040auth.AddrLen)
copy(key[0:offset], REDSFromValsSrcKey)
copy(key[offset:offset+v040auth.AddrLen], delAddr.Bytes())
copy(key[offset+v040auth.AddrLen:offset+2*v040auth.AddrLen], valDstAddr.Bytes())
return key
}
// gets the index-key for a redelegation, stored by destination-validator-index
// VALUE: none (key rearrangement used)
func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte {
REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr)
offset := len(REDSToValsDstKey)
// key is of the form REDSToValsDstKey || delAddr || valSrcAddr
key := make([]byte, len(REDSToValsDstKey)+2*v040auth.AddrLen)
copy(key[0:offset], REDSToValsDstKey)
copy(key[offset:offset+v040auth.AddrLen], delAddr.Bytes())
copy(key[offset+v040auth.AddrLen:offset+2*v040auth.AddrLen], valSrcAddr.Bytes())
return key
}
// GetREDKeyFromValSrcIndexKey rearranges the ValSrcIndexKey to get the REDKey
func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte {
// note that first byte is prefix byte
if len(indexKey) != 3*v040auth.AddrLen+1 {
panic("unexpected key length")
}
valSrcAddr := indexKey[1 : v040auth.AddrLen+1]
delAddr := indexKey[v040auth.AddrLen+1 : 2*v040auth.AddrLen+1]
valDstAddr := indexKey[2*v040auth.AddrLen+1 : 3*v040auth.AddrLen+1]
return GetREDKey(delAddr, valSrcAddr, valDstAddr)
}
// GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey
func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte {
// note that first byte is prefix byte
if len(indexKey) != 3*v040auth.AddrLen+1 {
panic("unexpected key length")
}
valDstAddr := indexKey[1 : v040auth.AddrLen+1]
delAddr := indexKey[v040auth.AddrLen+1 : 2*v040auth.AddrLen+1]
valSrcAddr := indexKey[2*v040auth.AddrLen+1 : 3*v040auth.AddrLen+1]
return GetREDKey(delAddr, valSrcAddr, valDstAddr)
}
// GetRedelegationTimeKey returns a key prefix for indexing an unbonding
// redelegation based on a completion time.
func GetRedelegationTimeKey(timestamp time.Time) []byte {
bz := sdk.FormatTimeBytes(timestamp)
return append(RedelegationQueueKey, bz...)
}
// GetREDsKey returns a key prefix for indexing a redelegation from a delegator
// address.
func GetREDsKey(delAddr sdk.AccAddress) []byte {
return append(RedelegationKey, delAddr.Bytes()...)
}
// GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to
// a source validator.
func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte {
return append(RedelegationByValSrcIndexKey, valSrcAddr.Bytes()...)
}
// GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a
// destination (target) validator.
func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte {
return append(RedelegationByValDstIndexKey, valDstAddr.Bytes()...)
}
// GetREDsByDelToValDstIndexKey returns a key prefix for indexing a redelegation
// from an address to a source validator.
func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte {
return append(GetREDsToValDstIndexKey(valDstAddr), delAddr.Bytes()...)
}
// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects.
func GetHistoricalInfoKey(height int64) []byte {
return append(HistoricalInfoKey, []byte(strconv.FormatInt(height, 10))...)
}

View File

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

View File

@ -0,0 +1,78 @@
package v042
import (
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040"
v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042"
v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
// migratePrefixAddressAddressAddress is a helper function that migrates all keys of format:
// prefix_bytes | address_1_bytes | address_2_bytes | address_3_bytes
// into format:
// prefix_bytes | address_1_len (1 byte) | address_1_bytes | address_2_len (1 byte) | address_2_bytes | address_3_len (1 byte) | address_3_bytes
func migratePrefixAddressAddressAddress(store sdk.KVStore, prefixBz []byte) {
oldStore := prefix.NewStore(store, prefixBz)
oldStoreIter := oldStore.Iterator(nil, nil)
defer oldStoreIter.Close()
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
addr1 := oldStoreIter.Key()[:v040auth.AddrLen]
addr2 := oldStoreIter.Key()[v040auth.AddrLen : 2*v040auth.AddrLen]
addr3 := oldStoreIter.Key()[2*v040auth.AddrLen:]
newStoreKey := append(append(append(
prefixBz,
address.MustLengthPrefix(addr1)...), address.MustLengthPrefix(addr2)...), address.MustLengthPrefix(addr3)...,
)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
}
const powerBytesLen = 8
func migrateValidatorsByPowerIndexKey(store sdk.KVStore) {
oldStore := prefix.NewStore(store, v040staking.ValidatorsByPowerIndexKey)
oldStoreIter := oldStore.Iterator(nil, nil)
defer oldStoreIter.Close()
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
powerBytes := oldStoreIter.Key()[:powerBytesLen]
valAddr := oldStoreIter.Key()[powerBytesLen:]
newStoreKey := append(append(types.ValidatorsByPowerIndexKey, powerBytes...), address.MustLengthPrefix(valAddr)...)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
}
// MigrateStore performs in-place store migrations from v0.40 to v0.42. The
// migration includes:
//
// - Change addresses to be length-prefixed.
func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error {
store := ctx.KVStore(storeKey)
v042distribution.MigratePrefixAddress(store, v040staking.LastValidatorPowerKey)
v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsKey)
v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsByConsAddrKey)
migrateValidatorsByPowerIndexKey(store)
v042distribution.MigratePrefixAddressAddress(store, v040staking.DelegationKey)
v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationKey)
v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationByValIndexKey)
migratePrefixAddressAddressAddress(store, v040staking.RedelegationKey)
migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValSrcIndexKey)
migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValDstIndexKey)
return nil
}

View File

@ -0,0 +1,137 @@
package v042_test
import (
"bytes"
"testing"
"time"
"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"
v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040"
v042staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042"
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)
func TestStoreMigration(t *testing.T) {
stakingKey := sdk.NewKVStoreKey("staking")
ctx := testutil.DefaultContext(stakingKey, sdk.NewTransientStoreKey("transient_test"))
store := ctx.KVStore(stakingKey)
_, pk1, addr1 := testdata.KeyTestPubAddr()
valAddr1 := sdk.ValAddress(addr1)
val := teststaking.NewValidator(t, valAddr1, pk1)
_, pk1, addr2 := testdata.KeyTestPubAddr()
valAddr2 := sdk.ValAddress(addr2)
_, _, addr3 := testdata.KeyTestPubAddr()
consAddr := sdk.ConsAddress(addr3.String())
_, _, addr4 := testdata.KeyTestPubAddr()
now := time.Now()
// Use dummy value for all keys.
value := []byte("foo")
testCases := []struct {
name string
oldKey []byte
newKey []byte
}{
{
"LastValidatorPowerKey",
v040staking.GetLastValidatorPowerKey(valAddr1),
types.GetLastValidatorPowerKey(valAddr1),
},
{
"LastTotalPowerKey",
v040staking.LastTotalPowerKey,
types.LastTotalPowerKey,
},
{
"ValidatorsKey",
v040staking.GetValidatorKey(valAddr1),
types.GetValidatorKey(valAddr1),
},
{
"ValidatorsByConsAddrKey",
v040staking.GetValidatorByConsAddrKey(consAddr),
types.GetValidatorByConsAddrKey(consAddr),
},
{
"ValidatorsByPowerIndexKey",
v040staking.GetValidatorsByPowerIndexKey(val),
types.GetValidatorsByPowerIndexKey(val),
},
{
"DelegationKey",
v040staking.GetDelegationKey(addr4, valAddr1),
types.GetDelegationKey(addr4, valAddr1),
},
{
"UnbondingDelegationKey",
v040staking.GetUBDKey(addr4, valAddr1),
types.GetUBDKey(addr4, valAddr1),
},
{
"UnbondingDelegationByValIndexKey",
v040staking.GetUBDByValIndexKey(addr4, valAddr1),
types.GetUBDByValIndexKey(addr4, valAddr1),
},
{
"RedelegationKey",
v040staking.GetREDKey(addr4, valAddr1, valAddr2),
types.GetREDKey(addr4, valAddr1, valAddr2),
},
{
"RedelegationByValSrcIndexKey",
v040staking.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2),
types.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2),
},
{
"RedelegationByValDstIndexKey",
v040staking.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2),
types.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2),
},
{
"UnbondingQueueKey",
v040staking.GetUnbondingDelegationTimeKey(now),
types.GetUnbondingDelegationTimeKey(now),
},
{
"RedelegationQueueKey",
v040staking.GetRedelegationTimeKey(now),
types.GetRedelegationTimeKey(now),
},
{
"ValidatorQueueKey",
v040staking.GetValidatorQueueKey(now, 4),
types.GetValidatorQueueKey(now, 4),
},
{
"HistoricalInfoKey",
v040staking.GetHistoricalInfoKey(4),
types.GetHistoricalInfoKey(4),
},
}
// Set all the old keys to the store
for _, tc := range testCases {
store.Set(tc.oldKey, value)
}
// Run migrations.
err := v042staking.MigrateStore(ctx, stakingKey)
require.NoError(t, err)
// Make sure the new keys are set and old keys are deleted.
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if bytes.Compare(tc.oldKey, tc.newKey) != 0 {
require.Nil(t, store.Get(tc.oldKey))
}
require.Equal(t, value, store.Get(tc.newKey))
})
}
}

View File

@ -138,6 +138,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
querier := keeper.Querier{Keeper: am.keeper}
types.RegisterQueryServer(cfg.QueryServer(), querier)
m := keeper.NewMigrator(am.keeper)
cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2)
}
// InitGenesis performs genesis initialization for the staking module. It returns
@ -158,7 +161,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json
}
// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }
func (AppModule) ConsensusVersion() uint64 { return 2 }
// BeginBlock returns the begin blocker for the staking module.
func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {

View File

@ -44,10 +44,10 @@ required lookups for slashing and validator-set updates. A third special index
throughout each block, unlike the first two indices which mirror the validator
records within a block.
- Validators: `0x21 | OperatorAddr -> ProtocolBuffer(validator)`
- ValidatorsByConsAddr: `0x22 | ConsAddr -> OperatorAddr`
- ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddr -> OperatorAddr`
- LastValidatorsPower: `0x11 OperatorAddr -> ProtocolBuffer(ConsensusPower)`
- Validators: `0x21 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(validator)`
- ValidatorsByConsAddr: `0x22 | ConsAddrLen (1 byte) | ConsAddr -> OperatorAddr`
- ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddrLen (1 byte) | OperatorAddr -> OperatorAddr`
- LastValidatorsPower: `0x11 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(ConsensusPower)`
`Validators` is the primary index - it ensures that each operator can have only one
associated validator, where the public key of that validator can change in the
@ -79,7 +79,7 @@ Each validator's state is stored in a `Validator` struct:
Delegations are identified by combining `DelegatorAddr` (the address of the delegator)
with the `ValidatorAddr` Delegators are indexed in the store as follows:
- Delegation: `0x31 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(delegation)`
- Delegation: `0x31 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(delegation)`
Stake holders may delegate coins to validators; under this circumstance their
funds are held in a `Delegation` data structure. It is owned by one
@ -115,8 +115,8 @@ detected.
`UnbondingDelegation` are indexed in the store as:
- UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)`
- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr -> nil`
- UnbondingDelegation: `0x32 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)`
- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddrLen (1 byte) | ValidatorAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil`
The first map here is used in queries, to lookup all unbonding delegations for
a given delegator, while the second map is used in slashing, to lookup all
@ -137,9 +137,9 @@ committed by the source validator.
`Redelegation` are indexed in the store as:
- Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)`
- RedelegationsBySrc: `0x35 | ValidatorSrcAddr | ValidatorDstAddr | DelegatorAddr -> nil`
- RedelegationsByDst: `0x36 | ValidatorDstAddr | ValidatorSrcAddr | DelegatorAddr -> nil`
- Redelegations: `0x34 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)`
- RedelegationsBySrc: `0x35 | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil`
- RedelegationsByDst: `0x36 | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil`
The first map here is used for queries, to lookup all redelegations for a given
delegator. The second map is used for slashing based on the `ValidatorSrcAddr`,