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:
Alexander Bezobchuk 2020-08-07 19:32:22 -04:00 committed by GitHub
parent 6ebc476474
commit 9ae17669d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 891 additions and 763 deletions

View File

@ -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.

View File

@ -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))

View File

@ -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())

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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)
}
)

View File

@ -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

View File

@ -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,
}
}

View File

@ -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")

View File

@ -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"`

View File

@ -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
}

View File

@ -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)
//__________________________________________________________

View File

@ -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

View File

@ -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)
}

View File

@ -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)
})
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}
```

View File

@ -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
}

View File

@ -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"
)

View File

@ -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{}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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