github.com/Finschia/finschia-sdk@v0.49.1/x/auth/types/genesis.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"sort"
     7  
     8  	proto "github.com/gogo/protobuf/proto"
     9  
    10  	"github.com/Finschia/finschia-sdk/codec"
    11  	"github.com/Finschia/finschia-sdk/codec/types"
    12  	"github.com/Finschia/finschia-sdk/types/module"
    13  )
    14  
    15  var _ types.UnpackInterfacesMessage = GenesisState{}
    16  
    17  // RandomGenesisAccountsFn defines the function required to generate custom account types
    18  type RandomGenesisAccountsFn func(simState *module.SimulationState) GenesisAccounts
    19  
    20  // NewGenesisState - Create a new genesis state
    21  func NewGenesisState(params Params, accounts GenesisAccounts) *GenesisState {
    22  	genAccounts, err := PackAccounts(accounts)
    23  	if err != nil {
    24  		panic(err)
    25  	}
    26  	return &GenesisState{
    27  		Params:   params,
    28  		Accounts: genAccounts,
    29  	}
    30  }
    31  
    32  // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
    33  func (g GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error {
    34  	for _, any := range g.Accounts {
    35  		var account GenesisAccount
    36  		err := unpacker.UnpackAny(any, &account)
    37  		if err != nil {
    38  			return err
    39  		}
    40  	}
    41  	return nil
    42  }
    43  
    44  // DefaultGenesisState - Return a default genesis state
    45  func DefaultGenesisState() *GenesisState {
    46  	return NewGenesisState(DefaultParams(), GenesisAccounts{})
    47  }
    48  
    49  // GetGenesisStateFromAppState returns x/auth GenesisState given raw application
    50  // genesis state.
    51  func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) GenesisState {
    52  	var genesisState GenesisState
    53  
    54  	if appState[ModuleName] != nil {
    55  		cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState)
    56  	}
    57  
    58  	return genesisState
    59  }
    60  
    61  // ValidateGenesis performs basic validation of auth genesis data returning an
    62  // error for any failed validation criteria.
    63  func ValidateGenesis(data GenesisState) error {
    64  	if err := data.Params.Validate(); err != nil {
    65  		return err
    66  	}
    67  
    68  	genAccs, err := UnpackAccounts(data.Accounts)
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	return ValidateGenAccounts(genAccs)
    74  }
    75  
    76  // SanitizeGenesisAccounts sorts accounts and coin sets.
    77  func SanitizeGenesisAccounts(genAccs GenesisAccounts) GenesisAccounts {
    78  	sort.Slice(genAccs, func(i, j int) bool {
    79  		return genAccs[i].GetAccountNumber() < genAccs[j].GetAccountNumber()
    80  	})
    81  
    82  	return genAccs
    83  }
    84  
    85  // ValidateGenAccounts validates an array of GenesisAccounts and checks for duplicates
    86  func ValidateGenAccounts(accounts GenesisAccounts) error {
    87  	addrMap := make(map[string]bool, len(accounts))
    88  
    89  	for _, acc := range accounts {
    90  		// check for duplicated accounts
    91  		addrStr := acc.GetAddress().String()
    92  		if _, ok := addrMap[addrStr]; ok {
    93  			return fmt.Errorf("duplicate account found in genesis state; address: %s", addrStr)
    94  		}
    95  
    96  		addrMap[addrStr] = true
    97  
    98  		// check account specific validation
    99  		if err := acc.Validate(); err != nil {
   100  			return fmt.Errorf("invalid account found in genesis state; address: %s, error: %s", addrStr, err.Error())
   101  		}
   102  	}
   103  	return nil
   104  }
   105  
   106  // GenesisAccountIterator implements genesis account iteration.
   107  type GenesisAccountIterator struct{}
   108  
   109  // IterateGenesisAccounts iterates over all the genesis accounts found in
   110  // appGenesis and invokes a callback on each genesis account. If any call
   111  // returns true, iteration stops.
   112  func (GenesisAccountIterator) IterateGenesisAccounts(
   113  	cdc codec.Codec, appGenesis map[string]json.RawMessage, cb func(AccountI) (stop bool),
   114  ) {
   115  	for _, genAcc := range GetGenesisStateFromAppState(cdc, appGenesis).Accounts {
   116  		acc, ok := genAcc.GetCachedValue().(AccountI)
   117  		if !ok {
   118  			panic("expected account")
   119  		}
   120  		if cb(acc) {
   121  			break
   122  		}
   123  	}
   124  }
   125  
   126  // PackAccounts converts GenesisAccounts to Any slice
   127  func PackAccounts(accounts GenesisAccounts) ([]*types.Any, error) {
   128  	accountsAny := make([]*types.Any, len(accounts))
   129  	for i, acc := range accounts {
   130  		msg, ok := acc.(proto.Message)
   131  		if !ok {
   132  			return nil, fmt.Errorf("cannot proto marshal %T", acc)
   133  		}
   134  		any, err := types.NewAnyWithValue(msg)
   135  		if err != nil {
   136  			return nil, err
   137  		}
   138  		accountsAny[i] = any
   139  	}
   140  
   141  	return accountsAny, nil
   142  }
   143  
   144  // UnpackAccounts converts Any slice to GenesisAccounts
   145  func UnpackAccounts(accountsAny []*types.Any) (GenesisAccounts, error) {
   146  	accounts := make(GenesisAccounts, len(accountsAny))
   147  	for i, any := range accountsAny {
   148  		acc, ok := any.GetCachedValue().(GenesisAccount)
   149  		if !ok {
   150  			return nil, fmt.Errorf("expected genesis account")
   151  		}
   152  		accounts[i] = acc
   153  	}
   154  
   155  	return accounts, nil
   156  }