tendermint/state/state.go

188 lines
5.5 KiB
Go
Raw Normal View History

package state
import (
"bytes"
2017-09-05 18:57:36 -07:00
"fmt"
"io/ioutil"
"time"
2015-11-01 11:34:08 -08:00
"github.com/tendermint/tendermint/types"
)
// database keys
var (
stateKey = []byte("stateKey")
)
2014-10-06 21:28:49 -07:00
//-----------------------------------------------------------------------------
// State is a short description of the latest committed block of the Tendermint consensus.
// It keeps all information necessary to validate new blocks,
// including the last validator set and the consensus params.
// All fields are exposed so the struct can be easily serialized,
// but none of them should be mutated directly.
2017-12-28 15:26:13 -08:00
// Instead, use state.Copy() or state.NextState(...).
2014-10-07 01:05:54 -07:00
// NOTE: not goroutine-safe.
type State struct {
// Immutable
ChainID string
2017-09-12 11:37:32 -07:00
// LastBlockHeight=0 at genesis (ie. block(H=0) does not exist)
LastBlockHeight int64
LastBlockTotalTx int64
LastBlockID types.BlockID
LastBlockTime time.Time
// LastValidators is used to validate block.LastCommit.
// Validators are persisted to the database separately every time they change,
// so we can query for historical validator sets.
// Note that if s.LastBlockHeight causes a valset change,
2017-09-05 18:57:36 -07:00
// we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1
Validators *types.ValidatorSet
LastValidators *types.ValidatorSet
LastHeightValidatorsChanged int64
2017-08-21 13:31:54 -07:00
// Consensus parameters used for validating blocks.
// Changes returned by EndBlock and updated after Commit.
ConsensusParams types.ConsensusParams
LastHeightConsensusParamsChanged int64
// Merkle root of the results from executing prev block
2017-12-26 16:53:26 -08:00
LastResultsHash []byte
// The latest AppHash we've received from calling abci.Commit()
AppHash []byte
2017-05-02 00:53:32 -07:00
}
2017-08-21 13:12:07 -07:00
// Copy makes a copy of the State for mutating.
func (s State) Copy() State {
2017-12-27 16:21:16 -08:00
return State{
ChainID: s.ChainID,
LastBlockHeight: s.LastBlockHeight,
LastBlockTotalTx: s.LastBlockTotalTx,
LastBlockID: s.LastBlockID,
LastBlockTime: s.LastBlockTime,
2017-09-04 15:27:04 -07:00
Validators: s.Validators.Copy(),
LastValidators: s.LastValidators.Copy(),
LastHeightValidatorsChanged: s.LastHeightValidatorsChanged,
ConsensusParams: s.ConsensusParams,
LastHeightConsensusParamsChanged: s.LastHeightConsensusParamsChanged,
AppHash: s.AppHash,
2017-12-26 16:53:26 -08:00
LastResultsHash: s.LastResultsHash,
}
}
2017-08-21 13:12:07 -07:00
// Equals returns true if the States are identical.
func (s State) Equals(s2 State) bool {
2018-04-03 06:50:53 -07:00
sbz, s2bz := s.Bytes(), s2.Bytes()
return bytes.Equal(sbz, s2bz)
2016-08-23 18:44:07 -07:00
}
2018-04-03 06:50:53 -07:00
// Bytes serializes the State using go-amino.
func (s State) Bytes() []byte {
2018-04-03 06:50:53 -07:00
return cdc.MustMarshalBinaryBare(s)
2016-08-23 18:44:07 -07:00
}
2017-12-27 17:03:48 -08:00
// IsEmpty returns true if the State is equal to the empty State.
func (s State) IsEmpty() bool {
2017-12-27 19:09:48 -08:00
return s.Validators == nil // XXX can't compare to Empty
}
2017-08-21 13:12:07 -07:00
// GetValidators returns the last and current validator sets.
func (s State) GetValidators() (last *types.ValidatorSet, current *types.ValidatorSet) {
2016-08-23 18:44:07 -07:00
return s.LastValidators, s.Validators
2015-06-19 08:36:20 -07:00
}
2017-12-27 17:03:48 -08:00
//------------------------------------------------------------------------
// Create a block from the latest state
// MakeBlock builds a block with the given txs and commit from the current state.
func (s State) MakeBlock(height int64, txs []types.Tx, commit *types.Commit) (*types.Block, *types.PartSet) {
// build base block
block := types.MakeBlock(height, txs, commit)
// fill header with state data
block.ChainID = s.ChainID
block.TotalTxs = s.LastBlockTotalTx + block.NumTxs
block.LastBlockID = s.LastBlockID
block.ValidatorsHash = s.Validators.Hash()
block.AppHash = s.AppHash
block.ConsensusHash = s.ConsensusParams.Hash()
block.LastResultsHash = s.LastResultsHash
return block, block.MakePartSet(s.ConsensusParams.BlockGossip.BlockPartSizeBytes)
}
//------------------------------------------------------------------------
// Genesis
2014-10-07 23:11:04 -07:00
// MakeGenesisStateFromFile reads and unmarshals state from the given
// file.
//
// Used during replay and in tests.
2017-12-27 17:03:48 -08:00
func MakeGenesisStateFromFile(genDocFile string) (State, error) {
genDoc, err := MakeGenesisDocFromFile(genDocFile)
if err != nil {
2017-12-27 17:03:48 -08:00
return State{}, err
}
return MakeGenesisState(genDoc)
}
// MakeGenesisDocFromFile reads and unmarshals genesis doc from the given file.
func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) {
2015-12-01 20:12:01 -08:00
genDocJSON, err := ioutil.ReadFile(genDocFile)
if err != nil {
return nil, fmt.Errorf("Couldn't read GenesisDoc file: %v", err)
}
2017-01-29 13:50:04 -08:00
genDoc, err := types.GenesisDocFromJSON(genDocJSON)
if err != nil {
return nil, fmt.Errorf("Error reading GenesisDoc: %v", err)
2017-01-29 13:50:04 -08:00
}
return genDoc, nil
}
// MakeGenesisState creates state from types.GenesisDoc.
2017-12-27 17:03:48 -08:00
func MakeGenesisState(genDoc *types.GenesisDoc) (State, error) {
2017-09-11 13:48:41 -07:00
err := genDoc.ValidateAndComplete()
if err != nil {
2017-12-27 17:03:48 -08:00
return State{}, fmt.Errorf("Error in genesis file: %v", err)
}
2015-11-01 11:34:08 -08:00
// Make validators slice
validators := make([]*types.Validator, len(genDoc.Validators))
for i, val := range genDoc.Validators {
pubKey := val.PubKey
address := pubKey.Address()
// Make validator
validators[i] = &types.Validator{
Address: address,
PubKey: pubKey,
2017-09-21 11:37:34 -07:00
VotingPower: val.Power,
}
}
2017-12-27 17:03:48 -08:00
return State{
ChainID: genDoc.ChainID,
LastBlockHeight: 0,
LastBlockID: types.BlockID{},
LastBlockTime: genDoc.GenesisTime,
2017-08-21 13:31:54 -07:00
Validators: types.NewValidatorSet(validators),
LastValidators: types.NewValidatorSet(nil),
2017-09-04 15:27:04 -07:00
LastHeightValidatorsChanged: 1,
ConsensusParams: *genDoc.ConsensusParams,
LastHeightConsensusParamsChanged: 1,
AppHash: genDoc.AppHash,
}, nil
}