github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/genesis.go (about) 1 package types 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 8 ethcmn "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/common/hexutil" 10 ) 11 12 type ( 13 // GenesisState defines the evm module genesis state 14 GenesisState struct { 15 Accounts []GenesisAccount `json:"accounts"` 16 TxsLogs []TransactionLogs `json:"txs_logs"` 17 ContractDeploymentWhitelist AddressList `json:"contract_deployment_whitelist"` 18 ContractBlockedList AddressList `json:"contract_blocked_list"` 19 ContractMethodBlockedList BlockedContractList `json:"contract_method_blocked_list,omitempty"` 20 ChainConfig ChainConfig `json:"chain_config"` 21 Params Params `json:"params"` 22 } 23 24 // GenesisAccount defines an account to be initialized in the genesis state. 25 // Its main difference between with Geth's GenesisAccount is that it uses a custom 26 // storage type and that it doesn't contain the private key field. 27 // NOTE: balance is omitted as it is imported from the auth account balance. 28 GenesisAccount struct { 29 Address string `json:"address"` 30 Code hexutil.Bytes `json:"code,omitempty"` 31 Storage Storage `json:"storage,omitempty"` 32 } 33 ) 34 35 // Validate performs a basic validation of a GenesisAccount fields. 36 func (ga GenesisAccount) Validate() error { 37 if ga.Address == (ethcmn.Address{}.String()) { 38 return fmt.Errorf("address cannot be the zero address %s", ga.Address) 39 } 40 if len(ga.Code) == 0 { 41 return errors.New("code bytes cannot be empty") 42 } 43 44 return ga.Storage.Validate() 45 } 46 47 func (ga GenesisAccount) MarshalJSON() ([]byte, error) { 48 formatState := &struct { 49 Address string `json:"address"` 50 Code string `json:"code,omitempty"` 51 Storage Storage `json:"storage,omitempty"` 52 }{ 53 Address: ga.Address, 54 Code: ga.Code.String(), 55 Storage: ga.Storage, 56 } 57 58 if ga.Code == nil { 59 formatState.Code = "" 60 } 61 return json.Marshal(formatState) 62 } 63 64 func (ga *GenesisAccount) UnmarshalJSON(input []byte) error { 65 formatState := &struct { 66 Address string `json:"address"` 67 Code string `json:"code,omitempty"` 68 Storage Storage `json:"storage,omitempty"` 69 }{} 70 if err := json.Unmarshal(input, &formatState); err != nil { 71 return err 72 } 73 74 ga.Address = formatState.Address 75 if formatState.Code == "" { 76 ga.Code = nil 77 } else { 78 ga.Code = hexutil.MustDecode(formatState.Code) 79 } 80 ga.Storage = formatState.Storage 81 return nil 82 } 83 84 // DefaultGenesisState sets default evm genesis state with empty accounts and default params and 85 // chain config values. 86 func DefaultGenesisState() GenesisState { 87 return GenesisState{ 88 Accounts: []GenesisAccount{}, 89 TxsLogs: []TransactionLogs{}, 90 ContractDeploymentWhitelist: AddressList{}, 91 ContractBlockedList: AddressList{}, 92 ChainConfig: DefaultChainConfig(), 93 Params: DefaultParams(), 94 } 95 } 96 97 // Validate performs basic genesis state validation returning an error upon any 98 // failure. 99 func (gs GenesisState) Validate() error { 100 seenAccounts := make(map[string]bool) 101 seenTxs := make(map[string]bool) 102 for _, acc := range gs.Accounts { 103 if seenAccounts[acc.Address] { 104 return fmt.Errorf("duplicated genesis account %s", acc.Address) 105 } 106 if err := acc.Validate(); err != nil { 107 return fmt.Errorf("invalid genesis account %s: %w", acc.Address, err) 108 } 109 seenAccounts[acc.Address] = true 110 } 111 112 for _, tx := range gs.TxsLogs { 113 if seenTxs[tx.Hash.String()] { 114 return fmt.Errorf("duplicated logs from transaction %s", tx.Hash.String()) 115 } 116 117 if err := tx.Validate(); err != nil { 118 return fmt.Errorf("invalid logs from transaction %s: %w", tx.Hash.String(), err) 119 } 120 121 seenTxs[tx.Hash.String()] = true 122 } 123 124 if err := gs.ChainConfig.Validate(); err != nil { 125 return err 126 } 127 128 return gs.Params.Validate() 129 }