github.com/vipernet-xyz/tm@v0.34.24/consensus/types/round_state.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/vipernet-xyz/tm/libs/bytes"
     9  	"github.com/vipernet-xyz/tm/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     int32         `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        int32               `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 int32        `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 mentioned above.
    88  	ValidBlockParts           *types.PartSet      `json:"valid_block_parts"`
    89  	Votes                     *HeightVoteSet      `json:"votes"`
    90  	CommitRound               int32               `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  	Proposer          types.ValidatorInfo `json:"proposer"`
   105  }
   106  
   107  // Compress the RoundState to RoundStateSimple
   108  func (rs *RoundState) RoundStateSimple() RoundStateSimple {
   109  	votesJSON, err := rs.Votes.MarshalJSON()
   110  	if err != nil {
   111  		panic(err)
   112  	}
   113  
   114  	addr := rs.Validators.GetProposer().Address
   115  	idx, _ := rs.Validators.GetByAddress(addr)
   116  
   117  	return RoundStateSimple{
   118  		HeightRoundStep:   fmt.Sprintf("%d/%d/%d", rs.Height, rs.Round, rs.Step),
   119  		StartTime:         rs.StartTime,
   120  		ProposalBlockHash: rs.ProposalBlock.Hash(),
   121  		LockedBlockHash:   rs.LockedBlock.Hash(),
   122  		ValidBlockHash:    rs.ValidBlock.Hash(),
   123  		Votes:             votesJSON,
   124  		Proposer: types.ValidatorInfo{
   125  			Address: addr,
   126  			Index:   idx,
   127  		},
   128  	}
   129  }
   130  
   131  // NewRoundEvent returns the RoundState with proposer information as an event.
   132  func (rs *RoundState) NewRoundEvent() types.EventDataNewRound {
   133  	addr := rs.Validators.GetProposer().Address
   134  	idx, _ := rs.Validators.GetByAddress(addr)
   135  
   136  	return types.EventDataNewRound{
   137  		Height: rs.Height,
   138  		Round:  rs.Round,
   139  		Step:   rs.Step.String(),
   140  		Proposer: types.ValidatorInfo{
   141  			Address: addr,
   142  			Index:   idx,
   143  		},
   144  	}
   145  }
   146  
   147  // CompleteProposalEvent returns information about a proposed block as an event.
   148  func (rs *RoundState) CompleteProposalEvent() types.EventDataCompleteProposal {
   149  	// We must construct BlockID from ProposalBlock and ProposalBlockParts
   150  	// cs.Proposal is not guaranteed to be set when this function is called
   151  	blockID := types.BlockID{
   152  		Hash:          rs.ProposalBlock.Hash(),
   153  		PartSetHeader: rs.ProposalBlockParts.Header(),
   154  	}
   155  
   156  	return types.EventDataCompleteProposal{
   157  		Height:  rs.Height,
   158  		Round:   rs.Round,
   159  		Step:    rs.Step.String(),
   160  		BlockID: blockID,
   161  	}
   162  }
   163  
   164  // RoundStateEvent returns the H/R/S of the RoundState as an event.
   165  func (rs *RoundState) RoundStateEvent() types.EventDataRoundState {
   166  	return types.EventDataRoundState{
   167  		Height: rs.Height,
   168  		Round:  rs.Round,
   169  		Step:   rs.Step.String(),
   170  	}
   171  }
   172  
   173  // String returns a string
   174  func (rs *RoundState) String() string {
   175  	return rs.StringIndented("")
   176  }
   177  
   178  // StringIndented returns a string
   179  func (rs *RoundState) StringIndented(indent string) string {
   180  	return fmt.Sprintf(`RoundState{
   181  %s  H:%v R:%v S:%v
   182  %s  StartTime:     %v
   183  %s  CommitTime:    %v
   184  %s  Validators:    %v
   185  %s  Proposal:      %v
   186  %s  ProposalBlock: %v %v
   187  %s  LockedRound:   %v
   188  %s  LockedBlock:   %v %v
   189  %s  ValidRound:   %v
   190  %s  ValidBlock:   %v %v
   191  %s  Votes:         %v
   192  %s  LastCommit:    %v
   193  %s  LastValidators:%v
   194  %s}`,
   195  		indent, rs.Height, rs.Round, rs.Step,
   196  		indent, rs.StartTime,
   197  		indent, rs.CommitTime,
   198  		indent, rs.Validators.StringIndented(indent+"  "),
   199  		indent, rs.Proposal,
   200  		indent, rs.ProposalBlockParts.StringShort(), rs.ProposalBlock.StringShort(),
   201  		indent, rs.LockedRound,
   202  		indent, rs.LockedBlockParts.StringShort(), rs.LockedBlock.StringShort(),
   203  		indent, rs.ValidRound,
   204  		indent, rs.ValidBlockParts.StringShort(), rs.ValidBlock.StringShort(),
   205  		indent, rs.Votes.StringIndented(indent+"  "),
   206  		indent, rs.LastCommit.StringShort(),
   207  		indent, rs.LastValidators.StringIndented(indent+"  "),
   208  		indent)
   209  }
   210  
   211  // StringShort returns a string
   212  func (rs *RoundState) StringShort() string {
   213  	return fmt.Sprintf(`RoundState{H:%v R:%v S:%v ST:%v}`,
   214  		rs.Height, rs.Round, rs.Step, rs.StartTime)
   215  }