cosmos-sdk/x/accounts/genesis.go

123 lines
3.2 KiB
Go

package accounts
import (
"context"
"fmt"
"cosmossdk.io/collections"
v1 "cosmossdk.io/x/accounts/v1"
)
func (k Keeper) ExportState(ctx context.Context) (*v1.GenesisState, error) {
genState := &v1.GenesisState{}
err := k.AccountsByType.Walk(ctx, nil, func(accAddr []byte, accType string) (stop bool, err error) {
accNum, err := k.AccountByNumber.Get(ctx, accAddr)
if err != nil {
return true, err
}
accState, err := k.exportAccount(ctx, accAddr, accType, accNum)
if err != nil {
return true, err
}
genState.Accounts = append(genState.Accounts, accState)
return false, nil
})
if err != nil {
return nil, err
}
return genState, nil
}
func (k Keeper) exportAccount(ctx context.Context, addr []byte, accType string, accNum uint64) (*v1.GenesisAccount, error) {
addrString, err := k.addressCodec.BytesToString(addr)
if err != nil {
return nil, err
}
account := &v1.GenesisAccount{
Address: addrString,
AccountType: accType,
AccountNumber: accNum,
State: nil,
}
rng := collections.NewPrefixedPairRange[uint64, []byte](accNum)
err = k.AccountsState.Walk(ctx, rng, func(key collections.Pair[uint64, []byte], value []byte) (stop bool, err error) {
account.State = append(account.State, &v1.KVPair{
Key: key.K2(),
Value: value,
})
return false, nil
})
if err != nil {
return nil, err
}
return account, nil
}
func (k Keeper) ImportState(ctx context.Context, genState *v1.GenesisState) error {
lastAccountNumber := uint64(0)
var err error
// import accounts
for _, acc := range genState.Accounts {
err = k.importAccount(ctx, acc)
if err != nil {
return fmt.Errorf("%w: %s", err, acc.Address)
}
// update lastAccountNumber if the current account being processed
// has a bigger account number.
if lastAccountNumber < acc.AccountNumber {
lastAccountNumber = acc.AccountNumber
}
}
// we set the latest account number only if there were any genesis accounts, otherwise
// we leave it unset.
if len(genState.Accounts) != 0 {
// due to sequence semantics, we store the next account number.
err = k.AccountNumber.Set(ctx, lastAccountNumber+1)
if err != nil {
return err
}
}
// after this execute account creation msgs.
for index, msgInit := range genState.InitAccountMsgs {
_, _, err = k.initFromMsg(ctx, msgInit)
if err != nil {
return fmt.Errorf("invalid genesis account msg init at index %d, msg %s: %w", index, msgInit, err)
}
}
return nil
}
func (k Keeper) importAccount(ctx context.Context, acc *v1.GenesisAccount) error {
// Check if the account type exists in the registered accounts
_, ok := k.accounts[acc.AccountType]
if !ok {
// If the account type does not exist, return an error
return fmt.Errorf("account type %s not found in the registered accounts", acc.AccountType)
}
addrBytes, err := k.addressCodec.StringToBytes(acc.Address)
if err != nil {
return err
}
err = k.AccountsByType.Set(ctx, addrBytes, acc.AccountType)
if err != nil {
return err
}
err = k.AccountByNumber.Set(ctx, addrBytes, acc.AccountNumber)
if err != nil {
return err
}
for _, kv := range acc.State {
err = k.AccountsState.Set(ctx, collections.Join(acc.AccountNumber, kv.Key), kv.Value)
if err != nil {
return err
}
}
return nil
}