github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/consensus/ipbft/types/vote.go (about)

     1  package types
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/intfoundation/intchain/rlp"
     9  	. "github.com/intfoundation/go-common"
    10  	"github.com/intfoundation/go-crypto"
    11  	"github.com/intfoundation/go-wire"
    12  )
    13  
    14  var (
    15  	ErrVoteUnexpectedStep          = errors.New("Unexpected step")
    16  	ErrVoteInvalidValidatorIndex   = errors.New("Invalid round vote validator index")
    17  	ErrVoteInvalidValidatorAddress = errors.New("Invalid round vote validator address")
    18  	ErrVoteInvalidSignature        = errors.New("Invalid round vote signature")
    19  	ErrVoteInvalidBlockHash        = errors.New("Invalid block hash")
    20  )
    21  
    22  type ErrVoteConflictingVotes struct {
    23  	VoteA *Vote
    24  	VoteB *Vote
    25  }
    26  
    27  func (err *ErrVoteConflictingVotes) Error() string {
    28  	return "Conflicting votes"
    29  }
    30  
    31  // Types of votes
    32  // TODO Make a new type "VoteType"
    33  const (
    34  	VoteTypePrevote   = byte(0x01)
    35  	VoteTypePrecommit = byte(0x02)
    36  )
    37  
    38  func IsVoteTypeValid(type_ byte) bool {
    39  	switch type_ {
    40  	case VoteTypePrevote:
    41  		return true
    42  	case VoteTypePrecommit:
    43  		return true
    44  	default:
    45  		return false
    46  	}
    47  }
    48  
    49  // Represents a prevote, precommit, or commit vote from validators for consensus.
    50  type Vote struct {
    51  	ValidatorAddress []byte           `json:"validator_address"`
    52  	ValidatorIndex   uint64           `json:"validator_index"`
    53  	Height           uint64           `json:"height"`
    54  	Round            uint64           `json:"round"`
    55  	Type             byte             `json:"type"`
    56  	BlockID          BlockID          `json:"block_id"` // zero if vote is nil.
    57  	Signature        crypto.Signature `json:"signature"`
    58  	SignBytes        []byte           `json:"sign_bytes"`
    59  }
    60  
    61  func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) {
    62  	wire.WriteJSON(CanonicalJSONOnceVote{
    63  		chainID,
    64  		CanonicalVote(vote),
    65  	}, w, n, err)
    66  }
    67  
    68  // EncodeRLP serializes ist into the Ethereum RLP format.
    69  func (vote *Vote) EncodeRLP(w io.Writer) error {
    70  	return rlp.Encode(w, []interface{}{
    71  		vote.ValidatorAddress,
    72  		vote.ValidatorIndex,
    73  		vote.Height,
    74  		vote.Round,
    75  		vote.Type,
    76  		vote.BlockID,
    77  		vote.Signature.Bytes(),
    78  	})
    79  }
    80  
    81  // DecodeRLP implements rlp.Decoder, and load the istanbul fields from a RLP stream.
    82  func (vote *Vote) DecodeRLP(s *rlp.Stream) error {
    83  	var vt struct {
    84  		ValidatorAddress []byte
    85  		ValidatorIndex   uint64
    86  		Height           uint64
    87  		Round            uint64
    88  		Type             byte
    89  		BlockID          BlockID
    90  		Signature        []byte
    91  	}
    92  
    93  	if err := s.Decode(&vt); err != nil {
    94  		return err
    95  	}
    96  
    97  	vote.ValidatorAddress = vt.ValidatorAddress
    98  	vote.ValidatorIndex = vt.ValidatorIndex
    99  	vote.Height = vt.Height
   100  	vote.Round = vt.Round
   101  	vote.Type = vt.Type
   102  	vote.BlockID = vt.BlockID
   103  
   104  	sig, err := crypto.SignatureFromBytes(vt.Signature)
   105  	if err != nil {
   106  		return err
   107  	}
   108  	vote.Signature = sig
   109  
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	return nil
   115  }
   116  
   117  func (vote *Vote) Copy() *Vote {
   118  	voteCopy := *vote
   119  	return &voteCopy
   120  }
   121  
   122  func (vote *Vote) String() string {
   123  	if vote == nil {
   124  		return "nil-Vote"
   125  	}
   126  	var typeString string
   127  	switch vote.Type {
   128  	case VoteTypePrevote:
   129  		typeString = "Prevote"
   130  	case VoteTypePrecommit:
   131  		typeString = "Precommit"
   132  	default:
   133  		PanicSanity("Unknown vote type")
   134  	}
   135  
   136  	return fmt.Sprintf("Vote{%v:%X %v/%02d/%v(%v) %X %v}",
   137  		vote.ValidatorIndex, Fingerprint(vote.ValidatorAddress),
   138  		vote.Height, vote.Round, vote.Type, typeString,
   139  		Fingerprint(vote.BlockID.Hash), vote.Signature)
   140  }