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.

99 lines
2.7 KiB

  1. package lite
  2. import (
  3. "bytes"
  4. "github.com/pkg/errors"
  5. "github.com/tendermint/tendermint/types"
  6. liteErr "github.com/tendermint/tendermint/lite/errors"
  7. )
  8. // Certifier checks the votes to make sure the block really is signed properly.
  9. // Certifier must know the current set of validitors by some other means.
  10. type Certifier interface {
  11. Certify(check Commit) error
  12. ChainID() string
  13. }
  14. // Commit is basically the rpc /commit response, but extended
  15. //
  16. // This is the basepoint for proving anything on the blockchain. It contains
  17. // a signed header. If the signatures are valid and > 2/3 of the known set,
  18. // we can store this checkpoint and use it to prove any number of aspects of
  19. // the system: such as txs, abci state, validator sets, etc...
  20. type Commit types.SignedHeader
  21. // FullCommit is a commit and the actual validator set,
  22. // the base info you need to update to a given point,
  23. // assuming knowledge of some previous validator set
  24. type FullCommit struct {
  25. Commit `json:"commit"`
  26. Validators *types.ValidatorSet `json:"validator_set"`
  27. }
  28. // NewFullCommit returns a new FullCommit.
  29. func NewFullCommit(commit Commit, vals *types.ValidatorSet) FullCommit {
  30. return FullCommit{
  31. Commit: commit,
  32. Validators: vals,
  33. }
  34. }
  35. // Height returns the height of the header.
  36. func (c Commit) Height() int64 {
  37. if c.Header == nil {
  38. return 0
  39. }
  40. return c.Header.Height
  41. }
  42. // ValidatorsHash returns the hash of the validator set.
  43. func (c Commit) ValidatorsHash() []byte {
  44. if c.Header == nil {
  45. return nil
  46. }
  47. return c.Header.ValidatorsHash
  48. }
  49. // ValidateBasic does basic consistency checks and makes sure the headers
  50. // and commits are all consistent and refer to our chain.
  51. //
  52. // Make sure to use a Verifier to validate the signatures actually provide
  53. // a significantly strong proof for this header's validity.
  54. func (c Commit) ValidateBasic(chainID string) error {
  55. // make sure the header is reasonable
  56. if c.Header == nil {
  57. return errors.New("Commit missing header")
  58. }
  59. if c.Header.ChainID != chainID {
  60. return errors.Errorf("Header belongs to another chain '%s' not '%s'",
  61. c.Header.ChainID, chainID)
  62. }
  63. if c.Commit == nil {
  64. return errors.New("Commit missing signatures")
  65. }
  66. // make sure the header and commit match (height and hash)
  67. if c.Commit.Height() != c.Header.Height {
  68. return liteErr.ErrHeightMismatch(c.Commit.Height(), c.Header.Height)
  69. }
  70. hhash := c.Header.Hash()
  71. chash := c.Commit.BlockID.Hash
  72. if !bytes.Equal(hhash, chash) {
  73. return errors.Errorf("Commits sign block %X header is block %X",
  74. chash, hhash)
  75. }
  76. // make sure the commit is reasonable
  77. err := c.Commit.ValidateBasic()
  78. if err != nil {
  79. return errors.WithStack(err)
  80. }
  81. // looks good, we just need to make sure the signatures are really from
  82. // empowered validators
  83. return nil
  84. }