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.

374 lines
10 KiB

  1. package types
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "time"
  7. "github.com/tendermint/tendermint/crypto"
  8. "github.com/tendermint/tendermint/internal/libs/protoio"
  9. tmbytes "github.com/tendermint/tendermint/libs/bytes"
  10. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  11. )
  12. const (
  13. nilVoteStr string = "nil-Vote"
  14. )
  15. var (
  16. ErrVoteUnexpectedStep = errors.New("unexpected step")
  17. ErrVoteInvalidValidatorIndex = errors.New("invalid validator index")
  18. ErrVoteInvalidValidatorAddress = errors.New("invalid validator address")
  19. ErrVoteInvalidSignature = errors.New("invalid signature")
  20. ErrVoteInvalidBlockHash = errors.New("invalid block hash")
  21. ErrVoteNonDeterministicSignature = errors.New("non-deterministic signature")
  22. ErrVoteNil = errors.New("nil vote")
  23. ErrVoteInvalidExtension = errors.New("invalid vote extension")
  24. )
  25. type ErrVoteConflictingVotes struct {
  26. VoteA *Vote
  27. VoteB *Vote
  28. }
  29. func (err *ErrVoteConflictingVotes) Error() string {
  30. return fmt.Sprintf("conflicting votes from validator %X", err.VoteA.ValidatorAddress)
  31. }
  32. func NewConflictingVoteError(vote1, vote2 *Vote) *ErrVoteConflictingVotes {
  33. return &ErrVoteConflictingVotes{
  34. VoteA: vote1,
  35. VoteB: vote2,
  36. }
  37. }
  38. // Address is hex bytes.
  39. type Address = crypto.Address
  40. // VoteExtensionToSign is a subset of VoteExtension
  41. // that is signed by the validators private key
  42. type VoteExtensionToSign struct {
  43. AppDataToSign []byte `json:"app_data_to_sign"`
  44. }
  45. func (ext VoteExtensionToSign) ToProto() *tmproto.VoteExtensionToSign {
  46. if ext.IsEmpty() {
  47. return nil
  48. }
  49. return &tmproto.VoteExtensionToSign{
  50. AppDataToSign: ext.AppDataToSign,
  51. }
  52. }
  53. func VoteExtensionToSignFromProto(pext *tmproto.VoteExtensionToSign) VoteExtensionToSign {
  54. if pext == nil {
  55. return VoteExtensionToSign{}
  56. }
  57. return VoteExtensionToSign{
  58. AppDataToSign: pext.AppDataToSign,
  59. }
  60. }
  61. func (ext VoteExtensionToSign) IsEmpty() bool {
  62. return len(ext.AppDataToSign) == 0
  63. }
  64. // BytesPacked returns a bytes-packed representation for
  65. // debugging and human identification. This function should
  66. // not be used for any logical operations.
  67. func (ext VoteExtensionToSign) BytesPacked() []byte {
  68. res := []byte{}
  69. res = append(res, ext.AppDataToSign...)
  70. return res
  71. }
  72. // ToVoteExtension constructs a VoteExtension from a VoteExtensionToSign
  73. func (ext VoteExtensionToSign) ToVoteExtension() VoteExtension {
  74. return VoteExtension{
  75. AppDataToSign: ext.AppDataToSign,
  76. }
  77. }
  78. // VoteExtension is a set of data provided by the application
  79. // that is additionally included in the vote
  80. type VoteExtension struct {
  81. AppDataToSign []byte `json:"app_data_to_sign"`
  82. AppDataSelfAuthenticating []byte `json:"app_data_self_authenticating"`
  83. }
  84. // ToSign constructs a VoteExtensionToSign from a VoteExtenstion
  85. func (ext VoteExtension) ToSign() VoteExtensionToSign {
  86. return VoteExtensionToSign{
  87. AppDataToSign: ext.AppDataToSign,
  88. }
  89. }
  90. // BytesPacked returns a bytes-packed representation for
  91. // debugging and human identification. This function should
  92. // not be used for any logical operations.
  93. func (ext VoteExtension) BytesPacked() []byte {
  94. res := []byte{}
  95. res = append(res, ext.AppDataToSign...)
  96. res = append(res, ext.AppDataSelfAuthenticating...)
  97. return res
  98. }
  99. // Vote represents a prevote, precommit, or commit vote from validators for
  100. // consensus.
  101. type Vote struct {
  102. Type tmproto.SignedMsgType `json:"type"`
  103. Height int64 `json:"height,string"`
  104. Round int32 `json:"round"` // assume there will not be greater than 2_147_483_647 rounds
  105. BlockID BlockID `json:"block_id"` // zero if vote is nil.
  106. Timestamp time.Time `json:"timestamp"`
  107. ValidatorAddress Address `json:"validator_address"`
  108. ValidatorIndex int32 `json:"validator_index"`
  109. Signature []byte `json:"signature"`
  110. VoteExtension VoteExtension `json:"vote_extension"`
  111. }
  112. // CommitSig converts the Vote to a CommitSig.
  113. func (vote *Vote) CommitSig() CommitSig {
  114. if vote == nil {
  115. return NewCommitSigAbsent()
  116. }
  117. var blockIDFlag BlockIDFlag
  118. switch {
  119. case vote.BlockID.IsComplete():
  120. blockIDFlag = BlockIDFlagCommit
  121. case vote.BlockID.IsNil():
  122. blockIDFlag = BlockIDFlagNil
  123. default:
  124. panic(fmt.Sprintf("Invalid vote %v - expected BlockID to be either empty or complete", vote))
  125. }
  126. return CommitSig{
  127. BlockIDFlag: blockIDFlag,
  128. ValidatorAddress: vote.ValidatorAddress,
  129. Timestamp: vote.Timestamp,
  130. Signature: vote.Signature,
  131. VoteExtension: vote.VoteExtension.ToSign(),
  132. }
  133. }
  134. // VoteSignBytes returns the proto-encoding of the canonicalized Vote, for
  135. // signing. Panics is the marshaling fails.
  136. //
  137. // The encoded Protobuf message is varint length-prefixed (using MarshalDelimited)
  138. // for backwards-compatibility with the Amino encoding, due to e.g. hardware
  139. // devices that rely on this encoding.
  140. //
  141. // See CanonicalizeVote
  142. func VoteSignBytes(chainID string, vote *tmproto.Vote) []byte {
  143. pb := CanonicalizeVote(chainID, vote)
  144. bz, err := protoio.MarshalDelimited(&pb)
  145. if err != nil {
  146. panic(err)
  147. }
  148. return bz
  149. }
  150. func (vote *Vote) Copy() *Vote {
  151. voteCopy := *vote
  152. voteCopy.VoteExtension = vote.VoteExtension.Copy()
  153. return &voteCopy
  154. }
  155. // String returns a string representation of Vote.
  156. //
  157. // 1. validator index
  158. // 2. first 6 bytes of validator address
  159. // 3. height
  160. // 4. round,
  161. // 5. type byte
  162. // 6. type string
  163. // 7. first 6 bytes of block hash
  164. // 8. first 6 bytes of signature
  165. // 9. first 6 bytes of vote extension
  166. // 10. timestamp
  167. func (vote *Vote) String() string {
  168. if vote == nil {
  169. return nilVoteStr
  170. }
  171. var typeString string
  172. switch vote.Type {
  173. case tmproto.PrevoteType:
  174. typeString = "Prevote"
  175. case tmproto.PrecommitType:
  176. typeString = "Precommit"
  177. default:
  178. panic("Unknown vote type")
  179. }
  180. return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %X %X @ %s}",
  181. vote.ValidatorIndex,
  182. tmbytes.Fingerprint(vote.ValidatorAddress),
  183. vote.Height,
  184. vote.Round,
  185. vote.Type,
  186. typeString,
  187. tmbytes.Fingerprint(vote.BlockID.Hash),
  188. tmbytes.Fingerprint(vote.Signature),
  189. tmbytes.Fingerprint(vote.VoteExtension.BytesPacked()),
  190. CanonicalTime(vote.Timestamp),
  191. )
  192. }
  193. func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
  194. if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) {
  195. return ErrVoteInvalidValidatorAddress
  196. }
  197. v := vote.ToProto()
  198. if !pubKey.VerifySignature(VoteSignBytes(chainID, v), vote.Signature) {
  199. return ErrVoteInvalidSignature
  200. }
  201. return nil
  202. }
  203. // ValidateBasic performs basic validation.
  204. func (vote *Vote) ValidateBasic() error {
  205. if !IsVoteTypeValid(vote.Type) {
  206. return errors.New("invalid Type")
  207. }
  208. if vote.Height < 0 {
  209. return errors.New("negative Height")
  210. }
  211. if vote.Round < 0 {
  212. return errors.New("negative Round")
  213. }
  214. // NOTE: Timestamp validation is subtle and handled elsewhere.
  215. if err := vote.BlockID.ValidateBasic(); err != nil {
  216. return fmt.Errorf("wrong BlockID: %w", err)
  217. }
  218. // BlockID.ValidateBasic would not err if we for instance have an empty hash but a
  219. // non-empty PartsSetHeader:
  220. if !vote.BlockID.IsNil() && !vote.BlockID.IsComplete() {
  221. return fmt.Errorf("blockID must be either empty or complete, got: %v", vote.BlockID)
  222. }
  223. if len(vote.ValidatorAddress) != crypto.AddressSize {
  224. return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
  225. crypto.AddressSize,
  226. len(vote.ValidatorAddress),
  227. )
  228. }
  229. if vote.ValidatorIndex < 0 {
  230. return errors.New("negative ValidatorIndex")
  231. }
  232. if len(vote.Signature) == 0 {
  233. return errors.New("signature is missing")
  234. }
  235. if len(vote.Signature) > MaxSignatureSize {
  236. return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
  237. }
  238. // XXX: add length verification for vote extension?
  239. return nil
  240. }
  241. func (ext VoteExtension) Copy() VoteExtension {
  242. res := VoteExtension{
  243. AppDataToSign: ext.AppDataToSign,
  244. AppDataSelfAuthenticating: ext.AppDataSelfAuthenticating,
  245. }
  246. return res
  247. }
  248. func (ext VoteExtension) IsEmpty() bool {
  249. if len(ext.AppDataToSign) != 0 {
  250. return false
  251. }
  252. if len(ext.AppDataSelfAuthenticating) != 0 {
  253. return false
  254. }
  255. return true
  256. }
  257. func (ext VoteExtension) ToProto() *tmproto.VoteExtension {
  258. if ext.IsEmpty() {
  259. return nil
  260. }
  261. return &tmproto.VoteExtension{
  262. AppDataToSign: ext.AppDataToSign,
  263. AppDataSelfAuthenticating: ext.AppDataSelfAuthenticating,
  264. }
  265. }
  266. // ToProto converts the handwritten type to proto generated type
  267. // return type, nil if everything converts safely, otherwise nil, error
  268. func (vote *Vote) ToProto() *tmproto.Vote {
  269. if vote == nil {
  270. return nil
  271. }
  272. return &tmproto.Vote{
  273. Type: vote.Type,
  274. Height: vote.Height,
  275. Round: vote.Round,
  276. BlockID: vote.BlockID.ToProto(),
  277. Timestamp: vote.Timestamp,
  278. ValidatorAddress: vote.ValidatorAddress,
  279. ValidatorIndex: vote.ValidatorIndex,
  280. Signature: vote.Signature,
  281. VoteExtension: vote.VoteExtension.ToProto(),
  282. }
  283. }
  284. func VotesToProto(votes []*Vote) (res []*tmproto.Vote) {
  285. if votes == nil {
  286. return nil
  287. }
  288. res = make([]*tmproto.Vote, len(votes))
  289. for i, vote := range votes {
  290. res[i] = vote.ToProto()
  291. }
  292. return
  293. }
  294. func VoteExtensionFromProto(pext *tmproto.VoteExtension) VoteExtension {
  295. ext := VoteExtension{}
  296. if pext != nil {
  297. ext.AppDataToSign = pext.AppDataToSign
  298. ext.AppDataSelfAuthenticating = pext.AppDataSelfAuthenticating
  299. }
  300. return ext
  301. }
  302. // FromProto converts a proto generetad type to a handwritten type
  303. // return type, nil if everything converts safely, otherwise nil, error
  304. func VoteFromProto(pv *tmproto.Vote) (*Vote, error) {
  305. if pv == nil {
  306. return nil, errors.New("nil vote")
  307. }
  308. blockID, err := BlockIDFromProto(&pv.BlockID)
  309. if err != nil {
  310. return nil, err
  311. }
  312. vote := new(Vote)
  313. vote.Type = pv.Type
  314. vote.Height = pv.Height
  315. vote.Round = pv.Round
  316. vote.BlockID = *blockID
  317. vote.Timestamp = pv.Timestamp
  318. vote.ValidatorAddress = pv.ValidatorAddress
  319. vote.ValidatorIndex = pv.ValidatorIndex
  320. vote.Signature = pv.Signature
  321. vote.VoteExtension = VoteExtensionFromProto(pv.VoteExtension)
  322. return vote, vote.ValidateBasic()
  323. }