gitlab.com/gpdionisio/tendermint@v0.34.19-dev2/blockchain/msgs.go (about)

     1  package blockchain
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/gogo/protobuf/proto"
     8  
     9  	bcproto "github.com/tendermint/tendermint/proto/tendermint/blockchain"
    10  	"github.com/tendermint/tendermint/types"
    11  )
    12  
    13  const (
    14  	// NOTE: keep up to date with bcproto.BlockResponse
    15  	BlockResponseMessagePrefixSize   = 4
    16  	BlockResponseMessageFieldKeySize = 1
    17  	MaxMsgSize                       = types.MaxBlockSizeBytes +
    18  		BlockResponseMessagePrefixSize +
    19  		BlockResponseMessageFieldKeySize
    20  )
    21  
    22  // EncodeMsg encodes a Protobuf message
    23  func EncodeMsg(pb proto.Message) ([]byte, error) {
    24  	msg := bcproto.Message{}
    25  
    26  	switch pb := pb.(type) {
    27  	case *bcproto.BlockRequest:
    28  		msg.Sum = &bcproto.Message_BlockRequest{BlockRequest: pb}
    29  	case *bcproto.BlockResponse:
    30  		msg.Sum = &bcproto.Message_BlockResponse{BlockResponse: pb}
    31  	case *bcproto.NoBlockResponse:
    32  		msg.Sum = &bcproto.Message_NoBlockResponse{NoBlockResponse: pb}
    33  	case *bcproto.StatusRequest:
    34  		msg.Sum = &bcproto.Message_StatusRequest{StatusRequest: pb}
    35  	case *bcproto.StatusResponse:
    36  		msg.Sum = &bcproto.Message_StatusResponse{StatusResponse: pb}
    37  	default:
    38  		return nil, fmt.Errorf("unknown message type %T", pb)
    39  	}
    40  
    41  	bz, err := proto.Marshal(&msg)
    42  	if err != nil {
    43  		return nil, fmt.Errorf("unable to marshal %T: %w", pb, err)
    44  	}
    45  
    46  	return bz, nil
    47  }
    48  
    49  // DecodeMsg decodes a Protobuf message.
    50  func DecodeMsg(bz []byte) (proto.Message, error) {
    51  	pb := &bcproto.Message{}
    52  
    53  	err := proto.Unmarshal(bz, pb)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	switch msg := pb.Sum.(type) {
    59  	case *bcproto.Message_BlockRequest:
    60  		return msg.BlockRequest, nil
    61  	case *bcproto.Message_BlockResponse:
    62  		return msg.BlockResponse, nil
    63  	case *bcproto.Message_NoBlockResponse:
    64  		return msg.NoBlockResponse, nil
    65  	case *bcproto.Message_StatusRequest:
    66  		return msg.StatusRequest, nil
    67  	case *bcproto.Message_StatusResponse:
    68  		return msg.StatusResponse, nil
    69  	default:
    70  		return nil, fmt.Errorf("unknown message type %T", msg)
    71  	}
    72  }
    73  
    74  // ValidateMsg validates a message.
    75  func ValidateMsg(pb proto.Message) error {
    76  	if pb == nil {
    77  		return errors.New("message cannot be nil")
    78  	}
    79  
    80  	switch msg := pb.(type) {
    81  	case *bcproto.BlockRequest:
    82  		if msg.Height < 0 {
    83  			return errors.New("negative Height")
    84  		}
    85  	case *bcproto.BlockResponse:
    86  		_, err := types.BlockFromProto(msg.Block)
    87  		if err != nil {
    88  			return err
    89  		}
    90  	case *bcproto.NoBlockResponse:
    91  		if msg.Height < 0 {
    92  			return errors.New("negative Height")
    93  		}
    94  	case *bcproto.StatusResponse:
    95  		if msg.Base < 0 {
    96  			return errors.New("negative Base")
    97  		}
    98  		if msg.Height < 0 {
    99  			return errors.New("negative Height")
   100  		}
   101  		if msg.Base > msg.Height {
   102  			return fmt.Errorf("base %v cannot be greater than height %v", msg.Base, msg.Height)
   103  		}
   104  	case *bcproto.StatusRequest:
   105  		return nil
   106  	default:
   107  		return fmt.Errorf("unknown message type %T", msg)
   108  	}
   109  	return nil
   110  }