github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/types/genesis.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "time" 9 10 "github.com/pkg/errors" 11 12 "github.com/tendermint/tendermint/crypto" 13 tmbytes "github.com/tendermint/tendermint/libs/bytes" 14 tmos "github.com/tendermint/tendermint/libs/os" 15 tmtime "github.com/tendermint/tendermint/types/time" 16 ) 17 18 const ( 19 // MaxChainIDLen is a maximum length of the chain ID. 20 MaxChainIDLen = 50 21 ) 22 23 //------------------------------------------------------------ 24 // core types for a genesis definition 25 // NOTE: any changes to the genesis definition should 26 // be reflected in the documentation: 27 // docs/tendermint-core/using-tendermint.md 28 29 // GenesisValidator is an initial validator. 30 type GenesisValidator struct { 31 Address Address `json:"address"` 32 PubKey crypto.PubKey `json:"pub_key"` 33 Power int64 `json:"power"` 34 Name string `json:"name"` 35 } 36 37 // GenesisDoc defines the initial conditions for a tendermint blockchain, in particular its validator set. 38 type GenesisDoc struct { 39 GenesisTime time.Time `json:"genesis_time"` 40 ChainID string `json:"chain_id"` 41 ConsensusParams *ConsensusParams `json:"consensus_params,omitempty"` 42 Validators []GenesisValidator `json:"validators,omitempty"` 43 AppHash tmbytes.HexBytes `json:"app_hash"` 44 AppState json.RawMessage `json:"app_state,omitempty"` 45 } 46 47 // SaveAs is a utility method for saving GenensisDoc as a JSON file. 48 func (genDoc *GenesisDoc) SaveAs(file string) error { 49 genDocBytes, err := cdc.MarshalJSONIndent(genDoc, "", " ") 50 if err != nil { 51 return err 52 } 53 return tmos.WriteFile(file, genDocBytes, 0644) 54 } 55 56 // ValidatorHash returns the hash of the validator set contained in the GenesisDoc 57 func (genDoc *GenesisDoc) ValidatorHash() []byte { 58 vals := make([]*Validator, len(genDoc.Validators)) 59 for i, v := range genDoc.Validators { 60 vals[i] = NewValidator(v.PubKey, v.Power) 61 } 62 vset := NewValidatorSet(vals) 63 return vset.Hash() 64 } 65 66 // ValidateAndComplete checks that all necessary fields are present 67 // and fills in defaults for optional fields left empty 68 func (genDoc *GenesisDoc) ValidateAndComplete() error { 69 if genDoc.ChainID == "" { 70 return errors.New("genesis doc must include non-empty chain_id") 71 } 72 if len(genDoc.ChainID) > MaxChainIDLen { 73 return errors.Errorf("chain_id in genesis doc is too long (max: %d)", MaxChainIDLen) 74 } 75 76 if genDoc.ConsensusParams == nil { 77 genDoc.ConsensusParams = DefaultConsensusParams() 78 } else if err := genDoc.ConsensusParams.Validate(); err != nil { 79 return err 80 } 81 82 for i, v := range genDoc.Validators { 83 if v.Power == 0 { 84 return errors.Errorf("the genesis file cannot contain validators with no voting power: %v", v) 85 } 86 if len(v.Address) > 0 && !bytes.Equal(v.PubKey.Address(), v.Address) { 87 return errors.Errorf("incorrect address for validator %v in the genesis file, should be %v", v, v.PubKey.Address()) 88 } 89 if len(v.Address) == 0 { 90 genDoc.Validators[i].Address = v.PubKey.Address() 91 } 92 } 93 94 if genDoc.GenesisTime.IsZero() { 95 genDoc.GenesisTime = tmtime.Now() 96 } 97 98 return nil 99 } 100 101 //------------------------------------------------------------ 102 // Make genesis state from file 103 104 // GenesisDocFromJSON unmarshalls JSON data into a GenesisDoc. 105 func GenesisDocFromJSON(jsonBlob []byte) (*GenesisDoc, error) { 106 genDoc := GenesisDoc{} 107 err := cdc.UnmarshalJSON(jsonBlob, &genDoc) 108 if err != nil { 109 return nil, err 110 } 111 112 if err := genDoc.ValidateAndComplete(); err != nil { 113 return nil, err 114 } 115 116 return &genDoc, err 117 } 118 119 // GenesisDocFromFile reads JSON data from a file and unmarshalls it into a GenesisDoc. 120 func GenesisDocFromFile(genDocFile string) (*GenesisDoc, error) { 121 jsonBlob, err := ioutil.ReadFile(genDocFile) 122 if err != nil { 123 return nil, errors.Wrap(err, "Couldn't read GenesisDoc file") 124 } 125 genDoc, err := GenesisDocFromJSON(jsonBlob) 126 if err != nil { 127 return nil, errors.Wrap(err, fmt.Sprintf("Error reading GenesisDoc at %v", genDocFile)) 128 } 129 return genDoc, nil 130 }