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 <anil@vitwit.com>
This commit is contained in:
Aaron Craelius 2020-06-16 15:57:37 -04:00 committed by GitHub
parent c134e8974e
commit c13809062a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 212 additions and 162 deletions

View File

@ -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) [\#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) [\#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 * (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: Migration guide:

View File

@ -64,6 +64,7 @@ const (
FlagKeyringBackend = "keyring-backend" FlagKeyringBackend = "keyring-backend"
FlagPage = "page" FlagPage = "page"
FlagLimit = "limit" FlagLimit = "limit"
FlagSignMode = "sign-mode"
) )
// LineBreak can be included in a command list to provide a blank line // 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().Bool(FlagOffline, false, "Offline mode (does not allow any online functionality")
c.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation") 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(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" // --gas can accept integers and "simulate"
c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf( c.Flags().Var(&GasFlagVar, "gas", fmt.Sprintf(

View File

@ -9,6 +9,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types" 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 // Factory defines a client transaction factory that facilitates generating and
@ -21,13 +22,19 @@ type Factory struct {
sequence uint64 sequence uint64
gas uint64 gas uint64
gasAdjustment float64 gasAdjustment float64
simulateAndExecute bool
chainID string chainID string
memo string memo string
fees sdk.Coins fees sdk.Coins
gasPrices sdk.DecCoins gasPrices sdk.DecCoins
signMode signing.SignMode
simulateAndExecute bool
} }
const (
signModeDirect = "direct"
signModeAminoJSON = "amino-json"
)
func NewFactoryFromCLI(input io.Reader) Factory { func NewFactoryFromCLI(input io.Reader) Factory {
kb, err := keyring.New( kb, err := keyring.New(
sdk.KeyringServiceName(), sdk.KeyringServiceName(),
@ -39,6 +46,15 @@ func NewFactoryFromCLI(input io.Reader) Factory {
panic(err) 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{ f := Factory{
keybase: kb, keybase: kb,
accountNumber: viper.GetUint64(flags.FlagAccountNumber), accountNumber: viper.GetUint64(flags.FlagAccountNumber),
@ -48,6 +64,7 @@ func NewFactoryFromCLI(input io.Reader) Factory {
simulateAndExecute: flags.GasFlagVar.Simulate, simulateAndExecute: flags.GasFlagVar.Simulate,
chainID: viper.GetString(flags.FlagChainID), chainID: viper.GetString(flags.FlagChainID),
memo: viper.GetString(flags.FlagMemo), memo: viper.GetString(flags.FlagMemo),
signMode: signMode,
} }
f = f.WithFees(viper.GetString(flags.FlagFees)) f = f.WithFees(viper.GetString(flags.FlagFees))

View File

@ -13,10 +13,11 @@ import (
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/client/input"
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/rest" "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 // 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 { if err != nil {
return err return err
} }
@ -209,24 +215,14 @@ func BuildUnsignedTx(txf Factory, msgs ...sdk.Msg) (client.TxBuilder, error) {
} }
} }
clientFee := txf.txGenerator.NewFee() tx := txf.txGenerator.NewTxBuilder()
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
}
if err := tx.SetMsgs(msgs...); err != nil { if err := tx.SetMsgs(msgs...); err != nil {
return nil, err return nil, err
} }
tx.SetMemo(txf.memo)
tx.SetFeeAmount(fees)
tx.SetGasLimit(txf.gas)
return tx, nil 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 // Create an empty signature literal as the ante handler will populate with a
// sentinel pubkey. // sentinel pubkey.
sig := txf.txGenerator.NewSignature() sig := signing.SignatureV2{}
if err := tx.SetSignatures(sig); err != nil { if err := tx.SetSignatures(sig); err != nil {
return nil, err 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 // Note, It is assumed the Factory has the necessary fields set that are required
// by the CanonicalSignBytes call. // 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 { 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 { 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 { if err != nil {
return nil, err return err
} }
sig := txf.txGenerator.NewSignature() signBytes, err := txf.txGenerator.SignModeHandler().GetSignBytes(
sig.SetSignature(sigBytes) signMode,
authsigning.SignerData{
if err := sig.SetPubKey(pubkey); err != nil { ChainID: txf.chainID,
return nil, err AccountNumber: txf.accountNumber,
AccountSequence: txf.sequence,
}, tx.GetTx(),
)
if err != nil {
return err
} }
if err := tx.SetSignatures(sig); err != nil { sigBytes, _, err := txf.keybase.Sign(name, signBytes)
return nil, err 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. // GasEstimateResponse defines a response definition for tx gas estimation.

View File

@ -4,6 +4,12 @@ import (
"errors" "errors"
"testing" "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/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
@ -105,5 +111,56 @@ func TestBuildUnsignedTx(t *testing.T) {
tx, err := tx.BuildUnsignedTx(txf, msg) tx, err := tx.BuildUnsignedTx(txf, msg)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, tx) 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)
} }

View File

@ -1,9 +1,9 @@
package client package client
import ( import (
"github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/signing"
) )
type ( type (
@ -11,22 +11,9 @@ type (
// application-defined concrete transaction type. The type returned must // application-defined concrete transaction type. The type returned must
// implement TxBuilder. // implement TxBuilder.
TxGenerator interface { TxGenerator interface {
NewTx() TxBuilder NewTxBuilder() TxBuilder
NewFee() Fee SignModeHandler() signing.SignModeHandler
NewSignature() Signature MarshalTx(tx sdk.Tx) ([]byte, error)
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)
} }
// TxBuilder defines an interface which an application-defined concrete transaction // 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 // signatures, and provide canonical bytes to sign over. The transaction must
// also know how to encode itself. // also know how to encode itself.
TxBuilder interface { TxBuilder interface {
GetTx() types.Tx GetTx() sdk.Tx
SetMsgs(...types.Msg) error SetMsgs(msgs ...sdk.Msg) error
GetSignatures() []types.Signature SetSignatures(signatures ...signingtypes.SignatureV2) error
SetSignatures(...Signature) error SetMemo(memo string)
GetFee() types.Fee SetFeeAmount(amount sdk.Coins)
SetFee(Fee) error SetGasLimit(limit uint64)
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)
} }
) )

View File

@ -57,6 +57,20 @@ type (
// require access to any other information. // require access to any other information.
ValidateBasic() error 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 // TxDecoder unmarshals transaction bytes

View File

@ -11,7 +11,7 @@ import (
) )
var ( 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. // 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) 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 // ValidateMemoDecorator will validate memo given the parameters passed in
// If memo is too large decorator returns with error, otherwise call next AnteHandler // If memo is too large decorator returns with error, otherwise call next AnteHandler
// CONTRACT: Tx must implement TxWithMemo interface // 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) { 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 { if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type") return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
} }

