Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Improvements

* (client) [#24561](https://github.com/cosmos/cosmos-sdk/pull/24561) TimeoutTimestamp flag has been changed to TimeoutDuration, which now sets the timeout timestamp of unordered transactions to the current time + duration passed.
* (telemetry) [#24541](https://github.com/cosmos/cosmos-sdk/pull/24541) Telemetry now includes a pre_blocker metric key. x/upgrade should migrate to this key in v0.54.0.
* (x/auth) [#24541](https://github.com/cosmos/cosmos-sdk/pull/24541) x/auth's PreBlocker now emits telemetry under the pre_blocker metric key.
* (x/bank) [#24431](https://github.com/cosmos/cosmos-sdk/pull/24431) Reduce the number of `ValidateDenom` calls in `bank.SendCoins` and `Coin`.
Expand Down
12 changes: 6 additions & 6 deletions client/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const (
FlagOffset = "offset"
FlagCountTotal = "count-total"
FlagTimeoutHeight = "timeout-height"
FlagTimeoutTimestamp = "timeout-timestamp"
TimeoutDuration = "timeout-duration"
FlagUnordered = "unordered"
FlagKeyAlgorithm = "algo"
FlagKeyType = "key-type"
Expand Down Expand Up @@ -137,9 +137,9 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
f.Bool(FlagOffline, false, "Offline mode (does not allow any online functionality)")
f.BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation")
f.String(FlagSignMode, "", "Choose sign mode (direct|amino-json|direct-aux|textual), this is an advanced feature")
f.Uint64(FlagTimeoutHeight, 0, "DEPRECATED: Please use --timeout-timestamp instead. Set a block timeout height to prevent the tx from being committed past a certain height")
f.Int64(FlagTimeoutTimestamp, 0, "Set a block timeout timestamp to prevent the tx from being committed past a certain time")
f.Bool(FlagUnordered, false, "Enable unordered transaction delivery; must be used in conjunction with --timeout-timestamp")
f.Uint64(FlagTimeoutHeight, 0, "DEPRECATED: Please use --timeout-duration instead. Set a block timeout height to prevent the tx from being committed past a certain height")
f.Duration(TimeoutDuration, 0, "TimeoutDuration is the duration the transaction will be considered valid in the mempool. If the transaction is still in the mempool, and the block time has passed the time of submission + TimeoutTimestamp, the transaction will be rejected.")
f.Bool(FlagUnordered, false, "Enable unordered transaction delivery; must be used in conjunction with --timeout-duration")
f.String(FlagFeePayer, "", "Fee payer pays fees for the transaction instead of deducting from the signer")
f.String(FlagFeeGranter, "", "Fee granter grants fees for the transaction")
f.String(FlagTip, "", "Tip is the amount that is going to be transferred to the fee payer on the target chain. This flag is only valid when used with --aux, and is ignored if the target chain didn't enable the TipDecorator")
Expand All @@ -149,8 +149,8 @@ func AddTxFlagsToCmd(cmd *cobra.Command) {
f.String(FlagGas, "", fmt.Sprintf("gas limit to set per-transaction; set to %q to calculate sufficient gas automatically. Note: %q option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of %q. (default %d)",
GasFlagAuto, GasFlagAuto, FlagFees, DefaultGasLimit))

cmd.MarkFlagsMutuallyExclusive(FlagTimeoutHeight, FlagTimeoutTimestamp)
cmd.MarkFlagsRequiredTogether(FlagUnordered, FlagTimeoutTimestamp)
cmd.MarkFlagsMutuallyExclusive(FlagTimeoutHeight, TimeoutDuration)
cmd.MarkFlagsRequiredTogether(FlagUnordered, TimeoutDuration)

AddKeyringFlags(f)
}
Expand Down
7 changes: 5 additions & 2 deletions client/tx/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,11 @@

gasAdj := clientCtx.Viper.GetFloat64(flags.FlagGasAdjustment)
memo := clientCtx.Viper.GetString(flags.FlagNote)
timestampUnix := clientCtx.Viper.GetInt64(flags.FlagTimeoutTimestamp)
timeoutTimestamp := time.Unix(timestampUnix, 0)
timeout := clientCtx.Viper.GetDuration(flags.TimeoutDuration)
var timeoutTimestamp time.Time
if timeout > 0 {
timeoutTimestamp = time.Now().Add(timeout)

Check warning

Code scanning / CodeQL

Calling the system time Warning

Calling the system time may be a possible source of non-determinism
}
timeoutHeight := clientCtx.Viper.GetUint64(flags.FlagTimeoutHeight)
unordered := clientCtx.Viper.GetBool(flags.FlagUnordered)

Expand Down
1 change: 1 addition & 0 deletions systemtests/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ func (c CLIWrapper) RunAndWait(args ...string) string {
// RunCommandWithArgs use for run cli command, not tx
func (c CLIWrapper) RunCommandWithArgs(args ...string) string {
c.t.Helper()
args = c.WithKeyringFlags(args...)
execOutput, _ := c.run(args)
return execOutput
}
Expand Down
38 changes: 22 additions & 16 deletions tests/systemtests/unordered_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/cosmos/cosmos-sdk/testutil"

Check failure on line 10 in tests/systemtests/unordered_tx_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

File is not properly formatted (gci)

Check failure on line 10 in tests/systemtests/unordered_tx_test.go

View workflow job for this annotation

GitHub Actions / Analyze

File is not properly formatted (gci)
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"

Expand All @@ -17,8 +17,8 @@
func TestUnorderedTXDuplicate(t *testing.T) {
// scenario: test unordered tx duplicate
// given a running chain with a tx in the unordered tx pool
// when a new tx with the same hash is broadcasted
// then the new tx should be rejected
// when a new tx with the same unordered nonce is broadcasted,
// then the new tx should be rejected.

systest.Sut.ResetChain(t)
cli := systest.NewCLIWrapper(t, systest.Sut, systest.Verbose)
Expand All @@ -31,22 +31,28 @@

systest.Sut.StartChain(t)

timeoutTimestamp := time.Now().Add(time.Minute)
// send tokens
cmd := []string{"tx", "bank", "send", account1Addr, account2Addr, "5000stake", "--from=" + account1Addr, "--fees=1stake", fmt.Sprintf("--timeout-timestamp=%v", timeoutTimestamp.Unix()), "--unordered", "--sequence=1", "--note=1"}
rsp1 := cli.Run(cmd...)
cmd := []string{"tx", "bank", "send", account1Addr, account2Addr, "5000stake", "--from=" + account1Addr, "--fees=1stake", "--timeout-duration=5m", "--unordered", "--note=1", "--chain-id=testing", "--generate-only"}
rsp1 := cli.RunCommandWithArgs(cmd...)
txFile := testutil.TempFile(t)
_, err := txFile.WriteString(rsp1)
require.NoError(t, err)

signCmd := []string{"tx", "sign", txFile.Name(), "--from=" + account1Addr, "--chain-id=testing"}
rsp1 = cli.RunCommandWithArgs(signCmd...)
signedFile := testutil.TempFile(t)
signedFile.WriteString(rsp1)

Check failure on line 44 in tests/systemtests/unordered_tx_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Error return value of `signedFile.WriteString` is not checked (errcheck)

Check failure on line 44 in tests/systemtests/unordered_tx_test.go

View workflow job for this annotation

GitHub Actions / Analyze

Error return value of `signedFile.WriteString` is not checked (errcheck)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Properly implemented transaction signing step

The explicit signing step is correctly implemented using the transaction file and chain ID. Note that line 44 is missing error handling for the file write operation.

Add error handling for the file write operation:

-signedFile.WriteString(rsp1)
+_, err = signedFile.WriteString(rsp1)
+require.NoError(t, err)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
signCmd := []string{"tx", "sign", txFile.Name(), "--from=" + account1Addr, "--chain-id=testing"}
rsp1 = cli.RunCommandWithArgs(signCmd...)
signedFile := testutil.TempFile(t)
signedFile.WriteString(rsp1)
signCmd := []string{"tx", "sign", txFile.Name(), "--from=" + account1Addr, "--chain-id=testing"}
rsp1 = cli.RunCommandWithArgs(signCmd...)
signedFile := testutil.TempFile(t)
_, err = signedFile.WriteString(rsp1)
require.NoError(t, err)

cmd = []string{"tx", "broadcast", signedFile.Name(), "--chain-id=testing"}
rsp1 = cli.RunCommandWithArgs(cmd...)
systest.RequireTxSuccess(t, rsp1)

assertDuplicateErr := func(xt assert.TestingT, gotErr error, gotOutputs ...interface{}) bool {
require.Len(t, gotOutputs, 1)
output := gotOutputs[0].(string)
code := gjson.Get(output, "code")
require.True(t, code.Exists())
require.Equal(t, int64(19), code.Int()) // 19 == already in mempool.
return false // always abort
}
rsp2 := cli.WithRunErrorMatcher(assertDuplicateErr).Run(cmd...)
cmd = []string{"tx", "broadcast", signedFile.Name(), "--chain-id=testing"}
rsp2, _ := cli.RunOnly(cmd...)
systest.RequireTxFailure(t, rsp2)
code := gjson.Get(rsp2, "code")
require.True(t, code.Exists())
require.Equal(t, int64(19), code.Int())

require.Eventually(t, func() bool {
return cli.QueryBalance(account2Addr, "stake") == 5000
Expand Down Expand Up @@ -86,7 +92,7 @@
code := gjson.Get(response, "code").Int()
require.Equal(t, int64(0), code)

bankSendCmdArgs = []string{"tx", "bank", "send", senderAddr, valAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + v50CLI.ChainID(), "--fees=10stake", "--sign-mode=direct", "--unordered", "--timeout-timestamp=10000"}
bankSendCmdArgs = []string{"tx", "bank", "send", senderAddr, valAddr, fmt.Sprintf("%d%s", transferAmount, denom), "--chain-id=" + v50CLI.ChainID(), "--fees=10stake", "--sign-mode=direct", "--unordered", "--timeout-duration=8m"}
res, ok = v53CLI.RunOnly(bankSendCmdArgs...)
require.True(t, ok)

Expand Down
Loading