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  }