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:
parent
c134e8974e
commit
c13809062a
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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())
|
||||||
}
|
}
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue