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