github.com/Finschia/ostracon@v1.1.5/blockchain/msgs_test.go (about)

     1  package blockchain
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"math"
     7  	"testing"
     8  
     9  	"github.com/Finschia/ostracon/crypto"
    10  	"github.com/gogo/protobuf/proto"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	voivrf "github.com/oasisprotocol/curve25519-voi/primitives/ed25519/extra/ecvrf"
    15  	bcproto "github.com/tendermint/tendermint/proto/tendermint/blockchain"
    16  
    17  	ocbcproto "github.com/Finschia/ostracon/proto/ostracon/blockchain"
    18  	sm "github.com/Finschia/ostracon/state"
    19  	"github.com/Finschia/ostracon/types"
    20  )
    21  
    22  func TestBcBlockRequestMessageValidateBasic(t *testing.T) {
    23  	testCases := []struct {
    24  		testName      string
    25  		requestHeight int64
    26  		expectErr     bool
    27  	}{
    28  		{"Valid Request Message", 0, false},
    29  		{"Valid Request Message", 1, false},
    30  		{"Invalid Request Message", -1, true},
    31  	}
    32  
    33  	for _, tc := range testCases {
    34  		tc := tc
    35  		t.Run(tc.testName, func(t *testing.T) {
    36  			request := bcproto.BlockRequest{Height: tc.requestHeight}
    37  			assert.Equal(t, tc.expectErr, ValidateMsg(&request) != nil, "Validate Basic had an unexpected result")
    38  		})
    39  	}
    40  }
    41  
    42  func TestBcNoBlockResponseMessageValidateBasic(t *testing.T) {
    43  	testCases := []struct {
    44  		testName          string
    45  		nonResponseHeight int64
    46  		expectErr         bool
    47  	}{
    48  		{"Valid Non-Response Message", 0, false},
    49  		{"Valid Non-Response Message", 1, false},
    50  		{"Invalid Non-Response Message", -1, true},
    51  	}
    52  
    53  	for _, tc := range testCases {
    54  		tc := tc
    55  		t.Run(tc.testName, func(t *testing.T) {
    56  			nonResponse := bcproto.NoBlockResponse{Height: tc.nonResponseHeight}
    57  			assert.Equal(t, tc.expectErr, ValidateMsg(&nonResponse) != nil, "Validate Basic had an unexpected result")
    58  		})
    59  	}
    60  }
    61  
    62  func TestBcStatusRequestMessageValidateBasic(t *testing.T) {
    63  	request := bcproto.StatusRequest{}
    64  	assert.NoError(t, ValidateMsg(&request))
    65  }
    66  
    67  func TestBcStatusResponseMessageValidateBasic(t *testing.T) {
    68  	testCases := []struct {
    69  		testName       string
    70  		responseHeight int64
    71  		expectErr      bool
    72  	}{
    73  		{"Valid Response Message", 0, false},
    74  		{"Valid Response Message", 1, false},
    75  		{"Invalid Response Message", -1, true},
    76  	}
    77  
    78  	for _, tc := range testCases {
    79  		tc := tc
    80  		t.Run(tc.testName, func(t *testing.T) {
    81  			response := bcproto.StatusResponse{Height: tc.responseHeight}
    82  			assert.Equal(t, tc.expectErr, ValidateMsg(&response) != nil, "Validate Basic had an unexpected result")
    83  		})
    84  	}
    85  }
    86  
    87  // nolint:lll // ignore line length in tests
    88  func TestBlockchainMessageVectors(t *testing.T) {
    89  	block := types.MakeBlock(int64(3), []types.Tx{types.Tx("Hello World")}, nil, nil, sm.InitStateVersion.Consensus)
    90  	block.Version.Block = 11 // overwrite updated protocol version
    91  	block.Version.App = 11   // overwrite updated protocol version
    92  
    93  	bpb, err := block.ToProto()
    94  	require.NoError(t, err)
    95  
    96  	testCases := []struct {
    97  		testName string
    98  		bmsg     proto.Message
    99  		expBytes string
   100  	}{
   101  		{"BlockRequestMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_BlockRequest{
   102  			BlockRequest: &bcproto.BlockRequest{Height: 1}}}, "0a020801"},
   103  		{"BlockRequestMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_BlockRequest{
   104  			BlockRequest: &bcproto.BlockRequest{Height: math.MaxInt64}}},
   105  			"0a0a08ffffffffffffffff7f"},
   106  		{"BlockResponseMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_BlockResponse{
   107  			BlockResponse: &ocbcproto.BlockResponse{Block: bpb}}}, "1a750a730a5d0a04080b100b1803220b088092b8c398feffffff012a0212003a20c4da88e876062aa1543400d50d0eaa0dac88096057949cfb7bca7f3a48c04bf96a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855120d0a0b48656c6c6f20576f726c641a00c23e00"},
   108  		{"NoBlockResponseMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_NoBlockResponse{
   109  			NoBlockResponse: &bcproto.NoBlockResponse{Height: 1}}}, "12020801"},
   110  		{"NoBlockResponseMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_NoBlockResponse{
   111  			NoBlockResponse: &bcproto.NoBlockResponse{Height: math.MaxInt64}}},
   112  			"120a08ffffffffffffffff7f"},
   113  		{"StatusRequestMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_StatusRequest{
   114  			StatusRequest: &bcproto.StatusRequest{}}},
   115  			"2200"},
   116  		{"StatusResponseMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_StatusResponse{
   117  			StatusResponse: &bcproto.StatusResponse{Height: 1, Base: 2}}},
   118  			"2a0408011002"},
   119  		{"StatusResponseMessage", &ocbcproto.Message{Sum: &ocbcproto.Message_StatusResponse{
   120  			StatusResponse: &bcproto.StatusResponse{Height: math.MaxInt64, Base: math.MaxInt64}}},
   121  			"2a1408ffffffffffffffff7f10ffffffffffffffff7f"},
   122  	}
   123  
   124  	for _, tc := range testCases {
   125  		tc := tc
   126  		t.Run(tc.testName, func(t *testing.T) {
   127  			bz, _ := proto.Marshal(tc.bmsg)
   128  
   129  			require.Equal(t, tc.expBytes, hex.EncodeToString(bz))
   130  		})
   131  	}
   132  }
   133  
   134  func TestEncodeDecodeValidateMsg(t *testing.T) {
   135  	height := int64(3)
   136  	block := types.MakeBlock(
   137  		height,
   138  		[]types.Tx{types.Tx("Hello World")},
   139  		&types.Commit{
   140  			Signatures: []types.CommitSig{
   141  				{
   142  					BlockIDFlag:      types.BlockIDFlagCommit,
   143  					ValidatorAddress: make([]byte, crypto.AddressSize),
   144  					Signature:        make([]byte, crypto.AddressSize),
   145  				},
   146  			},
   147  		},
   148  		nil,
   149  		sm.InitStateVersion.Consensus)
   150  	block.ProposerAddress = make([]byte, crypto.AddressSize)
   151  	round := int32(0)
   152  	proof := make([]byte, voivrf.ProofSize)
   153  	block.Entropy.Populate(round, proof)
   154  	bpb, err := block.ToProto()
   155  	require.NoError(t, err)
   156  
   157  	type args struct {
   158  		pb proto.Message
   159  	}
   160  	tests := []struct {
   161  		name    string
   162  		args    args
   163  		want    []byte
   164  		wantErr assert.ErrorAssertionFunc
   165  	}{
   166  		{
   167  			name:    "bcproto.BlockRequest",
   168  			args:    args{pb: &bcproto.BlockRequest{}},
   169  			want:    []byte{0xa, 0x0},
   170  			wantErr: assert.NoError,
   171  		},
   172  		{
   173  			name:    "ocbcproto.BlockResponse", // Ostracon
   174  			args:    args{pb: &ocbcproto.BlockResponse{Block: bpb}},
   175  			want:    []byte{0x1a, 0xc2, 0x2, 0xa, 0xbf, 0x2, 0xa, 0x93, 0x1, 0xa, 0x2, 0x8, 0xb, 0x18, 0x3, 0x22, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, 0x2a, 0x2, 0x12, 0x0, 0x32, 0x20, 0x1e, 0xba, 0x40, 0x13, 0xa, 0xf2, 0x5e, 0xd1, 0x9, 0x5f, 0x67, 0x86, 0xe5, 0x8d, 0xb9, 0x4d, 0xeb, 0xf4, 0x6a, 0x0, 0x7f, 0xc6, 0x8c, 0x20, 0x32, 0x39, 0x2f, 0xde, 0xdd, 0x32, 0x26, 0x7e, 0x3a, 0x20, 0xc4, 0xda, 0x88, 0xe8, 0x76, 0x6, 0x2a, 0xa1, 0x54, 0x34, 0x0, 0xd5, 0xd, 0xe, 0xaa, 0xd, 0xac, 0x88, 0x9, 0x60, 0x57, 0x94, 0x9c, 0xfb, 0x7b, 0xca, 0x7f, 0x3a, 0x48, 0xc0, 0x4b, 0xf9, 0x6a, 0x20, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, 0x72, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0xd, 0xa, 0xb, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x1a, 0x0, 0x22, 0x41, 0x1a, 0x2, 0x12, 0x0, 0x22, 0x3b, 0x8, 0x2, 0x12, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xb, 0x8, 0x80, 0x92, 0xb8, 0xc3, 0x98, 0xfe, 0xff, 0xff, 0xff, 0x1, 0x22, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc2, 0x3e, 0x52, 0x12, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
   176  			wantErr: assert.NoError,
   177  		},
   178  		{
   179  			name:    "bcproto.NoBlockResponse",
   180  			args:    args{pb: &bcproto.NoBlockResponse{}},
   181  			want:    []byte{0x12, 0x0},
   182  			wantErr: assert.NoError,
   183  		},
   184  		{
   185  			name:    "bcproto.StatusRequest",
   186  			args:    args{pb: &bcproto.StatusRequest{}},
   187  			want:    []byte{0x22, 0x0},
   188  			wantErr: assert.NoError,
   189  		},
   190  		{
   191  			name:    "bcproto.StatusResponse",
   192  			args:    args{pb: &bcproto.StatusResponse{}},
   193  			want:    []byte{0x2a, 0x0},
   194  			wantErr: assert.NoError,
   195  		},
   196  		{
   197  			name:    "default: unknown message type",
   198  			args:    args{pb: nil},
   199  			want:    nil,
   200  			wantErr: assert.Error,
   201  		},
   202  	}
   203  	for _, tt := range tests {
   204  		t.Run(tt.name, func(t *testing.T) {
   205  			{
   206  				// Encode
   207  				got, err := EncodeMsg(tt.args.pb)
   208  				if !tt.wantErr(t, err, fmt.Sprintf("EncodeMsg(%v)", tt.args.pb)) {
   209  					return
   210  				}
   211  				assert.Equalf(t, tt.want, got, "EncodeMsg(%v)", tt.args.pb)
   212  			}
   213  			{
   214  				// Decode
   215  				got, err := DecodeMsg(tt.want)
   216  				if !tt.wantErr(t, err, fmt.Sprintf("DecodeMsg(%v)", tt.want)) {
   217  					return
   218  				}
   219  				if got == nil {
   220  					assert.Equalf(t, tt.args.pb, got, "DecodeMsg(%v)", tt.want)
   221  				} else {
   222  					// NOTE: "tt.args.pb != got" since got.evidence is nil by DecodeMsg, but these can compare each "String"
   223  					assert.Equalf(t, tt.args.pb.String(), got.String(), "DecodeMsg(%v)", tt.want)
   224  				}
   225  			}
   226  			{
   227  				// Validate
   228  				tt.wantErr(t, ValidateMsg(tt.args.pb), fmt.Sprintf("ValidateMsg(%v)", tt.args.pb))
   229  			}
   230  		})
   231  	}
   232  }