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.

657 lines
18 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package state
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "time"
  7. . "github.com/tendermint/tendermint/account"
  8. . "github.com/tendermint/tendermint/binary"
  9. . "github.com/tendermint/tendermint/block"
  10. . "github.com/tendermint/tendermint/common"
  11. db_ "github.com/tendermint/tendermint/db"
  12. "github.com/tendermint/tendermint/merkle"
  13. )
  14. var (
  15. stateKey = []byte("stateKey")
  16. minBondAmount = uint64(1) // TODO adjust
  17. defaultAccountsCacheCapacity = 1000 // TODO adjust
  18. unbondingPeriodBlocks = uint(60 * 24 * 365) // TODO probably better to make it time based.
  19. validatorTimeoutBlocks = uint(10) // TODO adjust
  20. )
  21. //-----------------------------------------------------------------------------
  22. type InvalidTxError struct {
  23. Tx Tx
  24. Reason error
  25. }
  26. func (txErr InvalidTxError) Error() string {
  27. return fmt.Sprintf("Invalid tx: [%v] reason: [%v]", txErr.Tx, txErr.Reason)
  28. }
  29. //-----------------------------------------------------------------------------
  30. // NOTE: not goroutine-safe.
  31. type State struct {
  32. DB db_.DB
  33. LastBlockHeight uint
  34. LastBlockHash []byte
  35. LastBlockParts PartSetHeader
  36. LastBlockTime time.Time
  37. BondedValidators *ValidatorSet
  38. UnbondingValidators *ValidatorSet
  39. accounts merkle.Tree // Shouldn't be accessed directly.
  40. validatorInfos merkle.Tree // Shouldn't be accessed directly.
  41. }
  42. func LoadState(db db_.DB) *State {
  43. s := &State{DB: db}
  44. buf := db.Get(stateKey)
  45. if len(buf) == 0 {
  46. return nil
  47. } else {
  48. r, n, err := bytes.NewReader(buf), new(int64), new(error)
  49. s.LastBlockHeight = ReadUvarint(r, n, err)
  50. s.LastBlockHash = ReadByteSlice(r, n, err)
  51. s.LastBlockParts = ReadBinary(PartSetHeader{}, r, n, err).(PartSetHeader)
  52. s.LastBlockTime = ReadTime(r, n, err)
  53. s.BondedValidators = ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
  54. s.UnbondingValidators = ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
  55. accountsHash := ReadByteSlice(r, n, err)
  56. s.accounts = merkle.NewIAVLTree(BasicCodec, AccountCodec, defaultAccountsCacheCapacity, db)
  57. s.accounts.Load(accountsHash)
  58. validatorInfosHash := ReadByteSlice(r, n, err)
  59. s.validatorInfos = merkle.NewIAVLTree(BasicCodec, ValidatorInfoCodec, 0, db)
  60. s.validatorInfos.Load(validatorInfosHash)
  61. if *err != nil {
  62. panic(*err)
  63. }
  64. // TODO: ensure that buf is completely read.
  65. }
  66. return s
  67. }
  68. // Save this state into the db.
  69. func (s *State) Save() {
  70. s.accounts.Save()
  71. s.validatorInfos.Save()
  72. buf, n, err := new(bytes.Buffer), new(int64), new(error)
  73. WriteUvarint(s.LastBlockHeight, buf, n, err)
  74. WriteByteSlice(s.LastBlockHash, buf, n, err)
  75. WriteBinary(s.LastBlockParts, buf, n, err)
  76. WriteTime(s.LastBlockTime, buf, n, err)
  77. WriteBinary(s.BondedValidators, buf, n, err)
  78. WriteBinary(s.UnbondingValidators, buf, n, err)
  79. WriteByteSlice(s.accounts.Hash(), buf, n, err)
  80. WriteByteSlice(s.validatorInfos.Hash(), buf, n, err)
  81. if *err != nil {
  82. panic(*err)
  83. }
  84. s.DB.Set(stateKey, buf.Bytes())
  85. }
  86. func (s *State) Copy() *State {
  87. return &State{
  88. DB: s.DB,
  89. LastBlockHeight: s.LastBlockHeight,
  90. LastBlockHash: s.LastBlockHash,
  91. LastBlockParts: s.LastBlockParts,
  92. LastBlockTime: s.LastBlockTime,
  93. BondedValidators: s.BondedValidators.Copy(),
  94. UnbondingValidators: s.UnbondingValidators.Copy(),
  95. accounts: s.accounts.Copy(),
  96. validatorInfos: s.validatorInfos.Copy(),
  97. }
  98. }
  99. // The accounts from the TxInputs must either already have
  100. // account.PubKey.(type) != PubKeyNil, (it must be known),
  101. // or it must be specified in the TxInput. But not both.
  102. func (s *State) GetOrMakeAccounts(ins []*TxInput, outs []*TxOutput) (map[string]*Account, error) {
  103. accounts := map[string]*Account{}
  104. for _, in := range ins {
  105. // Account shouldn't be duplicated
  106. if _, ok := accounts[string(in.Address)]; ok {
  107. return nil, ErrTxDuplicateAddress
  108. }
  109. account := s.GetAccount(in.Address)
  110. if account == nil {
  111. return nil, ErrTxInvalidAddress
  112. }
  113. // PubKey should be present in either "account" or "in"
  114. if _, isNil := account.PubKey.(PubKeyNil); isNil {
  115. if _, isNil := in.PubKey.(PubKeyNil); isNil {
  116. return nil, ErrTxUnknownPubKey
  117. }
  118. if !bytes.Equal(in.PubKey.Address(), account.Address) {
  119. return nil, ErrTxInvalidPubKey
  120. }
  121. account.PubKey = in.PubKey
  122. } else {
  123. if _, isNil := in.PubKey.(PubKeyNil); !isNil {
  124. return nil, ErrTxRedeclaredPubKey
  125. }
  126. }
  127. accounts[string(in.Address)] = account
  128. }
  129. for _, out := range outs {
  130. // Account shouldn't be duplicated
  131. if _, ok := accounts[string(out.Address)]; ok {
  132. return nil, ErrTxDuplicateAddress
  133. }
  134. account := s.GetAccount(out.Address)
  135. // output account may be nil (new)
  136. if account == nil {
  137. account = &Account{
  138. Address: out.Address,
  139. PubKey: PubKeyNil{},
  140. Sequence: 0,
  141. Balance: 0,
  142. }
  143. }
  144. accounts[string(out.Address)] = account
  145. }
  146. return accounts, nil
  147. }
  148. func (s *State) ValidateInputs(accounts map[string]*Account, signBytes []byte, ins []*TxInput) (total uint64, err error) {
  149. for _, in := range ins {
  150. account := accounts[string(in.Address)]
  151. if account == nil {
  152. panic("ValidateInputs() expects account in accounts")
  153. }
  154. // Check TxInput basic
  155. if err := in.ValidateBasic(); err != nil {
  156. return 0, err
  157. }
  158. // Check amount
  159. if account.Balance < in.Amount {
  160. return 0, ErrTxInsufficientFunds
  161. }
  162. // Check signatures
  163. if !account.PubKey.VerifyBytes(signBytes, in.Signature) {
  164. return 0, ErrTxInvalidSignature
  165. }
  166. // Check sequences
  167. if account.Sequence+1 != in.Sequence {
  168. return 0, ErrTxInvalidSequence
  169. }
  170. // Good. Add amount to total
  171. total += in.Amount
  172. }
  173. return total, nil
  174. }
  175. func (s *State) ValidateOutputs(outs []*TxOutput) (total uint64, err error) {
  176. for _, out := range outs {
  177. // Check TxOutput basic
  178. if err := out.ValidateBasic(); err != nil {
  179. return 0, err
  180. }
  181. // Good. Add amount to total
  182. total += out.Amount
  183. }
  184. return total, nil
  185. }
  186. func (s *State) AdjustByInputs(accounts map[string]*Account, ins []*TxInput) {
  187. for _, in := range ins {
  188. account := accounts[string(in.Address)]
  189. if account == nil {
  190. panic("AdjustByInputs() expects account in accounts")
  191. }
  192. if account.Balance < in.Amount {
  193. panic("AdjustByInputs() expects sufficient funds")
  194. }
  195. account.Balance -= in.Amount
  196. account.Sequence += 1
  197. }
  198. }
  199. func (s *State) AdjustByOutputs(accounts map[string]*Account, outs []*TxOutput) {
  200. for _, out := range outs {
  201. account := accounts[string(out.Address)]
  202. if account == nil {
  203. panic("AdjustByOutputs() expects account in accounts")
  204. }
  205. account.Balance += out.Amount
  206. }
  207. }
  208. // If the tx is invalid, an error will be returned.
  209. // Unlike AppendBlock(), state will not be altered.
  210. func (s *State) ExecTx(tx_ Tx) error {
  211. // TODO: do something with fees
  212. fees := uint64(0)
  213. // Exec tx
  214. switch tx_.(type) {
  215. case *SendTx:
  216. tx := tx_.(*SendTx)
  217. accounts, err := s.GetOrMakeAccounts(tx.Inputs, tx.Outputs)
  218. if err != nil {
  219. return err
  220. }
  221. signBytes := SignBytes(tx)
  222. inTotal, err := s.ValidateInputs(accounts, signBytes, tx.Inputs)
  223. if err != nil {
  224. return err
  225. }
  226. outTotal, err := s.ValidateOutputs(tx.Outputs)
  227. if err != nil {
  228. return err
  229. }
  230. if outTotal > inTotal {
  231. return ErrTxInsufficientFunds
  232. }
  233. fee := inTotal - outTotal
  234. fees += fee
  235. // Good! Adjust accounts
  236. s.AdjustByInputs(accounts, tx.Inputs)
  237. s.AdjustByOutputs(accounts, tx.Outputs)
  238. s.SetAccounts(accounts)
  239. return nil
  240. case *BondTx:
  241. tx := tx_.(*BondTx)
  242. valInfo := s.GetValidatorInfo(tx.PubKey.Address())
  243. if valInfo != nil {
  244. // TODO: In the future, check that the validator wasn't destroyed,
  245. // add funds, merge UnbondTo outputs, and unbond validator.
  246. return errors.New("Adding coins to existing validators not yet supported")
  247. }
  248. accounts, err := s.GetOrMakeAccounts(tx.Inputs, nil)
  249. if err != nil {
  250. return err
  251. }
  252. signBytes := SignBytes(tx)
  253. inTotal, err := s.ValidateInputs(accounts, signBytes, tx.Inputs)
  254. if err != nil {
  255. return err
  256. }
  257. if err := tx.PubKey.ValidateBasic(); err != nil {
  258. return err
  259. }
  260. outTotal, err := s.ValidateOutputs(tx.UnbondTo)
  261. if err != nil {
  262. return err
  263. }
  264. if outTotal > inTotal {
  265. return ErrTxInsufficientFunds
  266. }
  267. fee := inTotal - outTotal
  268. fees += fee
  269. // Good! Adjust accounts
  270. s.AdjustByInputs(accounts, tx.Inputs)
  271. s.SetAccounts(accounts)
  272. // Add ValidatorInfo
  273. s.SetValidatorInfo(&ValidatorInfo{
  274. Address: tx.PubKey.Address(),
  275. PubKey: tx.PubKey,
  276. UnbondTo: tx.UnbondTo,
  277. FirstBondHeight: s.LastBlockHeight + 1,
  278. FirstBondAmount: outTotal,
  279. })
  280. // Add Validator
  281. added := s.BondedValidators.Add(&Validator{
  282. Address: tx.PubKey.Address(),
  283. PubKey: tx.PubKey,
  284. BondHeight: s.LastBlockHeight + 1,
  285. VotingPower: outTotal,
  286. Accum: 0,
  287. })
  288. if !added {
  289. panic("Failed to add validator")
  290. }
  291. return nil
  292. case *UnbondTx:
  293. tx := tx_.(*UnbondTx)
  294. // The validator must be active
  295. _, val := s.BondedValidators.GetByAddress(tx.Address)
  296. if val == nil {
  297. return ErrTxInvalidAddress
  298. }
  299. // Verify the signature
  300. signBytes := SignBytes(tx)
  301. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  302. return ErrTxInvalidSignature
  303. }
  304. // tx.Height must be greater than val.LastCommitHeight
  305. if tx.Height <= val.LastCommitHeight {
  306. return errors.New("Invalid unbond height")
  307. }
  308. // Good!
  309. s.unbondValidator(val)
  310. return nil
  311. case *RebondTx:
  312. tx := tx_.(*RebondTx)
  313. // The validator must be inactive
  314. _, val := s.UnbondingValidators.GetByAddress(tx.Address)
  315. if val == nil {
  316. return ErrTxInvalidAddress
  317. }
  318. // Verify the signature
  319. signBytes := SignBytes(tx)
  320. if !val.PubKey.VerifyBytes(signBytes, tx.Signature) {
  321. return ErrTxInvalidSignature
  322. }
  323. // tx.Height must be equal to the next height
  324. if tx.Height != s.LastBlockHeight+1 {
  325. return errors.New("Invalid rebond height")
  326. }
  327. // tx.Height must be
  328. // Good!
  329. s.rebondValidator(val)
  330. return nil
  331. case *DupeoutTx:
  332. tx := tx_.(*DupeoutTx)
  333. // Verify the signatures
  334. _, accused := s.BondedValidators.GetByAddress(tx.Address)
  335. voteASignBytes := SignBytes(&tx.VoteA)
  336. voteBSignBytes := SignBytes(&tx.VoteB)
  337. if !accused.PubKey.VerifyBytes(voteASignBytes, tx.VoteA.Signature) ||
  338. !accused.PubKey.VerifyBytes(voteBSignBytes, tx.VoteB.Signature) {
  339. return ErrTxInvalidSignature
  340. }
  341. // Verify equivocation
  342. // TODO: in the future, just require one vote from a previous height that
  343. // doesn't exist on this chain.
  344. if tx.VoteA.Height != tx.VoteB.Height {
  345. return errors.New("DupeoutTx heights don't match")
  346. }
  347. if tx.VoteA.Type == VoteTypeCommit && tx.VoteA.Round < tx.VoteB.Round {
  348. // Check special case.
  349. // Validators should not sign another vote after committing.
  350. } else {
  351. if tx.VoteA.Round != tx.VoteB.Round {
  352. return errors.New("DupeoutTx rounds don't match")
  353. }
  354. if tx.VoteA.Type != tx.VoteB.Type {
  355. return errors.New("DupeoutTx types don't match")
  356. }
  357. if bytes.Equal(tx.VoteA.BlockHash, tx.VoteB.BlockHash) {
  358. return errors.New("DupeoutTx blockhashes shouldn't match")
  359. }
  360. }
  361. // Good! (Bad validator!)
  362. s.destroyValidator(accused)
  363. return nil
  364. default:
  365. panic("Unknown Tx type")
  366. }
  367. }
  368. func (s *State) unbondValidator(val *Validator) {
  369. // Move validator to UnbondingValidators
  370. val, removed := s.BondedValidators.Remove(val.Address)
  371. if !removed {
  372. panic("Couldn't remove validator for unbonding")
  373. }
  374. val.UnbondHeight = s.LastBlockHeight + 1
  375. added := s.UnbondingValidators.Add(val)
  376. if !added {
  377. panic("Couldn't add validator for unbonding")
  378. }
  379. }
  380. func (s *State) rebondValidator(val *Validator) {
  381. // Move validator to BondingValidators
  382. val, removed := s.UnbondingValidators.Remove(val.Address)
  383. if !removed {
  384. panic("Couldn't remove validator for rebonding")
  385. }
  386. val.BondHeight = s.LastBlockHeight + 1
  387. added := s.BondedValidators.Add(val)
  388. if !added {
  389. panic("Couldn't add validator for rebonding")
  390. }
  391. }
  392. func (s *State) releaseValidator(val *Validator) {
  393. // Update validatorInfo
  394. valInfo := s.GetValidatorInfo(val.Address)
  395. if valInfo == nil {
  396. panic("Couldn't find validatorInfo for release")
  397. }
  398. valInfo.ReleasedHeight = s.LastBlockHeight + 1
  399. s.SetValidatorInfo(valInfo)
  400. // Send coins back to UnbondTo outputs
  401. accounts, err := s.GetOrMakeAccounts(nil, valInfo.UnbondTo)
  402. if err != nil {
  403. panic("Couldn't get or make unbondTo accounts")
  404. }
  405. s.AdjustByOutputs(accounts, valInfo.UnbondTo)
  406. s.SetAccounts(accounts)
  407. // Remove validator from UnbondingValidators
  408. _, removed := s.UnbondingValidators.Remove(val.Address)
  409. if !removed {
  410. panic("Couldn't remove validator for release")
  411. }
  412. }
  413. func (s *State) destroyValidator(val *Validator) {
  414. // Update validatorInfo
  415. valInfo := s.GetValidatorInfo(val.Address)
  416. if valInfo == nil {
  417. panic("Couldn't find validatorInfo for release")
  418. }
  419. valInfo.DestroyedHeight = s.LastBlockHeight + 1
  420. valInfo.DestroyedAmount = val.VotingPower
  421. s.SetValidatorInfo(valInfo)
  422. // Remove validator
  423. _, removed := s.BondedValidators.Remove(val.Address)
  424. if !removed {
  425. _, removed := s.UnbondingValidators.Remove(val.Address)
  426. if !removed {
  427. panic("Couldn't remove validator for destruction")
  428. }
  429. }
  430. }
  431. // "checkStateHash": If false, instead of checking the resulting
  432. // state.Hash() against block.StateHash, it *sets* the block.StateHash.
  433. // (used for constructing a new proposal)
  434. // NOTE: If an error occurs during block execution, state will be left
  435. // at an invalid state. Copy the state before calling AppendBlock!
  436. func (s *State) AppendBlock(block *Block, blockPartsHeader PartSetHeader, checkStateHash bool) error {
  437. // Basic block validation.
  438. err := block.ValidateBasic(s.LastBlockHeight, s.LastBlockHash, s.LastBlockParts, s.LastBlockTime)
  439. if err != nil {
  440. return err
  441. }
  442. // Validate block Validation.
  443. if block.Height == 1 {
  444. if len(block.Validation.Commits) != 0 {
  445. return errors.New("Block at height 1 (first block) should have no Validation commits")
  446. }
  447. } else {
  448. if uint(len(block.Validation.Commits)) != s.BondedValidators.Size() {
  449. return errors.New("Invalid block validation size")
  450. }
  451. var sumVotingPower uint64
  452. s.BondedValidators.Iterate(func(index uint, val *Validator) bool {
  453. commit := block.Validation.Commits[index]
  454. if commit.IsZero() {
  455. return false
  456. } else {
  457. vote := &Vote{
  458. Height: block.Height - 1,
  459. Round: commit.Round,
  460. Type: VoteTypeCommit,
  461. BlockHash: block.LastBlockHash,
  462. BlockParts: block.LastBlockParts,
  463. }
  464. if val.PubKey.VerifyBytes(SignBytes(vote), commit.Signature) {
  465. sumVotingPower += val.VotingPower
  466. return false
  467. } else {
  468. log.Warning("Invalid validation signature.\nval: %v\nvote: %v", val, vote)
  469. err = errors.New("Invalid validation signature")
  470. return true
  471. }
  472. }
  473. })
  474. if err != nil {
  475. return err
  476. }
  477. if sumVotingPower <= s.BondedValidators.TotalVotingPower()*2/3 {
  478. return errors.New("Insufficient validation voting power")
  479. }
  480. }
  481. // Commit each tx
  482. for _, tx := range block.Data.Txs {
  483. err := s.ExecTx(tx)
  484. if err != nil {
  485. return InvalidTxError{tx, err}
  486. }
  487. }
  488. // Update Validator.LastCommitHeight as necessary.
  489. for i, commit := range block.Validation.Commits {
  490. if commit.IsZero() {
  491. continue
  492. }
  493. _, val := s.BondedValidators.GetByIndex(uint(i))
  494. if val == nil {
  495. Panicf("Failed to fetch validator at index %v", i)
  496. }
  497. val.LastCommitHeight = block.Height - 1
  498. updated := s.BondedValidators.Update(val)
  499. if !updated {
  500. panic("Failed to update validator LastCommitHeight")
  501. }
  502. }
  503. // If any unbonding periods are over,
  504. // reward account with bonded coins.
  505. toRelease := []*Validator{}
  506. s.UnbondingValidators.Iterate(func(index uint, val *Validator) bool {
  507. if val.UnbondHeight+unbondingPeriodBlocks < block.Height {
  508. toRelease = append(toRelease, val)
  509. }
  510. return false
  511. })
  512. for _, val := range toRelease {
  513. s.releaseValidator(val)
  514. }
  515. // If any validators haven't signed in a while,
  516. // unbond them, they have timed out.
  517. toTimeout := []*Validator{}
  518. s.BondedValidators.Iterate(func(index uint, val *Validator) bool {
  519. if val.LastCommitHeight+validatorTimeoutBlocks < block.Height {
  520. toTimeout = append(toTimeout, val)
  521. }
  522. return false
  523. })
  524. for _, val := range toTimeout {
  525. s.unbondValidator(val)
  526. }
  527. // Increment validator AccumPowers
  528. s.BondedValidators.IncrementAccum(1)
  529. // Check or set block.StateHash
  530. stateHash := s.Hash()
  531. if checkStateHash {
  532. // State hash should match
  533. if !bytes.Equal(stateHash, block.StateHash) {
  534. return Errorf("Invalid state hash. Got %X, block says %X",
  535. stateHash, block.StateHash)
  536. }
  537. } else {
  538. // Set the state hash.
  539. if block.StateHash != nil {
  540. panic("Cannot overwrite block.StateHash")
  541. }
  542. block.StateHash = stateHash
  543. }
  544. s.LastBlockHeight = block.Height
  545. s.LastBlockHash = block.Hash()
  546. s.LastBlockParts = blockPartsHeader
  547. s.LastBlockTime = block.Time
  548. return nil
  549. }
  550. // The returned Account is a copy, so mutating it
  551. // has no side effects.
  552. func (s *State) GetAccount(address []byte) *Account {
  553. _, account := s.accounts.Get(address)
  554. if account == nil {
  555. return nil
  556. }
  557. return account.(*Account).Copy()
  558. }
  559. // The account is copied before setting, so mutating it
  560. // afterwards has no side effects.
  561. func (s *State) SetAccount(account *Account) {
  562. s.accounts.Set(account.Address, account.Copy())
  563. }
  564. // The accounts are copied before setting, so mutating it
  565. // afterwards has no side effects.
  566. func (s *State) SetAccounts(accounts map[string]*Account) {
  567. for _, account := range accounts {
  568. s.accounts.Set(account.Address, account.Copy())
  569. }
  570. }
  571. // The returned ValidatorInfo is a copy, so mutating it
  572. // has no side effects.
  573. func (s *State) GetValidatorInfo(address []byte) *ValidatorInfo {
  574. _, valInfo := s.validatorInfos.Get(address)
  575. if valInfo == nil {
  576. return nil
  577. }
  578. return valInfo.(*ValidatorInfo).Copy()
  579. }
  580. // Returns false if new, true if updated.
  581. // The valInfo is copied before setting, so mutating it
  582. // afterwards has no side effects.
  583. func (s *State) SetValidatorInfo(valInfo *ValidatorInfo) (updated bool) {
  584. return s.validatorInfos.Set(valInfo.Address, valInfo.Copy())
  585. }
  586. // Returns a hash that represents the state data,
  587. // excluding LastBlock*
  588. func (s *State) Hash() []byte {
  589. hashables := []merkle.Hashable{
  590. s.BondedValidators,
  591. s.UnbondingValidators,
  592. s.accounts,
  593. s.validatorInfos,
  594. }
  595. return merkle.HashFromHashables(hashables)
  596. }