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.

127 lines
3.1 KiB

10 years ago
10 years ago
10 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. LastBlockHash []byte
  24. LastBlockParts types.PartSetHeader
  25. LastBlockTime time.Time
  26. Validators *types.ValidatorSet
  27. LastValidators *types.ValidatorSet
  28. AppHash []byte
  29. }
  30. func LoadState(db dbm.DB) *State {
  31. s := &State{db: db}
  32. buf := db.Get(stateKey)
  33. if len(buf) == 0 {
  34. return nil
  35. } else {
  36. r, n, err := bytes.NewReader(buf), new(int), new(error)
  37. wire.ReadBinaryPtr(&s, r, 0, n, err)
  38. if *err != nil {
  39. // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
  40. Exit(Fmt("Data has been corrupted or its spec has changed: %v\n", *err))
  41. }
  42. // TODO: ensure that buf is completely read.
  43. }
  44. return s
  45. }
  46. func (s *State) Copy() *State {
  47. return &State{
  48. db: s.db,
  49. GenesisDoc: s.GenesisDoc,
  50. ChainID: s.ChainID,
  51. LastBlockHeight: s.LastBlockHeight,
  52. LastBlockHash: s.LastBlockHash,
  53. LastBlockParts: s.LastBlockParts,
  54. LastBlockTime: s.LastBlockTime,
  55. Validators: s.Validators.Copy(),
  56. LastValidators: s.LastValidators.Copy(),
  57. AppHash: s.AppHash,
  58. }
  59. }
  60. func (s *State) Save() {
  61. s.mtx.Lock()
  62. defer s.mtx.Unlock()
  63. buf, n, err := new(bytes.Buffer), new(int), new(error)
  64. wire.WriteBinary(s, buf, n, err)
  65. if *err != nil {
  66. PanicCrisis(*err)
  67. }
  68. s.db.Set(stateKey, buf.Bytes())
  69. }
  70. //-----------------------------------------------------------------------------
  71. // Genesis
  72. func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) *State {
  73. genDocJSON, err := ioutil.ReadFile(genDocFile)
  74. if err != nil {
  75. Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
  76. }
  77. genDoc := types.GenesisDocFromJSON(genDocJSON)
  78. return MakeGenesisState(db, genDoc)
  79. }
  80. func MakeGenesisState(db dbm.DB, genDoc *types.GenesisDoc) *State {
  81. if len(genDoc.Validators) == 0 {
  82. Exit(Fmt("The genesis file has no validators"))
  83. }
  84. if genDoc.GenesisTime.IsZero() {
  85. genDoc.GenesisTime = time.Now()
  86. }
  87. // Make validators slice
  88. validators := make([]*types.Validator, len(genDoc.Validators))
  89. for i, val := range genDoc.Validators {
  90. pubKey := val.PubKey
  91. address := pubKey.Address()
  92. // Make validator
  93. validators[i] = &types.Validator{
  94. Address: address,
  95. PubKey: pubKey,
  96. VotingPower: val.Amount,
  97. }
  98. }
  99. return &State{
  100. db: db,
  101. GenesisDoc: genDoc,
  102. ChainID: genDoc.ChainID,
  103. LastBlockHeight: 0,
  104. LastBlockHash: nil,
  105. LastBlockParts: types.PartSetHeader{},
  106. LastBlockTime: genDoc.GenesisTime,
  107. Validators: types.NewValidatorSet(validators),
  108. LastValidators: types.NewValidatorSet(nil),
  109. AppHash: genDoc.AppHash,
  110. }
  111. }