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.

146 lines
4.3 KiB

  1. package state
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "github.com/tendermint/tendermint/types"
  7. )
  8. //-----------------------------------------------------
  9. // Validate block
  10. func validateBlock(evidencePool EvidencePool, state State, block *types.Block) error {
  11. // Validate internal consistency.
  12. if err := block.ValidateBasic(); err != nil {
  13. return err
  14. }
  15. // Validate basic info.
  16. if block.Version.App != state.Version.Consensus.App ||
  17. block.Version.Block != state.Version.Consensus.Block {
  18. return fmt.Errorf("wrong Block.Header.Version. Expected %v, got %v",
  19. state.Version.Consensus,
  20. block.Version,
  21. )
  22. }
  23. if block.ChainID != state.ChainID {
  24. return fmt.Errorf("wrong Block.Header.ChainID. Expected %v, got %v",
  25. state.ChainID,
  26. block.ChainID,
  27. )
  28. }
  29. if state.LastBlockHeight == 0 && block.Height != state.InitialHeight {
  30. return fmt.Errorf("wrong Block.Header.Height. Expected %v for initial block, got %v",
  31. block.Height, state.InitialHeight)
  32. }
  33. if state.LastBlockHeight > 0 && block.Height != state.LastBlockHeight+1 {
  34. return fmt.Errorf("wrong Block.Header.Height. Expected %v, got %v",
  35. state.LastBlockHeight+1,
  36. block.Height,
  37. )
  38. }
  39. // Validate prev block info.
  40. if !block.LastBlockID.Equals(state.LastBlockID) {
  41. return fmt.Errorf("wrong Block.Header.LastBlockID. Expected %v, got %v",
  42. state.LastBlockID,
  43. block.LastBlockID,
  44. )
  45. }
  46. // Validate app info
  47. if !bytes.Equal(block.AppHash, state.AppHash) {
  48. return fmt.Errorf("wrong Block.Header.AppHash. Expected %X, got %v",
  49. state.AppHash,
  50. block.AppHash,
  51. )
  52. }
  53. hashCP := types.HashConsensusParams(state.ConsensusParams)
  54. if !bytes.Equal(block.ConsensusHash, hashCP) {
  55. return fmt.Errorf("wrong Block.Header.ConsensusHash. Expected %X, got %v",
  56. hashCP,
  57. block.ConsensusHash,
  58. )
  59. }
  60. if !bytes.Equal(block.LastResultsHash, state.LastResultsHash) {
  61. return fmt.Errorf("wrong Block.Header.LastResultsHash. Expected %X, got %v",
  62. state.LastResultsHash,
  63. block.LastResultsHash,
  64. )
  65. }
  66. if !bytes.Equal(block.ValidatorsHash, state.Validators.Hash()) {
  67. return fmt.Errorf("wrong Block.Header.ValidatorsHash. Expected %X, got %v",
  68. state.Validators.Hash(),
  69. block.ValidatorsHash,
  70. )
  71. }
  72. if !bytes.Equal(block.NextValidatorsHash, state.NextValidators.Hash()) {
  73. return fmt.Errorf("wrong Block.Header.NextValidatorsHash. Expected %X, got %v",
  74. state.NextValidators.Hash(),
  75. block.NextValidatorsHash,
  76. )
  77. }
  78. // Validate block LastCommit.
  79. if block.Height == state.InitialHeight {
  80. if len(block.LastCommit.Signatures) != 0 {
  81. return errors.New("initial block can't have LastCommit signatures")
  82. }
  83. } else {
  84. // LastCommit.Signatures length is checked in VerifyCommit.
  85. if err := state.LastValidators.VerifyCommit(
  86. state.ChainID, state.LastBlockID, block.Height-1, block.LastCommit); err != nil {
  87. return err
  88. }
  89. }
  90. // NOTE: We can't actually verify it's the right proposer because we don't
  91. // know what round the block was first proposed. So just check that it's
  92. // a legit address and a known validator.
  93. // The length is checked in ValidateBasic above.
  94. if !state.Validators.HasAddress(block.ProposerAddress) {
  95. return fmt.Errorf("block.Header.ProposerAddress %X is not a validator",
  96. block.ProposerAddress,
  97. )
  98. }
  99. // Validate block Time
  100. switch {
  101. case block.Height > state.InitialHeight:
  102. if !block.Time.After(state.LastBlockTime) {
  103. return fmt.Errorf("block time %v not greater than last block time %v",
  104. block.Time,
  105. state.LastBlockTime,
  106. )
  107. }
  108. medianTime := MedianTime(block.LastCommit, state.LastValidators)
  109. if !block.Time.Equal(medianTime) {
  110. return fmt.Errorf("invalid block time. Expected %v, got %v",
  111. medianTime,
  112. block.Time,
  113. )
  114. }
  115. case block.Height == state.InitialHeight:
  116. genesisTime := state.LastBlockTime
  117. if !block.Time.Equal(genesisTime) {
  118. return fmt.Errorf("block time %v is not equal to genesis time %v",
  119. block.Time,
  120. genesisTime,
  121. )
  122. }
  123. default:
  124. return fmt.Errorf("block height %v lower than initial height %v",
  125. block.Height, state.InitialHeight)
  126. }
  127. // Check evidence doesn't exceed the limit. MaxNumEvidence is capped at uint16, so conversion is always safe.
  128. if max, got := int(state.ConsensusParams.Evidence.MaxNum), len(block.Evidence.Evidence); got > max {
  129. return types.NewErrEvidenceOverflow(max, got)
  130. }
  131. // Validate all evidence.
  132. return evidencePool.CheckEvidence(block.Evidence.Evidence)
  133. }