Tx Height Timeout (#6089)
* Implement TxHeightTimeoutDecorator * Update error message * rename type * set height timeout * update tests * update *SignDoc) * rename * remove dup * fix build * cli updates * rest updates * cl++ * Update x/auth/ante/basic.go Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * Update x/auth/ante/basic.go Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * Update x/auth/ante/basic.go Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * Update x/auth/ante/basic.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * rename * rename * remove TimeoutHeight from SignDoc * updates * fix tests * update IBC cmd flags * use omitempty * update godoc * add test case to TestStdSignBytes Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
6ebc476474
commit
9ae17669d6
|
@ -156,6 +156,7 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa
|
|||
|
||||
### Features
|
||||
|
||||
* [\#6089](https://github.com/cosmos/cosmos-sdk/pull/6089) Transactions can now have a `TimeoutHeight` set which allows the transaction to be rejected if it's committed at a height greater than the timeout.
|
||||
* (tests) [\#6489](https://github.com/cosmos/cosmos-sdk/pull/6489) Introduce package `testutil`, new in-process testing network framework for use in integration and unit tests.
|
||||
* (crypto/multisig) [\#6241](https://github.com/cosmos/cosmos-sdk/pull/6241) Add Multisig type directly to the repo. Previously this was in tendermint.
|
||||
* (rest) [\#6167](https://github.com/cosmos/cosmos-sdk/pull/6167) Support `max-body-bytes` CLI flag for the REST service.
|
||||
|
|
|
@ -62,6 +62,7 @@ const (
|
|||
FlagPageKey = "page-key"
|
||||
FlagOffset = "offset"
|
||||
FlagCountTotal = "count-total"
|
||||
FlagTimeoutHeight = "timeout-height"
|
||||
)
|
||||
|
||||
// LineBreak can be included in a command list to provide a blank line
|
||||
|
@ -100,6 +101,7 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
|
|||
cmd.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation")
|
||||
cmd.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)")
|
||||
cmd.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json), this is an advanced feature")
|
||||
cmd.Flags().Uint64(FlagTimeoutHeight, 0, "Set a block timeout height to prevent the tx from being committed past a certain height")
|
||||
|
||||
// --gas can accept integers and "auto"
|
||||
cmd.Flags().String(FlagGas, "", fmt.Sprintf("gas limit to set per-transaction; set to %q to calculate sufficient gas automatically (default %d)", GasFlagAuto, DefaultGasLimit))
|
||||
|
|
|
@ -259,7 +259,7 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() {
|
|||
s.T().Log("decode transaction")
|
||||
tx2, err := s.TxConfig.TxDecoder()(txBytes)
|
||||
s.Require().NoError(err)
|
||||
tx3, ok := tx2.(signing.SigFeeMemoTx)
|
||||
tx3, ok := tx2.(signing.Tx)
|
||||
s.Require().True(ok)
|
||||
s.Require().Equal([]sdk.Msg{msg}, tx3.GetMsgs())
|
||||
s.Require().Equal(feeAmount, tx3.GetFee())
|
||||
|
@ -276,7 +276,7 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() {
|
|||
s.T().Log("JSON decode transaction")
|
||||
tx2, err = s.TxConfig.TxJSONDecoder()(jsonTxBytes)
|
||||
s.Require().NoError(err)
|
||||
tx3, ok = tx2.(signing.SigFeeMemoTx)
|
||||
tx3, ok = tx2.(signing.Tx)
|
||||
s.Require().True(ok)
|
||||
s.Require().Equal([]sdk.Msg{msg}, tx3.GetMsgs())
|
||||
s.Require().Equal(feeAmount, tx3.GetFee())
|
||||
|
|
|
@ -19,6 +19,7 @@ type Factory struct {
|
|||
accountNumber uint64
|
||||
sequence uint64
|
||||
gas uint64
|
||||
timeoutHeight uint64
|
||||
gasAdjustment float64
|
||||
chainID string
|
||||
memo string
|
||||
|
@ -48,6 +49,7 @@ func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) Factory {
|
|||
accSeq, _ := flagSet.GetUint64(flags.FlagSequence)
|
||||
gasAdj, _ := flagSet.GetFloat64(flags.FlagGasAdjustment)
|
||||
memo, _ := flagSet.GetString(flags.FlagMemo)
|
||||
timeoutHeight, _ := flagSet.GetUint64(flags.FlagTimeoutHeight)
|
||||
|
||||
gasStr, _ := flagSet.GetString(flags.FlagGas)
|
||||
gasSetting, _ := flags.ParseGasSetting(gasStr)
|
||||
|
@ -61,6 +63,7 @@ func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) Factory {
|
|||
simulateAndExecute: gasSetting.Simulate,
|
||||
accountNumber: accNum,
|
||||
sequence: accSeq,
|
||||
timeoutHeight: timeoutHeight,
|
||||
gasAdjustment: gasAdj,
|
||||
memo: memo,
|
||||
signMode: signMode,
|
||||
|
@ -85,6 +88,7 @@ func (f Factory) Memo() string { return f.memo }
|
|||
func (f Factory) Fees() sdk.Coins { return f.fees }
|
||||
func (f Factory) GasPrices() sdk.DecCoins { return f.gasPrices }
|
||||
func (f Factory) AccountRetriever() client.AccountRetriever { return f.accountRetriever }
|
||||
func (f Factory) TimeoutHeight() uint64 { return f.timeoutHeight }
|
||||
|
||||
// SimulateAndExecute returns the option to simulate and then execute the transaction
|
||||
// using the gas from the simulation results
|
||||
|
@ -183,3 +187,9 @@ func (f Factory) WithSignMode(mode signing.SignMode) Factory {
|
|||
f.signMode = mode
|
||||
return f
|
||||
}
|
||||
|
||||
// WithTimeoutHeight returns a copy of the Factory with an updated timeout height.
|
||||
func (f Factory) WithTimeoutHeight(height uint64) Factory {
|
||||
f.timeoutHeight = height
|
||||
return f
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// ConvertTxToStdTx converts a transaction to the legacy StdTx format
|
||||
func ConvertTxToStdTx(codec *codec.Codec, tx signing.SigFeeMemoTx) (types.StdTx, error) {
|
||||
func ConvertTxToStdTx(codec *codec.Codec, tx signing.Tx) (types.StdTx, error) {
|
||||
if stdTx, ok := tx.(types.StdTx); ok {
|
||||
return stdTx, nil
|
||||
}
|
||||
|
@ -33,9 +33,9 @@ func ConvertTxToStdTx(codec *codec.Codec, tx signing.SigFeeMemoTx) (types.StdTx,
|
|||
return stdTx, nil
|
||||
}
|
||||
|
||||
// CopyTx copies a SigFeeMemoTx to a new TxBuilder, allowing conversion between
|
||||
// CopyTx copies a Tx to a new TxBuilder, allowing conversion between
|
||||
// different transaction formats.
|
||||
func CopyTx(tx signing.SigFeeMemoTx, builder client.TxBuilder) error {
|
||||
func CopyTx(tx signing.Tx, builder client.TxBuilder) error {
|
||||
err := builder.SetMsgs(tx.GetMsgs()...)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -133,7 +133,7 @@ func (s *TestSuite) TestConvertAndEncodeStdTx() {
|
|||
decodedTx, err := s.protoCfg.TxDecoder()(txBz)
|
||||
s.Require().NoError(err)
|
||||
aminoBuilder2 := s.aminoCfg.NewTxBuilder()
|
||||
s.Require().NoError(tx2.CopyTx(decodedTx.(signing.SigFeeMemoTx), aminoBuilder2))
|
||||
s.Require().NoError(tx2.CopyTx(decodedTx.(signing.Tx), aminoBuilder2))
|
||||
s.Require().Equal(stdTx, aminoBuilder2.GetTx())
|
||||
|
||||
// just use amino everywhere
|
||||
|
|
|
@ -161,7 +161,8 @@ func WriteGeneratedTxResponse(
|
|||
WithMemo(br.Memo).
|
||||
WithChainID(br.ChainID).
|
||||
WithSimulateAndExecute(br.Simulate).
|
||||
WithTxConfig(ctx.TxConfig)
|
||||
WithTxConfig(ctx.TxConfig).
|
||||
WithTimeoutHeight(br.TimeoutHeight)
|
||||
|
||||
if br.Simulate || gasSetting.Simulate {
|
||||
if gasAdj < 0 {
|
||||
|
@ -238,6 +239,7 @@ func BuildUnsignedTx(txf Factory, msgs ...sdk.Msg) (client.TxBuilder, error) {
|
|||
tx.SetMemo(txf.memo)
|
||||
tx.SetFeeAmount(fees)
|
||||
tx.SetGasLimit(txf.gas)
|
||||
tx.SetTimeoutHeight(txf.TimeoutHeight())
|
||||
|
||||
return tx, nil
|
||||
}
|
||||
|
|
|
@ -34,12 +34,13 @@ type (
|
|||
// signatures, and provide canonical bytes to sign over. The transaction must
|
||||
// also know how to encode itself.
|
||||
TxBuilder interface {
|
||||
GetTx() signing.SigFeeMemoTx
|
||||
GetTx() signing.Tx
|
||||
|
||||
SetMsgs(msgs ...sdk.Msg) error
|
||||
SetSignatures(signatures ...signingtypes.SignatureV2) error
|
||||
SetMemo(memo string)
|
||||
SetFeeAmount(amount sdk.Coins)
|
||||
SetGasLimit(limit uint64)
|
||||
SetTimeoutHeight(height uint64)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -75,7 +75,7 @@ message TxBody {
|
|||
|
||||
// timeout is the block height after which this transaction will not
|
||||
// be processed by the chain
|
||||
int64 timeout_height = 3;
|
||||
uint64 timeout_height = 3;
|
||||
|
||||
// extension_options are arbitrary options that can be added by chains
|
||||
// when the default options are not sufficient. If any of these are present
|
||||
|
|
|
@ -14,12 +14,12 @@ func MakeEncodingConfig() EncodingConfig {
|
|||
amino := codec.New()
|
||||
interfaceRegistry := types.NewInterfaceRegistry()
|
||||
marshaler := codec.NewHybridCodec(amino, interfaceRegistry)
|
||||
txGen := tx.NewTxConfig(codec.NewProtoCodec(interfaceRegistry), std.DefaultPublicKeyCodec{}, tx.DefaultSignModes)
|
||||
txCfg := tx.NewTxConfig(codec.NewProtoCodec(interfaceRegistry), std.DefaultPublicKeyCodec{}, tx.DefaultSignModes)
|
||||
|
||||
return EncodingConfig{
|
||||
InterfaceRegistry: interfaceRegistry,
|
||||
Marshaler: marshaler,
|
||||
TxConfig: txGen,
|
||||
TxConfig: txCfg,
|
||||
Amino: amino,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,6 +106,10 @@ var (
|
|||
// ErrInvalidType defines an error an invalid type.
|
||||
ErrInvalidType = Register(RootCodespace, 29, "invalid type")
|
||||
|
||||
// ErrTxTimeoutHeight defines an error for when a tx is rejected out due to an
|
||||
// explicitly set timeout height.
|
||||
ErrTxTimeoutHeight = Register(RootCodespace, 30, "tx timeout height")
|
||||
|
||||
// ErrPanic is only set when we recover from a panic, so we know to
|
||||
// redact potentially sensitive system info
|
||||
ErrPanic = Register(UndefinedCodespace, 111222, "panic")
|
||||
|
|
|
@ -67,6 +67,7 @@ type BaseReq struct {
|
|||
ChainID string `json:"chain_id"`
|
||||
AccountNumber uint64 `json:"account_number"`
|
||||
Sequence uint64 `json:"sequence"`
|
||||
TimeoutHeight uint64 `json:"timeout_height"`
|
||||
Fees sdk.Coins `json:"fees"`
|
||||
GasPrices sdk.DecCoins `json:"gas_prices"`
|
||||
Gas string `json:"gas"`
|
||||
|
|
|
@ -260,7 +260,7 @@ type TxBody struct {
|
|||
Memo string `protobuf:"bytes,2,opt,name=memo,proto3" json:"memo,omitempty"`
|
||||
// timeout is the block height after which this transaction will not
|
||||
// be processed by the chain
|
||||
TimeoutHeight int64 `protobuf:"varint,3,opt,name=timeout_height,json=timeoutHeight,proto3" json:"timeout_height,omitempty"`
|
||||
TimeoutHeight uint64 `protobuf:"varint,3,opt,name=timeout_height,json=timeoutHeight,proto3" json:"timeout_height,omitempty"`
|
||||
// extension_options are arbitrary options that can be added by chains
|
||||
// when the default options are not sufficient. If any of these are present
|
||||
// and can't be handled, the transaction will be rejected
|
||||
|
@ -318,7 +318,7 @@ func (m *TxBody) GetMemo() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *TxBody) GetTimeoutHeight() int64 {
|
||||
func (m *TxBody) GetTimeoutHeight() uint64 {
|
||||
if m != nil {
|
||||
return m.TimeoutHeight
|
||||
}
|
||||
|
@ -749,31 +749,31 @@ var fileDescriptor_9b35c9d5d6b7bce8 = []byte{
|
|||
0x1b, 0x7a, 0xf5, 0x48, 0xd0, 0x09, 0xf4, 0x33, 0x22, 0x44, 0x94, 0xea, 0xe2, 0xed, 0xf1, 0xf6,
|
||||
0xe9, 0x43, 0xbf, 0x9e, 0xb3, 0xdf, 0xcc, 0xd9, 0x3f, 0x63, 0x15, 0x5e, 0xb3, 0x10, 0x82, 0x4e,
|
||||
0x46, 0xb2, 0x7a, 0x72, 0x0e, 0xd6, 0xb6, 0x2a, 0x51, 0xd2, 0x8c, 0xf0, 0x42, 0x86, 0x0b, 0x42,
|
||||
0xd3, 0x85, 0xd4, 0xff, 0xc1, 0xc6, 0xbb, 0x06, 0xbd, 0xd0, 0x20, 0x9a, 0xc0, 0x7d, 0x52, 0x4a,
|
||||
0xc2, 0x04, 0xe5, 0x2c, 0xe4, 0x2b, 0x49, 0x39, 0x13, 0xee, 0xbf, 0x5b, 0x6f, 0x90, 0xbd, 0xb7,
|
||||
0xe6, 0x7f, 0x57, 0xd3, 0xd1, 0x53, 0xf0, 0x18, 0x67, 0x61, 0x92, 0x53, 0x49, 0x93, 0x68, 0x19,
|
||||
0xde, 0x92, 0x70, 0xff, 0x0d, 0x09, 0x0f, 0x19, 0x67, 0xe7, 0x26, 0xf6, 0xab, 0x57, 0x72, 0x8f,
|
||||
0xe6, 0xd0, 0x6f, 0xb6, 0x0f, 0x7d, 0x0a, 0x3b, 0x6a, 0xe2, 0x24, 0xd7, 0xa3, 0x6b, 0x9a, 0xf3,
|
||||
0xce, 0xc6, 0xa2, 0x4e, 0xb5, 0x5b, 0xaf, 0xea, 0xb6, 0x58, 0xdb, 0x02, 0x0d, 0xc1, 0x9e, 0x13,
|
||||
0x62, 0x36, 0x7b, 0x6f, 0x23, 0xe0, 0x11, 0x21, 0x58, 0xb9, 0x46, 0x57, 0x00, 0x2f, 0x83, 0xd1,
|
||||
0x27, 0x00, 0xab, 0x22, 0x5e, 0xd2, 0x24, 0x7c, 0x46, 0x9a, 0xe3, 0x71, 0x9b, 0x30, 0x73, 0xb7,
|
||||
0xdf, 0x6b, 0xc2, 0xd7, 0xa4, 0xc2, 0xce, 0xaa, 0x31, 0xd5, 0x21, 0x65, 0x7c, 0x46, 0x5e, 0x77,
|
||||
0x48, 0x4f, 0xf8, 0x8c, 0xd4, 0x87, 0x94, 0x19, 0x6b, 0xf4, 0x7b, 0x1b, 0xfa, 0x0d, 0x8c, 0x3e,
|
||||
0x86, 0x9e, 0xa0, 0x2c, 0x5d, 0x12, 0xa3, 0x39, 0xb8, 0x25, 0xd6, 0x9f, 0x6a, 0xc6, 0x45, 0x0b,
|
||||
0x1b, 0x2e, 0xfa, 0x10, 0xba, 0x59, 0xb1, 0x94, 0xd4, 0x08, 0x1e, 0xdc, 0x16, 0xf4, 0x44, 0x11,
|
||||
0x2e, 0x5a, 0xb8, 0x66, 0x0e, 0x3e, 0x83, 0x5e, 0x9d, 0x06, 0x05, 0xd0, 0x51, 0xb5, 0x68, 0xc1,
|
||||
0xbd, 0xd3, 0xc3, 0x8d, 0xd8, 0xe6, 0x53, 0xa3, 0xfa, 0xa2, 0xf2, 0x60, 0x4d, 0x1c, 0x5c, 0x41,
|
||||
0x57, 0x27, 0x43, 0x9f, 0x43, 0x3f, 0xa6, 0x32, 0xca, 0xf3, 0xa8, 0x69, 0x91, 0xf7, 0x4a, 0x8b,
|
||||
0xce, 0x79, 0xb6, 0x8a, 0x12, 0x39, 0xa1, 0xf2, 0x4c, 0xb1, 0xf0, 0x9a, 0x8f, 0x4e, 0x01, 0xd6,
|
||||
0x7d, 0x52, 0xe7, 0x67, 0xbf, 0xae, 0x51, 0x4e, 0xd3, 0x28, 0x31, 0xe9, 0x82, 0x2d, 0x8a, 0x6c,
|
||||
0xf4, 0x13, 0xd8, 0x8f, 0x08, 0x41, 0x3f, 0x40, 0x2f, 0xca, 0xd4, 0x09, 0x99, 0x35, 0xd8, 0x69,
|
||||
0xa2, 0xcf, 0x39, 0x65, 0x93, 0x93, 0xe7, 0x7f, 0x1d, 0xb5, 0x7e, 0xfb, 0xfb, 0x68, 0x9c, 0x52,
|
||||
0xb9, 0x28, 0x62, 0x3f, 0xe1, 0x59, 0xf0, 0xbf, 0x2f, 0xec, 0x07, 0x62, 0xf6, 0x2c, 0x90, 0xd5,
|
||||
0x8a, 0xd4, 0x01, 0x02, 0x9b, 0x6c, 0xe8, 0x10, 0x9c, 0x34, 0x12, 0xe1, 0x92, 0x66, 0x54, 0xea,
|
||||
0x86, 0x76, 0x70, 0x3f, 0x8d, 0xc4, 0x37, 0xea, 0x3d, 0xf9, 0xe2, 0xf9, 0xb5, 0x67, 0xbd, 0xb8,
|
||||
0xf6, 0xac, 0x7f, 0xae, 0x3d, 0xeb, 0x97, 0x1b, 0xaf, 0xf5, 0xe2, 0xc6, 0x6b, 0xfd, 0x79, 0xe3,
|
||||
0xb5, 0x9e, 0x1e, 0xdf, 0x2d, 0x14, 0xc8, 0x32, 0xee, 0xe9, 0xcd, 0xff, 0xe8, 0xbf, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x40, 0xba, 0x1f, 0xb6, 0x40, 0x06, 0x00, 0x00,
|
||||
0xd3, 0x85, 0xd4, 0xff, 0xa1, 0x83, 0x77, 0x0d, 0x7a, 0xa1, 0x41, 0x34, 0x81, 0xfb, 0xa4, 0x94,
|
||||
0x84, 0x09, 0xca, 0x59, 0xc8, 0x57, 0x92, 0x72, 0x26, 0xdc, 0x7f, 0xb7, 0xde, 0x20, 0x7b, 0x6f,
|
||||
0xcd, 0xff, 0xae, 0xa6, 0xa3, 0xa7, 0xe0, 0x31, 0xce, 0xc2, 0x24, 0xa7, 0x92, 0x26, 0xd1, 0x32,
|
||||
0xbc, 0x25, 0xe1, 0xfe, 0x1b, 0x12, 0x1e, 0x32, 0xce, 0xce, 0x4d, 0xec, 0x57, 0xaf, 0xe4, 0x1e,
|
||||
0xcd, 0xa1, 0xdf, 0x6c, 0x1f, 0xfa, 0x14, 0x76, 0xd4, 0xc4, 0x49, 0xae, 0x47, 0xd7, 0x34, 0xe7,
|
||||
0x9d, 0x8d, 0x45, 0x9d, 0x6a, 0xb7, 0x5e, 0xd5, 0x6d, 0xb1, 0xb6, 0x05, 0x1a, 0x82, 0x3d, 0x27,
|
||||
0xc4, 0x6c, 0xf6, 0xde, 0x46, 0xc0, 0x23, 0x42, 0xb0, 0x72, 0x8d, 0xae, 0x00, 0x5e, 0x06, 0xa3,
|
||||
0x4f, 0x00, 0x56, 0x45, 0xbc, 0xa4, 0x49, 0xf8, 0x8c, 0x34, 0xc7, 0xe3, 0x36, 0x61, 0xe6, 0x6e,
|
||||
0xbf, 0xd7, 0x84, 0xaf, 0x49, 0x85, 0x9d, 0x55, 0x63, 0xaa, 0x43, 0xca, 0xf8, 0x8c, 0xbc, 0xee,
|
||||
0x90, 0x9e, 0xf0, 0x19, 0xa9, 0x0f, 0x29, 0x33, 0xd6, 0xe8, 0xf7, 0x36, 0xf4, 0x1b, 0x18, 0x7d,
|
||||
0x0c, 0x3d, 0x41, 0x59, 0xba, 0x24, 0x46, 0x73, 0x70, 0x4b, 0xac, 0x3f, 0xd5, 0x8c, 0x8b, 0x16,
|
||||
0x36, 0x5c, 0xf4, 0x21, 0x74, 0xb3, 0x62, 0x29, 0xa9, 0x11, 0x3c, 0xb8, 0x2d, 0xe8, 0x89, 0x22,
|
||||
0x5c, 0xb4, 0x70, 0xcd, 0x1c, 0x7c, 0x06, 0xbd, 0x3a, 0x0d, 0x0a, 0xa0, 0xa3, 0x6a, 0xd1, 0x82,
|
||||
0x7b, 0xa7, 0x87, 0x1b, 0xb1, 0xcd, 0xa7, 0x46, 0xf5, 0x45, 0xe5, 0xc1, 0x9a, 0x38, 0xb8, 0x82,
|
||||
0xae, 0x4e, 0x86, 0x3e, 0x87, 0x7e, 0x4c, 0x65, 0x94, 0xe7, 0x51, 0xd3, 0x22, 0xef, 0x95, 0x16,
|
||||
0x9d, 0xf3, 0x6c, 0x15, 0x25, 0x72, 0x42, 0xe5, 0x99, 0x62, 0xe1, 0x35, 0x1f, 0x9d, 0x02, 0xac,
|
||||
0xfb, 0xa4, 0xce, 0xcf, 0x7e, 0x5d, 0xa3, 0x9c, 0xa6, 0x51, 0x62, 0xd2, 0x05, 0x5b, 0x14, 0xd9,
|
||||
0xe8, 0x27, 0xb0, 0x1f, 0x11, 0x82, 0x7e, 0x80, 0x5e, 0x94, 0xa9, 0x13, 0x32, 0x6b, 0xb0, 0xd3,
|
||||
0x44, 0x9f, 0x73, 0xca, 0x26, 0x27, 0xcf, 0xff, 0x3a, 0x6a, 0xfd, 0xf6, 0xf7, 0xd1, 0x38, 0xa5,
|
||||
0x72, 0x51, 0xc4, 0x7e, 0xc2, 0xb3, 0xe0, 0x7f, 0x5f, 0xd8, 0x0f, 0xc4, 0xec, 0x59, 0x20, 0xab,
|
||||
0x15, 0xa9, 0x03, 0x04, 0x36, 0xd9, 0xd0, 0x21, 0x38, 0x69, 0x24, 0xc2, 0x25, 0xcd, 0xa8, 0xd4,
|
||||
0x0d, 0xed, 0xe0, 0x7e, 0x1a, 0x89, 0x6f, 0xd4, 0x7b, 0xf2, 0xc5, 0xf3, 0x6b, 0xcf, 0x7a, 0x71,
|
||||
0xed, 0x59, 0xff, 0x5c, 0x7b, 0xd6, 0x2f, 0x37, 0x5e, 0xeb, 0xc5, 0x8d, 0xd7, 0xfa, 0xf3, 0xc6,
|
||||
0x6b, 0x3d, 0x3d, 0xbe, 0x5b, 0x28, 0x90, 0x65, 0xdc, 0xd3, 0x9b, 0xff, 0xd1, 0x7f, 0x01, 0x00,
|
||||
0x00, 0xff, 0xff, 0x8a, 0xb6, 0xa1, 0x83, 0x40, 0x06, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Tx) Marshal() (dAtA []byte, err error) {
|
||||
|
@ -2157,7 +2157,7 @@ func (m *TxBody) Unmarshal(dAtA []byte) error {
|
|||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.TimeoutHeight |= int64(b&0x7F) << shift
|
||||
m.TimeoutHeight |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
|
|
|
@ -69,6 +69,14 @@ type (
|
|||
Tx
|
||||
GetMemo() string
|
||||
}
|
||||
|
||||
// TxWithTimeoutHeight extends the Tx interface by allowing a transaction to
|
||||
// set a height timeout.
|
||||
TxWithTimeoutHeight interface {
|
||||
Tx
|
||||
|
||||
GetTimeoutHeight() uint64
|
||||
}
|
||||
)
|
||||
|
||||
// TxDecoder unmarshals transaction bytes
|
||||
|
@ -76,5 +84,3 @@ type TxDecoder func(txBytes []byte) (Tx, error)
|
|||
|
||||
// TxEncoder marshals transaction to bytes
|
||||
type TxEncoder func(tx Tx) ([]byte, error)
|
||||
|
||||
//__________________________________________________________
|
||||
|
|
|
@ -18,6 +18,7 @@ func NewAnteHandler(
|
|||
NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewMempoolFeeDecorator(),
|
||||
NewValidateBasicDecorator(),
|
||||
TxTimeoutHeightDecorator{},
|
||||
NewValidateMemoDecorator(ak),
|
||||
NewConsumeGasForTxSizeDecorator(ak),
|
||||
NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
|
||||
|
|
|
@ -3,12 +3,11 @@ package ante
|
|||
import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/legacy"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
|
@ -141,3 +140,37 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim
|
|||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
type (
|
||||
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
|
||||
// tx height timeout.
|
||||
TxTimeoutHeightDecorator struct{}
|
||||
|
||||
// TxWithTimeoutHeight defines the interface a tx must implement in order for
|
||||
// TxHeightTimeoutDecorator to process the tx.
|
||||
TxWithTimeoutHeight interface {
|
||||
sdk.Tx
|
||||
|
||||
GetTimeoutHeight() uint64
|
||||
}
|
||||
)
|
||||
|
||||
// AnteHandle implements an AnteHandler decorator for the TxHeightTimeoutDecorator
|
||||
// type where the current block height is checked against the tx's height timeout.
|
||||
// If a height timeout is provided (non-zero) and is less than the current block
|
||||
// height, then an error is returned.
|
||||
func (txh TxTimeoutHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
timeoutTx, ok := tx.(TxWithTimeoutHeight)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "expected tx to implement TxWithTimeoutHeight")
|
||||
}
|
||||
|
||||
timeoutHeight := timeoutTx.GetTimeoutHeight()
|
||||
if timeoutHeight > 0 && uint64(ctx.BlockHeight()) > timeoutHeight {
|
||||
return ctx, sdkerrors.Wrapf(
|
||||
sdkerrors.ErrTxTimeoutHeight, "block height: %d, timeout height: %d", ctx.BlockHeight(), timeoutHeight,
|
||||
)
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
|
|
@ -161,3 +161,52 @@ func (suite *AnteTestSuite) TestConsumeGasForTxSize() {
|
|||
suite.Require().Nil(err, "ConsumeTxSizeGasDecorator returned error: %v", err)
|
||||
suite.Require().True(consumedSimGas >= expectedGas, "Simulate mode underestimates gas on AnteDecorator. Simulated cost: %d, expected cost: %d", consumedSimGas, expectedGas)
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) TestTxHeightTimeoutDecorator() {
|
||||
suite.SetupTest(true)
|
||||
|
||||
antehandler := sdk.ChainAnteDecorators(ante.TxTimeoutHeightDecorator{})
|
||||
|
||||
// keys and addresses
|
||||
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||
|
||||
// msg and signatures
|
||||
msg := testdata.NewTestMsg(addr1)
|
||||
feeAmount := testdata.NewTestFeeAmount()
|
||||
gasLimit := testdata.NewTestGasLimit()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
timeout uint64
|
||||
height int64
|
||||
expectErr bool
|
||||
}{
|
||||
{"default value", 0, 10, false},
|
||||
{"no timeout (greater height)", 15, 10, false},
|
||||
{"no timeout (same height)", 10, 10, false},
|
||||
{"timeout (smaller height)", 9, 10, true},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
suite.Run(tc.name, func() {
|
||||
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
suite.Require().NoError(suite.txBuilder.SetMsgs(msg))
|
||||
|
||||
suite.txBuilder.SetFeeAmount(feeAmount)
|
||||
suite.txBuilder.SetGasLimit(gasLimit)
|
||||
suite.txBuilder.SetMemo(strings.Repeat("01234567890", 10))
|
||||
suite.txBuilder.SetTimeoutHeight(tc.timeout)
|
||||
|
||||
privs, accNums, accSeqs := []crypto.PrivKey{priv1}, []uint64{0}, []uint64{0}
|
||||
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
ctx := suite.ctx.WithBlockHeight(tc.height)
|
||||
_, err = antehandler(ctx, tx, true)
|
||||
suite.Require().Equal(tc.expectErr, err != nil, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ func (suite *AnteTestSuite) CreateTestAccounts(numAccs int) []TestAccount {
|
|||
}
|
||||
|
||||
// CreateTestTx is a helper function to create a tx given multiple inputs.
|
||||
func (suite *AnteTestSuite) CreateTestTx(privs []crypto.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (xauthsigning.SigFeeMemoTx, error) {
|
||||
func (suite *AnteTestSuite) CreateTestTx(privs []crypto.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (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
|
||||
|
|
|
@ -47,18 +47,18 @@ func DecodeTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
tx, err := clientCtx.TxConfig.TxDecoder()(txBytes)
|
||||
txI, err := clientCtx.TxConfig.TxDecoder()(txBytes)
|
||||
if rest.CheckBadRequestError(w, err) {
|
||||
return
|
||||
}
|
||||
|
||||
sigFeeMemoTx, ok := tx.(signing.SigFeeMemoTx)
|
||||
tx, ok := txI.(signing.Tx)
|
||||
if !ok {
|
||||
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("%+v is not backwards compatible with %T", tx, authtypes.StdTx{}))
|
||||
return
|
||||
}
|
||||
|
||||
stdTx, err := clienttx.ConvertTxToStdTx(clientCtx.Codec, sigFeeMemoTx)
|
||||
stdTx, err := clienttx.ConvertTxToStdTx(clientCtx.Codec, tx)
|
||||
if rest.CheckBadRequestError(w, err) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
)
|
||||
|
||||
// SigVerifiableTx defines a Tx interface for all signature verification decorators
|
||||
// SigVerifiableTx defines a transaction interface for all signature verification
|
||||
// handlers.
|
||||
type SigVerifiableTx interface {
|
||||
types.Tx
|
||||
GetSigners() []types.AccAddress
|
||||
|
@ -16,10 +17,12 @@ type SigVerifiableTx interface {
|
|||
GetSignaturesV2() ([]signing.SignatureV2, error)
|
||||
}
|
||||
|
||||
// SigFeeMemoTx defines an interface for transactions that support all standard message, signature,
|
||||
// fee and memo interfaces.
|
||||
type SigFeeMemoTx interface {
|
||||
// Tx defines a transaction interface that supports all standard message, signature
|
||||
// fee, memo, and auxiliary interfaces.
|
||||
type Tx interface {
|
||||
SigVerifiableTx
|
||||
|
||||
types.TxWithMemo
|
||||
types.FeeTx
|
||||
types.TxWithTimeoutHeight
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@ package signing_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
@ -12,6 +10,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
"github.com/cosmos/cosmos-sdk/simapp"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
|
@ -50,8 +49,7 @@ func TestVerifySignature(t *testing.T) {
|
|||
AccountNumber: acc.GetAccountNumber(),
|
||||
AccountSequence: acc.GetSequence(),
|
||||
}
|
||||
signBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.AccountSequence,
|
||||
fee, msgs, memo)
|
||||
signBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.AccountSequence, 10, fee, msgs, memo)
|
||||
signature, err := priv.Sign(signBytes)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -61,6 +59,7 @@ func TestVerifySignature(t *testing.T) {
|
|||
|
||||
handler := MakeTestHandlerMap()
|
||||
stdTx := types.NewStdTx(msgs, fee, []types.StdSignature{stdSig}, memo)
|
||||
stdTx.TimeoutHeight = 10
|
||||
err = signing.VerifySignature(pubKey, signerData, sigV2.Data, handler, stdTx)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -68,8 +67,7 @@ func TestVerifySignature(t *testing.T) {
|
|||
multisigKey := multisig.NewPubKeyMultisigThreshold(2, pkSet)
|
||||
multisignature := multisig.NewMultisig(2)
|
||||
msgs = []sdk.Msg{testdata.NewTestMsg(addr, addr1)}
|
||||
multiSignBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.AccountSequence,
|
||||
fee, msgs, memo)
|
||||
multiSignBytes := types.StdSignBytes(signerData.ChainID, signerData.AccountNumber, signerData.AccountSequence, 10, fee, msgs, memo)
|
||||
|
||||
sig1, err := priv.Sign(multiSignBytes)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -58,12 +58,13 @@ will only be executable once on a particular blockchain.
|
|||
`json.RawMessage` is preferred over using the SDK types for future compatibility.
|
||||
|
||||
```go
|
||||
type StdSignDoc struct {
|
||||
AccountNumber uint64
|
||||
type StdSignMsg struct {
|
||||
ChainID string
|
||||
Fee json.RawMessage
|
||||
Memo string
|
||||
Msgs []json.RawMessage
|
||||
AccountNumber uint64
|
||||
Sequence uint64
|
||||
TimeoutHeight uint64
|
||||
Fee StdFee
|
||||
Msgs []sdk.Msg
|
||||
Memo string
|
||||
}
|
||||
```
|
||||
|
|
|
@ -38,8 +38,8 @@ type builder struct {
|
|||
}
|
||||
|
||||
var (
|
||||
_ authsigning.SigFeeMemoTx = &builder{}
|
||||
_ client.TxBuilder = &builder{}
|
||||
_ authsigning.Tx = &builder{}
|
||||
_ client.TxBuilder = &builder{}
|
||||
)
|
||||
|
||||
func newBuilder(pubkeyCodec types.PublicKeyCodec) *builder {
|
||||
|
@ -212,6 +212,11 @@ func (t *builder) GetSignatures() [][]byte {
|
|||
return t.tx.Signatures
|
||||
}
|
||||
|
||||
// GetTimeoutHeight returns the transaction's timeout height (if set).
|
||||
func (t *builder) GetTimeoutHeight() uint64 {
|
||||
return t.tx.Body.TimeoutHeight
|
||||
}
|
||||
|
||||
func (t *builder) GetSignaturesV2() ([]signing.SignatureV2, error) {
|
||||
signerInfos := t.tx.AuthInfo.SignerInfos
|
||||
sigs := t.tx.Signatures
|
||||
|
@ -253,6 +258,14 @@ func (t *builder) SetMsgs(msgs ...sdk.Msg) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetTimeoutHeight sets the transaction's height timeout.
|
||||
func (t *builder) SetTimeoutHeight(height uint64) {
|
||||
t.tx.Body.TimeoutHeight = height
|
||||
|
||||
// set bodyBz to nil because the cached bodyBz no longer matches tx.Body
|
||||
t.bodyBz = nil
|
||||
}
|
||||
|
||||
func (t *builder) SetMemo(memo string) {
|
||||
t.tx.Body.Memo = memo
|
||||
|
||||
|
@ -375,6 +388,6 @@ func (t *builder) setSignatures(sigs [][]byte) {
|
|||
t.tx.Signatures = sigs
|
||||
}
|
||||
|
||||
func (t *builder) GetTx() authsigning.SigFeeMemoTx {
|
||||
func (t *builder) GetTx() authsigning.Tx {
|
||||
return t
|
||||
}
|
||||
|
|
|
@ -4,18 +4,15 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
|
||||
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
|
|
|
@ -11,7 +11,12 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
// signModeLegacyAminoJSONHandler defines the SIGN_MODE_LEGACY_AMINO_JSON SignModeHandler
|
||||
const aminoNonCriticalFieldsError = "protobuf transaction contains unknown non-critical fields. This is a transaction malleability issue and SIGN_MODE_LEGACY_AMINO_JSON cannot be used."
|
||||
|
||||
var _ signing.SignModeHandler = signModeLegacyAminoJSONHandler{}
|
||||
|
||||
// signModeLegacyAminoJSONHandler defines the SIGN_MODE_LEGACY_AMINO_JSON
|
||||
// SignModeHandler.
|
||||
type signModeLegacyAminoJSONHandler struct{}
|
||||
|
||||
func (s signModeLegacyAminoJSONHandler) DefaultMode() signingtypes.SignMode {
|
||||
|
@ -22,8 +27,6 @@ func (s signModeLegacyAminoJSONHandler) Modes() []signingtypes.SignMode {
|
|||
return []signingtypes.SignMode{signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON}
|
||||
}
|
||||
|
||||
const aminoNonCriticalFieldsError = "protobuf transaction contains unknown non-critical fields. This is a transaction malleability issue and SIGN_MODE_LEGACY_AMINO_JSON cannot be used."
|
||||
|
||||
func (s signModeLegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode, data signing.SignerData, tx sdk.Tx) ([]byte, error) {
|
||||
if mode != signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON {
|
||||
return nil, fmt.Errorf("expected %s, got %s", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, mode)
|
||||
|
@ -41,21 +44,13 @@ func (s signModeLegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode,
|
|||
body := protoTx.tx.Body
|
||||
|
||||
if len(body.ExtensionOptions) != 0 || len(body.NonCriticalExtensionOptions) != 0 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"SIGN_MODE_LEGACY_AMINO_JSON does not support protobuf extension options.")
|
||||
}
|
||||
|
||||
if body.TimeoutHeight != 0 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"SIGN_MODE_LEGACY_AMINO_JSON does not support timeout height.")
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "SIGN_MODE_LEGACY_AMINO_JSON does not support protobuf extension options.")
|
||||
}
|
||||
|
||||
// nolint: staticcheck
|
||||
return types.StdSignBytes(
|
||||
data.ChainID, data.AccountNumber, data.AccountSequence,
|
||||
//nolint:staticcheck
|
||||
data.ChainID, data.AccountNumber, data.AccountSequence, protoTx.GetTimeoutHeight(),
|
||||
types.StdFee{Amount: protoTx.GetFee(), Gas: protoTx.GetGas()},
|
||||
tx.GetMsgs(), protoTx.GetMemo(),
|
||||
), nil
|
||||
}
|
||||
|
||||
var _ signing.SignModeHandler = signModeLegacyAminoJSONHandler{}
|
||||
|
|
|
@ -3,10 +3,9 @@ package tx
|
|||
import (
|
||||
"testing"
|
||||
|
||||
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
@ -19,16 +18,18 @@ var (
|
|||
_, _, addr1 = testdata.KeyTestPubAddr()
|
||||
_, _, addr2 = testdata.KeyTestPubAddr()
|
||||
|
||||
coins = sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}
|
||||
gas = uint64(10000)
|
||||
msg = testdata.NewTestMsg(addr1, addr2)
|
||||
memo = "foo"
|
||||
coins = sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}
|
||||
gas = uint64(10000)
|
||||
msg = testdata.NewTestMsg(addr1, addr2)
|
||||
memo = "foo"
|
||||
timeout = uint64(10)
|
||||
)
|
||||
|
||||
func buildTx(t *testing.T, bldr *builder) {
|
||||
bldr.SetFeeAmount(coins)
|
||||
bldr.SetGasLimit(gas)
|
||||
bldr.SetMemo(memo)
|
||||
bldr.SetTimeoutHeight(timeout)
|
||||
require.NoError(t, bldr.SetMsgs(msg))
|
||||
}
|
||||
|
||||
|
@ -52,7 +53,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
|||
signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSignBz := types.StdSignBytes(chainId, accNum, seqNum, types.StdFee{
|
||||
expectedSignBz := types.StdSignBytes(chainId, accNum, seqNum, timeout, types.StdFee{
|
||||
Amount: coins,
|
||||
Gas: gas,
|
||||
}, []sdk.Msg{msg}, memo)
|
||||
|
@ -63,14 +64,6 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
|||
_, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_DIRECT, signingData, tx)
|
||||
require.Error(t, err)
|
||||
|
||||
// expect error with timeout height
|
||||
bldr = newBuilder(std.DefaultPublicKeyCodec{})
|
||||
buildTx(t, bldr)
|
||||
bldr.tx.Body.TimeoutHeight = 10
|
||||
tx = bldr.GetTx()
|
||||
signBz, err = handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
||||
require.Error(t, err)
|
||||
|
||||
// expect error with extension options
|
||||
bldr = newBuilder(std.DefaultPublicKeyCodec{})
|
||||
buildTx(t, bldr)
|
||||
|
|
|
@ -39,6 +39,6 @@ func (stdTxSignModeHandler) GetSignBytes(mode signingtypes.SignMode, data signin
|
|||
}
|
||||
|
||||
return StdSignBytes(
|
||||
data.ChainID, data.AccountNumber, data.AccountSequence, StdFee{Amount: stdTx.GetFee(), Gas: stdTx.GetGas()}, tx.GetMsgs(), stdTx.GetMemo(),
|
||||
data.ChainID, data.AccountNumber, data.AccountSequence, stdTx.GetTimeoutHeight(), StdFee{Amount: stdTx.GetFee(), Gas: stdTx.GetGas()}, tx.GetMsgs(), stdTx.GetMemo(),
|
||||
), nil
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
@ -30,19 +29,21 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
|||
testdata.NewTestMsg(addr1, addr2),
|
||||
}
|
||||
|
||||
tx := StdTx{
|
||||
Msgs: msgs,
|
||||
Fee: fee,
|
||||
Signatures: nil,
|
||||
Memo: memo,
|
||||
}
|
||||
|
||||
var (
|
||||
chainId = "test-chain"
|
||||
accNum uint64 = 7
|
||||
seqNum uint64 = 7
|
||||
chainId = "test-chain"
|
||||
accNum uint64 = 7
|
||||
seqNum uint64 = 7
|
||||
timeoutHeight uint64 = 10
|
||||
)
|
||||
|
||||
tx := StdTx{
|
||||
Msgs: msgs,
|
||||
Fee: fee,
|
||||
Signatures: nil,
|
||||
Memo: memo,
|
||||
TimeoutHeight: timeoutHeight,
|
||||
}
|
||||
|
||||
handler := stdTxSignModeHandler{}
|
||||
signingData := signing.SignerData{
|
||||
ChainID: chainId,
|
||||
|
@ -52,7 +53,7 @@ func TestLegacyAminoJSONHandler_GetSignBytes(t *testing.T) {
|
|||
signBz, err := handler.GetSignBytes(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signingData, tx)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSignBz := StdSignBytes(chainId, accNum, seqNum, fee, msgs, memo)
|
||||
expectedSignBz := StdSignBytes(chainId, accNum, seqNum, timeoutHeight, fee, msgs, memo)
|
||||
|
||||
require.Equal(t, expectedSignBz, signBz)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ type StdTxBuilder struct {
|
|||
var _ client.TxBuilder = &StdTxBuilder{}
|
||||
|
||||
// GetTx implements TxBuilder.GetTx
|
||||
func (s *StdTxBuilder) GetTx() authsigning.SigFeeMemoTx {
|
||||
func (s *StdTxBuilder) GetTx() authsigning.Tx {
|
||||
return s.StdTx
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,11 @@ func (s *StdTxBuilder) SetMemo(memo string) {
|
|||
s.Memo = memo
|
||||
}
|
||||
|
||||
// SetTimeoutHeight sets the transaction's height timeout.
|
||||
func (s *StdTxBuilder) SetTimeoutHeight(height uint64) {
|
||||
s.TimeoutHeight = height
|
||||
}
|
||||
|
||||
// StdTxConfig is a context.TxConfig for StdTx
|
||||
type StdTxConfig struct {
|
||||
Cdc *codec.Codec
|
||||
|
|
|
@ -5,13 +5,15 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// StdSignMsg is a convenience structure for passing along
|
||||
// a Msg with the other requirements for a StdSignDoc before
|
||||
// it is signed. For use in the CLI.
|
||||
var _ types.UnpackInterfacesMessage = StdSignMsg{}
|
||||
|
||||
// StdSignMsg is a convenience structure for passing along a Msg with the other
|
||||
// requirements for a StdSignDoc before it is signed. For use in the CLI.
|
||||
type StdSignMsg struct {
|
||||
ChainID string `json:"chain_id" yaml:"chain_id"`
|
||||
AccountNumber uint64 `json:"account_number" yaml:"account_number"`
|
||||
Sequence uint64 `json:"sequence" yaml:"sequence"`
|
||||
TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"`
|
||||
Fee StdFee `json:"fee" yaml:"fee"`
|
||||
Msgs []sdk.Msg `json:"msgs" yaml:"msgs"`
|
||||
Memo string `json:"memo" yaml:"memo"`
|
||||
|
@ -19,11 +21,9 @@ type StdSignMsg struct {
|
|||
|
||||
// get message bytes
|
||||
func (msg StdSignMsg) Bytes() []byte {
|
||||
return StdSignBytes(msg.ChainID, msg.AccountNumber, msg.Sequence, msg.Fee, msg.Msgs, msg.Memo)
|
||||
return StdSignBytes(msg.ChainID, msg.AccountNumber, msg.Sequence, msg.TimeoutHeight, msg.Fee, msg.Msgs, msg.Memo)
|
||||
}
|
||||
|
||||
var _ types.UnpackInterfacesMessage = StdSignMsg{}
|
||||
|
||||
func (msg StdSignMsg) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
||||
for _, m := range msg.Msgs {
|
||||
err := types.UnpackInterfaces(m, unpacker)
|
||||
|
@ -31,5 +31,6 @@ func (msg StdSignMsg) UnpackInterfaces(unpacker types.AnyUnpacker) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -139,10 +139,11 @@ var _ sdk.Tx = (*StdTx)(nil)
|
|||
// 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"`
|
||||
Fee StdFee `json:"fee" yaml:"fee"`
|
||||
Signatures []StdSignature `json:"signatures" yaml:"signatures"`
|
||||
Memo string `json:"memo" yaml:"memo"`
|
||||
Msgs []sdk.Msg `json:"msg" yaml:"msg"`
|
||||
Fee StdFee `json:"fee" yaml:"fee"`
|
||||
Signatures []StdSignature `json:"signatures" yaml:"signatures"`
|
||||
Memo string `json:"memo" yaml:"memo"`
|
||||
TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"`
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
|
@ -212,6 +213,11 @@ func (tx StdTx) GetSigners() []sdk.AccAddress {
|
|||
// GetMemo returns the memo
|
||||
func (tx StdTx) GetMemo() string { return tx.Memo }
|
||||
|
||||
// GetTimeoutHeight returns the transaction's timeout height (if set).
|
||||
func (tx StdTx) GetTimeoutHeight() uint64 {
|
||||
return tx.TimeoutHeight
|
||||
}
|
||||
|
||||
// GetSignatures returns the signature of signers who signed the Msg.
|
||||
// CONTRACT: Length returned is same as length of
|
||||
// pubkeys returned from MsgKeySigners, and the order
|
||||
|
@ -277,15 +283,16 @@ func (tx StdTx) FeePayer() sdk.AccAddress {
|
|||
// inchain replay and enforce tx ordering per account).
|
||||
type StdSignDoc struct {
|
||||
AccountNumber uint64 `json:"account_number" yaml:"account_number"`
|
||||
ChainID string `json:"chain_id" yaml:"chain_id"`
|
||||
Fee json.RawMessage `json:"fee" yaml:"fee"`
|
||||
Memo string `json:"memo" yaml:"memo"`
|
||||
Msgs []json.RawMessage `json:"msgs" yaml:"msgs"`
|
||||
Sequence uint64 `json:"sequence" yaml:"sequence"`
|
||||
TimeoutHeight uint64 `json:"timeout_height,omitempty" yaml:"timeout_height"`
|
||||
ChainID string `json:"chain_id" yaml:"chain_id"`
|
||||
Memo string `json:"memo" yaml:"memo"`
|
||||
Fee json.RawMessage `json:"fee" yaml:"fee"`
|
||||
Msgs []json.RawMessage `json:"msgs" yaml:"msgs"`
|
||||
}
|
||||
|
||||
// StdSignBytes returns the bytes to sign for a transaction.
|
||||
func StdSignBytes(chainID string, accnum uint64, sequence uint64, fee StdFee, msgs []sdk.Msg, memo string) []byte {
|
||||
func StdSignBytes(chainID string, accnum, sequence, timeout uint64, fee StdFee, msgs []sdk.Msg, memo string) []byte {
|
||||
msgsBytes := make([]json.RawMessage, 0, len(msgs))
|
||||
for _, msg := range msgs {
|
||||
msgsBytes = append(msgsBytes, json.RawMessage(msg.GetSignBytes()))
|
||||
|
@ -298,8 +305,8 @@ func StdSignBytes(chainID string, accnum uint64, sequence uint64, fee StdFee, ms
|
|||
Memo: memo,
|
||||
Msgs: msgsBytes,
|
||||
Sequence: sequence,
|
||||
TimeoutHeight: timeout,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -4,13 +4,6 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
@ -19,8 +12,12 @@ import (
|
|||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
|
||||
"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"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -36,10 +33,10 @@ func NewTestStdFee() StdFee {
|
|||
}
|
||||
|
||||
// Deprecated, use TxBuilder.
|
||||
func NewTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []uint64, seqs []uint64, fee StdFee) sdk.Tx {
|
||||
func NewTestTx(ctx sdk.Context, msgs []sdk.Msg, privs []crypto.PrivKey, accNums []uint64, seqs []uint64, timeout uint64, fee StdFee) sdk.Tx {
|
||||
sigs := make([]StdSignature, len(privs))
|
||||
for i, priv := range privs {
|
||||
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], fee, msgs, "")
|
||||
signBytes := StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], timeout, fee, msgs, "")
|
||||
|
||||
sig, err := priv.Sign(signBytes)
|
||||
if err != nil {
|
||||
|
@ -68,12 +65,13 @@ func TestStdTx(t *testing.T) {
|
|||
|
||||
func TestStdSignBytes(t *testing.T) {
|
||||
type args struct {
|
||||
chainID string
|
||||
accnum uint64
|
||||
sequence uint64
|
||||
fee StdFee
|
||||
msgs []sdk.Msg
|
||||
memo string
|
||||
chainID string
|
||||
accnum uint64
|
||||
sequence uint64
|
||||
timeoutHeight uint64
|
||||
fee StdFee
|
||||
msgs []sdk.Msg
|
||||
memo string
|
||||
}
|
||||
defaultFee := NewTestStdFee()
|
||||
tests := []struct {
|
||||
|
@ -81,12 +79,16 @@ func TestStdSignBytes(t *testing.T) {
|
|||
want string
|
||||
}{
|
||||
{
|
||||
args{"1234", 3, 6, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo"},
|
||||
args{"1234", 3, 6, 10, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo"},
|
||||
fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150\",\"denom\":\"atom\"}],\"gas\":\"100000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\",\"timeout_height\":\"10\"}", addr),
|
||||
},
|
||||
{
|
||||
args{"1234", 3, 6, 0, defaultFee, []sdk.Msg{testdata.NewTestMsg(addr)}, "memo"},
|
||||
fmt.Sprintf("{\"account_number\":\"3\",\"chain_id\":\"1234\",\"fee\":{\"amount\":[{\"amount\":\"150\",\"denom\":\"atom\"}],\"gas\":\"100000\"},\"memo\":\"memo\",\"msgs\":[[\"%s\"]],\"sequence\":\"6\"}", addr),
|
||||
},
|
||||
}
|
||||
for i, tc := range tests {
|
||||
got := string(StdSignBytes(tc.args.chainID, tc.args.accnum, tc.args.sequence, tc.args.fee, tc.args.msgs, tc.args.memo))
|
||||
got := string(StdSignBytes(tc.args.chainID, tc.args.accnum, tc.args.sequence, tc.args.timeoutHeight, tc.args.fee, tc.args.msgs, tc.args.memo))
|
||||
require.Equal(t, tc.want, got, "Got unexpected result on test case i: %d", i)
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +109,7 @@ func TestTxValidateBasic(t *testing.T) {
|
|||
// require to fail validation upon invalid fee
|
||||
badFee := NewTestStdFee()
|
||||
badFee.Amount[0].Amount = sdk.NewInt(-5)
|
||||
tx := NewTestTx(ctx, nil, nil, nil, nil, badFee)
|
||||
tx := NewTestTx(ctx, nil, nil, nil, nil, 0, badFee)
|
||||
|
||||
err := tx.ValidateBasic()
|
||||
require.Error(t, err)
|
||||
|
@ -116,7 +118,7 @@ func TestTxValidateBasic(t *testing.T) {
|
|||
|
||||
// require to fail validation when no signatures exist
|
||||
privs, accNums, seqs := []crypto.PrivKey{}, []uint64{}, []uint64{}
|
||||
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, fee)
|
||||
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, 0, fee)
|
||||
|
||||
err = tx.ValidateBasic()
|
||||
require.Error(t, err)
|
||||
|
@ -125,7 +127,7 @@ func TestTxValidateBasic(t *testing.T) {
|
|||
|
||||
// require to fail validation when signatures do not match expected signers
|
||||
privs, accNums, seqs = []crypto.PrivKey{priv1}, []uint64{0, 1}, []uint64{0, 0}
|
||||
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, fee)
|
||||
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, 0, fee)
|
||||
|
||||
err = tx.ValidateBasic()
|
||||
require.Error(t, err)
|
||||
|
@ -135,7 +137,7 @@ func TestTxValidateBasic(t *testing.T) {
|
|||
// require to fail with invalid gas supplied
|
||||
badFee = NewTestStdFee()
|
||||
badFee.Gas = 9223372036854775808
|
||||
tx = NewTestTx(ctx, nil, nil, nil, nil, badFee)
|
||||
tx = NewTestTx(ctx, nil, nil, nil, nil, 0, badFee)
|
||||
|
||||
err = tx.ValidateBasic()
|
||||
require.Error(t, err)
|
||||
|
@ -144,7 +146,7 @@ func TestTxValidateBasic(t *testing.T) {
|
|||
|
||||
// require to pass when above criteria are matched
|
||||
privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}
|
||||
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, fee)
|
||||
tx = NewTestTx(ctx, msgs, privs, accNums, seqs, 0, fee)
|
||||
|
||||
err = tx.ValidateBasic()
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -16,9 +16,9 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
flagTimeoutHeight = "timeout-height"
|
||||
flagTimeoutTimestamp = "timeout-timestamp"
|
||||
flagAbsoluteTimeouts = "absolute-timeouts"
|
||||
flagPacketTimeoutHeight = "packet-timeout-height"
|
||||
flagPacketTimeoutTimestamp = "packet-timeout-timestamp"
|
||||
flagAbsoluteTimeouts = "absolute-timeouts"
|
||||
)
|
||||
|
||||
// NewTransferTxCmd returns the command to create a NewMsgTransfer transaction
|
||||
|
@ -49,12 +49,12 @@ to the counterparty channel. Any timeout set to 0 is disabled.`),
|
|||
return err
|
||||
}
|
||||
|
||||
timeoutHeight, err := cmd.Flags().GetUint64(flagTimeoutHeight)
|
||||
timeoutHeight, err := cmd.Flags().GetUint64(flagPacketTimeoutHeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timeoutTimestamp, err := cmd.Flags().GetUint64(flagTimeoutHeight)
|
||||
timeoutTimestamp, err := cmd.Flags().GetUint64(flagPacketTimeoutTimestamp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -92,8 +92,8 @@ to the counterparty channel. Any timeout set to 0 is disabled.`),
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().Uint64(flagTimeoutHeight, types.DefaultRelativePacketTimeoutHeight, "Timeout block height. The timeout is disabled when set to 0.")
|
||||
cmd.Flags().Uint64(flagTimeoutTimestamp, types.DefaultRelativePacketTimeoutTimestamp, "Timeout timestamp in nanoseconds. Default is 10 minutes. The timeout is disabled when set to 0.")
|
||||
cmd.Flags().Uint64(flagPacketTimeoutHeight, types.DefaultRelativePacketTimeoutHeight, "Packet timeout block height. The timeout is disabled when set to 0.")
|
||||
cmd.Flags().Uint64(flagPacketTimeoutTimestamp, types.DefaultRelativePacketTimeoutTimestamp, "Packet timeout timestamp in nanoseconds. Default is 10 minutes. The timeout is disabled when set to 0.")
|
||||
cmd.Flags().Bool(flagAbsoluteTimeouts, false, "Timeout flags are used as absolute timeouts.")
|
||||
flags.AddTxFlagsToCmd(cmd)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue