Skip to content

Commit

Permalink
feat(app)!: migrate pre-initialized module accounts (#2206)
Browse files Browse the repository at this point in the history
  • Loading branch information
haiyizxx authored Nov 12, 2024
1 parent 8fa58f2 commit 81d4315
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 9 deletions.
14 changes: 5 additions & 9 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,18 +478,14 @@ func (app *AxelarApp) setUpgradeBehaviour(configurator module.Configurator, keep
upgradeKeeper.SetUpgradeHandler(
upgradeName(app.Version()),
func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
updatedVM, err := app.mm.RunMigrations(ctx, configurator, fromVM)
err := MigratePreInitializedModuleAccounts(ctx, *GetKeeper[authkeeper.AccountKeeper](keepers), []string{nexusTypes.ModuleName})
if err != nil {
return updatedVM, err
return nil, err
}

// TODO: remove after v35 upgrade
// Override wasm module default params
if upgradeName(app.Version()) == "v0.35" && IsWasmEnabled() {
GetKeeper[wasm.Keeper](keepers).SetParams(ctx, wasmtypes.Params{
CodeUploadAccess: wasmtypes.AllowNobody,
InstantiateDefaultPermission: wasmtypes.AccessTypeNobody,
})
updatedVM, err := app.mm.RunMigrations(ctx, configurator, fromVM)
if err != nil {
return updatedVM, err
}

return updatedVM, err
Expand Down
78 changes: 78 additions & 0 deletions app/migrate_module_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package app

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

// MigratePreInitializedModuleAccounts migrates module accounts that were pre-initialized as BaseAccounts to ModuleAccounts,
// or creates new module accounts if they don't exist.
func MigratePreInitializedModuleAccounts(
ctx sdk.Context,
ak authkeeper.AccountKeeper,
moduleAccountsToInitialize []string,
) error {
for _, module := range moduleAccountsToInitialize {
addr, perms := ak.GetModuleAddressAndPermissions(module)
if addr == nil {
return fmt.Errorf(
"failed to get module address and permissions for module %s",
module,
)
}

acc := ak.GetAccount(ctx, addr)
// The account has not been initialized yet
if acc == nil {
initModuleAccount(ctx, ak, module, perms...)
continue
}

_, isModuleAccount := acc.(authtypes.ModuleAccountI)
if isModuleAccount {
ctx.Logger().Info(fmt.Sprintf(
"account for module %s was correctly initialized, skipping",
module,
))
continue
}

// Migrate from base account to module account
baseAccount, ok := acc.(*authtypes.BaseAccount)
if !ok {
panic(fmt.Sprintf("account %s must be a base account", acc.GetAddress()))
}

newModuleAccount := authtypes.NewModuleAccount(
baseAccount,
module,
perms...,
)
ak.SetModuleAccount(ctx, newModuleAccount)

ctx.Logger().Info(fmt.Sprintf(
"migrated %s module from base account %+v to module account %+v",
module,
baseAccount,
newModuleAccount,
))
}

return nil
}

// create a new module account
func initModuleAccount(ctx sdk.Context, ak authkeeper.AccountKeeper, moduleName string, perms ...string) {
newModuleAccount := authtypes.NewEmptyModuleAccount(moduleName, perms...)
maccI := (ak.NewAccount(ctx, newModuleAccount)).(authtypes.ModuleAccountI) // set the account number
ak.SetModuleAccount(ctx, maccI)

ctx.Logger().Info(fmt.Sprintf(
"initialized %s module account %+v",
moduleName,
newModuleAccount,
))
}
63 changes: 63 additions & 0 deletions app/migrate_module_account_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package app_test

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
params "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

"github.com/axelarnetwork/axelar-core/app"
"github.com/axelarnetwork/axelar-core/testutils/fake"
nexusTypes "github.com/axelarnetwork/axelar-core/x/nexus/types"
. "github.com/axelarnetwork/utils/test"
)

func TestMigratePreInitializedModuleAccounts(t *testing.T) {
var (
accountK authkeeper.AccountKeeper
ctx sdk.Context
)

Given("an account keeper", func() {
encodingConfig := app.MakeEncodingConfig()
ctx = sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger())
storeKey := sdk.NewKVStoreKey(authtypes.StoreKey)

moduleAccPerms := map[string][]string{
"module1": nil,
nexusTypes.ModuleName: {authtypes.Minter, authtypes.Burner},
}

accountK = authkeeper.NewAccountKeeper(
encodingConfig.Codec,
sdk.NewKVStoreKey(authtypes.StoreKey),
params.NewSubspace(encodingConfig.Codec, encodingConfig.Amino, storeKey, storeKey, authtypes.ModuleName),
authtypes.ProtoBaseAccount,
moduleAccPerms,
)
}).When("there is an pre-initialized module account", func() {
account := accountK.NewAccountWithAddress(ctx, authtypes.NewModuleAddress(nexusTypes.ModuleName))
accountK.SetAccount(ctx, account)

account = accountK.GetAccount(ctx, authtypes.NewModuleAddress(nexusTypes.ModuleName))
_, isModuleAccount := account.(authtypes.ModuleAccountI)
assert.False(t, isModuleAccount)

}).Then("migrating pre-initialized base account to module account", func(t *testing.T) {
err := app.MigratePreInitializedModuleAccounts(ctx, accountK, []string{"module1", nexusTypes.ModuleName})
assert.NoError(t, err)

account := accountK.GetAccount(ctx, authtypes.NewModuleAddress(nexusTypes.ModuleName))
_, isModuleAccount := account.(authtypes.ModuleAccountI)
assert.True(t, isModuleAccount)

account = accountK.GetAccount(ctx, authtypes.NewModuleAddress("module1"))
_, isModuleAccount = account.(authtypes.ModuleAccountI)
assert.True(t, isModuleAccount)
}).Run(t)
}

0 comments on commit 81d4315

Please sign in to comment.