You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.0 KiB

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