github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/consensus/types/round_state.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/tendermint/tendermint/libs/bytes"
     9  	"github.com/tendermint/tendermint/types"
    10  )
    11  
    12  //-----------------------------------------------------------------------------
    13  // RoundStepType enum type
    14  
    15  // RoundStepType enumerates the state of the consensus state machine
    16  type RoundStepType uint8 // These must be numeric, ordered.
    17  
    18  // RoundStepType
    19  const (
    20  	RoundStepNewHeight     = RoundStepType(0x01) // Wait til CommitTime + timeoutCommit
    21  	RoundStepNewRound      = RoundStepType(0x02) // Setup new round and go to RoundStepPropose
    22  	RoundStepPropose       = RoundStepType(0x03) // Did propose, gossip proposal
    23  	RoundStepPrevote       = RoundStepType(0x04) // Did prevote, gossip prevotes
    24  	RoundStepPrevoteWait   = RoundStepType(0x05) // Did receive any +2/3 prevotes, start timeout
    25  	RoundStepPrecommit     = RoundStepType(0x06) // Did precommit, gossip precommits
    26  	RoundStepPrecommitWait = RoundStepType(0x07) // Did receive any +2/3 precommits, start timeout
    27  	RoundStepCommit        = RoundStepType(0x08) // Entered commit state machine
    28  	// NOTE: RoundStepNewHeight acts as RoundStepCommitWait.
    29  
    30  	// NOTE: Update IsValid method if you change this!
    31  )
    32  
    33  // IsValid returns true if the step is valid, false if unknown/undefined.
    34  func (rs RoundStepType) IsValid() bool {
    35  	return uint8(rs) >= 0x01 && uint8(rs) <= 0x08
    36  }
    37  
    38  // String returns a string
    39  func (rs RoundStepType) String() string {
    40  	switch rs {
    41  	case RoundStepNewHeight:
    42  		return "RoundStepNewHeight"
    43  	case RoundStepNewRound:
    44  		return "RoundStepNewRound"
    45  	case RoundStepPropose:
    46  		return "RoundStepPropose"
    47  	case RoundStepPrevote:
    48  		return "RoundStepPrevote"
    49  	case RoundStepPrevoteWait:
    50  		return "RoundStepPrevoteWait"
    51  	case RoundStepPrecommit:
    52  		return "RoundStepPrecommit"
    53  	case RoundStepPrecommitWait:
    54  		return "RoundStepPrecommitWait"
    55  	case RoundStepCommit:
    56  		return "RoundStepCommit"
    57  	default:
    58  		return "RoundStepUnknown" // Cannot panic.
    59  	}
    60  }
    61  
    62  //-----------------------------------------------------------------------------
    63  
    64  // RoundState defines the internal consensus state.
    65  // NOTE: Not thread safe. Should only be manipulated by functions downstream
    66  // of the cs.receiveRoutine
    67  type RoundState struct {
    68  	Height    int64         `json:"height"` // Height we are working on
    69  	Round     int           `json:"round"`
    70  	Step      RoundStepType `json:"step"`
    71  	StartTime time.Time     `json:"start_time"`
    72  
    73  	// Subjective time when +2/3 precommits for Block at Round were found
    74  	CommitTime         time.Time           `json:"commit_time"`
    75  	Validators         *types.ValidatorSet `json:"validators"`
    76  	Proposal           *types.Proposal     `json:"proposal"`
    77  	ProposalBlock      *types.Block        `json:"proposal_block"`
    78  	ProposalBlockParts *types.PartSet      `json:"proposal_block_parts"`
    79  	LockedRound        int                 `json:"locked_round"`
    80  	LockedBlock        *types.Block        `json:"locked_block"`
    81  	LockedBlockParts   *types.PartSet      `json:"locked_block_parts"`
    82  
    83  	// Last known round with POL for non-nil valid block.
    84  	ValidRound int          `json:"valid_round"`
    85  	ValidBlock *types.Block `json:"valid_block"` // Last known block of POL mentioned above.
    86  
    87  	// Last known block parts of POL metnioned above.
    88  	ValidBlockParts           *types.PartSet      `json:"valid_block_parts"`
    89  	Votes                     *HeightVoteSet      `json:"votes"`
    90  	CommitRound               int                 `json:"commit_round"` //
    91  	LastCommit                *types.VoteSet      `json:"last_commit"`  // Last precommits at Height-1
    92  	LastValidators            *types.ValidatorSet `json:"last_validators"`
    93  	TriggeredTimeoutPrecommit bool                `json:"triggered_timeout_precommit"`
    94  }
    95  
    96  // Compressed version of the RoundState for use in RPC
    97  type RoundStateSimple struct {
    98  	HeightRoundStep   string          `json:"height/round/step"`
    99  	StartTime         time.Time       `json:"start_time"`
   100  	ProposalBlockHash bytes.HexBytes  `json:"proposal_block_hash"`
   101  	LockedBlockHash   bytes.HexBytes  `json:"locked_block_hash"`
   102  	ValidBlockHash    bytes.HexBytes  `json:"valid_block_hash"`
   103  	Votes             json.RawMessage `json:"height_vote_set"`
   104  }
   105  
   106  // Compress the RoundState to RoundStateSimple
   107  func (rs *RoundState) RoundStateSimple() RoundStateSimple {
   108  	votesJSON, err := rs.Votes.MarshalJSON()
   109  	if err != nil {
   110  		panic(err)
   111  	}
   112  	return RoundStateSimple{
   113  		HeightRoundStep:   fmt.Sprintf("%d/%d/%d", rs.Height, rs.Round, rs.Step),
   114  		StartTime:         rs.StartTime,
   115  		ProposalBlockHash: rs.ProposalBlock.Hash(),
   116  		LockedBlockHash:   rs.LockedBlock.Hash(),
   117  		ValidBlockHash:    rs.ValidBlock.Hash(),
   118  		Votes:             votesJSON,
   119  	}
   120  }
   121  
   122  // NewRoundEvent returns the RoundState with proposer information as an event.
   123  func (rs *RoundState) NewRoundEvent() types.EventDataNewRound {
   124  	addr := rs.Validators.GetProposer().Address
   125  	idx, _ := rs.Validators.GetByAddress(addr)
   126  
   127  	return types.EventDataNewRound{
   128  		Height: rs.Height,
   129  		Round:  rs.Round,
   130  		Step:   rs.Step.String(),
   131  		Proposer: types.ValidatorInfo{
   132  			Address: addr,
   133  			Index:   idx,
   134  		},
   135  	}
   136  }
   137  
   138  // CompleteProposalEvent returns information about a proposed block as an event.
   139  func (rs *RoundState) CompleteProposalEvent() types.EventDataCompleteProposal {
   140  	// We must construct BlockID from ProposalBlock and ProposalBlockParts
   141  	// cs.Proposal is not guaranteed to be set when this function is called
   142  	blockID := types.BlockID{
   143  		Hash:        rs.ProposalBlock.Hash(),
   144  		PartsHeader: rs.ProposalBlockParts.Header(),
   145  	}
   146  
   147  	return types.EventDataCompleteProposal{
   148  		Height:  rs.Height,
   149  		Round:   rs.Round,
   150  		Step:    rs.Step.String(),
   151  		BlockID: blockID,
   152  	}
   153  }
   154  
   155  // RoundStateEvent returns the H/R/S of the RoundState as an event.
   156  func (rs *RoundState) RoundStateEvent() types.EventDataRoundState {
   157  	return types.EventDataRoundState{
   158  		Height: rs.Height,
   159  		Round:  rs.Round,
   160  		Step:   rs.Step.String(),
   161  	}
   162  }
   163  
   164  // String returns a string
   165  func (rs *RoundState) String() string {
   166  	return rs.StringIndented("")
   167  }
   168  
   169  // StringIndented returns a string
   170  func (rs *RoundState) StringIndented(indent string) string {
   171  	return fmt.Sprintf(`RoundState{
   172  %s  H:%v R:%v S:%v
   173  %s  StartTime:     %v
   174  %s  CommitTime:    %v
   175  %s  Validators:    %v
   176  %s  Proposal:      %v
   177  %s  ProposalBlock: %v %v
   178  %s  LockedRound:   %v
   179  %s  LockedBlock:   %v %v
   180  %s  ValidRound:   %v
   181  %s  ValidBlock:   %v %v
   182  %s  Votes:         %v
   183  %s  LastCommit:    %v
   184  %s  LastValidators:%v
   185  %s}`,
   186  		indent, rs.Height, rs.Round, rs.Step,
   187  		indent, rs.StartTime,
   188  		indent, rs.CommitTime,
   189  		indent, rs.Validators.StringIndented(indent+"  "),
   190  		indent, rs.Proposal,
   191  		indent, rs.ProposalBlockParts.StringShort(), rs.ProposalBlock.StringShort(),
   192  		indent, rs.LockedRound,
   193  		indent, rs.LockedBlockParts.StringShort(), rs.LockedBlock.StringShort(),
   194  		indent, rs.ValidRound,
   195  		indent, rs.ValidBlockParts.StringShort(), rs.ValidBlock.StringShort(),
   196  		indent, rs.Votes.StringIndented(indent+"  "),
   197  		indent, rs.LastCommit.StringShort(),
   198  		indent, rs.LastValidators.StringIndented(indent+"  "),
   199  		indent)
   200  }
   201  
   202  // StringShort returns a string
   203  func (rs *RoundState) StringShort() string {
   204  	return fmt.Sprintf(`RoundState{H:%v R:%v S:%v ST:%v}`,
   205  		rs.Height, rs.Round, rs.Step, rs.StartTime)
   206  }
   207  
   208  //-----------------------------------------------------------
   209  // These methods are for Protobuf Compatibility
   210  
   211  // Size returns the size of the amino encoding, in bytes.
   212  func (rs *RoundStateSimple) Size() int {
   213  	bs, _ := rs.Marshal()
   214  	return len(bs)
   215  }
   216  
   217  // Marshal returns the amino encoding.
   218  func (rs *RoundStateSimple) Marshal() ([]byte, error) {
   219  	return cdc.MarshalBinaryBare(rs)
   220  }
   221  
   222  // MarshalTo calls Marshal and copies to the given buffer.
   223  func (rs *RoundStateSimple) MarshalTo(data []byte) (int, error) {
   224  	bs, err := rs.Marshal()
   225  	if err != nil {
   226  		return -1, err
   227  	}
   228  	return copy(data, bs), nil
   229  }
   230  
   231  // Unmarshal deserializes from amino encoded form.
   232  func (rs *RoundStateSimple) Unmarshal(bs []byte) error {
   233  	return cdc.UnmarshalBinaryBare(bs, rs)
   234  }