From 09bf0ff77b94161fcdac7a6e91724f813bf92d25 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 3 Oct 2024 13:48:25 +0200 Subject: [PATCH] fix half conflicts and revert tests --- go.mod | 2 +- go.sum | 4 +- simapp/go.mod | 2 +- simapp/go.sum | 4 +- tests/go.mod | 2 +- tests/go.sum | 4 +- tests/integration/rapidgen/rapidgen.go | 5 +- .../tx/aminojson/aminojson_test.go | 414 ++++++++++-------- tests/integration/tx/context_test.go | 20 +- tests/integration/tx/internal/util.go | 221 ---------- x/tx/CHANGELOG.md | 8 +- 11 files changed, 272 insertions(+), 414 deletions(-) delete mode 100644 tests/integration/tx/internal/util.go diff --git a/go.mod b/go.mod index 93e473bc5dc1..54cb97e3f63d 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1 - cosmossdk.io/x/tx v0.13.5 + cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871 github.com/99designs/keyring v1.2.1 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 github.com/bits-and-blooms/bitset v1.8.0 diff --git a/go.sum b/go.sum index 7a4cfedc0a8a..57e9bc9eab38 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y= cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM= -cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= -cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= +cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871 h1:+lRwWQRVvB3jgRgdqrgeFUJ45BoXZh/UeeAV5f/m2Gk= +cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek= filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= diff --git a/simapp/go.mod b/simapp/go.mod index 685d5f570066..3c7157da8d78 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -16,7 +16,7 @@ require ( cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 cosmossdk.io/x/nft v0.1.1 - cosmossdk.io/x/tx v0.13.5 + cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871 cosmossdk.io/x/upgrade v0.1.4 github.com/cometbft/cometbft v0.38.12 github.com/cosmos/cosmos-db v1.0.2 diff --git a/simapp/go.sum b/simapp/go.sum index ad8dbdeb39e4..b7f3422a1af2 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -210,8 +210,8 @@ cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= cosmossdk.io/x/nft v0.1.1 h1:pslAVS8P5NkW080+LWOamInjDcq+v2GSCo+BjN9sxZ8= cosmossdk.io/x/nft v0.1.1/go.mod h1:Kac6F6y2gsKvoxU+fy8uvxRTi4BIhLOor2zgCNQwVgY= -cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= -cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= +cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871 h1:+lRwWQRVvB3jgRgdqrgeFUJ45BoXZh/UeeAV5f/m2Gk= +cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38= cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= diff --git a/tests/go.mod b/tests/go.mod index be3db502fe7a..58f871b12fa6 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -14,7 +14,7 @@ require ( cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 cosmossdk.io/x/nft v0.1.1 // indirect - cosmossdk.io/x/tx v0.13.5 + cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871 cosmossdk.io/x/upgrade v0.1.4 github.com/cometbft/cometbft v0.38.12 github.com/cosmos/cosmos-db v1.0.2 diff --git a/tests/go.sum b/tests/go.sum index 0521bf1ba569..079779a509ed 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -208,8 +208,8 @@ cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= cosmossdk.io/x/nft v0.1.1 h1:pslAVS8P5NkW080+LWOamInjDcq+v2GSCo+BjN9sxZ8= cosmossdk.io/x/nft v0.1.1/go.mod h1:Kac6F6y2gsKvoxU+fy8uvxRTi4BIhLOor2zgCNQwVgY= -cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= -cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= +cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871 h1:+lRwWQRVvB3jgRgdqrgeFUJ45BoXZh/UeeAV5f/m2Gk= +cosmossdk.io/x/tx v0.13.6-0.20241003112805-ff8789a02871/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38= cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= diff --git a/tests/integration/rapidgen/rapidgen.go b/tests/integration/rapidgen/rapidgen.go index bd293de062a3..08f2346ab523 100644 --- a/tests/integration/rapidgen/rapidgen.go +++ b/tests/integration/rapidgen/rapidgen.go @@ -231,6 +231,7 @@ var ( NonsignableTypes = []GeneratedType{ GenType(&authtypes.Params{}, &authapi.Params{}, GenOpts), GenType(&authtypes.BaseAccount{}, &authapi.BaseAccount{}, GenOpts.WithAnyTypes(&ed25519.PubKey{})), + GenType(&authtypes.ModuleAccount{}, &authapi.ModuleAccount{}, GenOpts.WithAnyTypes(&ed25519.PubKey{})), GenType(&authtypes.ModuleCredential{}, &authapi.ModuleCredential{}, GenOpts), GenType(&authztypes.GenericAuthorization{}, &authzapi.GenericAuthorization{}, GenOpts), @@ -271,9 +272,7 @@ var ( GenType(&slashingtypes.Params{}, &slashingapi.Params{}, GenOpts.WithDisallowNil()), - // JSON ordering of one of fields to be fixed in https://github.com/cosmos/cosmos-sdk/pull/21782 - // TODO uncomment once merged - // GenType(&stakingtypes.StakeAuthorization{}, &stakingapi.StakeAuthorization{}, GenOpts), + GenType(&stakingtypes.StakeAuthorization{}, &stakingapi.StakeAuthorization{}, GenOpts), GenType(&upgradetypes.CancelSoftwareUpgradeProposal{}, &upgradeapi.CancelSoftwareUpgradeProposal{}, GenOpts), // nolint:staticcheck // testing legacy code path GenType(&upgradetypes.SoftwareUpgradeProposal{}, &upgradeapi.SoftwareUpgradeProposal{}, GenOpts.WithDisallowNil()), // nolint:staticcheck // testing legacy code path diff --git a/tests/integration/tx/aminojson/aminojson_test.go b/tests/integration/tx/aminojson/aminojson_test.go index b48b78a5418c..eb271308f8d6 100644 --- a/tests/integration/tx/aminojson/aminojson_test.go +++ b/tests/integration/tx/aminojson/aminojson_test.go @@ -1,13 +1,9 @@ package aminojson import ( - "bytes" + "context" "fmt" -<<<<<<< HEAD "reflect" -======= - stdmath "math" ->>>>>>> 2d40cc1ab (fix(x/tx): fix amino json drift from legacy spec (#21825)) "testing" "time" @@ -15,16 +11,31 @@ import ( gogoproto "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" "pgregory.net/rapid" authapi "cosmossdk.io/api/cosmos/auth/v1beta1" + authzapi "cosmossdk.io/api/cosmos/authz/v1beta1" bankapi "cosmossdk.io/api/cosmos/bank/v1beta1" v1beta1 "cosmossdk.io/api/cosmos/base/v1beta1" + "cosmossdk.io/api/cosmos/crypto/ed25519" + multisigapi "cosmossdk.io/api/cosmos/crypto/multisig" + "cosmossdk.io/api/cosmos/crypto/secp256k1" + distapi "cosmossdk.io/api/cosmos/distribution/v1beta1" + gov_v1_api "cosmossdk.io/api/cosmos/gov/v1" + gov_v1beta1_api "cosmossdk.io/api/cosmos/gov/v1beta1" msgv1 "cosmossdk.io/api/cosmos/msg/v1" + slashingapi "cosmossdk.io/api/cosmos/slashing/v1beta1" + stakingapi "cosmossdk.io/api/cosmos/staking/v1beta1" + txv1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1" + vestingapi "cosmossdk.io/api/cosmos/vesting/v1beta1" "cosmossdk.io/math" "cosmossdk.io/x/evidence" feegrantmodule "cosmossdk.io/x/feegrant/module" "cosmossdk.io/x/tx/signing/aminojson" + signing_testutil "cosmossdk.io/x/tx/signing/testutil" "cosmossdk.io/x/upgrade" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -32,13 +43,17 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" secp256k1types "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/tests/integration/rapidgen" - "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal" gogo_testpb "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/gogo/testpb" + pulsar_testpb "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/pulsar/testpb" "github.com/cosmos/cosmos-sdk/testutil/testdata" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/bech32" "github.com/cosmos/cosmos-sdk/types/module/testutil" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" @@ -76,7 +91,6 @@ import ( // In order for step 3 to work certain restrictions on the data generated in step 1 must be enforced and are described // by the mutation of genOpts passed to the generator. func TestAminoJSON_Equivalence(t *testing.T) { -<<<<<<< HEAD encCfg := testutil.MakeTestEncodingConfig( auth.AppModuleBasic{}, authzmodule.AppModuleBasic{}, bank.AppModuleBasic{}, consensus.AppModuleBasic{}, distribution.AppModuleBasic{}, evidence.AppModuleBasic{}, feegrantmodule.AppModuleBasic{}, @@ -84,25 +98,6 @@ func TestAminoJSON_Equivalence(t *testing.T) { slashing.AppModuleBasic{}, staking.AppModuleBasic{}, upgrade.AppModuleBasic{}, vesting.AppModuleBasic{}) legacytx.RegressionTestingAminoCodec = encCfg.Amino aj := aminojson.NewEncoder(aminojson.EncoderOptions{DoNotSortFields: true}) -======= - fixture := internal.NewSigningFixture(t, internal.SigningFixtureOptions{}, - auth.AppModule{}, - authzmodule.AppModule{}, - bank.AppModule{}, - consensus.AppModule{}, - distribution.AppModule{}, - evidence.AppModule{}, - feegrantmodule.AppModule{}, - gov.AppModule{}, - groupmodule.AppModule{}, - mint.AppModule{}, - slashing.AppModule{}, - staking.AppModule{}, - upgrade.AppModule{}, - vesting.AppModule{}, - ) - aj := aminojson.NewEncoder(aminojson.EncoderOptions{}) ->>>>>>> 2d40cc1ab (fix(x/tx): fix amino json drift from legacy spec (#21825)) for _, tt := range rapidgen.DefaultGeneratedTypes { desc := tt.Pulsar.ProtoReflect().Descriptor() @@ -110,7 +105,7 @@ func TestAminoJSON_Equivalence(t *testing.T) { t.Run(name, func(t *testing.T) { gen := rapidproto.MessageGenerator(tt.Pulsar, tt.Opts) fmt.Printf("testing %s\n", tt.Pulsar.ProtoReflect().Descriptor().FullName()) - rapid.Check(t, func(r *rapid.T) { + rapid.Check(t, func(t *rapid.T) { // uncomment to debug; catch a panic and inspect application state // defer func() { // if r := recover(); r != nil { @@ -119,28 +114,26 @@ func TestAminoJSON_Equivalence(t *testing.T) { // } // }() - msg := gen.Draw(r, "msg") + msg := gen.Draw(t, "msg") postFixPulsarMessage(msg) gogo := tt.Gogo sanity := tt.Pulsar protoBz, err := proto.Marshal(msg) - require.NoError(r, err) + require.NoError(t, err) err = proto.Unmarshal(protoBz, sanity) - require.NoError(r, err) + require.NoError(t, err) - err = fixture.UnmarshalGogoProto(protoBz, gogo) - require.NoError(r, err) + err = encCfg.Codec.Unmarshal(protoBz, gogo) + require.NoError(t, err) - legacyAminoJSON := fixture.MarshalLegacyAminoJSON(t, gogo) + legacyAminoJSON, err := encCfg.Amino.MarshalJSON(gogo) + require.NoError(t, err) aminoJSON, err := aj.Marshal(msg) - require.NoError(r, err) - if !bytes.Equal(legacyAminoJSON, aminoJSON) { - require.Failf(r, "JSON mismatch", "legacy: %s\n x/tx: %s\n", - string(legacyAminoJSON), string(aminoJSON)) - } + require.NoError(t, err) + require.Equal(t, string(legacyAminoJSON), string(aminoJSON)) // test amino json signer handler equivalence if !proto.HasExtension(desc.Options(), msgv1.E_Signer) { @@ -148,13 +141,47 @@ func TestAminoJSON_Equivalence(t *testing.T) { return } - fixture.RequireLegacyAminoEquivalent(t, gogo) + handlerOptions := signing_testutil.HandlerArgumentOptions{ + ChainID: "test-chain", + Memo: "sometestmemo", + Msg: tt.Pulsar, + AccNum: 1, + AccSeq: 2, + SignerAddress: "signerAddress", + Fee: &txv1beta1.Fee{ + Amount: []*v1beta1.Coin{{Denom: "uatom", Amount: "1000"}}, + }, + } + + signerData, txData, err := signing_testutil.MakeHandlerArguments(handlerOptions) + require.NoError(t, err) + + handler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) + signBz, err := handler.GetSignBytes(context.Background(), signerData, txData) + require.NoError(t, err) + + legacyHandler := tx.NewSignModeLegacyAminoJSONHandler() + txBuilder := encCfg.TxConfig.NewTxBuilder() + require.NoError(t, txBuilder.SetMsgs([]types.Msg{tt.Gogo}...)) + txBuilder.SetMemo(handlerOptions.Memo) + txBuilder.SetFeeAmount(types.Coins{types.NewInt64Coin("uatom", 1000)}) + theTx := txBuilder.GetTx() + + legacySigningData := signing.SignerData{ + ChainID: handlerOptions.ChainID, + Address: handlerOptions.SignerAddress, + AccountNumber: handlerOptions.AccNum, + Sequence: handlerOptions.AccSeq, + } + legacySignBz, err := legacyHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + legacySigningData, theTx) + require.NoError(t, err) + require.Equal(t, string(legacySignBz), string(signBz)) }) }) } } -<<<<<<< HEAD func newAny(t *testing.T, msg proto.Message) *anypb.Any { bz, err := proto.Marshal(msg) require.NoError(t, err) @@ -171,139 +198,157 @@ func TestAminoJSON_LegacyParity(t *testing.T) { bank.AppModuleBasic{}, distribution.AppModuleBasic{}, slashing.AppModuleBasic{}, staking.AppModuleBasic{}, vesting.AppModuleBasic{}, gov.AppModuleBasic{}) legacytx.RegressionTestingAminoCodec = encCfg.Amino -======= -// TestAminoJSON_LegacyParity tests that the Encoder encoder produces the same output as the Encoder encoder. -func TestAminoJSON_LegacyParity(t *testing.T) { - fixture := internal.NewSigningFixture(t, internal.SigningFixtureOptions{}, - auth.AppModule{}, authzmodule.AppModule{}, - bank.AppModule{}, distribution.AppModule{}, slashing.AppModule{}, staking.AppModule{}, - vesting.AppModule{}, gov.AppModule{}) - aj := aminojson.NewEncoder(aminojson.EncoderOptions{}) ->>>>>>> 2d40cc1ab (fix(x/tx): fix amino json drift from legacy spec (#21825)) + aj := aminojson.NewEncoder(aminojson.EncoderOptions{DoNotSortFields: true}) addr1 := types.AccAddress("addr1") now := time.Now() + genericAuth, _ := codectypes.NewAnyWithValue(&authztypes.GenericAuthorization{Msg: "foo"}) + genericAuthPulsar := newAny(t, &authzapi.GenericAuthorization{Msg: "foo"}) pubkeyAny, _ := codectypes.NewAnyWithValue(&secp256k1types.PubKey{Key: []byte("foo")}) - dec5point4 := math.LegacyMustNewDecFromStr("5.4") - failingBaseAccount := authtypes.NewBaseAccountWithAddress(addr1) - failingBaseAccount.AccountNumber = stdmath.MaxUint64 + pubkeyAnyPulsar := newAny(t, &secp256k1.PubKey{Key: []byte("foo")}) + dec10bz, _ := math.LegacyNewDec(10).Marshal() + int123bz, _ := math.NewInt(123).Marshal() cases := map[string]struct { - gogo gogoproto.Message - fails bool + gogo gogoproto.Message + pulsar proto.Message + pulsarMarshalFails bool + + // this will fail in cases where a lossy encoding of an empty array to protobuf occurs. the unmarshalled bytes + // represent the array as nil, and a subsequent marshal to JSON represent the array as null instead of empty. + roundTripUnequal bool + + // pulsar does not support marshaling a math.Dec as anything except a string. Therefore, we cannot unmarshal + // a pulsar encoded Math.dec (the string representation of a Decimal) into a gogo Math.dec (expecting an int64). + protoUnmarshalFails bool }{ - "auth/params": { - gogo: &authtypes.Params{TxSigLimit: 10}, - }, - "auth/module_account_nil_permissions": { + "auth/params": {gogo: &authtypes.Params{TxSigLimit: 10}, pulsar: &authapi.Params{TxSigLimit: 10}}, + "auth/module_account": { gogo: &authtypes.ModuleAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress( - addr1, - ), + BaseAccount: authtypes.NewBaseAccountWithAddress(addr1), Permissions: []string{}, }, - }, - "auth/module_account/max_uint64": { - gogo: &authtypes.ModuleAccount{ - BaseAccount: failingBaseAccount, - }, - fails: true, - }, - "auth/module_account_empty_permissions": { - gogo: &authtypes.ModuleAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress( - addr1, - ), - // empty set and nil are indistinguishable from the protoreflect API since they both - // marshal to zero proto bytes, there empty set is not supported. - Permissions: []string{}, + pulsar: &authapi.ModuleAccount{ + BaseAccount: &authapi.BaseAccount{Address: addr1.String()}, Permissions: []string{}, }, - fails: true, + roundTripUnequal: true, }, "auth/base_account": { - gogo: &authtypes.BaseAccount{Address: addr1.String(), PubKey: pubkeyAny, AccountNumber: 1, Sequence: 2}, + gogo: &authtypes.BaseAccount{Address: addr1.String(), PubKey: pubkeyAny}, + pulsar: &authapi.BaseAccount{Address: addr1.String(), PubKey: pubkeyAnyPulsar}, }, "authz/msg_grant": { gogo: &authztypes.MsgGrant{ - Granter: addr1.String(), Grantee: addr1.String(), Grant: authztypes.Grant{Expiration: &now, Authorization: genericAuth}, }, + pulsar: &authzapi.MsgGrant{ + Grant: &authzapi.Grant{Expiration: timestamppb.New(now), Authorization: genericAuthPulsar}, + }, }, "authz/msg_update_params": { - gogo: &authtypes.MsgUpdateParams{Params: authtypes.Params{TxSigLimit: 10}}, + gogo: &authtypes.MsgUpdateParams{Params: authtypes.Params{TxSigLimit: 10}}, + pulsar: &authapi.MsgUpdateParams{Params: &authapi.Params{TxSigLimit: 10}}, }, "authz/msg_exec/empty_msgs": { - gogo: &authztypes.MsgExec{Msgs: []*codectypes.Any{}}, + gogo: &authztypes.MsgExec{Msgs: []*codectypes.Any{}}, + pulsar: &authzapi.MsgExec{Msgs: []*anypb.Any{}}, }, "distribution/delegator_starting_info": { - gogo: &disttypes.DelegatorStartingInfo{Stake: math.LegacyNewDec(10)}, + gogo: &disttypes.DelegatorStartingInfo{}, + pulsar: &distapi.DelegatorStartingInfo{}, }, "distribution/delegator_starting_info/non_zero_dec": { - gogo: &disttypes.DelegatorStartingInfo{Stake: math.LegacyNewDec(10)}, + gogo: &disttypes.DelegatorStartingInfo{Stake: math.LegacyNewDec(10)}, + pulsar: &distapi.DelegatorStartingInfo{Stake: "10.000000000000000000"}, + protoUnmarshalFails: true, }, "distribution/delegation_delegator_reward": { - gogo: &disttypes.DelegationDelegatorReward{}, + gogo: &disttypes.DelegationDelegatorReward{}, + pulsar: &distapi.DelegationDelegatorReward{}, }, "distribution/community_pool_spend_proposal_with_deposit": { gogo: &disttypes.CommunityPoolSpendProposalWithDeposit{}, pulsar: &distapi.CommunityPoolSpendProposalWithDeposit{}, //nolint:staticcheck // keep test as is testing legacy parity }, "distribution/msg_withdraw_delegator_reward": { - gogo: &disttypes.MsgWithdrawDelegatorReward{DelegatorAddress: "foo"}, + gogo: &disttypes.MsgWithdrawDelegatorReward{DelegatorAddress: "foo"}, + pulsar: &distapi.MsgWithdrawDelegatorReward{DelegatorAddress: "foo"}, }, "crypto/ed25519": { - gogo: &ed25519types.PubKey{Key: []byte("key")}, + gogo: &ed25519types.PubKey{Key: []byte("key")}, + pulsar: &ed25519.PubKey{Key: []byte("key")}, }, "crypto/secp256k1": { - gogo: &secp256k1types.PubKey{Key: []byte("key")}, + gogo: &secp256k1types.PubKey{Key: []byte("key")}, + pulsar: &secp256k1.PubKey{Key: []byte("key")}, }, "crypto/legacy_amino_pubkey": { - gogo: &multisig.LegacyAminoPubKey{PubKeys: []*codectypes.Any{pubkeyAny}}, + gogo: &multisig.LegacyAminoPubKey{PubKeys: []*codectypes.Any{pubkeyAny}}, + pulsar: &multisigapi.LegacyAminoPubKey{PublicKeys: []*anypb.Any{pubkeyAnyPulsar}}, }, - "crypto/legacy_amino_pubkey_empty": { - gogo: &multisig.LegacyAminoPubKey{}, + "crypto/legacy_amino_pubkey/empty": { + gogo: &multisig.LegacyAminoPubKey{}, + pulsar: &multisigapi.LegacyAminoPubKey{}, }, "consensus/evidence_params/duration": { - gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: 1e9 + 7}, + gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: 1e9 + 7}, + pulsar: &gov_v1beta1_api.VotingParams{VotingPeriod: &durationpb.Duration{Seconds: 1, Nanos: 7}}, }, "consensus/evidence_params/big_duration": { - gogo: &gov_v1beta1_types.VotingParams{ - VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999, - }, + gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999}, + pulsar: &gov_v1beta1_api.VotingParams{VotingPeriod: &durationpb.Duration{ + Seconds: rapidproto.MaxDurationSeconds, Nanos: 999999999, + }}, }, "consensus/evidence_params/too_big_duration": { - gogo: &gov_v1beta1_types.VotingParams{ - VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999, - }, + gogo: &gov_v1beta1_types.VotingParams{VotingPeriod: time.Duration(rapidproto.MaxDurationSeconds*1e9) + 999999999}, + pulsar: &gov_v1beta1_api.VotingParams{VotingPeriod: &durationpb.Duration{ + Seconds: rapidproto.MaxDurationSeconds + 1, Nanos: 999999999, + }}, + pulsarMarshalFails: true, }, // amino.dont_omitempty + empty/nil lists produce some surprising results "bank/send_authorization/empty_coins": { - gogo: &banktypes.SendAuthorization{SpendLimit: []types.Coin{}}, + gogo: &banktypes.SendAuthorization{SpendLimit: []types.Coin{}}, + pulsar: &bankapi.SendAuthorization{SpendLimit: []*v1beta1.Coin{}}, }, "bank/send_authorization/nil_coins": { - gogo: &banktypes.SendAuthorization{SpendLimit: nil}, + gogo: &banktypes.SendAuthorization{SpendLimit: nil}, + pulsar: &bankapi.SendAuthorization{SpendLimit: nil}, }, "bank/send_authorization/empty_list": { - gogo: &banktypes.SendAuthorization{AllowList: []string{}}, + gogo: &banktypes.SendAuthorization{AllowList: []string{}}, + pulsar: &bankapi.SendAuthorization{AllowList: []string{}}, }, "bank/send_authorization/nil_list": { - gogo: &banktypes.SendAuthorization{AllowList: nil}, + gogo: &banktypes.SendAuthorization{AllowList: nil}, + pulsar: &bankapi.SendAuthorization{AllowList: nil}, }, "bank/msg_multi_send/nil_everything": { - gogo: &banktypes.MsgMultiSend{}, + gogo: &banktypes.MsgMultiSend{}, + pulsar: &bankapi.MsgMultiSend{}, }, "gov/v1_msg_submit_proposal": { - gogo: &gov_v1_types.MsgSubmitProposal{}, + gogo: &gov_v1_types.MsgSubmitProposal{}, + pulsar: &gov_v1_api.MsgSubmitProposal{}, }, + "slashing/params/empty_dec": { + gogo: &slashingtypes.Params{DowntimeJailDuration: 1e9 + 7}, + pulsar: &slashingapi.Params{DowntimeJailDuration: &durationpb.Duration{Seconds: 1, Nanos: 7}}, + }, + // This test cases demonstrates the expected contract and proper way to set a cosmos.Dec field represented + // as bytes in protobuf message, namely: + // dec10bz, _ := types.NewDec(10).Marshal() "slashing/params/dec": { gogo: &slashingtypes.Params{ - DowntimeJailDuration: 1e9 + 7, - MinSignedPerWindow: math.LegacyNewDec(10), - SlashFractionDoubleSign: math.LegacyZeroDec(), - SlashFractionDowntime: math.LegacyZeroDec(), + DowntimeJailDuration: 1e9 + 7, + MinSignedPerWindow: math.LegacyNewDec(10), + }, + pulsar: &slashingapi.Params{ + DowntimeJailDuration: &durationpb.Duration{Seconds: 1, Nanos: 7}, + MinSignedPerWindow: dec10bz, }, }, -<<<<<<< HEAD "staking/create_validator": { gogo: &stakingtypes.MsgCreateValidator{Pubkey: pubkeyAny}, pulsar: &stakingapi.MsgCreateValidator{ @@ -311,115 +356,140 @@ func TestAminoJSON_LegacyParity(t *testing.T) { Description: &stakingapi.Description{}, Commission: &stakingapi.CommissionRates{}, Value: &v1beta1.Coin{}, -======= - "staking/msg_update_params": { - gogo: &stakingtypes.MsgUpdateParams{ - Params: stakingtypes.Params{ - UnbondingTime: 0, - KeyRotationFee: types.Coin{}, - MinCommissionRate: math.LegacyZeroDec(), - }, - }, - }, - "staking/create_validator": { - gogo: &stakingtypes.MsgCreateValidator{ - Pubkey: pubkeyAny, - Commission: stakingtypes.CommissionRates{ - Rate: dec5point4, - MaxRate: math.LegacyZeroDec(), - MaxChangeRate: math.LegacyZeroDec(), - }, - MinSelfDelegation: math.NewIntFromUint64(10), ->>>>>>> 2d40cc1ab (fix(x/tx): fix amino json drift from legacy spec (#21825)) }, }, "staking/msg_cancel_unbonding_delegation_response": { - gogo: &stakingtypes.MsgCancelUnbondingDelegationResponse{}, + gogo: &stakingtypes.MsgCancelUnbondingDelegationResponse{}, + pulsar: &stakingapi.MsgCancelUnbondingDelegationResponse{}, }, "staking/stake_authorization_empty": { - gogo: &stakingtypes.StakeAuthorization{}, + gogo: &stakingtypes.StakeAuthorization{}, + pulsar: &stakingapi.StakeAuthorization{}, }, "staking/stake_authorization_allow": { gogo: &stakingtypes.StakeAuthorization{ - MaxTokens: &types.Coin{Denom: "foo", Amount: math.NewInt(123)}, Validators: &stakingtypes.StakeAuthorization_AllowList{ - AllowList: &stakingtypes.StakeAuthorization_Validators{ - Address: []string{"foo"}, - }, + AllowList: &stakingtypes.StakeAuthorization_Validators{Address: []string{"foo"}}, }, - AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, }, - }, - "staking/stake_authorization_deny": { - gogo: &stakingtypes.StakeAuthorization{ - MaxTokens: &types.Coin{Denom: "foo", Amount: math.NewInt(123)}, - Validators: &stakingtypes.StakeAuthorization_DenyList{ - DenyList: &stakingtypes.StakeAuthorization_Validators{}, + pulsar: &stakingapi.StakeAuthorization{ + Validators: &stakingapi.StakeAuthorization_AllowList{ + AllowList: &stakingapi.StakeAuthorization_Validators{Address: []string{"foo"}}, }, - AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, }, - // to be fixed in https://github.com/cosmos/cosmos-sdk/pull/21782 - // TODO remove once merged - fails: true, }, "vesting/base_account_empty": { - gogo: &vestingtypes.BaseVestingAccount{BaseAccount: &authtypes.BaseAccount{}}, + gogo: &vestingtypes.BaseVestingAccount{BaseAccount: &authtypes.BaseAccount{}}, + pulsar: &vestingapi.BaseVestingAccount{BaseAccount: &authapi.BaseAccount{}}, }, "vesting/base_account_pubkey": { - gogo: &vestingtypes.BaseVestingAccount{ - BaseAccount: &authtypes.BaseAccount{PubKey: pubkeyAny}, - }, + gogo: &vestingtypes.BaseVestingAccount{BaseAccount: &authtypes.BaseAccount{PubKey: pubkeyAny}}, + pulsar: &vestingapi.BaseVestingAccount{BaseAccount: &authapi.BaseAccount{PubKey: pubkeyAnyPulsar}}, }, "math/int_as_string": { - gogo: &gogo_testpb.IntAsString{IntAsString: math.NewInt(123)}, + gogo: &gogo_testpb.IntAsString{IntAsString: math.NewInt(123)}, + pulsar: &pulsar_testpb.IntAsString{IntAsString: "123"}, }, "math/int_as_string/empty": { - gogo: &gogo_testpb.IntAsString{}, + gogo: &gogo_testpb.IntAsString{}, + pulsar: &pulsar_testpb.IntAsString{}, }, "math/int_as_bytes": { - gogo: &gogo_testpb.IntAsBytes{IntAsBytes: math.NewInt(123)}, + gogo: &gogo_testpb.IntAsBytes{IntAsBytes: math.NewInt(123)}, + pulsar: &pulsar_testpb.IntAsBytes{IntAsBytes: int123bz}, }, "math/int_as_bytes/empty": { - gogo: &gogo_testpb.IntAsBytes{}, + gogo: &gogo_testpb.IntAsBytes{}, + pulsar: &pulsar_testpb.IntAsBytes{}, }, } for name, tc := range cases { t.Run(name, func(t *testing.T) { - legacyBytes := fixture.MarshalLegacyAminoJSON(t, tc.gogo) - dynamicBytes, err := aj.Marshal(fixture.DynamicMessage(t, tc.gogo)) + gogoBytes, err := encCfg.Amino.MarshalJSON(tc.gogo) + require.NoError(t, err) + + pulsarBytes, err := aj.Marshal(tc.pulsar) + if tc.pulsarMarshalFails { + require.Error(t, err) + return + } + require.NoError(t, err) + + fmt.Printf("pulsar: %s\n", string(pulsarBytes)) + fmt.Printf(" gogo: %s\n", string(gogoBytes)) + require.Equal(t, string(gogoBytes), string(pulsarBytes)) + + pulsarProtoBytes, err := proto.Marshal(tc.pulsar) + require.NoError(t, err) + + gogoType := reflect.TypeOf(tc.gogo).Elem() + newGogo := reflect.New(gogoType).Interface().(gogoproto.Message) + + err = encCfg.Codec.Unmarshal(pulsarProtoBytes, newGogo) + if tc.protoUnmarshalFails { + require.Error(t, err) + return + } require.NoError(t, err) - t.Logf("legacy: %s\n", string(legacyBytes)) - t.Logf(" sut: %s\n", string(dynamicBytes)) - if tc.fails { - require.NotEqual(t, string(legacyBytes), string(dynamicBytes)) + newGogoBytes, err := encCfg.Amino.MarshalJSON(newGogo) + require.NoError(t, err) + if tc.roundTripUnequal { + require.NotEqual(t, string(gogoBytes), string(newGogoBytes)) return } - require.Equal(t, string(legacyBytes), string(dynamicBytes)) + require.Equal(t, string(gogoBytes), string(newGogoBytes)) // test amino json signer handler equivalence - if !proto.HasExtension(fixture.MessageDescriptor(t, tc.gogo).Options(), msgv1.E_Signer) { + msg, ok := tc.gogo.(legacytx.LegacyMsg) + if !ok { // not signable return } - fixture.RequireLegacyAminoEquivalent(t, tc.gogo) + + handlerOptions := signing_testutil.HandlerArgumentOptions{ + ChainID: "test-chain", + Memo: "sometestmemo", + Msg: tc.pulsar, + AccNum: 1, + AccSeq: 2, + SignerAddress: "signerAddress", + Fee: &txv1beta1.Fee{ + Amount: []*v1beta1.Coin{{Denom: "uatom", Amount: "1000"}}, + }, + } + + signerData, txData, err := signing_testutil.MakeHandlerArguments(handlerOptions) + require.NoError(t, err) + + handler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) + signBz, err := handler.GetSignBytes(context.Background(), signerData, txData) + require.NoError(t, err) + + legacyHandler := tx.NewSignModeLegacyAminoJSONHandler() + txBuilder := encCfg.TxConfig.NewTxBuilder() + require.NoError(t, txBuilder.SetMsgs([]types.Msg{msg}...)) + txBuilder.SetMemo(handlerOptions.Memo) + txBuilder.SetFeeAmount(types.Coins{types.NewInt64Coin("uatom", 1000)}) + theTx := txBuilder.GetTx() + + legacySigningData := signing.SignerData{ + ChainID: handlerOptions.ChainID, + Address: handlerOptions.SignerAddress, + AccountNumber: handlerOptions.AccNum, + Sequence: handlerOptions.AccSeq, + } + legacySignBz, err := legacyHandler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + legacySigningData, theTx) + require.NoError(t, err) + require.Equal(t, string(legacySignBz), string(signBz)) }) } } func TestSendAuthorization(t *testing.T) { -<<<<<<< HEAD encCfg := testutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, authzmodule.AppModuleBasic{}, distribution.AppModuleBasic{}, bank.AppModuleBasic{}) -======= - encCfg := testutil.MakeTestEncodingConfig( - codectestutil.CodecOptions{}, - auth.AppModule{}, - authzmodule.AppModule{}, - distribution.AppModule{}, - bank.AppModule{}, - ) ->>>>>>> 2d40cc1ab (fix(x/tx): fix amino json drift from legacy spec (#21825)) aj := aminojson.NewEncoder(aminojson.EncoderOptions{}) diff --git a/tests/integration/tx/context_test.go b/tests/integration/tx/context_test.go index e2814de77c69..2210c9c934fd 100644 --- a/tests/integration/tx/context_test.go +++ b/tests/integration/tx/context_test.go @@ -3,19 +3,29 @@ package tx import ( "testing" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "cosmossdk.io/depinject" "cosmossdk.io/log" "cosmossdk.io/x/tx/signing" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal" "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/pulsar/testpb" "github.com/cosmos/cosmos-sdk/testutil/configurator" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - "github.com/stretchr/testify/require" ) -func ProvideCustomGetSigner() signing.CustomGetSigner { - return internal.TestRepeatedFieldsSigner +func ProvideCustomGetSigners() signing.CustomGetSigner { + return signing.CustomGetSigner{ + MsgType: proto.MessageName(&testpb.TestRepeatedFields{}), + Fn: func(msg proto.Message) ([][]byte, error) { + testMsg := msg.(*testpb.TestRepeatedFields) + // arbitrary logic + signer := testMsg.NullableDontOmitempty[1].Value + return [][]byte{[]byte(signer)}, nil + }, + } } func TestDefineCustomGetSigners(t *testing.T) { @@ -30,7 +40,7 @@ func TestDefineCustomGetSigners(t *testing.T) { configurator.ConsensusModule(), ), depinject.Supply(log.NewNopLogger()), - depinject.Provide(ProvideCustomGetSigner), + depinject.Provide(ProvideCustomGetSigners), ), &interfaceRegistry, ) diff --git a/tests/integration/tx/internal/util.go b/tests/integration/tx/internal/util.go deleted file mode 100644 index e3f6a5828997..000000000000 --- a/tests/integration/tx/internal/util.go +++ /dev/null @@ -1,221 +0,0 @@ -package internal - -import ( - "bytes" - "context" - "encoding/json" - "testing" - - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/dynamicpb" - - "cosmossdk.io/core/transaction" - "cosmossdk.io/x/tx/signing" - "cosmossdk.io/x/tx/signing/aminojson" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/std" - "github.com/cosmos/cosmos-sdk/tests/integration/tx/internal/pulsar/testpb" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" - "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" - authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/x/auth/tx" - gogoproto "github.com/cosmos/gogoproto/proto" -) - -var TestRepeatedFieldsSigner = signing.CustomGetSigner{ - MsgType: proto.MessageName(&testpb.TestRepeatedFields{}), - Fn: func(msg proto.Message) ([][]byte, error) { - testMsg := msg.(*testpb.TestRepeatedFields) - // arbitrary logic - signer := testMsg.NullableDontOmitempty[1].Value - return [][]byte{[]byte(signer)}, nil - }, -} - -type noOpAddressCodec struct{} - -func (a noOpAddressCodec) StringToBytes(text string) ([]byte, error) { - return []byte(text), nil -} - -func (a noOpAddressCodec) BytesToString(bz []byte) (string, error) { - return string(bz), nil -} - -type SigningFixture struct { - txConfig client.TxConfig - legacy *codec.LegacyAmino - protoCodec *codec.ProtoCodec - options SigningFixtureOptions - registry codectypes.InterfaceRegistry -} - -type SigningFixtureOptions struct { - DoNotSortFields bool -} - -func NewSigningFixture( - t *testing.T, - options SigningFixtureOptions, - modules ...module.AppModule, -) *SigningFixture { - t.Helper() - // set up transaction and signing infra - addressCodec, valAddressCodec := noOpAddressCodec{}, noOpAddressCodec{} - customGetSigners := []signing.CustomGetSigner{TestRepeatedFieldsSigner} - interfaceRegistry, _, err := codec.ProvideInterfaceRegistry( - addressCodec, - valAddressCodec, - customGetSigners, - ) - require.NoError(t, err) - protoCodec := codec.ProvideProtoCodec(interfaceRegistry) - signingOptions := &signing.Options{ - FileResolver: interfaceRegistry, - AddressCodec: addressCodec, - ValidatorAddressCodec: valAddressCodec, - } - for _, customGetSigner := range customGetSigners { - signingOptions.DefineCustomGetSigners(customGetSigner.MsgType, customGetSigner.Fn) - } - txConfig, err := tx.NewTxConfigWithOptions( - protoCodec, - tx.ConfigOptions{ - EnabledSignModes: []signingtypes.SignMode{ - signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, - }, - SigningOptions: signingOptions, - }) - require.NoError(t, err) - - legacyAminoCodec := codec.NewLegacyAmino() - mb := module.NewManager(modules...) - std.RegisterLegacyAminoCodec(legacyAminoCodec) - std.RegisterInterfaces(interfaceRegistry) - mb.RegisterLegacyAminoCodec(legacyAminoCodec) - mb.RegisterInterfaces(interfaceRegistry) - - return &SigningFixture{ - txConfig: txConfig, - legacy: legacyAminoCodec, - options: options, - protoCodec: protoCodec, - registry: interfaceRegistry, - } -} - -func (s *SigningFixture) RequireLegacyAminoEquivalent(t *testing.T, msg transaction.Msg) { - t.Helper() - // create tx envelope - txBuilder := s.txConfig.NewTxBuilder() - err := txBuilder.SetMsgs([]types.Msg{msg}...) - require.NoError(t, err) - builtTx := txBuilder.GetTx() - - // round trip it to simulate application usage - txBz, err := s.txConfig.TxEncoder()(builtTx) - require.NoError(t, err) - theTx, err := s.txConfig.TxDecoder()(txBz) - require.NoError(t, err) - - // create signing envelope - signerData := signing.SignerData{ - Address: "sender-address", - ChainID: "test-chain", - AccountNumber: 0, - Sequence: 0, - } - adaptableTx, ok := theTx.(authsigning.V2AdaptableTx) - require.True(t, ok) - - legacytx.RegressionTestingAminoCodec = s.legacy - defer func() { - legacytx.RegressionTestingAminoCodec = nil - }() - legacyAminoSignHandler := tx.NewSignModeLegacyAminoJSONHandler() - legacyBz, err := legacyAminoSignHandler.GetSignBytes( - signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, - authsigning.SignerData{ - ChainID: signerData.ChainID, - Address: signerData.Address, - AccountNumber: signerData.AccountNumber, - Sequence: signerData.Sequence, - }, - theTx) - require.NoError(t, err) - - handler := aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{}) - signBz, err := handler.GetSignBytes( - context.Background(), - signerData, - adaptableTx.GetSigningTxData(), - ) - require.NoError(t, err) - - require.Truef(t, - bytes.Equal(legacyBz, signBz), - "legacy: %s\n x/tx: %s", string(legacyBz), string(signBz)) -} - -func (s *SigningFixture) MarshalLegacyAminoJSON(t *testing.T, o any) []byte { - t.Helper() - bz, err := s.legacy.MarshalJSON(o) - require.NoError(t, err) - if s.options.DoNotSortFields { - return bz - } - sortedBz, err := sortJson(bz) - require.NoError(t, err) - return sortedBz -} - -func (s *SigningFixture) UnmarshalGogoProto(bz []byte, ptr transaction.Msg) error { - return s.protoCodec.Unmarshal(bz, ptr) -} - -func (s *SigningFixture) MessageDescriptor(t *testing.T, msg transaction.Msg) protoreflect.MessageDescriptor { - t.Helper() - typeName := gogoproto.MessageName(msg) - msgDesc, err := s.registry.FindDescriptorByName(protoreflect.FullName(typeName)) - require.NoError(t, err) - return msgDesc.(protoreflect.MessageDescriptor) -} - -// DynamicMessage is identical to the Decoder implementation in -// https://github.com/cosmos/cosmos-sdk/blob/6d2f6ff068c81c5783e01319beaa51c7dbb43edd/x/tx/decode/decode.go#L136 -// It is duplicated here to test dynamic message implementations specifically. -// The code path linked above is also covered in this package. -func (s *SigningFixture) DynamicMessage(t *testing.T, msg transaction.Msg) proto.Message { - t.Helper() - msgDesc := s.MessageDescriptor(t, msg) - protoBz, err := gogoproto.Marshal(msg) - require.NoError(t, err) - dynamicMsg := dynamicpb.NewMessageType(msgDesc).New().Interface() - err = proto.Unmarshal(protoBz, dynamicMsg) - require.NoError(t, err) - return dynamicMsg -} - -// sortJson sorts the JSON bytes by way of the side effect of unmarshalling and remarshalling -// the JSON using encoding/json. This hacky way of sorting JSON fields was used by the legacy -// amino JSON encoding x/auth/migrations/legacytx.StdSignBytes. It is used here ensure the x/tx -// JSON encoding is equivalent to the legacy amino JSON encoding. -func sortJson(bz []byte) ([]byte, error) { - var c any - err := json.Unmarshal(bz, &c) - if err != nil { - return nil, err - } - js, err := json.Marshal(c) - if err != nil { - return nil, err - } - return js, nil -} diff --git a/x/tx/CHANGELOG.md b/x/tx/CHANGELOG.md index 12d1b368e861..1d2d3f502622 100644 --- a/x/tx/CHANGELOG.md +++ b/x/tx/CHANGELOG.md @@ -33,12 +33,12 @@ Since v0.13.0, x/tx follows Cosmos SDK semver: https://github.com/cosmos/cosmos- ## [Unreleased] -<<<<<<< HEAD -======= +## [v0.13.6](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.6) - 2024-10-XX + +### Bug Fixes + * [#21825](https://github.com/cosmos/cosmos-sdk/pull/21825) Fix decimal encoding and field ordering in Amino JSON encoder. -* [#21850](https://github.com/cosmos/cosmos-sdk/pull/21850) Support bytes field as signer. ->>>>>>> 2d40cc1ab (fix(x/tx): fix amino json drift from legacy spec (#21825)) ## [v0.13.5](https://github.com/cosmos/cosmos-sdk/releases/tag/x/tx/v0.13.5) - 2024-09-18 ### Improvements