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 }