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 }