From 57bedb100648195aae479ce1c023b9e61d6b68c0 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Tue, 24 Jan 2023 11:17:04 +0100 Subject: [PATCH] feat(textual): Add client-side infra (#14661) Co-authored-by: Jeancarlo Barrios --- CHANGELOG.md | 1 + client/cmd.go | 11 ++- client/flags/flags.go | 4 + client/tx/factory.go | 2 + client/tx/tx.go | 4 +- client/v2/go.mod | 2 +- client/v2/go.sum | 6 +- crypto/keyring/keyring.go | 31 ++++--- crypto/keyring/keyring_ledger_test.go | 7 +- crypto/keyring/keyring_test.go | 27 +++--- crypto/ledger/ledger_mock.go | 2 +- crypto/ledger/ledger_secp256k1.go | 30 +++++-- crypto/types/types.go | 11 +++ go.mod | 2 +- go.sum | 4 +- scripts/mockgen.sh | 1 + simapp/go.mod | 4 +- simapp/go.sum | 6 +- simapp/simd/cmd/root.go | 20 ++++- tests/go.mod | 6 +- tests/go.sum | 6 +- tools/confix/go.sum | 2 - tools/cosmovisor/go.sum | 2 - tools/rosetta/go.sum | 2 - x/auth/ante/ante_test.go | 10 +-- x/auth/ante/basic_test.go | 12 +-- x/auth/ante/fee_test.go | 7 +- x/auth/ante/setup_test.go | 5 +- x/auth/ante/sigverify_test.go | 88 ++++++++++++------- x/auth/ante/testutil_test.go | 34 ++++++-- x/auth/tx/config/config.go | 55 +----------- x/auth/tx/config/textual.go | 91 ++++++++++++++++++++ x/auth/tx/testutil/expected_keepers_mocks.go | 51 +++++++++++ x/auth/tx/testutil/suite.go | 2 +- x/evidence/go.mod | 2 +- x/evidence/go.sum | 4 +- x/nft/go.mod | 6 +- x/nft/go.sum | 10 +-- x/tx/go.sum | 2 - 39 files changed, 381 insertions(+), 191 deletions(-) create mode 100644 x/auth/tx/config/textual.go create mode 100644 x/auth/tx/testutil/expected_keepers_mocks.go diff --git a/CHANGELOG.md b/CHANGELOG.md index f87abc9225..74ed0ac82b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -165,6 +165,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* (crypto/keyring) [#13734](https://github.com/cosmos/cosmos-sdk/pull/13834) The keyring's `Sign` method now takes a new `signMode` argument. It is only used if the signing key is a Ledger hardware device. You can set it to 0 in all other cases. * (x/evidence) [14724](https://github.com/cosmos/cosmos-sdk/pull/14724) Extract Evidence in its own go.mod and rename the package to `cosmossdk.io/x/evidence`. * (x/nft) [#14725](https://github.com/cosmos/cosmos-sdk/pull/14725) Extract NFT in its own go.mod and rename the package to `cosmossdk.io/x/nft`. * (tx) [#14634](https://github.com/cosmos/cosmos-sdk/pull/14634) Move the `tx` go module to `x/tx`. diff --git a/client/cmd.go b/client/cmd.go index 8ff09a8f13..c755f57d35 100644 --- a/client/cmd.go +++ b/client/cmd.go @@ -281,10 +281,19 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err clientCtx = clientCtx.WithFrom(from).WithFromAddress(fromAddr).WithFromName(fromName) + // TODO Remove this once SIGN_MODE_TEXTUAL is released + // ref: https://github.com/cosmos/cosmos-sdk/issues/11970 + if keyType == keyring.TypeLedger && clientCtx.SignModeStr == flags.SignModeTextual { + return clientCtx, fmt.Errorf("SIGN_MODE_TEXTUAL is currently not supported, please follow https://github.com/cosmos/cosmos-sdk/issues/11970") + } + // If the `from` signer account is a ledger key, we need to use // SIGN_MODE_AMINO_JSON, because ledger doesn't support proto yet. // ref: https://github.com/cosmos/cosmos-sdk/issues/8109 - if keyType == keyring.TypeLedger && clientCtx.SignModeStr != flags.SignModeLegacyAminoJSON && !clientCtx.LedgerHasProtobuf { + if keyType == keyring.TypeLedger && + clientCtx.SignModeStr != flags.SignModeLegacyAminoJSON && + clientCtx.SignModeStr != flags.SignModeTextual && + !clientCtx.LedgerHasProtobuf { fmt.Println("Default sign-mode 'direct' not supported by Ledger, using sign-mode 'amino-json'.") clientCtx = clientCtx.WithSignModeStr(flags.SignModeLegacyAminoJSON) } diff --git a/client/flags/flags.go b/client/flags/flags.go index 4faae4ef87..18160c6589 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -35,6 +35,10 @@ const ( SignModeLegacyAminoJSON = "amino-json" // SignModeDirectAux is the value of the --sign-mode flag for SIGN_MODE_DIRECT_AUX SignModeDirectAux = "direct-aux" + // SignModeTextual is the value of the --sign-mode flag for SIGN_MODE_TEXTUAL. + // Choosing this flag will result in an error for now, as Textual should be + // used only for TESTING purposes for now. + SignModeTextual = "textual" // SignModeEIP191 is the value of the --sign-mode flag for SIGN_MODE_EIP_191 SignModeEIP191 = "eip-191" ) diff --git a/client/tx/factory.go b/client/tx/factory.go index 3d174c0e89..cb2a7b0e27 100644 --- a/client/tx/factory.go +++ b/client/tx/factory.go @@ -58,6 +58,8 @@ func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) Factory { signMode = signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON case flags.SignModeDirectAux: signMode = signing.SignMode_SIGN_MODE_DIRECT_AUX + case flags.SignModeTextual: + signMode = signing.SignMode_SIGN_MODE_TEXTUAL case flags.SignModeEIP191: signMode = signing.SignMode_SIGN_MODE_EIP_191 } diff --git a/client/tx/tx.go b/client/tx/tx.go index ca748fac6d..420119cc7b 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -309,7 +309,7 @@ func Sign(ctx context.Context, txf Factory, name string, txBuilder client.TxBuil } // Sign those bytes - sigBytes, _, err := txf.keybase.Sign(name, bytesToSign) + sigBytes, _, err := txf.keybase.Sign(name, bytesToSign, signMode) if err != nil { return err } @@ -409,7 +409,7 @@ func makeAuxSignerData(clientCtx client.Context, f Factory, msgs ...sdk.Msg) (tx return tx.AuxSignerData{}, err } - sig, _, err := clientCtx.Keyring.Sign(name, signBz) + sig, _, err := clientCtx.Keyring.Sign(name, signBz, f.signMode) if err != nil { return tx.AuxSignerData{}, err } diff --git a/client/v2/go.mod b/client/v2/go.mod index b18d80a15c..1afe3c4f31 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -37,7 +37,7 @@ require ( github.com/cosmos/gogoproto v1.4.3 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.19.4 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect diff --git a/client/v2/go.sum b/client/v2/go.sum index 2c6fe6598c..1b28bb8c82 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -37,8 +37,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= -cosmossdk.io/core v0.4.1 h1:5icpjPmw8J4uFp6w8OoLJPxsw6X3kRi9nAtTr3qp2Ok= -cosmossdk.io/core v0.4.1/go.mod h1:Zqd1GB+krTF3bzhTnPNwzy3NTtXu+MKLX/9sPQXTIDE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= @@ -143,8 +141,8 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4 github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok= github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= +github.com/cosmos/ledger-cosmos-go v0.13.0 h1:ex0CvCxToSR7j5WjrghPu2Bu9sSXKikjnVvUryNnx4s= +github.com/cosmos/ledger-cosmos-go v0.13.0/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM= diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index e3407dfcb4..3f6c5cdf05 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -23,6 +23,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/go-bip39" ) @@ -103,10 +104,10 @@ type Keyring interface { // Signer is implemented by key stores that want to provide signing capabilities. type Signer interface { // Sign sign byte messages with a user key. - Sign(uid string, msg []byte) ([]byte, types.PubKey, error) + Sign(uid string, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error) // SignByAddress sign byte messages with a user key providing the address. - SignByAddress(address sdk.Address, msg []byte) ([]byte, types.PubKey, error) + SignByAddress(address sdk.Address, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error) } // Importer is implemented by key stores that support import of public and private keys. @@ -356,7 +357,7 @@ func (ks keystore) ImportPubKey(uid string, armor string) error { return nil } -func (ks keystore) Sign(uid string, msg []byte) ([]byte, types.PubKey, error) { +func (ks keystore) Sign(uid string, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error) { k, err := ks.Key(uid) if err != nil { return nil, nil, err @@ -377,7 +378,7 @@ func (ks keystore) Sign(uid string, msg []byte) ([]byte, types.PubKey, error) { return sig, priv.PubKey(), nil case k.GetLedger() != nil: - return SignWithLedger(k, msg) + return SignWithLedger(k, msg, signMode) // multi or offline record default: @@ -390,13 +391,13 @@ func (ks keystore) Sign(uid string, msg []byte) ([]byte, types.PubKey, error) { } } -func (ks keystore) SignByAddress(address sdk.Address, msg []byte) ([]byte, types.PubKey, error) { +func (ks keystore) SignByAddress(address sdk.Address, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error) { k, err := ks.KeyByAddress(address) if err != nil { return nil, nil, err } - return ks.Sign(k.Name, msg) + return ks.Sign(k.Name, msg, signMode) } func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (*Record, error) { @@ -598,7 +599,7 @@ func (ks keystore) SupportedAlgorithms() (SigningAlgoList, SigningAlgoList) { // SignWithLedger signs a binary message with the ledger device referenced by an Info object // and returns the signed bytes and the public key. It returns an error if the device could // not be queried or it returned an error. -func SignWithLedger(k *Record, msg []byte) (sig []byte, pub types.PubKey, err error) { +func SignWithLedger(k *Record, msg []byte, signMode signing.SignMode) (sig []byte, pub types.PubKey, err error) { ledgerInfo := k.GetLedger() if ledgerInfo == nil { return nil, nil, errors.New("not a ledger object") @@ -611,9 +612,19 @@ func SignWithLedger(k *Record, msg []byte) (sig []byte, pub types.PubKey, err er return } - sig, err = priv.Sign(msg) - if err != nil { - return nil, nil, err + switch signMode { + case signing.SignMode_SIGN_MODE_TEXTUAL: + sig, err = priv.Sign(msg) + if err != nil { + return nil, nil, err + } + case signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON: + sig, err = priv.SignLedgerAminoJSON(msg) + if err != nil { + return nil, nil, err + } + default: + return nil, nil, fmt.Errorf("got invalid sign mode %d, expected LEGACY_AMINO_JSON or TEXTUAL", signMode) } if !priv.PubKey().VerifySignature(msg, sig) { diff --git a/crypto/keyring/keyring_ledger_test.go b/crypto/keyring/keyring_ledger_test.go index 6845b60882..abd0fbe93a 100644 --- a/crypto/keyring/keyring_ledger_test.go +++ b/crypto/keyring/keyring_ledger_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" ) func TestInMemoryCreateLedger(t *testing.T) { @@ -66,10 +67,10 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.Equal(t, "key", k.Name) d1 := []byte("my first message") - s1, pub1, err := kb.Sign("key", d1) + s1, pub1, err := kb.Sign("key", d1, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.NoError(t, err) - s2, pub2, err := SignWithLedger(k, d1) + s2, pub2, err := SignWithLedger(k, d1, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.NoError(t, err) require.True(t, pub1.Equals(pub2)) @@ -86,7 +87,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { k, _, err = kb.NewMnemonic("test", English, types.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) - _, _, err = SignWithLedger(k, d1) + _, _, err = SignWithLedger(k, d1, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Error(t, err) require.Equal(t, "not a ledger object", err.Error()) } diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index e73964610f..f4af9d6126 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -22,6 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" ) const ( @@ -191,7 +192,7 @@ func TestSignVerifyKeyRing(t *testing.T) { d3 := []byte("feels like I forgot something...") // try signing both data with both .. - s11, pub1, err := kb.Sign(n1, d1) + s11, pub1, err := kb.Sign(n1, d1, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.NoError(t, err) key1, err := kr1.GetPubKey() @@ -199,11 +200,11 @@ func TestSignVerifyKeyRing(t *testing.T) { require.NotNil(t, key1) require.Equal(t, key1, pub1) - s12, pub1, err := kb.Sign(n1, d2) + s12, pub1, err := kb.Sign(n1, d2, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Nil(t, err) require.Equal(t, key1, pub1) - s21, pub2, err := kb.Sign(n2, d1) + s21, pub2, err := kb.Sign(n2, d1, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Nil(t, err) key2, err := kr2.GetPubKey() @@ -211,7 +212,7 @@ func TestSignVerifyKeyRing(t *testing.T) { require.NotNil(t, key2) require.Equal(t, key2, pub2) - s22, pub2, err := kb.Sign(n2, d2) + s22, pub2, err := kb.Sign(n2, d2, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Nil(t, err) require.Equal(t, key2, pub2) @@ -250,7 +251,7 @@ func TestSignVerifyKeyRing(t *testing.T) { require.NoError(t, err) require.Equal(t, i3.Name, n3) - _, _, err = kb.Sign(n3, d3) + _, _, err = kb.Sign(n3, d3, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Error(t, err) require.Equal(t, "cannot sign with offline keys", err.Error()) } @@ -642,23 +643,23 @@ func TestInMemorySignVerify(t *testing.T) { d3 := []byte("feels like I forgot something...") // try signing both data with both .. - s11, pub1, err := cstore.Sign(n1, d1) + s11, pub1, err := cstore.Sign(n1, d1, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Nil(t, err) key1, err := kr1.GetPubKey() require.NoError(t, err) require.Equal(t, key1, pub1) - s12, pub1, err := cstore.Sign(n1, d2) + s12, pub1, err := cstore.Sign(n1, d2, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Nil(t, err) require.Equal(t, key1, pub1) - s21, pub2, err := cstore.Sign(n2, d1) + s21, pub2, err := cstore.Sign(n2, d1, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Nil(t, err) key2, err := kr2.GetPubKey() require.NoError(t, err) require.Equal(t, key2, pub2) - s22, pub2, err := cstore.Sign(n2, d2) + s22, pub2, err := cstore.Sign(n2, d2, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Nil(t, err) require.Equal(t, key2, pub2) @@ -698,7 +699,7 @@ func TestInMemorySignVerify(t *testing.T) { require.Equal(t, i3.Name, n3) // Now try to sign data with a secret-less key - _, _, err = cstore.Sign(n3, d3) + _, _, err = cstore.Sign(n3, d3, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.Error(t, err) require.Equal(t, "cannot sign with offline keys", err.Error()) } @@ -933,7 +934,7 @@ func ExampleNew() { // We need to use passphrase to generate a signature tx := []byte("deadbeef") - sig, pub, err := cstore.Sign("Bob", tx) + sig, pub, err := cstore.Sign("Bob", tx, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) if err != nil { fmt.Println("don't accept real passphrase") } @@ -1204,7 +1205,7 @@ func TestAltKeyring_Sign(t *testing.T) { msg := []byte("some message") - sign, key, err := kr.Sign(uid, msg) + sign, key, err := kr.Sign(uid, msg, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.NoError(t, err) require.True(t, key.VerifySignature(msg, sign)) @@ -1223,7 +1224,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { addr, err := mnemonic.GetAddress() require.NoError(t, err) - sign, key, err := kr.SignByAddress(addr, msg) + sign, key, err := kr.SignByAddress(addr, msg, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.NoError(t, err) require.True(t, key.VerifySignature(msg, sign)) diff --git a/crypto/ledger/ledger_mock.go b/crypto/ledger/ledger_mock.go index 9d9ff9f0c6..b01b4ea4e5 100644 --- a/crypto/ledger/ledger_mock.go +++ b/crypto/ledger/ledger_mock.go @@ -86,7 +86,7 @@ func (mock LedgerSECP256K1Mock) GetAddressPubKeySECP256K1(derivationPath []uint3 return pk, addr, err } -func (mock LedgerSECP256K1Mock) SignSECP256K1(derivationPath []uint32, message []byte) ([]byte, error) { +func (mock LedgerSECP256K1Mock) SignSECP256K1(derivationPath []uint32, message []byte, p2 byte) ([]byte, error) { path := hd.NewParams(derivationPath[0], derivationPath[1], derivationPath[2], derivationPath[3] != 0, derivationPath[4]) seed, err := bip39.NewSeedWithErrorChecking(testdata.TestMnemonic, "") if err != nil { diff --git a/crypto/ledger/ledger_secp256k1.go b/crypto/ledger/ledger_secp256k1.go index 2aa996df9d..c3d390ed88 100644 --- a/crypto/ledger/ledger_secp256k1.go +++ b/crypto/ledger/ledger_secp256k1.go @@ -35,7 +35,10 @@ type ( // Returns a compressed pubkey and bech32 address (requires user confirmation) GetAddressPubKeySECP256K1([]uint32, string) ([]byte, string, error) // Signs a message (requires user confirmation) - SignSECP256K1([]uint32, []byte) ([]byte, error) + // The last byte denotes the SIGN_MODE to be used by Ledger: 0 for + // LEGACY_AMINO_JSON, 1 for TEXTUAL. It corresponds to the P2 value + // in https://github.com/cosmos/ledger-cosmos/blob/main/docs/APDUSPEC.md + SignSECP256K1([]uint32, []byte, byte) ([]byte, error) } // Options hosts customization options to account for differences in Ledger @@ -92,7 +95,7 @@ func SetSkipDERConversion() { // This function is marked as unsafe as it will retrieve a pubkey without user verification. // It can only be used to verify a pubkey but never to create new accounts/keys. In that case, // please refer to NewPrivKeySecp256k1 -func NewPrivKeySecp256k1Unsafe(path hd.BIP44Params) (types.LedgerPrivKey, error) { +func NewPrivKeySecp256k1Unsafe(path hd.BIP44Params) (types.LedgerPrivKeyAminoJSON, error) { device, err := getDevice() if err != nil { return nil, err @@ -129,7 +132,8 @@ func (pkl PrivKeyLedgerSecp256k1) PubKey() types.PubKey { return pkl.CachedPubKey } -// Sign returns a secp256k1 signature for the corresponding message +// Sign returns a secp256k1 signature for the corresponding message using +// SIGN_MODE_TEXTUAL. func (pkl PrivKeyLedgerSecp256k1) Sign(message []byte) ([]byte, error) { device, err := getDevice() if err != nil { @@ -137,7 +141,19 @@ func (pkl PrivKeyLedgerSecp256k1) Sign(message []byte) ([]byte, error) { } defer warnIfErrors(device.Close) - return sign(device, pkl, message) + return sign(device, pkl, message, 1) +} + +// SignLedgerAminoJSON returns a secp256k1 signature for the corresponding message using +// SIGN_MODE_LEGACY_AMINO_JSON. +func (pkl PrivKeyLedgerSecp256k1) SignLedgerAminoJSON(message []byte) ([]byte, error) { + device, err := getDevice() + if err != nil { + return nil, err + } + defer warnIfErrors(device.Close) + + return sign(device, pkl, message, 0) } // ShowAddress triggers a ledger device to show the corresponding address. @@ -269,13 +285,15 @@ func validateKey(device SECP256K1, pkl PrivKeyLedgerSecp256k1) error { // Communication is checked on NewPrivKeyLedger and PrivKeyFromBytes, returning // an error, so this should only trigger if the private key is held in memory // for a while before use. -func sign(device SECP256K1, pkl PrivKeyLedgerSecp256k1, msg []byte) ([]byte, error) { +// +// Last byte P2 is 0 for LEGACY_AMINO_JSON, and 1 for TEXTUAL. +func sign(device SECP256K1, pkl PrivKeyLedgerSecp256k1, msg []byte, p2 byte) ([]byte, error) { err := validateKey(device, pkl) if err != nil { return nil, err } - sig, err := device.SignSECP256K1(pkl.Path.DerivationPath(), msg) + sig, err := device.SignSECP256K1(pkl.Path.DerivationPath(), msg, p2) if err != nil { return nil, err } diff --git a/crypto/types/types.go b/crypto/types/types.go index 0f86a59208..5fafe5a2cb 100644 --- a/crypto/types/types.go +++ b/crypto/types/types.go @@ -29,6 +29,17 @@ type LedgerPrivKey interface { Type() string } +// LedgerPrivKeyAminoJSON is a Ledger PrivKey type that supports signing with +// SIGN_MODE_LEGACY_AMINO_JSON. It is added as a non-breaking change, instead of directly +// on the LedgerPrivKey interface (whose Sign method will sign with TEXTUAL), +// and will be deprecated/removed once LEGACY_AMINO_JSON is removed. +type LedgerPrivKeyAminoJSON interface { + LedgerPrivKey + // SignLedgerAminoJSON signs a messages on the Ledger device using + // SIGN_MODE_LEGACY_AMINO_JSON. + SignLedgerAminoJSON(msg []byte) ([]byte, error) +} + // PrivKey defines a private key and extends proto.Message. For now, it extends // LedgerPrivKey (see godoc for LedgerPrivKey). Ultimately, we should remove // LedgerPrivKey and add its methods here directly. diff --git a/go.mod b/go.mod index 2fbd19fc68..4d4c642a96 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/cosmos/gogogateway v1.2.0 github.com/cosmos/gogoproto v1.4.3 github.com/cosmos/iavl v0.20.0-alpha1 - github.com/cosmos/ledger-cosmos-go v0.12.2 + github.com/cosmos/ledger-cosmos-go v0.13.0 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 github.com/google/gofuzz v1.2.0 diff --git a/go.sum b/go.sum index 7d4fd70469..18bb1776e4 100644 --- a/go.sum +++ b/go.sum @@ -215,8 +215,8 @@ github.com/cosmos/iavl v0.20.0-alpha1 h1:tP+Qv4MdnLVmrrhIAGpLRQOOhFGgci0hpJ4VI3x github.com/cosmos/iavl v0.20.0-alpha1/go.mod h1:25YJYzilTErJ2mKfNB3xyWL9IsCwEQdNzdIutg2mh3U= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= +github.com/cosmos/ledger-cosmos-go v0.13.0 h1:ex0CvCxToSR7j5WjrghPu2Bu9sSXKikjnVvUryNnx4s= +github.com/cosmos/ledger-cosmos-go v0.13.0/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= diff --git a/scripts/mockgen.sh b/scripts/mockgen.sh index 41e1db7b70..fe7458ea09 100755 --- a/scripts/mockgen.sh +++ b/scripts/mockgen.sh @@ -14,6 +14,7 @@ $mockgen_cmd -source=x/feegrant/expected_keepers.go -package testutil -destinati $mockgen_cmd -source=x/mint/types/expected_keepers.go -package testutil -destination x/mint/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/params/proposal_handler_test.go -package testutil -destination x/params/testutil/staking_keeper_mock.go $mockgen_cmd -source=x/crisis/types/expected_keepers.go -package testutil -destination x/crisis/testutil/expected_keepers_mocks.go +$mockgen_cmd -source=x/auth/tx/config/expected_keepers.go -package testutil -destination x/auth/tx/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/types/expected_keepers.go -package testutil -destination x/auth/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/auth/ante/expected_keepers.go -package testutil -destination x/auth/ante/testutil/expected_keepers_mocks.go $mockgen_cmd -source=x/authz/expected_keepers.go -package testutil -destination x/authz/testutil/expected_keepers_mocks.go diff --git a/simapp/go.mod b/simapp/go.mod index 12a594869d..0b2bb1fe1b 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -63,7 +63,7 @@ require ( github.com/cosmos/gogoproto v1.4.3 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.20.0-alpha1 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.0 // indirect github.com/cosmos/rosetta-sdk-go v0.9.0 // indirect github.com/creachadair/atomicfile v0.2.7 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect @@ -184,6 +184,7 @@ require ( ) replace ( + cosmossdk.io/collections => ../collections cosmossdk.io/x/evidence => ../x/evidence // TODO tag all extracted modules after SDK refactor cosmossdk.io/x/nft => ../x/nft @@ -191,7 +192,6 @@ replace ( github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 // Simapp always use the latest version of the cosmos-sdk github.com/cosmos/cosmos-sdk => ../. - cosmossdk.io/collections => ../collections // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.8.1 diff --git a/simapp/go.sum b/simapp/go.sum index 037353e3cc..18aab42ed4 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -50,8 +50,6 @@ cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= cosmossdk.io/client/v2 v2.0.0-20230104083136-11f46a0bae58 h1:q0AkHBZnYhsnnS3AmTUu1BOO+TH3oNOsXbG6oeExwvg= cosmossdk.io/client/v2 v2.0.0-20230104083136-11f46a0bae58/go.mod h1:ztqtfnFSD3edvhNOAShzKod13nfKLM1sZj0uu0fo56w= -cosmossdk.io/collections v0.0.0-20230106101515-aeac21494476 h1:dszme7EMNp/qxjgZKjhY4lm5SN+g1Tz95UlX/qZUK64= -cosmossdk.io/collections v0.0.0-20230106101515-aeac21494476/go.mod h1:q4avveOJ2Cbgab/Hm/yXDHFPM7NW9InEVysd8TzNPCE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= @@ -222,8 +220,8 @@ github.com/cosmos/iavl v0.20.0-alpha1 h1:tP+Qv4MdnLVmrrhIAGpLRQOOhFGgci0hpJ4VI3x github.com/cosmos/iavl v0.20.0-alpha1/go.mod h1:25YJYzilTErJ2mKfNB3xyWL9IsCwEQdNzdIutg2mh3U= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= +github.com/cosmos/ledger-cosmos-go v0.13.0 h1:ex0CvCxToSR7j5WjrghPu2Bu9sSXKikjnVvUryNnx4s= +github.com/cosmos/ledger-cosmos-go v0.13.0/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cosmos/rosetta-sdk-go v0.9.0 h1:3mj2naR+GUhUXabtb96WWSsPFZDCYkdtp6r0jffgugg= github.com/cosmos/rosetta-sdk-go v0.9.0/go.mod h1:2v41yXL25xxAXrczVSnbDHcQH9CgildruDlGQGKW/JU= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index 693c5f7b30..edd04be482 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -5,8 +5,6 @@ import ( "io" "os" - rosettaCmd "cosmossdk.io/tools/rosetta/cmd" - dbm "github.com/cosmos/cosmos-db" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -16,6 +14,7 @@ import ( "cosmossdk.io/simapp" "cosmossdk.io/simapp/params" confixcmd "cosmossdk.io/tools/confix/cmd" + rosettaCmd "cosmossdk.io/tools/rosetta/cmd" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/config" @@ -24,12 +23,15 @@ import ( "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/pruning" "github.com/cosmos/cosmos-sdk/client/rpc" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" serverconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/crisis" @@ -53,7 +55,6 @@ func NewRootCmd() *cobra.Command { initClientCtx := client.Context{}. WithCodec(encodingConfig.Codec). WithInterfaceRegistry(encodingConfig.InterfaceRegistry). - WithTxConfig(encodingConfig.TxConfig). WithLegacyAmino(encodingConfig.Amino). WithInput(os.Stdin). WithAccountRetriever(types.AccountRetriever{}). @@ -78,6 +79,19 @@ func NewRootCmd() *cobra.Command { return err } + // This needs to go after ReadFromClientConfig, as that function + // sets the RPC client needed for SIGN_MODE_TEXTUAL. + // + // TODO Currently, the TxConfig below doesn't include Textual, so + // an error will arise when using the --textual flag. + // ref: https://github.com/cosmos/cosmos-sdk/issues/11970 + txConfigWithTextual := tx.NewTxConfigWithTextual( + codec.NewProtoCodec(encodingConfig.InterfaceRegistry), + encodingConfig.TxConfig.SignModeHandler().Modes(), + txmodule.NewTextualWithGRPCConn(initClientCtx), + ) + initClientCtx = initClientCtx.WithTxConfig(txConfigWithTextual) + if err := client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil { return err } diff --git a/tests/go.mod b/tests/go.mod index d0822c818a..d06704f80e 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -62,7 +62,7 @@ require ( github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.20.0-alpha1 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.0 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -178,13 +178,13 @@ require ( ) replace ( + cosmossdk.io/collections => ../collections // We always want to test against the latest version of the simapp. cosmossdk.io/simapp => ../simapp + cosmossdk.io/x/evidence => ../x/evidence // TODO tag all extracted modules after SDK refactor cosmossdk.io/x/nft => ../x/nft - cosmossdk.io/x/evidence => ../x/evidence github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0 - cosmossdk.io/collections => ../collections // We always want to test against the latest version of the SDK. github.com/cosmos/cosmos-sdk => ../. // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. diff --git a/tests/go.sum b/tests/go.sum index 4559116928..0a2186f344 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -50,8 +50,6 @@ cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= cosmossdk.io/client/v2 v2.0.0-20230104083136-11f46a0bae58 h1:q0AkHBZnYhsnnS3AmTUu1BOO+TH3oNOsXbG6oeExwvg= cosmossdk.io/client/v2 v2.0.0-20230104083136-11f46a0bae58/go.mod h1:ztqtfnFSD3edvhNOAShzKod13nfKLM1sZj0uu0fo56w= -cosmossdk.io/collections v0.0.0-20230106101515-aeac21494476 h1:dszme7EMNp/qxjgZKjhY4lm5SN+g1Tz95UlX/qZUK64= -cosmossdk.io/collections v0.0.0-20230106101515-aeac21494476/go.mod h1:q4avveOJ2Cbgab/Hm/yXDHFPM7NW9InEVysd8TzNPCE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= @@ -217,8 +215,8 @@ github.com/cosmos/iavl v0.20.0-alpha1 h1:tP+Qv4MdnLVmrrhIAGpLRQOOhFGgci0hpJ4VI3x github.com/cosmos/iavl v0.20.0-alpha1/go.mod h1:25YJYzilTErJ2mKfNB3xyWL9IsCwEQdNzdIutg2mh3U= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= +github.com/cosmos/ledger-cosmos-go v0.13.0 h1:ex0CvCxToSR7j5WjrghPu2Bu9sSXKikjnVvUryNnx4s= +github.com/cosmos/ledger-cosmos-go v0.13.0/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= diff --git a/tools/confix/go.sum b/tools/confix/go.sum index 6e7a76f3f1..95d71f798c 100644 --- a/tools/confix/go.sum +++ b/tools/confix/go.sum @@ -37,8 +37,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= -cosmossdk.io/core v0.4.1 h1:5icpjPmw8J4uFp6w8OoLJPxsw6X3kRi9nAtTr3qp2Ok= -cosmossdk.io/core v0.4.1/go.mod h1:Zqd1GB+krTF3bzhTnPNwzy3NTtXu+MKLX/9sPQXTIDE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= diff --git a/tools/cosmovisor/go.sum b/tools/cosmovisor/go.sum index a21296455d..bccc2fde58 100644 --- a/tools/cosmovisor/go.sum +++ b/tools/cosmovisor/go.sum @@ -48,8 +48,6 @@ cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgy cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= -cosmossdk.io/core v0.4.1 h1:5icpjPmw8J4uFp6w8OoLJPxsw6X3kRi9nAtTr3qp2Ok= -cosmossdk.io/core v0.4.1/go.mod h1:Zqd1GB+krTF3bzhTnPNwzy3NTtXu+MKLX/9sPQXTIDE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= diff --git a/tools/rosetta/go.sum b/tools/rosetta/go.sum index 0dad089bc8..de9392269b 100644 --- a/tools/rosetta/go.sum +++ b/tools/rosetta/go.sum @@ -37,8 +37,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= -cosmossdk.io/core v0.4.1 h1:5icpjPmw8J4uFp6w8OoLJPxsw6X3kRi9nAtTr3qp2Ok= -cosmossdk.io/core v0.4.1/go.mod h1:Zqd1GB+krTF3bzhTnPNwzy3NTtXu+MKLX/9sPQXTIDE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index c4532c7bd1..c8b2101fb6 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -118,7 +118,7 @@ func TestAnteHandlerSigErrors(t *testing.T) { // Create tx manually to test the tx's signers require.NoError(t, suite.txBuilder.SetMsgs(msgs...)) - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) // tx.GetSigners returns addresses in correct order: addr1, addr2, addr3 @@ -1141,7 +1141,7 @@ func TestAnteHandlerSetPubKey(t *testing.T) { suite.txBuilder.SetGasLimit(gasLimit) // Manually create tx, and remove signature. - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) txBuilder, err := suite.clientCtx.TxConfig.WrapTxBuilder(tx) require.NoError(t, err) @@ -1187,7 +1187,7 @@ func TestAnteHandlerSetPubKey(t *testing.T) { suite.txBuilder.SetGasLimit(gasLimit) // Manually create tx, and remove signature. - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) txBuilder, err := suite.clientCtx.TxConfig.WrapTxBuilder(tx) require.NoError(t, err) @@ -1435,7 +1435,7 @@ func TestAnteHandlerReCheck(t *testing.T) { // test that operations skipped on recheck do not run privs, accNums, accSeqs := []cryptotypes.PrivKey{accs[0].priv}, []uint64{0}, []uint64{0} - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) // make signature array empty which would normally cause ValidateBasicDecorator and SigVerificationDecorator fail @@ -1447,7 +1447,7 @@ func TestAnteHandlerReCheck(t *testing.T) { _, err = suite.anteHandler(suite.ctx, txBuilder.GetTx(), false) require.Nil(t, err, "AnteHandler errored on recheck unexpectedly: %v", err) - tx, err = suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err = suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) txBytes, err := json.Marshal(tx) require.Nil(t, err, "Error marshalling tx: %v", err) diff --git a/x/auth/ante/basic_test.go b/x/auth/ante/basic_test.go index fedc81ed82..dafbe76949 100644 --- a/x/auth/ante/basic_test.go +++ b/x/auth/ante/basic_test.go @@ -31,7 +31,7 @@ func TestValidateBasic(t *testing.T) { suite.txBuilder.SetGasLimit(gasLimit) privs, accNums, accSeqs := []cryptotypes.PrivKey{}, []uint64{}, []uint64{} - invalidTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + invalidTx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) vbd := ante.NewValidateBasicDecorator() @@ -41,7 +41,7 @@ func TestValidateBasic(t *testing.T) { require.ErrorIs(t, err, sdkerrors.ErrNoSignatures, "Did not error on invalid tx") privs, accNums, accSeqs = []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0} - validTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + validTx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) _, err = antehandler(suite.ctx, validTx, false) @@ -73,7 +73,7 @@ func TestValidateMemo(t *testing.T) { privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0} suite.txBuilder.SetMemo(strings.Repeat("01234567890", 500)) - invalidTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + invalidTx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) // require that long memos get rejected @@ -84,7 +84,7 @@ func TestValidateMemo(t *testing.T) { require.ErrorIs(t, err, sdkerrors.ErrMemoTooLarge, "Did not error on tx with high memo") suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10)) - validTx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + validTx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) // require small memos pass ValidateMemo Decorator @@ -123,7 +123,7 @@ func TestConsumeGasForTxSize(t *testing.T) { suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10)) privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0} - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) txBytes, err := suite.clientCtx.TxConfig.TxJSONEncoder()(tx) @@ -215,7 +215,7 @@ func TestTxHeightTimeoutDecorator(t *testing.T) { suite.txBuilder.SetTimeoutHeight(tc.timeout) privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0} - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) ctx := suite.ctx.WithBlockHeight(tc.height) diff --git a/x/auth/ante/fee_test.go b/x/auth/ante/fee_test.go index 9653cb1ae2..182e5ae8f0 100644 --- a/x/auth/ante/fee_test.go +++ b/x/auth/ante/fee_test.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/golang/mock/gomock" @@ -32,7 +33,7 @@ func TestDeductFeeDecorator_ZeroGas(t *testing.T) { s.txBuilder.SetGasLimit(0) privs, accNums, accSeqs := []cryptotypes.PrivKey{accs[0].priv}, []uint64{0}, []uint64{0} - tx, err := s.CreateTestTx(privs, accNums, accSeqs, s.ctx.ChainID()) + tx, err := s.CreateTestTx(s.ctx, privs, accNums, accSeqs, s.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) // Set IsCheckTx to true @@ -67,7 +68,7 @@ func TestEnsureMempoolFees(t *testing.T) { s.bankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), accs[0].acc.GetAddress(), authtypes.FeeCollectorName, feeAmount).Return(nil).Times(3) privs, accNums, accSeqs := []cryptotypes.PrivKey{accs[0].priv}, []uint64{0}, []uint64{0} - tx, err := s.CreateTestTx(privs, accNums, accSeqs, s.ctx.ChainID()) + tx, err := s.CreateTestTx(s.ctx, privs, accNums, accSeqs, s.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) // Set high gas price so standard test fee fails @@ -124,7 +125,7 @@ func TestDeductFees(t *testing.T) { s.txBuilder.SetGasLimit(gasLimit) privs, accNums, accSeqs := []cryptotypes.PrivKey{accs[0].priv}, []uint64{0}, []uint64{0} - tx, err := s.CreateTestTx(privs, accNums, accSeqs, s.ctx.ChainID()) + tx, err := s.CreateTestTx(s.ctx, privs, accNums, accSeqs, s.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) dfd := ante.NewDeductFeeDecorator(s.accountKeeper, s.bankKeeper, nil, nil) diff --git a/x/auth/ante/setup_test.go b/x/auth/ante/setup_test.go index c3c6943e4d..004410032c 100644 --- a/x/auth/ante/setup_test.go +++ b/x/auth/ante/setup_test.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/stretchr/testify/require" ) @@ -28,7 +29,7 @@ func TestSetup(t *testing.T) { suite.txBuilder.SetGasLimit(gasLimit) privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0} - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) sud := ante.NewSetUpContextDecorator() @@ -63,7 +64,7 @@ func TestRecoverPanic(t *testing.T) { suite.txBuilder.SetGasLimit(gasLimit) privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1}, []uint64{0}, []uint64{0} - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) sud := ante.NewSetUpContextDecorator() diff --git a/x/auth/ante/sigverify_test.go b/x/auth/ante/sigverify_test.go index f3b197ec9d..f2e7e7f87b 100644 --- a/x/auth/ante/sigverify_test.go +++ b/x/auth/ante/sigverify_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/client" @@ -20,7 +21,10 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) func TestSetPubKey(t *testing.T) { @@ -48,7 +52,7 @@ func TestSetPubKey(t *testing.T) { suite.txBuilder.SetGasLimit(testdata.NewTestGasLimit()) privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0} - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) spkd := ante.NewSetPubKeyDecorator(suite.accountKeeper) @@ -122,6 +126,16 @@ func TestConsumeSignatureVerificationGas(t *testing.T) { func TestSigVerification(t *testing.T) { suite := SetupTestSuite(t, true) + suite.txBankKeeper.EXPECT().DenomMetadata(suite.ctx, gomock.Any()).Return(&banktypes.QueryDenomMetadataResponse{}, nil).AnyTimes() + + enabledSignModes := []signing.SignMode{signing.SignMode_SIGN_MODE_DIRECT, signing.SignMode_SIGN_MODE_TEXTUAL, signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON} + // Since TEXTUAL is not enabled by default, we create a custom TxConfig + // here which includes it. + suite.clientCtx.TxConfig = authtx.NewTxConfigWithTextual( + codec.NewProtoCodec(suite.encCfg.InterfaceRegistry), + enabledSignModes, + txmodule.NewTextualWithGRPCConn(suite.clientCtx), + ) suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // make block height non-zero to ensure account numbers part of signBytes @@ -147,7 +161,12 @@ func TestSigVerification(t *testing.T) { gasLimit := testdata.NewTestGasLimit() spkd := ante.NewSetPubKeyDecorator(suite.accountKeeper) - svd := ante.NewSigVerificationDecorator(suite.accountKeeper, suite.clientCtx.TxConfig.SignModeHandler()) + anteTxConfig := authtx.NewTxConfigWithTextual( + codec.NewProtoCodec(suite.encCfg.InterfaceRegistry), + enabledSignModes, + txmodule.NewTextualWithBankKeeper(suite.txBankKeeper), + ) + svd := ante.NewSigVerificationDecorator(suite.accountKeeper, anteTxConfig.SignModeHandler()) antehandler := sdk.ChainAnteDecorators(spkd, svd) type testCase struct { @@ -155,7 +174,7 @@ func TestSigVerification(t *testing.T) { privs []cryptotypes.PrivKey accNums []uint64 accSeqs []uint64 - invalidSigs bool + invalidSigs bool // used for testing sigverify on RecheckTx recheck bool shouldErr bool } @@ -169,36 +188,41 @@ func TestSigVerification(t *testing.T) { {"valid tx", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}, validSigs, false, false}, {"no err on recheck", []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 0, 0}, []uint64{0, 0, 0}, !validSigs, true, false}, } + for i, tc := range testCases { - suite.ctx = suite.ctx.WithIsReCheckTx(tc.recheck) - suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test + for _, signMode := range enabledSignModes { + t.Run(fmt.Sprintf("%s with %s", tc.name, signMode), func(t *testing.T) { + suite.ctx = suite.ctx.WithIsReCheckTx(tc.recheck) + suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // Create new txBuilder for each test - require.NoError(t, suite.txBuilder.SetMsgs(msgs...)) - suite.txBuilder.SetFeeAmount(feeAmount) - suite.txBuilder.SetGasLimit(gasLimit) + require.NoError(t, suite.txBuilder.SetMsgs(msgs...)) + suite.txBuilder.SetFeeAmount(feeAmount) + suite.txBuilder.SetGasLimit(gasLimit) - tx, err := suite.CreateTestTx(tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID()) - require.NoError(t, err) - if tc.invalidSigs { - txSigs, _ := tx.GetSignaturesV2() - badSig, _ := tc.privs[0].Sign([]byte("unrelated message")) - txSigs[0] = signing.SignatureV2{ - PubKey: tc.privs[0].PubKey(), - Data: &signing.SingleSignatureData{ - SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), - Signature: badSig, - }, - Sequence: tc.accSeqs[0], - } - suite.txBuilder.SetSignatures(txSigs...) - tx = suite.txBuilder.GetTx() - } + tx, err := suite.CreateTestTx(suite.ctx, tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID(), signMode) + require.NoError(t, err) + if tc.invalidSigs { + txSigs, _ := tx.GetSignaturesV2() + badSig, _ := tc.privs[0].Sign([]byte("unrelated message")) + txSigs[0] = signing.SignatureV2{ + PubKey: tc.privs[0].PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), + Signature: badSig, + }, + Sequence: tc.accSeqs[0], + } + suite.txBuilder.SetSignatures(txSigs...) + tx = suite.txBuilder.GetTx() + } - _, err = antehandler(suite.ctx, tx, false) - if tc.shouldErr { - require.NotNil(t, err, "TestCase %d: %s did not error as expected", i, tc.name) - } else { - require.Nil(t, err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err) + _, err = antehandler(suite.ctx, tx, false) + if tc.shouldErr { + require.NotNil(t, err, "TestCase %d: %s did not error as expected", i, tc.name) + } else { + require.Nil(t, err, "TestCase %d: %s errored unexpectedly. Err: %v", i, tc.name, err) + } + }) } } } @@ -285,7 +309,7 @@ func TestSigVerification_ExplicitAmino(t *testing.T) { suite.txBuilder.SetFeeAmount(feeAmount) suite.txBuilder.SetGasLimit(gasLimit) - tx, err := suite.CreateTestTx(tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, tc.privs, tc.accNums, tc.accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) require.NoError(t, err) _, err = antehandler(suite.ctx, tx, false) @@ -346,7 +370,7 @@ func runSigDecorators(t *testing.T, params types.Params, _ bool, privs ...crypto suite.txBuilder.SetFeeAmount(feeAmount) suite.txBuilder.SetGasLimit(gasLimit) - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) spkd := ante.NewSetPubKeyDecorator(suite.accountKeeper) @@ -381,7 +405,7 @@ func TestIncrementSequenceDecorator(t *testing.T) { suite.txBuilder.SetFeeAmount(feeAmount) suite.txBuilder.SetGasLimit(gasLimit) - tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) + tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) isd := ante.NewIncrementSequenceDecorator(suite.accountKeeper) diff --git a/x/auth/ante/testutil_test.go b/x/auth/ante/testutil_test.go index 900f6bfb71..2743b78736 100644 --- a/x/auth/ante/testutil_test.go +++ b/x/auth/ante/testutil_test.go @@ -5,12 +5,20 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + + // TODO We don't need to import these API types if we use gogo's registry + // ref: https://github.com/cosmos/cosmos-sdk/issues/14647 + _ "cosmossdk.io/api/cosmos/bank/v1beta1" + _ "cosmossdk.io/api/cosmos/crypto/secp256k1" + _ "github.com/cosmos/cosmos-sdk/testutil/testdata_pulsar" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/tx" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" @@ -21,7 +29,9 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/keeper" xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" + txtestutil "github.com/cosmos/cosmos-sdk/x/auth/tx/testutil" "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank" ) // TestAccount represents an account used in the tests in x/auth/ante. @@ -38,6 +48,7 @@ type AnteTestSuite struct { txBuilder client.TxBuilder accountKeeper keeper.AccountKeeper bankKeeper *authtestutil.MockBankKeeper + txBankKeeper *txtestutil.MockBankKeeper feeGrantKeeper *antetestutil.MockFeegrantKeeper encCfg moduletestutil.TestEncodingConfig } @@ -47,13 +58,13 @@ func SetupTestSuite(t *testing.T, isCheckTx bool) *AnteTestSuite { suite := &AnteTestSuite{} ctrl := gomock.NewController(t) suite.bankKeeper = authtestutil.NewMockBankKeeper(ctrl) - + suite.txBankKeeper = txtestutil.NewMockBankKeeper(ctrl) suite.feeGrantKeeper = antetestutil.NewMockFeegrantKeeper(ctrl) key := storetypes.NewKVStoreKey(types.StoreKey) testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) suite.ctx = testCtx.Ctx.WithIsCheckTx(isCheckTx).WithBlockHeight(1) // app.BaseApp.NewContext(isCheckTx, tmproto.Header{}).WithBlockHeight(1) - suite.encCfg = moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}) + suite.encCfg = moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}) maccPerms := map[string][]string{ "fee_collector": nil, @@ -76,7 +87,8 @@ func SetupTestSuite(t *testing.T, isCheckTx bool) *AnteTestSuite { testdata.RegisterInterfaces(suite.encCfg.InterfaceRegistry) suite.clientCtx = client.Context{}. - WithTxConfig(suite.encCfg.TxConfig) + WithTxConfig(suite.encCfg.TxConfig). + WithClient(clitestutil.NewMockTendermintRPC(abci.ResponseQuery{})) anteHandler, err := ante.NewAnteHandler( ante.HandlerOptions{ @@ -136,7 +148,7 @@ func (suite *AnteTestSuite) DeliverMsgs(t *testing.T, privs []cryptotypes.PrivKe suite.txBuilder.SetFeeAmount(feeAmount) suite.txBuilder.SetGasLimit(gasLimit) - tx, txErr := suite.CreateTestTx(privs, accNums, accSeqs, chainID) + tx, txErr := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, chainID, signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, txErr) return suite.anteHandler(suite.ctx, tx, simulate) } @@ -149,7 +161,7 @@ func (suite *AnteTestSuite) RunTestCase(t *testing.T, tc TestCase, args TestCase // Theoretically speaking, ante handler unit tests should only test // ante handlers, but here we sometimes also test the tx creation // process. - tx, txErr := suite.CreateTestTx(args.privs, args.accNums, args.accSeqs, args.chainID) + tx, txErr := suite.CreateTestTx(suite.ctx, args.privs, args.accNums, args.accSeqs, args.chainID, signing.SignMode_SIGN_MODE_DIRECT) newCtx, anteErr := suite.anteHandler(suite.ctx, tx, tc.simulate) if tc.expPass { @@ -175,7 +187,11 @@ func (suite *AnteTestSuite) RunTestCase(t *testing.T, tc TestCase, args TestCase } // CreateTestTx is a helper function to create a tx given multiple inputs. -func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (xauthsigning.Tx, error) { +func (suite *AnteTestSuite) CreateTestTx( + ctx sdk.Context, privs []cryptotypes.PrivKey, + accNums []uint64, accSeqs []uint64, + chainID string, signMode signing.SignMode, +) (xauthsigning.Tx, error) { // First round: we gather all the signer infos. We use the "set empty // signature" hack to do that. var sigsV2 []signing.SignatureV2 @@ -183,7 +199,7 @@ func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums [] sigV2 := signing.SignatureV2{ PubKey: priv.PubKey(), Data: &signing.SingleSignatureData{ - SignMode: suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), + SignMode: signMode, Signature: nil, }, Sequence: accSeqs[i], @@ -200,12 +216,14 @@ func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums [] sigsV2 = []signing.SignatureV2{} for i, priv := range privs { signerData := xauthsigning.SignerData{ + Address: sdk.AccAddress(priv.PubKey().Address()).String(), ChainID: chainID, AccountNumber: accNums[i], Sequence: accSeqs[i], + PubKey: priv.PubKey(), } sigV2, err := tx.SignWithPrivKey( - nil, suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData, // nolint:staticcheck // SA1019: signing.SignerData is deprecated + ctx, signMode, signerData, suite.txBuilder, priv, suite.clientCtx.TxConfig, accSeqs[i]) if err != nil { return nil, err diff --git a/x/auth/tx/config/config.go b/x/auth/tx/config/config.go index 5a9305bd44..4369bd9619 100644 --- a/x/auth/tx/config/config.go +++ b/x/auth/tx/config/config.go @@ -1,17 +1,11 @@ package tx import ( - "context" "fmt" - "google.golang.org/grpc/codes" - grpcstatus "google.golang.org/grpc/status" - - bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1" "cosmossdk.io/core/appmodule" "cosmossdk.io/depinject" - "cosmossdk.io/x/tx/textual" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" @@ -21,7 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/posthandler" "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/bank/types" feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" ) @@ -55,7 +48,7 @@ type TxOutputs struct { } func ProvideModule(in TxInputs) TxOutputs { - textual := newTextualWithBankKeeper(in.TxBankKeeper) + textual := NewTextualWithBankKeeper(in.TxBankKeeper) txConfig := tx.NewTxConfigWithTextual(in.ProtoCodecMarshaler, tx.DefaultSignModes, textual) baseAppOption := func(app *baseapp.BaseApp) { @@ -120,49 +113,3 @@ func newAnteHandler(txConfig client.TxConfig, in TxInputs) (sdk.AnteHandler, err return anteHandler, nil } - -// newTextualWithBankKeeper creates a new Textual struct using the given -// BankKeeper to retrieve coin metadata. -func newTextualWithBankKeeper(bk BankKeeper) textual.Textual { - textual := textual.NewTextual(func(ctx context.Context, denom string) (*bankv1beta1.Metadata, error) { - res, err := bk.DenomMetadata(ctx, &types.QueryDenomMetadataRequest{Denom: denom}) - if err != nil { - status, ok := grpcstatus.FromError(err) - if !ok { - return nil, err - } - - // This means we didn't find any metadata for this denom. Returning - // empty metadata. - if status.Code() == codes.NotFound { - return nil, nil - } - - return nil, err - } - - m := &bankv1beta1.Metadata{ - Base: res.Metadata.Base, - Display: res.Metadata.Display, - // fields below are not strictly needed by Textual - // but added here for completeness. - Description: res.Metadata.Description, - Name: res.Metadata.Name, - Symbol: res.Metadata.Symbol, - Uri: res.Metadata.URI, - UriHash: res.Metadata.URIHash, - } - m.DenomUnits = make([]*bankv1beta1.DenomUnit, len(res.Metadata.DenomUnits)) - for i, d := range res.Metadata.DenomUnits { - m.DenomUnits[i] = &bankv1beta1.DenomUnit{ - Denom: d.Denom, - Exponent: d.Exponent, - Aliases: d.Aliases, - } - } - - return m, nil - }) - - return textual -} diff --git a/x/auth/tx/config/textual.go b/x/auth/tx/config/textual.go new file mode 100644 index 0000000000..0d6315f4cf --- /dev/null +++ b/x/auth/tx/config/textual.go @@ -0,0 +1,91 @@ +package tx + +import ( + "context" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" + + bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" + "cosmossdk.io/x/tx/textual" + "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// NewTextualWithGRPCConn returns a new Textual instance where the metadata +// queries are done via gRPC using the provided GRPC client connection. In the +// SDK, you can pass a client.Context as the GRPC connection. +// +// Example: +// +// clientCtx := client.GetClientContextFromCmd(cmd) +// txt := tx.NewTextualWithGRPCConn(clientCtxx) +func NewTextualWithGRPCConn(grpcConn grpc.ClientConnInterface) textual.Textual { + return textual.NewTextual(func(ctx context.Context, denom string) (*bankv1beta1.Metadata, error) { + bankQueryClient := bankv1beta1.NewQueryClient(grpcConn) + res, err := bankQueryClient.DenomMetadata(ctx, &bankv1beta1.QueryDenomMetadataRequest{ + Denom: denom, + }) + if err != nil { + return nil, metadataExists(err) + } + + return res.Metadata, nil + }) +} + +// NewTextualWithBankKeeper creates a new Textual struct using the given +// BankKeeper to retrieve coin metadata. +// +// Note: Once we switch to ADR-033, and keepers become ADR-033 clients to each +// other, this function could probably be deprecated in favor of +// `NewTextualWithGRPCConn`. +func NewTextualWithBankKeeper(bk BankKeeper) textual.Textual { + textual := textual.NewTextual(func(ctx context.Context, denom string) (*bankv1beta1.Metadata, error) { + res, err := bk.DenomMetadata(ctx, &types.QueryDenomMetadataRequest{Denom: denom}) + if err != nil { + return nil, metadataExists(err) + } + + m := &bankv1beta1.Metadata{ + Base: res.Metadata.Base, + Display: res.Metadata.Display, + // fields below are not strictly needed by Textual + // but added here for completeness. + Description: res.Metadata.Description, + Name: res.Metadata.Name, + Symbol: res.Metadata.Symbol, + Uri: res.Metadata.URI, + UriHash: res.Metadata.URIHash, + } + m.DenomUnits = make([]*bankv1beta1.DenomUnit, len(res.Metadata.DenomUnits)) + for i, d := range res.Metadata.DenomUnits { + m.DenomUnits[i] = &bankv1beta1.DenomUnit{ + Denom: d.Denom, + Exponent: d.Exponent, + Aliases: d.Aliases, + } + } + + return m, nil + }) + + return textual +} + +// metadataExists parses the error, and only propagates the error if it's +// different than a "not found" error. +func metadataExists(err error) error { + status, ok := grpcstatus.FromError(err) + if !ok { + return err + } + + // This means we didn't find any metadata for this denom. Returning + // empty metadata. + if status.Code() == codes.NotFound { + return nil + } + + return err +} diff --git a/x/auth/tx/testutil/expected_keepers_mocks.go b/x/auth/tx/testutil/expected_keepers_mocks.go new file mode 100644 index 0000000000..fada0426cf --- /dev/null +++ b/x/auth/tx/testutil/expected_keepers_mocks.go @@ -0,0 +1,51 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: x/auth/tx/config/expected_keepers.go + +// Package testutil is a generated GoMock package. +package testutil + +import ( + context "context" + reflect "reflect" + + types "github.com/cosmos/cosmos-sdk/x/bank/types" + gomock "github.com/golang/mock/gomock" +) + +// MockBankKeeper is a mock of BankKeeper interface. +type MockBankKeeper struct { + ctrl *gomock.Controller + recorder *MockBankKeeperMockRecorder +} + +// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. +type MockBankKeeperMockRecorder struct { + mock *MockBankKeeper +} + +// NewMockBankKeeper creates a new mock instance. +func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { + mock := &MockBankKeeper{ctrl: ctrl} + mock.recorder = &MockBankKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { + return m.recorder +} + +// DenomMetadata mocks base method. +func (m *MockBankKeeper) DenomMetadata(c context.Context, req *types.QueryDenomMetadataRequest) (*types.QueryDenomMetadataResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DenomMetadata", c, req) + ret0, _ := ret[0].(*types.QueryDenomMetadataResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DenomMetadata indicates an expected call of DenomMetadata. +func (mr *MockBankKeeperMockRecorder) DenomMetadata(c, req interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DenomMetadata", reflect.TypeOf((*MockBankKeeper)(nil).DenomMetadata), c, req) +} diff --git a/x/auth/tx/testutil/suite.go b/x/auth/tx/testutil/suite.go index b9f2d41c74..1704d42b10 100644 --- a/x/auth/tx/testutil/suite.go +++ b/x/auth/tx/testutil/suite.go @@ -1,4 +1,4 @@ -package tx +package testutil import ( "bytes" diff --git a/x/evidence/go.mod b/x/evidence/go.mod index f025fc4c4d..508d6c3016 100644 --- a/x/evidence/go.mod +++ b/x/evidence/go.mod @@ -49,7 +49,7 @@ require ( github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.20.0-alpha1 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.0 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/x/evidence/go.sum b/x/evidence/go.sum index 4e6b6d0b62..26ded38677 100644 --- a/x/evidence/go.sum +++ b/x/evidence/go.sum @@ -193,8 +193,8 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4 github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.20.0-alpha1 h1:tP+Qv4MdnLVmrrhIAGpLRQOOhFGgci0hpJ4VI3xtHhM= github.com/cosmos/iavl v0.20.0-alpha1/go.mod h1:25YJYzilTErJ2mKfNB3xyWL9IsCwEQdNzdIutg2mh3U= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= +github.com/cosmos/ledger-cosmos-go v0.13.0 h1:ex0CvCxToSR7j5WjrghPu2Bu9sSXKikjnVvUryNnx4s= +github.com/cosmos/ledger-cosmos-go v0.13.0/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= diff --git a/x/nft/go.mod b/x/nft/go.mod index 2923dee63f..c139658c7a 100644 --- a/x/nft/go.mod +++ b/x/nft/go.mod @@ -17,7 +17,7 @@ require ( github.com/spf13/cobra v1.6.1 github.com/stretchr/testify v1.8.1 github.com/tendermint/tendermint v0.37.0-rc2 - google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9 + google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5 google.golang.org/grpc v1.52.0 ) @@ -48,7 +48,7 @@ require ( github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.20.0-alpha1 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.0 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -150,6 +150,6 @@ require ( replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.8.1 replace ( - github.com/cosmos/cosmos-sdk => ../.. cosmossdk.io/collections => ../../collections + github.com/cosmos/cosmos-sdk => ../.. ) diff --git a/x/nft/go.sum b/x/nft/go.sum index 29cf70d929..26ded38677 100644 --- a/x/nft/go.sum +++ b/x/nft/go.sum @@ -37,8 +37,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= -cosmossdk.io/collections v0.0.0-20230106101515-aeac21494476 h1:dszme7EMNp/qxjgZKjhY4lm5SN+g1Tz95UlX/qZUK64= -cosmossdk.io/collections v0.0.0-20230106101515-aeac21494476/go.mod h1:q4avveOJ2Cbgab/Hm/yXDHFPM7NW9InEVysd8TzNPCE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/depinject v1.0.0-alpha.3 h1:6evFIgj//Y3w09bqOUOzEpFj5tsxBqdc5CfkO7z+zfw= @@ -195,8 +193,8 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4 github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.20.0-alpha1 h1:tP+Qv4MdnLVmrrhIAGpLRQOOhFGgci0hpJ4VI3xtHhM= github.com/cosmos/iavl v0.20.0-alpha1/go.mod h1:25YJYzilTErJ2mKfNB3xyWL9IsCwEQdNzdIutg2mh3U= -github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= -github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= +github.com/cosmos/ledger-cosmos-go v0.13.0 h1:ex0CvCxToSR7j5WjrghPu2Bu9sSXKikjnVvUryNnx4s= +github.com/cosmos/ledger-cosmos-go v0.13.0/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -1248,8 +1246,8 @@ google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9 h1:ru6tJGasqJpgjM4q3Qq2fS3FKQ6CPPSRqgolUVBc994= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5 h1:wJT65XLOzhpSPCdAmmKfz94SlmnQzDzjm3Cj9k3fsXY= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= diff --git a/x/tx/go.sum b/x/tx/go.sum index 81b4dd4f65..6444985df7 100644 --- a/x/tx/go.sum +++ b/x/tx/go.sum @@ -1,7 +1,5 @@ cosmossdk.io/api v0.2.6 h1:AoNwaLLapcLsphhMK6+o0kZl+D6MMUaHVqSdwinASGU= cosmossdk.io/api v0.2.6/go.mod h1:u/d+GAxil0nWpl1XnQL8nkziQDIWuBDhv8VnDm/s6dI= -cosmossdk.io/core v0.4.1 h1:5icpjPmw8J4uFp6w8OoLJPxsw6X3kRi9nAtTr3qp2Ok= -cosmossdk.io/core v0.4.1/go.mod h1:Zqd1GB+krTF3bzhTnPNwzy3NTtXu+MKLX/9sPQXTIDE= cosmossdk.io/core v0.5.0 h1:37BkURamssr1FQkE6ZNSjgesLYMflREiykK/Z3k4l7Q= cosmossdk.io/core v0.5.0/go.mod h1:QVJT+YsJWs0pD/HuczGY5y/WEc9JCn1ycLsuCDUvFlc= cosmossdk.io/math v1.0.0-beta.4 h1:JtKedVLGzA0vv84xjYmZ75RKG35Kf2WwcFu8IjRkIIw=