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