View File

@ -9,17 +9,9 @@ import (
) )
var ( 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 // MempoolFeeDecorator will check if the transaction's fee is at least as large
// as the local validator's minimum gasFee (defined in validator config). // 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. // 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) { 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 { if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") 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) { 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 { if !ok {
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
} }

View File

@ -10,7 +10,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" 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"
"github.com/cosmos/cosmos-sdk/x/auth/signing/amino"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
) )
@ -19,7 +18,7 @@ func MakeTestHandlerMap() signing.SignModeHandler {
return signing.NewSignModeHandlerMap( return signing.NewSignModeHandlerMap(
signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON,
[]signing.SignModeHandler{ []signing.SignModeHandler{
amino.LegacyAminoJSONHandler{}, authtypes.LegacyAminoJSONHandler{},
}, },
) )
} }
@ -59,7 +58,7 @@ func TestHandlerMap_GetSignBytes(t *testing.T) {
) )
handler := MakeTestHandlerMap() handler := MakeTestHandlerMap()
aminoJSONHandler := amino.LegacyAminoJSONHandler{} aminoJSONHandler := authtypes.LegacyAminoJSONHandler{}
signingData := signing.SignerData{ signingData := signing.SignerData{
ChainID: chainId, ChainID: chainId,

View File

@ -1,13 +1,11 @@
package amino package types
import ( import (
"fmt" "fmt"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" 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" "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 // 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) 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 { if !ok {
return nil, fmt.Errorf("expected FeeTx, got %T", tx) return nil, fmt.Errorf("expected FeeTx, got %T", tx)
} }
memoTx, ok := tx.(ante.TxWithMemo) memoTx, ok := tx.(sdk.TxWithMemo)
if !ok { if !ok {
return nil, fmt.Errorf("expected TxWithMemo, got %T", tx) return nil, fmt.Errorf("expected TxWithMemo, got %T", tx)
} }
return authtypes.StdSignBytes( return 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 data.ChainID, data.AccountNumber, data.AccountSequence, StdFee{Amount: feeTx.GetFee(), Gas: feeTx.GetGas()}, tx.GetMsgs(), memoTx.GetMemo(),
), nil ), nil
} }

View File

@ -1,8 +1,10 @@
package amino_test package types_test
import ( import (
"testing" "testing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/secp256k1"
@ -11,7 +13,6 @@ import (
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/signing" "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" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
) )
@ -49,7 +50,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
seqNum uint64 = 7 seqNum uint64 = 7
) )
handler := amino.LegacyAminoJSONHandler{} handler := types.LegacyAminoJSONHandler{}
signingData := signing.SignerData{ signingData := signing.SignerData{
ChainID: chainId, ChainID: chainId,
AccountNumber: accNum, AccountNumber: accNum,
@ -68,11 +69,11 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
} }
func TestLegacyAminoJSONHandler_DefaultMode(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()) require.Equal(t, signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, handler.DefaultMode())
} }
func TestLegacyAminoJSONHandler_Modes(t *testing.T) { 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()) require.Equal(t, []signingtypes.SignMode{signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON}, handler.Modes())
} }

