From c13809062ab16bf193ad3919c77ec03c79b76cc8 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Tue, 16 Jun 2020 15:57:37 -0400 Subject: [PATCH] Update TxBuilder to use SignatureV2 (#6443) * Update TxBuilder to use SignatureV2 * Fix unit tests * Lint * lint * Cleanup * Address review feedback * Add Sign tests * Add more cases for sign tests * Fix lint * Fix gofmt * Deprecate StdTx * Undeprecate StdTx, but leave a comment to use the protobuf Tx * Address review comment Co-authored-by: anilCSE --- CHANGELOG.md | 1 + client/flags/flags.go | 2 + client/tx/factory.go | 19 +++- client/tx/tx.go | 85 +++++++++++------ client/tx/tx_test.go | 59 +++++++++++- client/tx_generator.go | 43 +++------ types/tx_msg.go | 14 +++ x/auth/ante/basic.go | 10 +- x/auth/ante/fee.go | 14 +-- x/auth/signing/handler_map_test.go | 5 +- .../amino/amino.go => types/amino_signing.go} | 12 +-- .../amino_signing_test.go} | 11 ++- x/auth/types/client_tx.go | 95 +++++++------------ x/auth/types/stdtx.go | 4 +- 14 files changed, 212 insertions(+), 162 deletions(-) rename x/auth/{signing/amino/amino.go => types/amino_signing.go} (72%) rename x/auth/{signing/amino/amino_test.go => types/amino_signing_test.go} (90%) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5e36a46c..845c12bef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -123,6 +123,7 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa * (modules) [\#6326](https://github.com/cosmos/cosmos-sdk/pull/6326) `AppModuleBasic.GetQueryCmd` now takes a single `CLIContext` parameter. * (modules) [\#6336](https://github.com/cosmos/cosmos-sdk/pull/6336) `AppModuleBasic.RegisterQueryService` method was added to support gRPC queries, and `QuerierRoute` and `NewQuerierHandler` were deprecated. * (modules) [\#6311](https://github.com/cosmos/cosmos-sdk/issues/6311) Remove `alias.go` usage +* (x/auth) [\#6443](https://github.com/cosmos/cosmos-sdk/issues/6443) Move `FeeTx` and `TxWithMemo` interfaces from `x/auth/ante` to `types`. Migration guide: diff --git a/client/flags/flags.go b/client/flags/flags.go index 1f76f27be..f5c4e9d0c 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -64,6 +64,7 @@ const ( FlagKeyringBackend = "keyring-backend" FlagPage = "page" FlagLimit = "limit" + FlagSignMode = "sign-mode" ) // LineBreak can be included in a command list to provide a blank line @@ -116,6 +117,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { c.Flags().Bool(FlagOffline, false, "Offline mode (does not allow any online functionality") c.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation") c.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") + c.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json), this is an advanced feature") // --gas can accept integers and "simulate" c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf( diff --git a/client/tx/factory.go b/client/tx/factory.go index 33508acbf..9d9490eb6 100644 --- a/client/tx/factory.go +++ b/client/tx/factory.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" ) // Factory defines a client transaction factory that facilitates generating and @@ -21,13 +22,19 @@ type Factory struct { sequence uint64 gas uint64 gasAdjustment float64 - simulateAndExecute bool chainID string memo string fees sdk.Coins gasPrices sdk.DecCoins + signMode signing.SignMode + simulateAndExecute bool } +const ( + signModeDirect = "direct" + signModeAminoJSON = "amino-json" +) + func NewFactoryFromCLI(input io.Reader) Factory { kb, err := keyring.New( sdk.KeyringServiceName(), @@ -39,6 +46,15 @@ func NewFactoryFromCLI(input io.Reader) Factory { panic(err) } + signModeStr := viper.GetString(flags.FlagSignMode) + signMode := signing.SignMode_SIGN_MODE_UNSPECIFIED + switch signModeStr { + case signModeDirect: + signMode = signing.SignMode_SIGN_MODE_DIRECT + case signModeAminoJSON: + signMode = signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON + } + f := Factory{ keybase: kb, accountNumber: viper.GetUint64(flags.FlagAccountNumber), @@ -48,6 +64,7 @@ func NewFactoryFromCLI(input io.Reader) Factory { simulateAndExecute: flags.GasFlagVar.Simulate, chainID: viper.GetString(flags.FlagChainID), memo: viper.GetString(flags.FlagMemo), + signMode: signMode, } f = f.WithFees(viper.GetString(flags.FlagFees)) diff --git a/client/tx/tx.go b/client/tx/tx.go index 234f5e986..ced903911 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -13,10 +13,11 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" - clientkeys "github.com/cosmos/cosmos-sdk/client/keys" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" ) // GenerateOrBroadcastTx will either generate and print and unsigned transaction @@ -108,7 +109,12 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error { } } - txBytes, err := Sign(txf, clientCtx.GetFromName(), clientkeys.DefaultKeyPass, tx) + err = Sign(txf, clientCtx.GetFromName(), tx) + if err != nil { + return err + } + + txBytes, err := clientCtx.TxGenerator.MarshalTx(tx.GetTx()) if err != nil { return err } @@ -209,24 +215,14 @@ func BuildUnsignedTx(txf Factory, msgs ...sdk.Msg) (client.TxBuilder, error) { } } - clientFee := txf.txGenerator.NewFee() - clientFee.SetAmount(fees) - clientFee.SetGas(txf.gas) - - tx := txf.txGenerator.NewTx() - tx.SetMemo(txf.memo) - - if err := tx.SetFee(clientFee); err != nil { - return nil, err - } - - if err := tx.SetSignatures(); err != nil { - return nil, err - } + tx := txf.txGenerator.NewTxBuilder() if err := tx.SetMsgs(msgs...); err != nil { return nil, err } + tx.SetMemo(txf.memo) + tx.SetFeeAmount(fees) + tx.SetGasLimit(txf.gas) return tx, nil } @@ -242,7 +238,7 @@ func BuildSimTx(txf Factory, msgs ...sdk.Msg) ([]byte, error) { // Create an empty signature literal as the ante handler will populate with a // sentinel pubkey. - sig := txf.txGenerator.NewSignature() + sig := signing.SignatureV2{} if err := tx.SetSignatures(sig); err != nil { return nil, err @@ -312,33 +308,60 @@ func PrepareFactory(clientCtx client.Context, txf Factory) (Factory, error) { // // Note, It is assumed the Factory has the necessary fields set that are required // by the CanonicalSignBytes call. -func Sign(txf Factory, name, passphrase string, tx client.TxBuilder) ([]byte, error) { +func Sign(txf Factory, name string, tx client.TxBuilder) error { if txf.keybase == nil { - return nil, errors.New("keybase must be set prior to signing a transaction") + return errors.New("keybase must be set prior to signing a transaction") } - signBytes, err := tx.CanonicalSignBytes(txf.chainID, txf.accountNumber, txf.sequence) + signMode := txf.signMode + if signMode == signing.SignMode_SIGN_MODE_UNSPECIFIED { + // use the SignModeHandler's default mode if unspecified + signMode = txf.txGenerator.SignModeHandler().DefaultMode() + } + + key, err := txf.keybase.Key(name) if err != nil { - return nil, err + return err } - sigBytes, pubkey, err := txf.keybase.Sign(name, signBytes) + pubKey := key.GetPubKey() + sigData := &signing.SingleSignatureData{ + SignMode: signMode, + Signature: nil, + } + sig := signing.SignatureV2{ + PubKey: pubKey, + Data: sigData, + } + err = tx.SetSignatures(sig) if err != nil { - return nil, err + return err } - sig := txf.txGenerator.NewSignature() - sig.SetSignature(sigBytes) - - if err := sig.SetPubKey(pubkey); err != nil { - return nil, err + signBytes, err := txf.txGenerator.SignModeHandler().GetSignBytes( + signMode, + authsigning.SignerData{ + ChainID: txf.chainID, + AccountNumber: txf.accountNumber, + AccountSequence: txf.sequence, + }, tx.GetTx(), + ) + if err != nil { + return err } - if err := tx.SetSignatures(sig); err != nil { - return nil, err + sigBytes, _, err := txf.keybase.Sign(name, signBytes) + if err != nil { + return err } - return txf.txGenerator.MarshalTx(tx.GetTx()) + sigData.Signature = sigBytes + sig = signing.SignatureV2{ + PubKey: pubKey, + Data: sigData, + } + + return tx.SetSignatures(sig) } // GasEstimateResponse defines a response definition for tx gas estimation. diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go index 5440060a6..daa0dea73 100644 --- a/client/tx/tx_test.go +++ b/client/tx/tx_test.go @@ -4,6 +4,12 @@ import ( "errors" "testing" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/tests" + + "github.com/cosmos/cosmos-sdk/x/auth/ante" + "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/client" @@ -105,5 +111,56 @@ func TestBuildUnsignedTx(t *testing.T) { tx, err := tx.BuildUnsignedTx(txf, msg) require.NoError(t, err) require.NotNil(t, tx) - require.Equal(t, []sdk.Signature{}, tx.GetSignatures()) + require.Empty(t, tx.GetTx().(ante.SigVerifiableTx).GetSignatures()) +} + +func TestSign(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + path := hd.CreateHDPath(118, 0, 0).String() + kr, err := keyring.New(t.Name(), "test", dir, nil) + require.NoError(t, err) + + var from = "test_sign" + + _, seed, err := kr.NewMnemonic(from, keyring.English, path, hd.Secp256k1) + require.NoError(t, err) + require.NoError(t, kr.Delete(from)) + + info, err := kr.NewAccount(from, seed, "", path, hd.Secp256k1) + require.NoError(t, err) + + txf := tx.Factory{}. + WithTxGenerator(NewTestTxGenerator()). + WithAccountNumber(50). + WithSequence(23). + WithFees("50stake"). + WithMemo("memo"). + WithChainID("test-chain") + + msg := banktypes.NewMsgSend(info.GetAddress(), sdk.AccAddress("to"), nil) + txn, err := tx.BuildUnsignedTx(txf, msg) + require.NoError(t, err) + + t.Log("should failed if txf without keyring") + err = tx.Sign(txf, from, txn) + require.Error(t, err) + + txf = tx.Factory{}. + WithKeybase(kr). + WithTxGenerator(NewTestTxGenerator()). + WithAccountNumber(50). + WithSequence(23). + WithFees("50stake"). + WithMemo("memo"). + WithChainID("test-chain") + + t.Log("should succeed if txf with keyring") + err = tx.Sign(txf, from, txn) + require.NoError(t, err) + + t.Log("should fail for non existing key") + err = tx.Sign(txf, "non_existing_key", txn) + require.Error(t, err) } diff --git a/client/tx_generator.go b/client/tx_generator.go index f840bd39e..b7c4c1666 100644 --- a/client/tx_generator.go +++ b/client/tx_generator.go @@ -1,9 +1,9 @@ package client import ( - "github.com/tendermint/tendermint/crypto" - - "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/signing" ) type ( @@ -11,22 +11,9 @@ type ( // application-defined concrete transaction type. The type returned must // implement TxBuilder. TxGenerator interface { - NewTx() TxBuilder - NewFee() Fee - NewSignature() Signature - MarshalTx(tx types.Tx) ([]byte, error) - } - - Fee interface { - types.Fee - SetGas(uint64) - SetAmount(types.Coins) - } - - Signature interface { - types.Signature - SetPubKey(crypto.PubKey) error - SetSignature([]byte) + NewTxBuilder() TxBuilder + SignModeHandler() signing.SignModeHandler + MarshalTx(tx sdk.Tx) ([]byte, error) } // TxBuilder defines an interface which an application-defined concrete transaction @@ -34,18 +21,12 @@ type ( // signatures, and provide canonical bytes to sign over. The transaction must // also know how to encode itself. TxBuilder interface { - GetTx() types.Tx + GetTx() sdk.Tx - SetMsgs(...types.Msg) error - GetSignatures() []types.Signature - SetSignatures(...Signature) error - GetFee() types.Fee - SetFee(Fee) error - GetMemo() string - SetMemo(string) - - // CanonicalSignBytes returns the canonical sign bytes to sign over, given a - // chain ID, along with an account and sequence number. - CanonicalSignBytes(cid string, num, seq uint64) ([]byte, error) + SetMsgs(msgs ...sdk.Msg) error + SetSignatures(signatures ...signingtypes.SignatureV2) error + SetMemo(memo string) + SetFeeAmount(amount sdk.Coins) + SetGasLimit(limit uint64) } ) diff --git a/types/tx_msg.go b/types/tx_msg.go index ef619bb92..3524d9e75 100644 --- a/types/tx_msg.go +++ b/types/tx_msg.go @@ -57,6 +57,20 @@ type ( // require access to any other information. ValidateBasic() error } + + // FeeTx defines the interface to be implemented by Tx to use the FeeDecorators + FeeTx interface { + Tx + GetGas() uint64 + GetFee() Coins + FeePayer() AccAddress + } + + // Tx must have GetMemo() method to use ValidateMemoDecorator + TxWithMemo interface { + Tx + GetMemo() string + } ) // TxDecoder unmarshals transaction bytes diff --git a/x/auth/ante/basic.go b/x/auth/ante/basic.go index b1ed1e8d3..f7120e627 100644 --- a/x/auth/ante/basic.go +++ b/x/auth/ante/basic.go @@ -11,7 +11,7 @@ import ( ) var ( - _ TxWithMemo = (*types.StdTx)(nil) // assert StdTx implements TxWithMemo + _ sdk.TxWithMemo = (*types.StdTx)(nil) // assert StdTx implements TxWithMemo ) // ValidateBasicDecorator will call tx.ValidateBasic and return any non-nil error. @@ -37,12 +37,6 @@ func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulat return next(ctx, tx, simulate) } -// Tx must have GetMemo() method to use ValidateMemoDecorator -type TxWithMemo interface { - sdk.Tx - GetMemo() string -} - // ValidateMemoDecorator will validate memo given the parameters passed in // If memo is too large decorator returns with error, otherwise call next AnteHandler // CONTRACT: Tx must implement TxWithMemo interface @@ -57,7 +51,7 @@ func NewValidateMemoDecorator(ak AccountKeeper) ValidateMemoDecorator { } func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { - memoTx, ok := tx.(TxWithMemo) + memoTx, ok := tx.(sdk.TxWithMemo) if !ok { return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") } diff --git a/x/auth/ante/fee.go b/x/auth/ante/fee.go index 900caf18d..5f323c5ca 100644 --- a/x/auth/ante/fee.go +++ b/x/auth/ante/fee.go @@ -9,17 +9,9 @@ import ( ) var ( - _ FeeTx = (*types.StdTx)(nil) // assert StdTx implements FeeTx + _ sdk.FeeTx = (*types.StdTx)(nil) // assert StdTx implements FeeTx ) -// FeeTx defines the interface to be implemented by Tx to use the FeeDecorators -type FeeTx interface { - sdk.Tx - GetGas() uint64 - GetFee() sdk.Coins - FeePayer() sdk.AccAddress -} - // MempoolFeeDecorator will check if the transaction's fee is at least as large // as the local validator's minimum gasFee (defined in validator config). // If fee is too low, decorator returns error and tx is rejected from mempool. @@ -33,7 +25,7 @@ func NewMempoolFeeDecorator() MempoolFeeDecorator { } func (mfd MempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - feeTx, ok := tx.(FeeTx) + feeTx, ok := tx.(sdk.FeeTx) if !ok { return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") } @@ -82,7 +74,7 @@ func NewDeductFeeDecorator(ak AccountKeeper, bk types.BankKeeper) DeductFeeDecor } func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - feeTx, ok := tx.(FeeTx) + feeTx, ok := tx.(sdk.FeeTx) if !ok { return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") } diff --git a/x/auth/signing/handler_map_test.go b/x/auth/signing/handler_map_test.go index 9e964693b..f4a7db276 100644 --- a/x/auth/signing/handler_map_test.go +++ b/x/auth/signing/handler_map_test.go @@ -10,7 +10,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/x/auth/signing/amino" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -19,7 +18,7 @@ func MakeTestHandlerMap() signing.SignModeHandler { return signing.NewSignModeHandlerMap( signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, []signing.SignModeHandler{ - amino.LegacyAminoJSONHandler{}, + authtypes.LegacyAminoJSONHandler{}, }, ) } @@ -59,7 +58,7 @@ func TestHandlerMap_GetSignBytes(t *testing.T) { ) handler := MakeTestHandlerMap() - aminoJSONHandler := amino.LegacyAminoJSONHandler{} + aminoJSONHandler := authtypes.LegacyAminoJSONHandler{} signingData := signing.SignerData{ ChainID: chainId, diff --git a/x/auth/signing/amino/amino.go b/x/auth/types/amino_signing.go similarity index 72% rename from x/auth/signing/amino/amino.go rename to x/auth/types/amino_signing.go index f9efc3d91..f8747ca1d 100644 --- a/x/auth/signing/amino/amino.go +++ b/x/auth/types/amino_signing.go @@ -1,13 +1,11 @@ -package amino +package types import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" - "github.com/cosmos/cosmos-sdk/x/auth/ante" "github.com/cosmos/cosmos-sdk/x/auth/signing" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) // LegacyAminoJSONHandler is a SignModeHandler that handles SIGN_MODE_LEGACY_AMINO_JSON @@ -31,17 +29,17 @@ func (LegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode, data sign return nil, fmt.Errorf("expected %s, got %s", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, mode) } - feeTx, ok := tx.(ante.FeeTx) + feeTx, ok := tx.(sdk.FeeTx) if !ok { return nil, fmt.Errorf("expected FeeTx, got %T", tx) } - memoTx, ok := tx.(ante.TxWithMemo) + memoTx, ok := tx.(sdk.TxWithMemo) if !ok { return nil, fmt.Errorf("expected TxWithMemo, got %T", tx) } - return authtypes.StdSignBytes( - data.ChainID, data.AccountNumber, data.AccountSequence, authtypes.StdFee{Amount: feeTx.GetFee(), Gas: feeTx.GetGas()}, tx.GetMsgs(), memoTx.GetMemo(), // nolint:staticcheck // SA1019: authtypes.StdFee is deprecated, will be removed once proto migration is completed + return StdSignBytes( + data.ChainID, data.AccountNumber, data.AccountSequence, StdFee{Amount: feeTx.GetFee(), Gas: feeTx.GetGas()}, tx.GetMsgs(), memoTx.GetMemo(), ), nil } diff --git a/x/auth/signing/amino/amino_test.go b/x/auth/types/amino_signing_test.go similarity index 90% rename from x/auth/signing/amino/amino_test.go rename to x/auth/types/amino_signing_test.go index 7faa937f3..9def92a52 100644 --- a/x/auth/signing/amino/amino_test.go +++ b/x/auth/types/amino_signing_test.go @@ -1,8 +1,10 @@ -package amino_test +package types_test import ( "testing" + "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/secp256k1" @@ -11,7 +13,6 @@ import ( signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/signing" - "github.com/cosmos/cosmos-sdk/x/auth/signing/amino" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -49,7 +50,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) { seqNum uint64 = 7 ) - handler := amino.LegacyAminoJSONHandler{} + handler := types.LegacyAminoJSONHandler{} signingData := signing.SignerData{ ChainID: chainId, AccountNumber: accNum, @@ -68,11 +69,11 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) { } func TestLegacyAminoJSONHandler_DefaultMode(t *testing.T) { - handler := amino.LegacyAminoJSONHandler{} + handler := types.LegacyAminoJSONHandler{} require.Equal(t, signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, handler.DefaultMode()) } func TestLegacyAminoJSONHandler_Modes(t *testing.T) { - handler := amino.LegacyAminoJSONHandler{} + handler := types.LegacyAminoJSONHandler{} require.Equal(t, []signingtypes.SignMode{signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON}, handler.Modes()) } diff --git a/x/auth/types/client_tx.go b/x/auth/types/client_tx.go index 0dcbe3ffc..d314b4f3b 100644 --- a/x/auth/types/client_tx.go +++ b/x/auth/types/client_tx.go @@ -1,16 +1,20 @@ package types import ( - "github.com/tendermint/tendermint/crypto" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" ) -// StdTxBuilder wraps StdTx to implement to the context.TxBuilder interface +// StdTxBuilder wraps StdTx to implement to the context.TxBuilder interface. +// Note that this type just exists for backwards compatibility with amino StdTx +// and will not work for protobuf transactions. type StdTxBuilder struct { StdTx + cdc *codec.Codec } var _ client.TxBuilder = &StdTxBuilder{} @@ -26,42 +30,40 @@ func (s *StdTxBuilder) SetMsgs(msgs ...sdk.Msg) error { return nil } -// GetSignatures implements TxBuilder.GetSignatures -func (s StdTxBuilder) GetSignatures() []sdk.Signature { - res := make([]sdk.Signature, len(s.Signatures)) - for i, sig := range s.Signatures { - res[i] = sig - } - return res -} - // SetSignatures implements TxBuilder.SetSignatures -func (s *StdTxBuilder) SetSignatures(signatures ...client.Signature) error { +func (s *StdTxBuilder) SetSignatures(signatures ...signing.SignatureV2) error { sigs := make([]StdSignature, len(signatures)) for i, sig := range signatures { - pubKey := sig.GetPubKey() + pubKey := sig.PubKey var pubKeyBz []byte if pubKey != nil { pubKeyBz = pubKey.Bytes() } + + var sigBz []byte + var err error + if sig.Data != nil { + sigBz, err = SignatureDataToAminoSignature(legacy.Cdc, sig.Data) + if err != nil { + return err + } + } + sigs[i] = StdSignature{ PubKey: pubKeyBz, - Signature: sig.GetSignature(), + Signature: sigBz, } } s.Signatures = sigs return nil } -// GetFee implements TxBuilder.GetFee -func (s StdTxBuilder) GetFee() sdk.Fee { - return s.Fee +func (s *StdTxBuilder) SetFeeAmount(amount sdk.Coins) { + s.StdTx.Fee.Amount = amount } -// SetFee implements TxBuilder.SetFee -func (s *StdTxBuilder) SetFee(fee client.Fee) error { - s.Fee = StdFee{Amount: fee.GetAmount(), Gas: fee.GetGas()} - return nil +func (s *StdTxBuilder) SetGasLimit(limit uint64) { + s.StdTx.Fee.Gas = limit } // SetMemo implements TxBuilder.SetMemo @@ -69,11 +71,6 @@ func (s *StdTxBuilder) SetMemo(memo string) { s.Memo = memo } -// CanonicalSignBytes implements TxBuilder.CanonicalSignBytes -func (s StdTxBuilder) CanonicalSignBytes(cid string, num, seq uint64) ([]byte, error) { - return StdSignBytes(cid, num, seq, s.Fee, s.Msgs, s.Memo), nil -} - // StdTxGenerator is a context.TxGenerator for StdTx type StdTxGenerator struct { Cdc *codec.Codec @@ -81,19 +78,12 @@ type StdTxGenerator struct { var _ client.TxGenerator = StdTxGenerator{} -// NewTx implements TxGenerator.NewTx -func (s StdTxGenerator) NewTx() client.TxBuilder { - return &StdTxBuilder{} -} - -// NewFee implements TxGenerator.NewFee -func (s StdTxGenerator) NewFee() client.Fee { - return &StdFee{} -} - -// NewSignature implements TxGenerator.NewSignature -func (s StdTxGenerator) NewSignature() client.Signature { - return &StdSignature{} +// NewTxBuilder implements TxGenerator.NewTxBuilder +func (s StdTxGenerator) NewTxBuilder() client.TxBuilder { + return &StdTxBuilder{ + StdTx: StdTx{}, + cdc: s.Cdc, + } } // MarshalTx implements TxGenerator.MarshalTx @@ -101,27 +91,6 @@ func (s StdTxGenerator) MarshalTx(tx sdk.Tx) ([]byte, error) { return DefaultTxEncoder(s.Cdc)(tx) } -var _ client.Fee = &StdFee{} - -// SetGas implements Fee.SetGas -func (fee *StdFee) SetGas(gas uint64) { - fee.Gas = gas -} - -// SetAmount implements Fee.SetAmount -func (fee *StdFee) SetAmount(coins sdk.Coins) { - fee.Amount = coins -} - -var _ client.Signature = &StdSignature{} - -// SetPubKey implements Signature.SetPubKey -func (ss *StdSignature) SetPubKey(key crypto.PubKey) error { - ss.PubKey = key.Bytes() - return nil -} - -// SetSignature implements Signature.SetSignature -func (ss *StdSignature) SetSignature(bytes []byte) { - ss.Signature = bytes +func (s StdTxGenerator) SignModeHandler() authsigning.SignModeHandler { + return LegacyAminoJSONHandler{} } diff --git a/x/auth/types/stdtx.go b/x/auth/types/stdtx.go index c81c3cd91..8fda16529 100644 --- a/x/auth/types/stdtx.go +++ b/x/auth/types/stdtx.go @@ -145,7 +145,8 @@ func CountSubKeys(pub crypto.PubKey) int { var _ sdk.Tx = (*StdTx)(nil) -// StdTx is a standard way to wrap a Msg with Fee and Signatures. +// StdTx is the legacy transaction format for wrapping a Msg with Fee and Signatures. +// It only works with Amino, please prefer the new protobuf Tx in types/tx. // NOTE: the first signature is the fee payer (Signatures must not be nil). type StdTx struct { Msgs []sdk.Msg `json:"msg" yaml:"msg"` @@ -154,6 +155,7 @@ type StdTx struct { Memo string `json:"memo" yaml:"memo"` } +// Deprecated func NewStdTx(msgs []sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx { return StdTx{ Msgs: msgs,