github.com/okex/exchain@v1.8.0/libs/tendermint/types/vote.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "time" 8 9 "github.com/tendermint/go-amino" 10 11 "github.com/okex/exchain/libs/tendermint/crypto" 12 tmbytes "github.com/okex/exchain/libs/tendermint/libs/bytes" 13 tmproto "github.com/okex/exchain/libs/tendermint/proto/types" 14 ) 15 16 const ( 17 // MaxVoteBytes is a maximum vote size (including amino overhead). 18 MaxVoteBytes int64 = 223 19 nilVoteStr string = "nil-Vote" 20 ) 21 22 var ( 23 ErrVoteUnexpectedStep = errors.New("unexpected step") 24 ErrVoteInvalidValidatorIndex = errors.New("invalid validator index") 25 ErrVoteInvalidValidatorAddress = errors.New("invalid validator address") 26 ErrVoteInvalidSignature = errors.New("invalid signature") 27 ErrVoteInvalidBlockHash = errors.New("invalid block hash") 28 ErrVoteNonDeterministicSignature = errors.New("non-deterministic signature") 29 ErrVoteNil = errors.New("nil vote") 30 ) 31 32 type ErrVoteConflictingVotes struct { 33 *DuplicateVoteEvidence 34 } 35 36 func (err *ErrVoteConflictingVotes) Error() string { 37 return fmt.Sprintf("Conflicting votes from validator %v", err.PubKey.Address()) 38 } 39 40 func NewConflictingVoteError(val *Validator, vote1, vote2 *Vote) *ErrVoteConflictingVotes { 41 return &ErrVoteConflictingVotes{ 42 NewDuplicateVoteEvidence(val.PubKey, vote1, vote2), 43 } 44 } 45 46 // Address is hex bytes. 47 type Address = crypto.Address 48 49 // Vote represents a prevote, precommit, or commit vote from validators for 50 // consensus. 51 type Vote struct { 52 Type SignedMsgType `json:"type"` 53 Height int64 `json:"height"` 54 Round int `json:"round"` 55 BlockID BlockID `json:"block_id"` // zero if vote is nil. 56 Timestamp time.Time `json:"timestamp"` 57 ValidatorAddress Address `json:"validator_address"` 58 ValidatorIndex int `json:"validator_index"` 59 Signature []byte `json:"signature"` 60 HasVC bool `json:"has_vc"` // enterNewRoundAVC at this Height 61 } 62 63 func (vote Vote) AminoSize(cdc *amino.Codec) int { 64 var size = 0 65 66 if vote.Type != 0 { 67 size += 1 + amino.UvarintSize(uint64(vote.Type)) 68 } 69 70 if vote.Height != 0 { 71 size += 1 + amino.UvarintSize(uint64(vote.Height)) 72 } 73 74 if vote.Round != 0 { 75 size += 1 + amino.UvarintSize(uint64(vote.Round)) 76 } 77 78 blockIDSize := vote.BlockID.AminoSize(cdc) 79 if blockIDSize != 0 { 80 size += 1 + amino.UvarintSize(uint64(blockIDSize)) + blockIDSize 81 } 82 83 timestampSize := amino.TimeSize(vote.Timestamp) 84 if timestampSize != 0 { 85 size += 1 + amino.UvarintSize(uint64(timestampSize)) + timestampSize 86 } 87 88 if len(vote.ValidatorAddress) != 0 { 89 size += 1 + amino.ByteSliceSize(vote.ValidatorAddress) 90 } 91 92 if vote.ValidatorIndex != 0 { 93 size += 1 + amino.UvarintSize(uint64(vote.ValidatorIndex)) 94 } 95 96 if len(vote.Signature) != 0 { 97 size += 1 + amino.ByteSliceSize(vote.Signature) 98 } 99 if vote.HasVC { 100 size += 1 + 1 101 } 102 103 return size 104 } 105 106 func (vote *Vote) UnmarshalFromAmino(cdc *amino.Codec, data []byte) error { 107 var dataLen uint64 = 0 108 var subData []byte 109 var timestampUpdated bool 110 111 for { 112 data = data[dataLen:] 113 if len(data) == 0 { 114 break 115 } 116 117 pos, pbType, err := amino.ParseProtoPosAndTypeMustOneByte(data[0]) 118 if err != nil { 119 return err 120 } 121 data = data[1:] 122 123 if pbType == amino.Typ3_ByteLength { 124 var n int 125 dataLen, n, err = amino.DecodeUvarint(data) 126 if err != nil { 127 return err 128 } 129 data = data[n:] 130 if len(data) < int(dataLen) { 131 return fmt.Errorf("invalid data len") 132 } 133 subData = data[:dataLen] 134 } 135 136 switch pos { 137 case 1: 138 u64, n, err := amino.DecodeUvarint(data) 139 if err != nil { 140 return err 141 } 142 vote.Type = SignedMsgType(u64) 143 dataLen = uint64(n) 144 case 2: 145 u64, n, err := amino.DecodeUvarint(data) 146 if err != nil { 147 return err 148 } 149 vote.Height = int64(u64) 150 dataLen = uint64(n) 151 case 3: 152 u64, n, err := amino.DecodeUvarint(data) 153 if err != nil { 154 return err 155 } 156 vote.Round = int(u64) 157 dataLen = uint64(n) 158 case 4: 159 err = vote.BlockID.UnmarshalFromAmino(cdc, subData) 160 if err != nil { 161 return err 162 } 163 case 5: 164 vote.Timestamp, _, err = amino.DecodeTime(subData) 165 if err != nil { 166 return err 167 } 168 timestampUpdated = true 169 case 6: 170 vote.ValidatorAddress = make([]byte, len(subData)) 171 copy(vote.ValidatorAddress, subData) 172 case 7: 173 u64, n, err := amino.DecodeUvarint(data) 174 if err != nil { 175 return err 176 } 177 vote.ValidatorIndex = int(u64) 178 dataLen = uint64(n) 179 case 8: 180 vote.Signature = make([]byte, len(subData)) 181 copy(vote.Signature, subData) 182 case 9: 183 var n int 184 vote.HasVC, n, err = amino.DecodeBool(data) 185 if err != nil { 186 return err 187 } 188 dataLen = uint64(n) 189 default: 190 return fmt.Errorf("unexpect feild num %d", pos) 191 } 192 } 193 if !timestampUpdated { 194 vote.Timestamp = amino.ZeroTime 195 } 196 return nil 197 } 198 199 // CommitSig converts the Vote to a CommitSig. 200 func (vote *Vote) CommitSig() CommitSig { 201 if vote == nil { 202 return NewCommitSigAbsent() 203 } 204 205 var blockIDFlag BlockIDFlag 206 switch { 207 case vote.BlockID.IsComplete(): 208 blockIDFlag = BlockIDFlagCommit 209 case vote.BlockID.IsZero(): 210 blockIDFlag = BlockIDFlagNil 211 default: 212 panic(fmt.Sprintf("Invalid vote %v - expected BlockID to be either empty or complete", vote)) 213 } 214 215 return CommitSig{ 216 BlockIDFlag: blockIDFlag, 217 ValidatorAddress: vote.ValidatorAddress, 218 Timestamp: vote.Timestamp, 219 Signature: vote.Signature, 220 } 221 } 222 223 func (vote *Vote) SignBytes(chainID string) []byte { 224 if HigherThanVenus1(vote.Height) { 225 return vote.ibcSignBytes(chainID) 226 } 227 return vote.originSignBytes(chainID) 228 } 229 230 func (vote *Vote) ibcSignBytes(chainID string) []byte { 231 return VoteSignBytes(chainID, vote) 232 } 233 func (vote *Vote) originSignBytes(chainId string) []byte { 234 bz, err := cdc.MarshalBinaryLengthPrefixed(CanonicalizeVote(chainId, vote)) 235 if err != nil { 236 panic(err) 237 } 238 return bz 239 } 240 241 func (vote *Vote) Copy() *Vote { 242 voteCopy := *vote 243 return &voteCopy 244 } 245 246 func (vote *Vote) String() string { 247 if vote == nil { 248 return nilVoteStr 249 } 250 251 var typeString string 252 switch vote.Type { 253 case PrevoteType: 254 typeString = "Prevote" 255 case PrecommitType: 256 typeString = "Precommit" 257 default: 258 panic("Unknown vote type") 259 } 260 261 return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %X @ %s}", 262 vote.ValidatorIndex, 263 tmbytes.Fingerprint(vote.ValidatorAddress), 264 vote.Height, 265 vote.Round, 266 vote.Type, 267 typeString, 268 tmbytes.Fingerprint(vote.BlockID.Hash), 269 tmbytes.Fingerprint(vote.Signature), 270 CanonicalTime(vote.Timestamp), 271 ) 272 } 273 274 func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error { 275 if !bytes.Equal(pubKey.Address(), vote.ValidatorAddress) { 276 return ErrVoteInvalidValidatorAddress 277 } 278 279 if !pubKey.VerifyBytes(vote.SignBytes(chainID), vote.Signature) { 280 return ErrVoteInvalidSignature 281 } 282 return nil 283 } 284 285 // ValidateBasic performs basic validation. 286 func (vote *Vote) ValidateBasic() error { 287 if !IsVoteTypeValid(vote.Type) { 288 return errors.New("invalid Type") 289 } 290 if vote.Height < 0 { 291 return errors.New("negative Height") 292 } 293 if vote.Round < 0 { 294 return errors.New("negative Round") 295 } 296 297 // NOTE: Timestamp validation is subtle and handled elsewhere. 298 299 if err := vote.BlockID.ValidateBasic(); err != nil { 300 return fmt.Errorf("wrong BlockID: %v", err) 301 } 302 // BlockID.ValidateBasic would not err if we for instance have an empty hash but a 303 // non-empty PartsSetHeader: 304 if !vote.BlockID.IsZero() && !vote.BlockID.IsComplete() { 305 return fmt.Errorf("blockID must be either empty or complete, got: %v", vote.BlockID) 306 } 307 if len(vote.ValidatorAddress) != crypto.AddressSize { 308 return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes", 309 crypto.AddressSize, 310 len(vote.ValidatorAddress), 311 ) 312 } 313 if vote.ValidatorIndex < 0 { 314 return errors.New("negative ValidatorIndex") 315 } 316 if len(vote.Signature) == 0 { 317 return errors.New("signature is missing") 318 } 319 if len(vote.Signature) > MaxSignatureSize { 320 return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) 321 } 322 return nil 323 } 324 325 // ToProto converts the handwritten type to proto generated type 326 // return type, nil if everything converts safely, otherwise nil, error 327 func (vote *Vote) ToProto() *tmproto.Vote { 328 if vote == nil { 329 return nil 330 } 331 332 return &tmproto.Vote{ 333 Type: tmproto.SignedMsgType(vote.Type), 334 Height: vote.Height, 335 Round: int64(vote.Round), 336 BlockID: vote.BlockID.ToProto(), 337 Timestamp: vote.Timestamp, 338 ValidatorAddress: vote.ValidatorAddress, 339 ValidatorIndex: int64(vote.ValidatorIndex), 340 Signature: vote.Signature, 341 } 342 } 343 344 // FromProto converts a proto generetad type to a handwritten type 345 // return type, nil if everything converts safely, otherwise nil, error 346 func VoteFromProto(pv *tmproto.Vote) (*Vote, error) { 347 if pv == nil { 348 return nil, errors.New("nil vote") 349 } 350 351 blockID, err := BlockIDFromProto(&pv.BlockID) 352 if err != nil { 353 return nil, err 354 } 355 356 vote := new(Vote) 357 vote.Type = SignedMsgType(pv.Type) 358 vote.Height = pv.Height 359 vote.Round = int(pv.Round) 360 vote.BlockID = *blockID 361 vote.Timestamp = pv.Timestamp 362 vote.ValidatorAddress = pv.ValidatorAddress 363 vote.ValidatorIndex = int(pv.ValidatorIndex) 364 vote.Signature = pv.Signature 365 366 return vote, vote.ValidateBasic() 367 }