github.com/cosmos/cosmos-sdk@v0.50.10/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/cosmos/cosmos-sdk/codec" 13 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 14 "github.com/cosmos/cosmos-sdk/testutil/testdata" 15 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 16 "github.com/cosmos/cosmos-sdk/types/tx" 17 signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" 18 "github.com/cosmos/cosmos-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(nil) 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 /testpb.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 tt := tt 105 t.Run(tt.name, func(t *testing.T) { 106 bodyBz, err := tt.body.Marshal() 107 require.NoError(t, err) 108 109 authInfoBz, err := tt.authInfo.Marshal() 110 require.NoError(t, err) 111 112 txRaw := &tx.TxRaw{ 113 BodyBytes: bodyBz, 114 AuthInfoBytes: authInfoBz, 115 } 116 txBz, err := txRaw.Marshal() 117 require.NoError(t, err) 118 119 _, err = decoder(txBz) 120 if tt.shouldErr { 121 require.Error(t, err) 122 } else { 123 require.NoError(t, err) 124 } 125 126 if tt.shouldAminoErr != "" { 127 handler := signModeLegacyAminoJSONHandler{} 128 decoder := DefaultTxDecoder(codec.NewProtoCodec(codectypes.NewInterfaceRegistry())) 129 theTx, err := decoder(txBz) 130 require.NoError(t, err) 131 _, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signing.SignerData{}, theTx) 132 require.EqualError(t, err, tt.shouldAminoErr) 133 } 134 }) 135 } 136 137 t.Log("test TxRaw no new fields, should succeed") 138 txRaw := &testdata.TestUpdatedTxRaw{} 139 txBz, err := txRaw.Marshal() 140 require.NoError(t, err) 141 _, err = decoder(txBz) 142 require.NoError(t, err) 143 144 t.Log("new field in TxRaw should fail") 145 txRaw = &testdata.TestUpdatedTxRaw{ 146 NewField_5: []byte("abc"), 147 } 148 txBz, err = txRaw.Marshal() 149 require.NoError(t, err) 150 _, err = decoder(txBz) 151 require.Error(t, err) 152 153 // 154 t.Log("new \"non-critical\" field in TxRaw should fail") 155 txRaw = &testdata.TestUpdatedTxRaw{ 156 NewField_1024: []byte("abc"), 157 } 158 txBz, err = txRaw.Marshal() 159 require.NoError(t, err) 160 _, err = decoder(txBz) 161 require.Error(t, err) 162 } 163 164 func TestRejectNonADR027(t *testing.T) { 165 registry := codectypes.NewInterfaceRegistry() 166 cdc := codec.NewProtoCodec(registry) 167 decoder := DefaultTxDecoder(cdc) 168 169 body := &testdata.TestUpdatedTxBody{Memo: "AAA"} // Look for "65 65 65" when debugging the bytes stream. 170 bodyBz, err := body.Marshal() 171 require.NoError(t, err) 172 authInfo := &testdata.TestUpdatedAuthInfo{Fee: &tx.Fee{GasLimit: 127}} // Look for "127" when debugging the bytes stream. 173 authInfoBz, err := authInfo.Marshal() 174 require.NoError(t, err) 175 txRaw := &tx.TxRaw{ 176 BodyBytes: bodyBz, 177 AuthInfoBytes: authInfoBz, 178 Signatures: [][]byte{{41}, {42}, {43}}, // Look for "42" when debugging the bytes stream. 179 } 180 181 // We know these bytes are ADR-027-compliant. 182 txBz, err := txRaw.Marshal() 183 184 // From the `txBz`, we extract the 3 components: 185 // bodyBz, authInfoBz, sigsBz. 186 // In our tests, we will try to decode txs with those 3 components in all 187 // possible orders. 188 // 189 // Consume "BodyBytes" field. 190 _, _, m := protowire.ConsumeField(txBz) 191 bodyBz = append([]byte{}, txBz[:m]...) 192 txBz = txBz[m:] // Skip over "BodyBytes" bytes. 193 // Consume "AuthInfoBytes" field. 194 _, _, m = protowire.ConsumeField(txBz) 195 authInfoBz = append([]byte{}, txBz[:m]...) 196 txBz = txBz[m:] // Skip over "AuthInfoBytes" bytes. 197 // Consume "Signature" field, it's the remaining bytes. 198 sigsBz := append([]byte{}, txBz...) 199 200 // bodyBz's length prefix is 5, with `5` as varint encoding. We also try a 201 // longer varint encoding for 5: `133 00`. 202 longVarintBodyBz := append(append([]byte{bodyBz[0]}, byte(133), byte(0o0)), bodyBz[2:]...) 203 204 tests := []struct { 205 name string 206 txBz []byte 207 shouldErr bool 208 }{ 209 { 210 "authInfo, body, sigs", 211 append(append(authInfoBz, bodyBz...), sigsBz...), 212 true, 213 }, 214 { 215 "authInfo, sigs, body", 216 append(append(authInfoBz, sigsBz...), bodyBz...), 217 true, 218 }, 219 { 220 "sigs, body, authInfo", 221 append(append(sigsBz, bodyBz...), authInfoBz...), 222 true, 223 }, 224 { 225 "sigs, authInfo, body", 226 append(append(sigsBz, authInfoBz...), bodyBz...), 227 true, 228 }, 229 { 230 "body, sigs, authInfo", 231 append(append(bodyBz, sigsBz...), authInfoBz...), 232 true, 233 }, 234 { 235 "body, authInfo, sigs (valid txRaw)", 236 append(append(bodyBz, authInfoBz...), sigsBz...), 237 false, 238 }, 239 { 240 "longer varint than needed", 241 append(append(longVarintBodyBz, authInfoBz...), sigsBz...), 242 true, 243 }, 244 } 245 246 for _, tt := range tests { 247 tt := tt 248 t.Run(tt.name, func(t *testing.T) { 249 _, err = decoder(tt.txBz) 250 if tt.shouldErr { 251 require.Error(t, err) 252 } else { 253 require.NoError(t, err) 254 } 255 }) 256 } 257 } 258 259 func TestVarintMinLength(t *testing.T) { 260 tests := []struct { 261 n uint64 262 }{ 263 {1<<7 - 1}, 264 {1 << 7}, 265 {1<<14 - 1}, 266 {1 << 14}, 267 {1<<21 - 1}, 268 {1 << 21}, 269 {1<<28 - 1}, 270 {1 << 28}, 271 {1<<35 - 1}, 272 {1 << 35}, 273 {1<<42 - 1}, 274 {1 << 42}, 275 {1<<49 - 1}, 276 {1 << 49}, 277 {1<<56 - 1}, 278 {1 << 56}, 279 {1<<63 - 1}, 280 {1 << 63}, 281 {math.MaxUint64}, 282 } 283 284 for _, tt := range tests { 285 tt := tt 286 t.Run(fmt.Sprintf("test %d", tt.n), func(t *testing.T) { 287 l1 := varintMinLength(tt.n) 288 buf := make([]byte, binary.MaxVarintLen64) 289 l2 := binary.PutUvarint(buf, tt.n) 290 require.Equal(t, l2, l1) 291 }) 292 } 293 }