github.com/Finschia/finschia-sdk@v0.49.1/x/auth/tx/encode_decode_test.go (about)

     1  package tx
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  	"google.golang.org/protobuf/encoding/protowire"
    11  
    12  	"github.com/Finschia/finschia-sdk/codec"
    13  	codectypes "github.com/Finschia/finschia-sdk/codec/types"
    14  	"github.com/Finschia/finschia-sdk/testutil/testdata"
    15  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
    16  	"github.com/Finschia/finschia-sdk/types/tx"
    17  	signingtypes "github.com/Finschia/finschia-sdk/types/tx/signing"
    18  	"github.com/Finschia/finschia-sdk/x/auth/signing"
    19  )
    20  
    21  func TestDefaultTxDecoderError(t *testing.T) {
    22  	registry := codectypes.NewInterfaceRegistry()
    23  	cdc := codec.NewProtoCodec(registry)
    24  	encoder := DefaultTxEncoder()
    25  	decoder := DefaultTxDecoder(cdc)
    26  
    27  	builder := newBuilder()
    28  	err := builder.SetMsgs(testdata.NewTestMsg())
    29  	require.NoError(t, err)
    30  
    31  	txBz, err := encoder(builder.GetTx())
    32  	require.NoError(t, err)
    33  
    34  	_, err = decoder(txBz)
    35  	require.EqualError(t, err, "unable to resolve type URL /testdata.TestMsg: tx parse error")
    36  
    37  	testdata.RegisterInterfaces(registry)
    38  	_, err = decoder(txBz)
    39  	require.NoError(t, err)
    40  }
    41  
    42  func TestUnknownFields(t *testing.T) {
    43  	registry := codectypes.NewInterfaceRegistry()
    44  	cdc := codec.NewProtoCodec(registry)
    45  	decoder := DefaultTxDecoder(cdc)
    46  
    47  	tests := []struct {
    48  		name           string
    49  		body           *testdata.TestUpdatedTxBody
    50  		authInfo       *testdata.TestUpdatedAuthInfo
    51  		shouldErr      bool
    52  		shouldAminoErr string
    53  	}{
    54  		{
    55  			name: "no new fields should pass",
    56  			body: &testdata.TestUpdatedTxBody{
    57  				Memo: "foo",
    58  			},
    59  			authInfo:  &testdata.TestUpdatedAuthInfo{},
    60  			shouldErr: false,
    61  		},
    62  		{
    63  			name: "non-critical fields in TxBody should not error on decode, but should error with amino",
    64  			body: &testdata.TestUpdatedTxBody{
    65  				Memo:                         "foo",
    66  				SomeNewFieldNonCriticalField: "blah",
    67  			},
    68  			authInfo:       &testdata.TestUpdatedAuthInfo{},
    69  			shouldErr:      false,
    70  			shouldAminoErr: fmt.Sprintf("%s: %s", aminoNonCriticalFieldsError, sdkerrors.ErrInvalidRequest.Error()),
    71  		},
    72  		{
    73  			name: "critical fields in TxBody should error on decode",
    74  			body: &testdata.TestUpdatedTxBody{
    75  				Memo:         "foo",
    76  				SomeNewField: 10,
    77  			},
    78  			authInfo:  &testdata.TestUpdatedAuthInfo{},
    79  			shouldErr: true,
    80  		},
    81  		{
    82  			name: "critical fields in AuthInfo should error on decode",
    83  			body: &testdata.TestUpdatedTxBody{
    84  				Memo: "foo",
    85  			},
    86  			authInfo: &testdata.TestUpdatedAuthInfo{
    87  				NewField_3: []byte("xyz"),
    88  			},
    89  			shouldErr: true,
    90  		},
    91  		{
    92  			name: "non-critical fields in AuthInfo should error on decode",
    93  			body: &testdata.TestUpdatedTxBody{
    94  				Memo: "foo",
    95  			},
    96  			authInfo: &testdata.TestUpdatedAuthInfo{
    97  				NewField_1024: []byte("xyz"),
    98  			},
    99  			shouldErr: true,
   100  		},
   101  	}
   102  
   103  	for _, tt := range tests {
   104  		t.Run(tt.name, func(t *testing.T) {
   105  			bodyBz, err := tt.body.Marshal()
   106  			require.NoError(t, err)
   107  
   108  			authInfoBz, err := tt.authInfo.Marshal()
   109  			require.NoError(t, err)
   110  
   111  			txRaw := &tx.TxRaw{
   112  				BodyBytes:     bodyBz,
   113  				AuthInfoBytes: authInfoBz,
   114  			}
   115  			txBz, err := txRaw.Marshal()
   116  			require.NoError(t, err)
   117  
   118  			_, err = decoder(txBz)
   119  			if tt.shouldErr {
   120  				require.Error(t, err)
   121  			} else {
   122  				require.NoError(t, err)
   123  			}
   124  
   125  			if tt.shouldAminoErr != "" {
   126  				handler := signModeLegacyAminoJSONHandler{}
   127  				decoder := DefaultTxDecoder(codec.NewProtoCodec(codectypes.NewInterfaceRegistry()))
   128  				theTx, err := decoder(txBz)
   129  				require.NoError(t, err)
   130  				_, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signing.SignerData{}, theTx)
   131  				require.EqualError(t, err, tt.shouldAminoErr)
   132  			}
   133  		})
   134  	}
   135  
   136  	t.Log("test TxRaw no new fields, should succeed")
   137  	txRaw := &testdata.TestUpdatedTxRaw{}
   138  	txBz, err := txRaw.Marshal()
   139  	require.NoError(t, err)
   140  	_, err = decoder(txBz)
   141  	require.NoError(t, err)
   142  
   143  	t.Log("new field in TxRaw should fail")
   144  	txRaw = &testdata.TestUpdatedTxRaw{
   145  		NewField_5: []byte("abc"),
   146  	}
   147  	txBz, err = txRaw.Marshal()
   148  	require.NoError(t, err)
   149  	_, err = decoder(txBz)
   150  	require.Error(t, err)
   151  
   152  	//
   153  	t.Log("new \"non-critical\" field in TxRaw should fail")
   154  	txRaw = &testdata.TestUpdatedTxRaw{
   155  		NewField_1024: []byte("abc"),
   156  	}
   157  	txBz, err = txRaw.Marshal()
   158  	require.NoError(t, err)
   159  	_, err = decoder(txBz)
   160  	require.Error(t, err)
   161  }
   162  
   163  func TestRejectNonADR027(t *testing.T) {
   164  	registry := codectypes.NewInterfaceRegistry()
   165  	cdc := codec.NewProtoCodec(registry)
   166  	decoder := DefaultTxDecoder(cdc)
   167  
   168  	body := &testdata.TestUpdatedTxBody{Memo: "AAA"} // Look for "65 65 65" when debugging the bytes stream.
   169  	bodyBz, err := body.Marshal()
   170  	require.NoError(t, err)
   171  	authInfo := &testdata.TestUpdatedAuthInfo{Fee: &tx.Fee{GasLimit: 127}} // Look for "127" when debugging the bytes stream.
   172  	authInfoBz, err := authInfo.Marshal()
   173  	require.NoError(t, err)
   174  	txRaw := &tx.TxRaw{
   175  		BodyBytes:     bodyBz,
   176  		AuthInfoBytes: authInfoBz,
   177  		Signatures:    [][]byte{{41}, {42}, {43}}, // Look for "42" when debugging the bytes stream.
   178  	}
   179  
   180  	// We know these bytes are ADR-027-compliant.
   181  	txBz, err := txRaw.Marshal()
   182  
   183  	// From the `txBz`, we extract the 3 components:
   184  	// bodyBz, authInfoBz, sigsBz.
   185  	// In our tests, we will try to decode txs with those 3 components in all
   186  	// possible orders.
   187  	//
   188  	// Consume "BodyBytes" field.
   189  	_, _, m := protowire.ConsumeField(txBz)
   190  	bodyBz = append([]byte{}, txBz[:m]...)
   191  	txBz = txBz[m:] // Skip over "BodyBytes" bytes.
   192  	// Consume "AuthInfoBytes" field.
   193  	_, _, m = protowire.ConsumeField(txBz)
   194  	authInfoBz = append([]byte{}, txBz[:m]...)
   195  	txBz = txBz[m:] // Skip over "AuthInfoBytes" bytes.
   196  	// Consume "Signature" field, it's the remaining bytes.
   197  	sigsBz := append([]byte{}, txBz...)
   198  
   199  	// bodyBz's length prefix is 5, with `5` as varint encoding. We also try a
   200  	// longer varint encoding for 5: `133 00`.
   201  	longVarintBodyBz := append(append([]byte{bodyBz[0]}, byte(133), byte(0o0)), bodyBz[2:]...)
   202  
   203  	tests := []struct {
   204  		name      string
   205  		txBz      []byte
   206  		shouldErr bool
   207  	}{
   208  		{
   209  			"authInfo, body, sigs",
   210  			append(append(authInfoBz, bodyBz...), sigsBz...),
   211  			true,
   212  		},
   213  		{
   214  			"authInfo, sigs, body",
   215  			append(append(authInfoBz, sigsBz...), bodyBz...),
   216  			true,
   217  		},
   218  		{
   219  			"sigs, body, authInfo",
   220  			append(append(sigsBz, bodyBz...), authInfoBz...),
   221  			true,
   222  		},
   223  		{
   224  			"sigs, authInfo, body",
   225  			append(append(sigsBz, authInfoBz...), bodyBz...),
   226  			true,
   227  		},
   228  		{
   229  			"body, sigs, authInfo",
   230  			append(append(bodyBz, sigsBz...), authInfoBz...),
   231  			true,
   232  		},
   233  		{
   234  			"body, authInfo, sigs (valid txRaw)",
   235  			append(append(bodyBz, authInfoBz...), sigsBz...),
   236  			false,
   237  		},
   238  		{
   239  			"longer varint than needed",
   240  			append(append(longVarintBodyBz, authInfoBz...), sigsBz...),
   241  			true,
   242  		},
   243  	}
   244  
   245  	for _, tt := range tests {
   246  		t.Run(tt.name, func(t *testing.T) {
   247  			_, err = decoder(tt.txBz)
   248  			if tt.shouldErr {
   249  				require.Error(t, err)
   250  			} else {
   251  				require.NoError(t, err)
   252  			}
   253  		})
   254  	}
   255  }
   256  
   257  func TestVarintMinLength(t *testing.T) {
   258  	tests := []struct {
   259  		n uint64
   260  	}{
   261  		{1<<7 - 1},
   262  		{1 << 7},
   263  		{1<<14 - 1},
   264  		{1 << 14},
   265  		{1<<21 - 1},
   266  		{1 << 21},
   267  		{1<<28 - 1},
   268  		{1 << 28},
   269  		{1<<35 - 1},
   270  		{1 << 35},
   271  		{1<<42 - 1},
   272  		{1 << 42},
   273  		{1<<49 - 1},
   274  		{1 << 49},
   275  		{1<<56 - 1},
   276  		{1 << 56},
   277  		{1<<63 - 1},
   278  		{1 << 63},
   279  		{math.MaxUint64},
   280  	}
   281  
   282  	for _, tt := range tests {
   283  		t.Run(fmt.Sprintf("test %d", tt.n), func(t *testing.T) {
   284  			l1 := varintMinLength(tt.n)
   285  			buf := make([]byte, binary.MaxVarintLen64)
   286  			l2 := binary.PutUvarint(buf, tt.n)
   287  			require.Equal(t, l2, l1)
   288  		})
   289  	}
   290  }