refactor(auth): use collections for GlobalAccountNumber (#15830)

Co-authored-by: testinginprod <testinginprod@somewhere.idk>
This commit is contained in:
testinginprod
2023-04-17 08:57:08 +00:00
committed by GitHub
co-authored by testinginprod
parent 0931193521
commit 73c8064145
15 changed files with 144 additions and 61 deletions
+13 -34
View File
@@ -7,12 +7,10 @@ import (
"cosmossdk.io/collections"
"cosmossdk.io/log"
gogotypes "github.com/cosmos/gogoproto/types"
"cosmossdk.io/core/address"
"cosmossdk.io/core/store"
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
"github.com/cosmos/cosmos-sdk/codec"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
@@ -74,7 +72,8 @@ type AccountKeeper struct {
// State
ParamsState collections.Item[types.Params] // NOTE: name is this because it conflicts with the Params gRPC method impl
ParamsState collections.Item[types.Params] // NOTE: name is this because it conflicts with the Params gRPC method impl
AccountNumber collections.Sequence
}
var _ AccountKeeperI = &AccountKeeper{}
@@ -99,13 +98,14 @@ func NewAccountKeeper(
sb := collections.NewSchemaBuilder(storeService)
return AccountKeeper{
storeService: storeService,
proto: proto,
cdc: cdc,
permAddrs: permAddrs,
addressCdc: bech32Codec,
authority: authority,
ParamsState: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)),
storeService: storeService,
proto: proto,
cdc: cdc,
permAddrs: permAddrs,
addressCdc: bech32Codec,
authority: authority,
ParamsState: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)),
AccountNumber: collections.NewSequence(sb, types.GlobalAccountNumberKey, "account_number"),
}
}
@@ -148,32 +148,11 @@ func (ak AccountKeeper) GetSequence(ctx context.Context, addr sdk.AccAddress) (u
// NextAccountNumber returns and increments the global account number counter.
// If the global account number is not set, it initializes it with value 0.
func (ak AccountKeeper) NextAccountNumber(ctx context.Context) uint64 {
var accNumber uint64
store := ak.storeService.OpenKVStore(ctx)
bz, err := store.Get(types.GlobalAccountNumberKey)
n, err := ak.AccountNumber.Next(ctx)
if err != nil {
// panics only on nil key, which should not be possible
panic(err)
}
if bz == nil {
// initialize the account numbers
accNumber = 0
} else {
val := gogotypes.UInt64Value{}
err := ak.cdc.Unmarshal(bz, &val)
if err != nil {
panic(err)
}
accNumber = val.GetValue()
}
bz = ak.cdc.MustMarshal(&gogotypes.UInt64Value{Value: accNumber + 1})
store.Set(types.GlobalAccountNumberKey, bz)
return accNumber
return n
}
// GetModulePermissions fetches per-module account permissions.
+8
View File
@@ -8,6 +8,7 @@ import (
v2 "github.com/cosmos/cosmos-sdk/x/auth/migrations/v2"
v3 "github.com/cosmos/cosmos-sdk/x/auth/migrations/v3"
v4 "github.com/cosmos/cosmos-sdk/x/auth/migrations/v4"
v5 "github.com/cosmos/cosmos-sdk/x/auth/migrations/v5"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
@@ -59,6 +60,13 @@ func (m Migrator) Migrate3to4(ctx sdk.Context) error {
return v4.Migrate(ctx, m.keeper.storeService, m.legacySubspace, m.keeper.cdc)
}
// Migrate4To5 migrates the x/auth module state from the consensus version 4 to 5.
// It migrates the GlobalAccountNumber from being a protobuf defined value to a
// big-endian encoded uint64, it also migrates it to use a more canonical prefix.
func (m Migrator) Migrate4To5(ctx sdk.Context) error {
return v5.Migrate(ctx, m.keeper.storeService, m.keeper.AccountNumber)
}
// V45_SetAccount implements V45_SetAccount
// set the account without map to accAddr to accNumber.
//
-4
View File
@@ -1,4 +0,0 @@
// v5 is an empty package that exists because of the group module.
// the group module v2 migration actually migrates the auth module state (replace group policies accounts from module accounts to base accounts).
// the auth state does not migrate if the group module is not enabled.
package v5
+45
View File
@@ -0,0 +1,45 @@
package v5
import (
"context"
"cosmossdk.io/collections"
storetypes "cosmossdk.io/core/store"
"github.com/cosmos/gogoproto/types"
)
var LegacyGlobalAccountNumberKey = []byte("globalAccountNumber")
func Migrate(ctx context.Context, storeService storetypes.KVStoreService, sequence collections.Sequence) error {
store := storeService.OpenKVStore(ctx)
b, err := store.Get(LegacyGlobalAccountNumberKey)
if err != nil {
return err
}
if b == nil {
// this would mean no account was ever created in this chain which is being migrated?
// we're doing nothing as the collections.Sequence already handles the non-existing value.
return nil
}
// get old value
v := new(types.UInt64Value)
err = v.Unmarshal(b)
if err != nil {
return err
}
// set the old value in the collection
err = sequence.Set(ctx, v.Value)
if err != nil {
return err
}
// remove the value from the old prefix.
err = store.Delete(LegacyGlobalAccountNumberKey)
if err != nil {
return err
}
return nil
}
+44
View File
@@ -0,0 +1,44 @@
package v5
import (
"testing"
"cosmossdk.io/collections"
"cosmossdk.io/collections/colltest"
"github.com/cosmos/gogoproto/types"
"github.com/stretchr/testify/require"
)
func TestMigrate(t *testing.T) {
kv, ctx := colltest.MockStore()
sb := collections.NewSchemaBuilder(kv)
seq := collections.NewSequence(sb, collections.NewPrefix(0), "seq")
wantValue := uint64(100)
// set old sequence to wanted value
legacySeqBytes, err := (&types.UInt64Value{Value: wantValue}).Marshal()
require.NoError(t, err)
err = kv.OpenKVStore(ctx).Set(LegacyGlobalAccountNumberKey, legacySeqBytes)
require.NoError(t, err)
err = Migrate(ctx, kv, seq)
require.NoError(t, err)
// check that after migration the sequence is what we want it to be
gotValue, err := seq.Peek(ctx)
require.NoError(t, err)
require.Equal(t, wantValue, gotValue)
// case the global account number was not set
ctx = kv.NewStoreContext() // this resets the store to zero
wantValue = collections.DefaultSequenceStart
err = Migrate(ctx, kv, seq)
require.NoError(t, err)
gotValue, err = seq.Next(ctx)
require.NoError(t, err)
require.Equal(t, wantValue, gotValue)
}
+3 -4
View File
@@ -33,7 +33,7 @@ import (
)
// ConsensusVersion defines the current x/auth module consensus version.
const ConsensusVersion = 4
const ConsensusVersion = 5
var (
_ module.AppModule = AppModule{}
@@ -147,9 +147,8 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
panic(fmt.Sprintf("failed to migrate x/%s from version 3 to 4: %v", types.ModuleName, err))
}
// see migrations/v5/doc.go
if err := cfg.RegisterMigration(types.ModuleName, 4, func(ctx sdk.Context) error { return nil }); err != nil {
panic(fmt.Sprintf("failed to migrate x/%s from version 4 to 5: %v", types.ModuleName, err))
if err := cfg.RegisterMigration(types.ModuleName, 4, m.Migrate4To5); err != nil {
panic(fmt.Sprintf("failed to migrate x/%s from version 4 to 5", types.ModuleName))
}
}
+3 -2
View File
@@ -23,8 +23,9 @@ var (
// AddressStoreKeyPrefix prefix for account-by-address store
AddressStoreKeyPrefix = []byte{0x01}
// param key for global account number
GlobalAccountNumberKey = []byte("globalAccountNumber")
// GlobalAccountNumberKey identifies the prefix where the monotonically increasing
// account number is stored.
GlobalAccountNumberKey = collections.NewPrefix(2)
// AccountNumberStoreKeyPrefix prefix for account-by-id store
AccountNumberStoreKeyPrefix = []byte("accountNumber")