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

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