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.

96 lines
2.6 KiB

  1. package certifiers
  2. import (
  3. "bytes"
  4. "github.com/pkg/errors"
  5. "github.com/tendermint/tendermint/types"
  6. certerr "github.com/tendermint/tendermint/certifiers/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. func NewFullCommit(commit Commit, vals *types.ValidatorSet) FullCommit {
  29. return FullCommit{
  30. Commit: commit,
  31. Validators: vals,
  32. }
  33. }
  34. func (c Commit) Height() int {
  35. if c.Header == nil {
  36. return 0
  37. }
  38. return c.Header.Height
  39. }
  40. func (c Commit) ValidatorsHash() []byte {
  41. if c.Header == nil {
  42. return nil
  43. }
  44. return c.Header.ValidatorsHash
  45. }
  46. // ValidateBasic does basic consistency checks and makes sure the headers
  47. // and commits are all consistent and refer to our chain.
  48. //
  49. // Make sure to use a Verifier to validate the signatures actually provide
  50. // a significantly strong proof for this header's validity.
  51. func (c Commit) ValidateBasic(chainID string) error {
  52. // make sure the header is reasonable
  53. if c.Header == nil {
  54. return errors.New("Commit missing header")
  55. }
  56. if c.Header.ChainID != chainID {
  57. return errors.Errorf("Header belongs to another chain '%s' not '%s'",
  58. c.Header.ChainID, chainID)
  59. }
  60. if c.Commit == nil {
  61. return errors.New("Commit missing signatures")
  62. }
  63. // make sure the header and commit match (height and hash)
  64. if c.Commit.Height() != c.Header.Height {
  65. return certerr.ErrHeightMismatch(c.Commit.Height(), c.Header.Height)
  66. }
  67. hhash := c.Header.Hash()
  68. chash := c.Commit.BlockID.Hash
  69. if !bytes.Equal(hhash, chash) {
  70. return errors.Errorf("Commits sign block %X header is block %X",
  71. chash, hhash)
  72. }
  73. // make sure the commit is reasonable
  74. err := c.Commit.ValidateBasic()
  75. if err != nil {
  76. return errors.WithStack(err)
  77. }
  78. // looks good, we just need to make sure the signatures are really from
  79. // empowered validators
  80. return nil
  81. }