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