123 lines
3.2 KiB
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
|
|
}
|