You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.6 KiB

10 years ago
10 years ago
10 years ago
8 years ago
8 years ago
8 years ago
  1. package state
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "sync"
  6. "time"
  7. . "github.com/tendermint/go-common"
  8. dbm "github.com/tendermint/go-db"
  9. "github.com/tendermint/go-wire"
  10. "github.com/tendermint/tendermint/types"
  11. )
  12. var (
  13. stateKey = []byte("stateKey")
  14. )
  15. //-----------------------------------------------------------------------------
  16. // NOTE: not goroutine-safe.
  17. type State struct {
  18. mtx sync.Mutex
  19. db dbm.DB
  20. GenesisDoc *types.GenesisDoc
  21. ChainID string
  22. LastBlockHeight int // Genesis state has this set to 0. So, Block(H=0) does not exist.
  23. LastBlockID types.BlockID
  24. LastBlockTime time.Time
  25. Validators *types.ValidatorSet
  26. LastValidators *types.ValidatorSet
  27. AppHash []byte
  28. }
  29. func LoadState(db dbm.DB) *State {
  30. s := &State{db: db}
  31. buf := db.Get(stateKey)
  32. if len(buf) == 0 {
  33. return nil
  34. } else {
  35. r, n, err := bytes.NewReader(buf), new(int), new(error)
  36. wire.ReadBinaryPtr(&s, r, 0, n, err)
  37. if *err != nil {
  38. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  39. Exit(Fmt("Data has been corrupted or its spec has changed: %v\n", *err))
  40. }
  41. // TODO: ensure that buf is completely read.
  42. }
  43. return s
  44. }
  45. func (s *State) Copy() *State {
  46. return &State{
  47. db: s.db,
  48. GenesisDoc: s.GenesisDoc,
  49. ChainID: s.ChainID,
  50. LastBlockHeight: s.LastBlockHeight,
  51. LastBlockID: s.LastBlockID,
  52. LastBlockTime: s.LastBlockTime,
  53. Validators: s.Validators.Copy(),
  54. LastValidators: s.LastValidators.Copy(),
  55. AppHash: s.AppHash,
  56. }
  57. }
  58. func (s *State) Save() {
  59. s.mtx.Lock()
  60. defer s.mtx.Unlock()
  61. s.db.Set(stateKey, s.Bytes())
  62. }
  63. func (s *State) Equals(s2 *State) bool {
  64. return bytes.Equal(s.Bytes(), s2.Bytes())
  65. }
  66. func (s *State) Bytes() []byte {
  67. buf, n, err := new(bytes.Buffer), new(int), new(error)
  68. wire.WriteBinary(s, buf, n, err)
  69. if *err != nil {
  70. PanicCrisis(*err)
  71. }
  72. return buf.Bytes()
  73. }
  74. // Mutate state variables to match block and validators
  75. func (s *State) SetBlockAndValidators(header *types.Header, blockPartsHeader types.PartSetHeader, prevValSet, nextValSet *types.ValidatorSet) {
  76. s.LastBlockHeight = header.Height
  77. s.LastBlockID = types.BlockID{block.Hash(), blockPartsHeader}
  78. s.LastBlockTime = header.Time
  79. s.Validators = nextValSet
  80. s.LastValidators = prevValSet
  81. }
  82. func (s *State) GetValidators() (*types.ValidatorSet, *types.ValidatorSet) {
  83. return s.LastValidators, s.Validators
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Genesis
  87. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
  88. genDocJSON, err := ioutil.ReadFile(genDocFile)
  89. if err != nil {
  90. Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
  91. }
  92. genDoc := types.GenesisDocFromJSON(genDocJSON)
  93. return MakeGenesisState(db, genDoc)
  94. }
  95. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
  96. if len(genDoc.Validators) == 0 {
  97. Exit(Fmt("The genesis file has no validators"))
  98. }
  99. if genDoc.GenesisTime.IsZero() {
  100. genDoc.GenesisTime = time.Now()
  101. }
  102. // Make validators slice
  103. validators := make([]*types.Validator, len(genDoc.Validators))
  104. for i, val := range genDoc.Validators {
  105. pubKey := val.PubKey
  106. address := pubKey.Address()
  107. // Make validator
  108. validators[i] = &types.Validator{
  109. Address: address,
  110. PubKey: pubKey,
  111. VotingPower: val.Amount,
  112. }
  113. }
  114. return &State{
  115. db: db,
  116. GenesisDoc: genDoc,
  117. ChainID: genDoc.ChainID,
  118. LastBlockHeight: 0,
  119. LastBlockID: types.BlockID{},
  120. LastBlockTime: genDoc.GenesisTime,
  121. Validators: types.NewValidatorSet(validators),
  122. LastValidators: types.NewValidatorSet(nil),
  123. AppHash: genDoc.AppHash,
  124. }
  125. }