View File

@ -1,16 +1,20 @@
package types package types
import ( import (
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/legacy"
sdk "github.com/cosmos/cosmos-sdk/types" 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 { type StdTxBuilder struct {
StdTx StdTx
cdc *codec.Codec
} }
var _ client.TxBuilder = &StdTxBuilder{} var _ client.TxBuilder = &StdTxBuilder{}
@ -26,42 +30,40 @@ func (s *StdTxBuilder) SetMsgs(msgs ...sdk.Msg) error {
return nil 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 // 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)) sigs := make([]StdSignature, len(signatures))
for i, sig := range signatures { for i, sig := range signatures {
pubKey := sig.GetPubKey() pubKey := sig.PubKey
var pubKeyBz []byte var pubKeyBz []byte
if pubKey != nil { if pubKey != nil {
pubKeyBz = pubKey.Bytes() 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{ sigs[i] = StdSignature{
PubKey: pubKeyBz, PubKey: pubKeyBz,
Signature: sig.GetSignature(), Signature: sigBz,
} }
} }
s.Signatures = sigs s.Signatures = sigs
return nil return nil
} }
// GetFee implements TxBuilder.GetFee func (s *StdTxBuilder) SetFeeAmount(amount sdk.Coins) {
func (s StdTxBuilder) GetFee() sdk.Fee { s.StdTx.Fee.Amount = amount
return s.Fee
} }
// SetFee implements TxBuilder.SetFee func (s *StdTxBuilder) SetGasLimit(limit uint64) {
func (s *StdTxBuilder) SetFee(fee client.Fee) error { s.StdTx.Fee.Gas = limit
s.Fee = StdFee{Amount: fee.GetAmount(), Gas: fee.GetGas()}
return nil
} }
// SetMemo implements TxBuilder.SetMemo // SetMemo implements TxBuilder.SetMemo
@ -69,11 +71,6 @@ func (s *StdTxBuilder) SetMemo(memo string) {
s.Memo = memo 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 // StdTxGenerator is a context.TxGenerator for StdTx
type StdTxGenerator struct { type StdTxGenerator struct {
Cdc *codec.Codec Cdc *codec.Codec
@ -81,19 +78,12 @@ type StdTxGenerator struct {
var _ client.TxGenerator = StdTxGenerator{} var _ client.TxGenerator = StdTxGenerator{}
// NewTx implements TxGenerator.NewTx // NewTxBuilder implements TxGenerator.NewTxBuilder
func (s StdTxGenerator) NewTx() client.TxBuilder { func (s StdTxGenerator) NewTxBuilder() client.TxBuilder {
return &StdTxBuilder{} return &StdTxBuilder{
} StdTx: StdTx{},
cdc: s.Cdc,
// NewFee implements TxGenerator.NewFee }
func (s StdTxGenerator) NewFee() client.Fee {
return &StdFee{}
}
// NewSignature implements TxGenerator.NewSignature
func (s StdTxGenerator) NewSignature() client.Signature {
return &StdSignature{}
} }
// MarshalTx implements TxGenerator.MarshalTx // MarshalTx implements TxGenerator.MarshalTx
@ -101,27 +91,6 @@ func (s StdTxGenerator) MarshalTx(tx sdk.Tx) ([]byte, error) {
return DefaultTxEncoder(s.Cdc)(tx) return DefaultTxEncoder(s.Cdc)(tx)
} }
var _ client.Fee = &StdFee{} func (s StdTxGenerator) SignModeHandler() authsigning.SignModeHandler {
return LegacyAminoJSONHandler{}
// 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
} }

View File

@ -145,7 +145,8 @@ func CountSubKeys(pub crypto.PubKey) int {
var _ sdk.Tx = (*StdTx)(nil) 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). // NOTE: the first signature is the fee payer (Signatures must not be nil).
type StdTx struct { type StdTx struct {
Msgs []sdk.Msg `json:"msg" yaml:"msg"` Msgs []sdk.Msg `json:"msg" yaml:"msg"`
@ -154,6 +155,7 @@ type StdTx struct {
Memo string `json:"memo" yaml:"memo"` Memo string `json:"memo" yaml:"memo"`
} }
// Deprecated
func NewStdTx(msgs []sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx { func NewStdTx(msgs []sdk.Msg, fee StdFee, sigs []StdSignature, memo string) StdTx {
return StdTx{ return StdTx{
Msgs: msgs, Msgs: msgs,