tendermint/state/state.go

128 lines
3.1 KiB
Go
Raw Normal View History

package state
import (
"bytes"
"io/ioutil"
2015-12-01 20:12:01 -08:00
"sync"
"time"
. "github.com/tendermint/go-common"
dbm "github.com/tendermint/go-db"
"github.com/tendermint/go-wire"
2015-11-01 11:34:08 -08:00
"github.com/tendermint/tendermint/types"
)
var (
2015-11-01 11:34:08 -08:00
stateKey = []byte("stateKey")
)
2014-10-06 21:28:49 -07:00
//-----------------------------------------------------------------------------
2014-10-07 01:05:54 -07:00
// NOTE: not goroutine-safe.
type State struct {
2015-12-01 20:12:01 -08:00
mtx sync.Mutex
db dbm.DB
GenesisDoc *types.GenesisDoc
2015-11-01 11:34:08 -08:00
ChainID string
LastBlockHeight int // Genesis state has this set to 0. So, Block(H=0) does not exist.
2015-11-01 11:34:08 -08:00
LastBlockHash []byte
LastBlockParts types.PartSetHeader
LastBlockTime time.Time
Validators *types.ValidatorSet
LastValidators *types.ValidatorSet
AppHash []byte
}
func LoadState(db dbm.DB) *State {
2015-12-01 20:12:01 -08:00
s := &State{db: db}
buf := db.Get(stateKey)
if len(buf) == 0 {
2014-10-03 17:59:54 -07:00
return nil
} else {
2015-11-10 13:10:43 -08:00
r, n, err := bytes.NewReader(buf), new(int), new(error)
2015-12-01 20:12:01 -08:00
wire.ReadBinaryPtr(&s, r, 0, n, err)
if *err != nil {
2015-06-16 21:16:58 -07:00
// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
Exit(Fmt("Data has been corrupted or its spec has changed: %v\n", *err))
}
2014-10-11 21:27:58 -07:00
// TODO: ensure that buf is completely read.
}
return s
}
func (s *State) Copy() *State {
return &State{
2015-12-01 20:12:01 -08:00
db: s.db,
GenesisDoc: s.GenesisDoc,
2015-11-01 11:34:08 -08:00
ChainID: s.ChainID,
LastBlockHeight: s.LastBlockHeight,
LastBlockHash: s.LastBlockHash,
LastBlockParts: s.LastBlockParts,
LastBlockTime: s.LastBlockTime,
2015-12-01 20:12:01 -08:00
Validators: s.Validators.Copy(),
LastValidators: s.LastValidators.Copy(),
AppHash: s.AppHash,
}
}
2015-12-01 20:12:01 -08:00
func (s *State) Save() {
s.mtx.Lock()
defer s.mtx.Unlock()
2015-12-01 20:12:01 -08:00
buf, n, err := new(bytes.Buffer), new(int), new(error)
wire.WriteBinary(s, buf, n, err)
if *err != nil {
PanicCrisis(*err)
2015-03-18 01:27:16 -07:00
}
2015-12-01 20:12:01 -08:00
s.db.Set(stateKey, buf.Bytes())
2015-06-19 08:36:20 -07:00
}
//-----------------------------------------------------------------------------
// Genesis
2014-10-07 23:11:04 -07:00
2015-12-01 20:12:01 -08:00
func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
genDocJSON, err := ioutil.ReadFile(genDocFile)
if err != nil {
Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
}
2015-12-01 20:12:01 -08:00
genDoc := types.GenesisDocFromJSON(genDocJSON)
return MakeGenesisState(db, genDoc)
}
2015-11-01 11:34:08 -08:00
func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
if len(genDoc.Validators) == 0 {
Exit(Fmt("The genesis file has no validators"))
}
if genDoc.GenesisTime.IsZero() {
genDoc.GenesisTime = time.Now()
}
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,
VotingPower: val.Amount,
}
}
return &State{
2015-12-01 20:12:01 -08:00
db: db,
GenesisDoc: genDoc,
2015-11-01 11:34:08 -08:00
ChainID: genDoc.ChainID,
LastBlockHeight: 0,
LastBlockHash: nil,
LastBlockParts: types.PartSetHeader{},
LastBlockTime: genDoc.GenesisTime,
Validators: types.NewValidatorSet(validators),
LastValidators: types.NewValidatorSet(nil),
AppHash: genDoc.AppHash,
}
}