github.com/516108736/tendermint@v0.36.0/consensus/msgs.go (about)

     1  package consensus
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/gogo/protobuf/proto"
     8  
     9  	cstypes "github.com/tendermint/tendermint/consensus/types"
    10  	"github.com/tendermint/tendermint/libs/bits"
    11  	tmmath "github.com/tendermint/tendermint/libs/math"
    12  	"github.com/tendermint/tendermint/p2p"
    13  	tmcons "github.com/tendermint/tendermint/proto/tendermint/consensus"
    14  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    15  	"github.com/tendermint/tendermint/types"
    16  )
    17  
    18  // MsgToProto takes a consensus message type and returns the proto defined consensus message
    19  func MsgToProto(msg Message) (*tmcons.Message, error) {
    20  	if msg == nil {
    21  		return nil, errors.New("consensus: message is nil")
    22  	}
    23  	var pb tmcons.Message
    24  
    25  	switch msg := msg.(type) {
    26  	case *NewRoundStepMessage:
    27  		pb = tmcons.Message{
    28  			Sum: &tmcons.Message_NewRoundStep{
    29  				NewRoundStep: &tmcons.NewRoundStep{
    30  					Height:                msg.Height,
    31  					Round:                 msg.Round,
    32  					Step:                  uint32(msg.Step),
    33  					SecondsSinceStartTime: msg.SecondsSinceStartTime,
    34  					LastCommitRound:       msg.LastCommitRound,
    35  				},
    36  			},
    37  		}
    38  	case *NewValidBlockMessage:
    39  		pbPartSetHeader := msg.BlockPartSetHeader.ToProto()
    40  		pbBits := msg.BlockParts.ToProto()
    41  		pb = tmcons.Message{
    42  			Sum: &tmcons.Message_NewValidBlock{
    43  				NewValidBlock: &tmcons.NewValidBlock{
    44  					Height:             msg.Height,
    45  					Round:              msg.Round,
    46  					BlockPartSetHeader: pbPartSetHeader,
    47  					BlockParts:         pbBits,
    48  					IsCommit:           msg.IsCommit,
    49  				},
    50  			},
    51  		}
    52  	case *ProposalMessage:
    53  		pbP := msg.Proposal.ToProto()
    54  		pb = tmcons.Message{
    55  			Sum: &tmcons.Message_Proposal{
    56  				Proposal: &tmcons.Proposal{
    57  					Proposal: *pbP,
    58  				},
    59  			},
    60  		}
    61  	case *ProposalPOLMessage:
    62  		pbBits := msg.ProposalPOL.ToProto()
    63  		pb = tmcons.Message{
    64  			Sum: &tmcons.Message_ProposalPol{
    65  				ProposalPol: &tmcons.ProposalPOL{
    66  					Height:           msg.Height,
    67  					ProposalPolRound: msg.ProposalPOLRound,
    68  					ProposalPol:      *pbBits,
    69  				},
    70  			},
    71  		}
    72  	case *BlockPartMessage:
    73  		parts, err := msg.Part.ToProto()
    74  		if err != nil {
    75  			return nil, fmt.Errorf("msg to proto error: %w", err)
    76  		}
    77  		pb = tmcons.Message{
    78  			Sum: &tmcons.Message_BlockPart{
    79  				BlockPart: &tmcons.BlockPart{
    80  					Height: msg.Height,
    81  					Round:  msg.Round,
    82  					Part:   *parts,
    83  				},
    84  			},
    85  		}
    86  	case *VoteMessage:
    87  		vote := msg.Vote.ToProto()
    88  		pb = tmcons.Message{
    89  			Sum: &tmcons.Message_Vote{
    90  				Vote: &tmcons.Vote{
    91  					Vote: vote,
    92  				},
    93  			},
    94  		}
    95  	case *HasVoteMessage:
    96  		pb = tmcons.Message{
    97  			Sum: &tmcons.Message_HasVote{
    98  				HasVote: &tmcons.HasVote{
    99  					Height: msg.Height,
   100  					Round:  msg.Round,
   101  					Type:   msg.Type,
   102  					Index:  msg.Index,
   103  				},
   104  			},
   105  		}
   106  	case *VoteSetMaj23Message:
   107  		bi := msg.BlockID.ToProto()
   108  		pb = tmcons.Message{
   109  			Sum: &tmcons.Message_VoteSetMaj23{
   110  				VoteSetMaj23: &tmcons.VoteSetMaj23{
   111  					Height:  msg.Height,
   112  					Round:   msg.Round,
   113  					Type:    msg.Type,
   114  					BlockID: bi,
   115  				},
   116  			},
   117  		}
   118  	case *VoteSetBitsMessage:
   119  		bi := msg.BlockID.ToProto()
   120  		bits := msg.Votes.ToProto()
   121  
   122  		vsb := &tmcons.Message_VoteSetBits{
   123  			VoteSetBits: &tmcons.VoteSetBits{
   124  				Height:  msg.Height,
   125  				Round:   msg.Round,
   126  				Type:    msg.Type,
   127  				BlockID: bi,
   128  			},
   129  		}
   130  
   131  		if bits != nil {
   132  			vsb.VoteSetBits.Votes = *bits
   133  		}
   134  
   135  		pb = tmcons.Message{
   136  			Sum: vsb,
   137  		}
   138  
   139  	default:
   140  		return nil, fmt.Errorf("consensus: message not recognized: %T", msg)
   141  	}
   142  
   143  	return &pb, nil
   144  }
   145  
   146  // MsgFromProto takes a consensus proto message and returns the native go type
   147  func MsgFromProto(msg *tmcons.Message) (Message, error) {
   148  	if msg == nil {
   149  		return nil, errors.New("consensus: nil message")
   150  	}
   151  	var pb Message
   152  
   153  	switch msg := msg.Sum.(type) {
   154  	case *tmcons.Message_NewRoundStep:
   155  		rs, err := tmmath.SafeConvertUint8(int64(msg.NewRoundStep.Step))
   156  		// deny message based on possible overflow
   157  		if err != nil {
   158  			return nil, fmt.Errorf("denying message due to possible overflow: %w", err)
   159  		}
   160  		pb = &NewRoundStepMessage{
   161  			Height:                msg.NewRoundStep.Height,
   162  			Round:                 msg.NewRoundStep.Round,
   163  			Step:                  cstypes.RoundStepType(rs),
   164  			SecondsSinceStartTime: msg.NewRoundStep.SecondsSinceStartTime,
   165  			LastCommitRound:       msg.NewRoundStep.LastCommitRound,
   166  		}
   167  	case *tmcons.Message_NewValidBlock:
   168  		pbPartSetHeader, err := types.PartSetHeaderFromProto(&msg.NewValidBlock.BlockPartSetHeader)
   169  		if err != nil {
   170  			return nil, fmt.Errorf("parts to proto error: %w", err)
   171  		}
   172  
   173  		pbBits := new(bits.BitArray)
   174  		pbBits.FromProto(msg.NewValidBlock.BlockParts)
   175  
   176  		pb = &NewValidBlockMessage{
   177  			Height:             msg.NewValidBlock.Height,
   178  			Round:              msg.NewValidBlock.Round,
   179  			BlockPartSetHeader: *pbPartSetHeader,
   180  			BlockParts:         pbBits,
   181  			IsCommit:           msg.NewValidBlock.IsCommit,
   182  		}
   183  	case *tmcons.Message_Proposal:
   184  		pbP, err := types.ProposalFromProto(&msg.Proposal.Proposal)
   185  		if err != nil {
   186  			return nil, fmt.Errorf("proposal msg to proto error: %w", err)
   187  		}
   188  
   189  		pb = &ProposalMessage{
   190  			Proposal: pbP,
   191  		}
   192  	case *tmcons.Message_ProposalPol:
   193  		pbBits := new(bits.BitArray)
   194  		pbBits.FromProto(&msg.ProposalPol.ProposalPol)
   195  		pb = &ProposalPOLMessage{
   196  			Height:           msg.ProposalPol.Height,
   197  			ProposalPOLRound: msg.ProposalPol.ProposalPolRound,
   198  			ProposalPOL:      pbBits,
   199  		}
   200  	case *tmcons.Message_BlockPart:
   201  		parts, err := types.PartFromProto(&msg.BlockPart.Part)
   202  		if err != nil {
   203  			return nil, fmt.Errorf("blockpart msg to proto error: %w", err)
   204  		}
   205  		pb = &BlockPartMessage{
   206  			Height: msg.BlockPart.Height,
   207  			Round:  msg.BlockPart.Round,
   208  			Part:   parts,
   209  		}
   210  	case *tmcons.Message_Vote:
   211  		vote, err := types.VoteFromProto(msg.Vote.Vote)
   212  		if err != nil {
   213  			return nil, fmt.Errorf("vote msg to proto error: %w", err)
   214  		}
   215  
   216  		pb = &VoteMessage{
   217  			Vote: vote,
   218  		}
   219  	case *tmcons.Message_HasVote:
   220  		pb = &HasVoteMessage{
   221  			Height: msg.HasVote.Height,
   222  			Round:  msg.HasVote.Round,
   223  			Type:   msg.HasVote.Type,
   224  			Index:  msg.HasVote.Index,
   225  		}
   226  	case *tmcons.Message_VoteSetMaj23:
   227  		bi, err := types.BlockIDFromProto(&msg.VoteSetMaj23.BlockID)
   228  		if err != nil {
   229  			return nil, fmt.Errorf("voteSetMaj23 msg to proto error: %w", err)
   230  		}
   231  		pb = &VoteSetMaj23Message{
   232  			Height:  msg.VoteSetMaj23.Height,
   233  			Round:   msg.VoteSetMaj23.Round,
   234  			Type:    msg.VoteSetMaj23.Type,
   235  			BlockID: *bi,
   236  		}
   237  	case *tmcons.Message_VoteSetBits:
   238  		bi, err := types.BlockIDFromProto(&msg.VoteSetBits.BlockID)
   239  		if err != nil {
   240  			return nil, fmt.Errorf("voteSetBits msg to proto error: %w", err)
   241  		}
   242  		bits := new(bits.BitArray)
   243  		bits.FromProto(&msg.VoteSetBits.Votes)
   244  
   245  		pb = &VoteSetBitsMessage{
   246  			Height:  msg.VoteSetBits.Height,
   247  			Round:   msg.VoteSetBits.Round,
   248  			Type:    msg.VoteSetBits.Type,
   249  			BlockID: *bi,
   250  			Votes:   bits,
   251  		}
   252  	default:
   253  		return nil, fmt.Errorf("consensus: message not recognized: %T", msg)
   254  	}
   255  
   256  	if err := pb.ValidateBasic(); err != nil {
   257  		return nil, err
   258  	}
   259  
   260  	return pb, nil
   261  }
   262  
   263  // MustEncode takes the reactors msg, makes it proto and marshals it
   264  // this mimics `MustMarshalBinaryBare` in that is panics on error
   265  func MustEncode(msg Message) []byte {
   266  	pb, err := MsgToProto(msg)
   267  	if err != nil {
   268  		panic(err)
   269  	}
   270  	enc, err := proto.Marshal(pb)
   271  	if err != nil {
   272  		panic(err)
   273  	}
   274  	return enc
   275  }
   276  
   277  // WALToProto takes a WAL message and return a proto walMessage and error
   278  func WALToProto(msg WALMessage) (*tmcons.WALMessage, error) {
   279  	var pb tmcons.WALMessage
   280  
   281  	switch msg := msg.(type) {
   282  	case types.EventDataRoundState:
   283  		pb = tmcons.WALMessage{
   284  			Sum: &tmcons.WALMessage_EventDataRoundState{
   285  				EventDataRoundState: &tmproto.EventDataRoundState{
   286  					Height: msg.Height,
   287  					Round:  msg.Round,
   288  					Step:   msg.Step,
   289  				},
   290  			},
   291  		}
   292  	case msgInfo:
   293  		consMsg, err := MsgToProto(msg.Msg)
   294  		if err != nil {
   295  			return nil, err
   296  		}
   297  		pb = tmcons.WALMessage{
   298  			Sum: &tmcons.WALMessage_MsgInfo{
   299  				MsgInfo: &tmcons.MsgInfo{
   300  					Msg:    *consMsg,
   301  					PeerID: string(msg.PeerID),
   302  				},
   303  			},
   304  		}
   305  	case timeoutInfo:
   306  		pb = tmcons.WALMessage{
   307  			Sum: &tmcons.WALMessage_TimeoutInfo{
   308  				TimeoutInfo: &tmcons.TimeoutInfo{
   309  					Duration: msg.Duration,
   310  					Height:   msg.Height,
   311  					Round:    msg.Round,
   312  					Step:     uint32(msg.Step),
   313  				},
   314  			},
   315  		}
   316  	case EndHeightMessage:
   317  		pb = tmcons.WALMessage{
   318  			Sum: &tmcons.WALMessage_EndHeight{
   319  				EndHeight: &tmcons.EndHeight{
   320  					Height: msg.Height,
   321  				},
   322  			},
   323  		}
   324  	default:
   325  		return nil, fmt.Errorf("to proto: wal message not recognized: %T", msg)
   326  	}
   327  
   328  	return &pb, nil
   329  }
   330  
   331  // WALFromProto takes a proto wal message and return a consensus walMessage and error
   332  func WALFromProto(msg *tmcons.WALMessage) (WALMessage, error) {
   333  	if msg == nil {
   334  		return nil, errors.New("nil WAL message")
   335  	}
   336  	var pb WALMessage
   337  
   338  	switch msg := msg.Sum.(type) {
   339  	case *tmcons.WALMessage_EventDataRoundState:
   340  		pb = types.EventDataRoundState{
   341  			Height: msg.EventDataRoundState.Height,
   342  			Round:  msg.EventDataRoundState.Round,
   343  			Step:   msg.EventDataRoundState.Step,
   344  		}
   345  	case *tmcons.WALMessage_MsgInfo:
   346  		walMsg, err := MsgFromProto(&msg.MsgInfo.Msg)
   347  		if err != nil {
   348  			return nil, fmt.Errorf("msgInfo from proto error: %w", err)
   349  		}
   350  		pb = msgInfo{
   351  			Msg:    walMsg,
   352  			PeerID: p2p.ID(msg.MsgInfo.PeerID),
   353  		}
   354  
   355  	case *tmcons.WALMessage_TimeoutInfo:
   356  		tis, err := tmmath.SafeConvertUint8(int64(msg.TimeoutInfo.Step))
   357  		// deny message based on possible overflow
   358  		if err != nil {
   359  			return nil, fmt.Errorf("denying message due to possible overflow: %w", err)
   360  		}
   361  		pb = timeoutInfo{
   362  			Duration: msg.TimeoutInfo.Duration,
   363  			Height:   msg.TimeoutInfo.Height,
   364  			Round:    msg.TimeoutInfo.Round,
   365  			Step:     cstypes.RoundStepType(tis),
   366  		}
   367  		return pb, nil
   368  	case *tmcons.WALMessage_EndHeight:
   369  		pb := EndHeightMessage{
   370  			Height: msg.EndHeight.Height,
   371  		}
   372  		return pb, nil
   373  	default:
   374  		return nil, fmt.Errorf("from proto: wal message not recognized: %T", msg)
   375  	}
   376  	return pb, nil
   377  }