From 2cf378174d87a6dc05e514e2f939ec6d78c96b3e Mon Sep 17 00:00:00 2001 From: Marko Date: Mon, 15 Jul 2024 11:40:41 +0200 Subject: [PATCH] fix: use contents of the tx as identifier in cache (#20533) Co-authored-by: Alexander Peters --- client/tx/factory.go | 1 + client/v2/go.mod | 6 +- depinject/appconfig/config_test.go | 1 - .../adr-070-unordered-transactions.md | 41 +++++++--- simapp/ante.go | 2 +- tests/sims/authz/operations_test.go | 2 +- tests/systemtests/system.go | 20 +++-- tests/systemtests/unordered_tx_test.go | 52 ++++++++++++ x/auth/ante/unordered.go | 79 ++++++++++++++++++- x/auth/ante/unordered_test.go | 38 +++++---- x/authz/go.mod | 6 +- x/authz/go.sum | 2 - x/authz/keeper/genesis_test.go | 2 +- x/authz/keeper/keeper.go | 4 +- x/authz/keeper/keeper_test.go | 2 +- x/authz/migrations/v2/store_test.go | 2 +- x/authz/module/abci_test.go | 2 +- 17 files changed, 207 insertions(+), 55 deletions(-) create mode 100644 tests/systemtests/unordered_tx_test.go diff --git a/client/tx/factory.go b/client/tx/factory.go index 22053ba3d7..598d389d5f 100644 --- a/client/tx/factory.go +++ b/client/tx/factory.go @@ -361,6 +361,7 @@ func (f Factory) BuildUnsignedTx(msgs ...sdk.Msg) (client.TxBuilder, error) { tx.SetFeeGranter(f.feeGranter) tx.SetFeePayer(f.feePayer) tx.SetTimeoutHeight(f.TimeoutHeight()) + tx.SetUnordered(f.Unordered()) if etx, ok := tx.(client.ExtendedTxBuilder); ok { etx.SetExtensionOptions(f.extOptions...) diff --git a/client/v2/go.mod b/client/v2/go.mod index 9c5612998f..565eddcc13 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -9,11 +9,8 @@ require ( cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 cosmossdk.io/x/gov v0.0.0-20231113122742-912390d5fc4a cosmossdk.io/x/tx v0.13.3 - github.com/chzyer/readline v1.5.1 // indirect - github.com/cockroachdb/errors v1.11.1 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.51.0 - github.com/manifoldco/promptui v0.9.0 // indirect github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 google.golang.org/grpc v1.64.1 @@ -43,6 +40,8 @@ require ( github.com/bgentry/speakeasy v0.2.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chzyer/readline v1.5.1 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect @@ -113,6 +112,7 @@ require ( github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/linxGnu/grocksdb v1.8.14 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/minio/highwayhash v1.0.2 // indirect diff --git a/depinject/appconfig/config_test.go b/depinject/appconfig/config_test.go index c0eb5eaebc..4c98ae2221 100644 --- a/depinject/appconfig/config_test.go +++ b/depinject/appconfig/config_test.go @@ -235,7 +235,6 @@ func ProvideModuleC(key StoreKey, b KeeperB) KeeperC { type keeperC struct { key StoreKey - b KeeperB } type KeeperC interface { diff --git a/docs/architecture/adr-070-unordered-transactions.md b/docs/architecture/adr-070-unordered-transactions.md index 7d29f0fbc6..b3547b1075 100644 --- a/docs/architecture/adr-070-unordered-transactions.md +++ b/docs/architecture/adr-070-unordered-transactions.md @@ -261,15 +261,35 @@ func (d *DedupTxDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, return nil, errorsmod.Wrapf(sdkerrors.ErrLogic, "unordered tx ttl exceeds %d", d.maxUnOrderedTTL) } - // check for duplicates - if d.m.Contains(tx.Hash()) { - return nil, errorsmod.Wrap(sdkerrors.ErrLogic, "tx is duplicated") - } + // in order to create a deterministic hash based on the tx, we need to hash the contents of the tx with signature + // Get a Buffer from the pool + buf := bufPool.Get().(*bytes.Buffer) + // Make sure to reset the buffer + buf.Reset() - if !ctx.IsCheckTx() { - // a new tx included in the block, add the hash to the unordered tx manager - d.m.Add(tx.Hash(), tx.TimeoutHeight()) - } + // Use the buffer + for _, msg := range tx.GetMsgs() { + // loop through the messages and write them to the buffer + // encoding the msg to bytes makes it deterministic within the state machine. + // Malleability is not a concern here because the state machine will encode the transaction deterministically. + bz, err := proto.Marshal(msg) + if err != nil { + return ctx, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "failed to marshal message") + } + + buf.Write(bz) + } + + // check for duplicates + // check for duplicates + if d.txManager.Contains(txHash) { + return ctx, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "tx %X is duplicated") + } + + if d.env.TransactionService.ExecMode(ctx) == transaction.ExecModeFinalize { + // a new tx included in the block, add the hash to the unordered tx manager + d.txManager.Add(txHash, ttl) + } return next(ctx, tx, simulate) } @@ -282,10 +302,7 @@ encoding is not malleable. If a given transaction, which is otherwise valid, can be encoded to produce different hashes, which reflect the same valid transaction, then a duplicate unordered transaction can be submitted and included in a block. -In order to prevent this, transactions should be encoded in a deterministic manner. -[ADR-027](./adr-027-deterministic-protobuf-serialization.md) provides such a mechanism. -However, it is important to note that the way a transaction is signed should ensure -ADR-027 is followed. E.g. we want to avoid Amino signing. +In order to prevent this, the decoded transaction contents is taken. Starting with the content of the transaction we marshal the transaction in order to prevent a client reordering the transaction. Next we include the gas and timeout height as part of the identifier. All these fields are signed over in the transaction payload. If one of them changes the signature will not match the transaction. ### State Management diff --git a/simapp/ante.go b/simapp/ante.go index fb54d1baed..f39b8369ba 100644 --- a/simapp/ante.go +++ b/simapp/ante.go @@ -39,7 +39,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker), ante.NewValidateBasicDecorator(options.Environment), ante.NewTxTimeoutHeightDecorator(options.Environment), - ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, options.TxManager, options.Environment), + ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, options.TxManager, options.Environment, ante.DefaultSha256Cost), ante.NewValidateMemoDecorator(options.AccountKeeper), ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper), ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker), diff --git a/tests/sims/authz/operations_test.go b/tests/sims/authz/operations_test.go index 6abed78156..cec2ff2451 100644 --- a/tests/sims/authz/operations_test.go +++ b/tests/sims/authz/operations_test.go @@ -9,8 +9,8 @@ import ( "github.com/stretchr/testify/suite" "cosmossdk.io/core/header" + "cosmossdk.io/core/log" "cosmossdk.io/depinject" - "cosmossdk.io/log" _ "cosmossdk.io/x/accounts" // import as blank for app wiring _ "cosmossdk.io/x/auth" // import as blank for app wiring authkeeper "cosmossdk.io/x/auth/keeper" diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go index 285af4e03f..a9aec879a7 100644 --- a/tests/systemtests/system.go +++ b/tests/systemtests/system.go @@ -44,7 +44,7 @@ type TestnetInitializer interface { type SystemUnderTest struct { execBinary string blockListener *EventListener - currentHeight int64 + currentHeight atomic.Int64 outputDir string testnetInitializer TestnetInitializer @@ -164,7 +164,7 @@ func (s *SystemUnderTest) StartChain(t *testing.T, xargs ...string) { s.blockListener.Subscribe("tm.event='NewBlock'", func(e ctypes.ResultEvent) (more bool) { newBlock, ok := e.Data.(tmtypes.EventDataNewBlock) require.True(t, ok, "unexpected type %T", e.Data) - atomic.StoreInt64(&s.currentHeight, newBlock.Block.Height) + s.currentHeight.Store(newBlock.Block.Height) return true }), ) @@ -362,12 +362,12 @@ func (s *SystemUnderTest) PrintBuffer() { // AwaitBlockHeight blocks until te target height is reached. An optional timeout parameter can be passed to abort early func (s *SystemUnderTest) AwaitBlockHeight(t *testing.T, targetHeight int64, timeout ...time.Duration) { t.Helper() - require.Greater(t, targetHeight, s.currentHeight) + require.Greater(t, targetHeight, s.currentHeight.Load()) var maxWaitTime time.Duration if len(timeout) != 0 { maxWaitTime = timeout[0] } else { - maxWaitTime = time.Duration(targetHeight-s.currentHeight+3) * s.blockTime + maxWaitTime = time.Duration(targetHeight-s.currentHeight.Load()+3) * s.blockTime } abort := time.NewTimer(maxWaitTime).C for { @@ -393,10 +393,10 @@ func (s *SystemUnderTest) AwaitNextBlock(t *testing.T, timeout ...time.Duration) } done := make(chan int64) go func() { - for start, current := atomic.LoadInt64(&s.currentHeight), atomic.LoadInt64(&s.currentHeight); current == start; current = atomic.LoadInt64(&s.currentHeight) { + for start, current := s.currentHeight.Load(), s.currentHeight.Load(); current == start; current = s.currentHeight.Load() { time.Sleep(s.blockTime) } - done <- atomic.LoadInt64(&s.currentHeight) + done <- s.currentHeight.Load() close(done) }() select { @@ -434,7 +434,7 @@ func (s *SystemUnderTest) ResetChain(t *testing.T) { // reset all validator nodes s.ForEachNodeExecAndWait(t, []string{"comet", "unsafe-reset-all"}) - s.currentHeight = 0 + s.currentHeight.Store(0) s.dirty = false } @@ -465,7 +465,7 @@ func (s *SystemUnderTest) ModifyGenesisJSON(t *testing.T, mutators ...GenesisMut // modify json without enforcing a reset func (s *SystemUnderTest) modifyGenesisJSON(t *testing.T, mutators ...GenesisMutator) { t.Helper() - require.Empty(t, s.currentHeight, "forced chain reset required") + require.Empty(t, s.currentHeight.Load(), "forced chain reset required") current, err := os.ReadFile(filepath.Join(WorkDir, s.nodePath(0), "config", "genesis.json")) require.NoError(t, err) for _, m := range mutators { @@ -727,6 +727,10 @@ func (s *SystemUnderTest) anyNodeRunning() bool { return len(s.pids) != 0 } +func (s *SystemUnderTest) CurrentHeight() int64 { + return s.currentHeight.Load() +} + type Node struct { ID string IP string diff --git a/tests/systemtests/unordered_tx_test.go b/tests/systemtests/unordered_tx_test.go new file mode 100644 index 0000000000..4d74cbec2e --- /dev/null +++ b/tests/systemtests/unordered_tx_test.go @@ -0,0 +1,52 @@ +//go:build system_test + +package systemtests + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +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 + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + // add genesis account with some tokens + account1Addr := cli.AddKey("account1") + account2Addr := cli.AddKey("account2") + sut.ModifyGenesisCLI(t, + []string{"genesis", "add-genesis-account", account1Addr, "10000000stake"}, + ) + + sut.StartChain(t) + + height := sut.CurrentHeight() + timeoutHeight := height + 15 + timeoutHeightStr := strconv.Itoa(int(timeoutHeight)) + // send tokens + rsp1 := cli.Run("tx", "bank", "send", account1Addr, account2Addr, "5000stake", "--from="+account1Addr, "--fees=1stake", "--timeout-height="+timeoutHeightStr, "--unordered", "--sequence=1", "--note=1") + RequireTxSuccess(t, rsp1) + + assertDuplicateErr := func(xt assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + require.Len(t, gotOutputs, 1) + assert.Contains(t, gotOutputs[0], "is duplicated: invalid request") + return false // always abort + } + rsp2 := cli.WithRunErrorMatcher(assertDuplicateErr).Run("tx", "bank", "send", account1Addr, account2Addr, "5000stake", "--from="+account1Addr, "--fees=1stake", "--timeout-height="+timeoutHeightStr, "--unordered", "--sequence=1") + RequireTxFailure(t, rsp2) + + // assert TX executed before timeout + for cli.QueryBalance(account2Addr, "stake") != 5000 { + t.Log("query balance") + if current := sut.AwaitNextBlock(t); current > timeoutHeight { + t.Fatal("TX was not executed before timeout") + } + } +} diff --git a/x/auth/ante/unordered.go b/x/auth/ante/unordered.go index 193f554512..16b2837c43 100644 --- a/x/auth/ante/unordered.go +++ b/x/auth/ante/unordered.go @@ -1,7 +1,12 @@ package ante import ( + "bytes" "crypto/sha256" + "encoding/binary" + "sync" + + "github.com/golang/protobuf/proto" // nolint: staticcheck // for proto.Message "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/transaction" @@ -12,6 +17,15 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) +// bufPool is a pool of bytes.Buffer objects to reduce memory allocations. +var bufPool = sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, +} + +const DefaultSha256Cost = 25 + var _ sdk.AnteDecorator = (*UnorderedTxDecorator)(nil) // UnorderedTxDecorator defines an AnteHandler decorator that is responsible for @@ -31,13 +45,15 @@ type UnorderedTxDecorator struct { maxUnOrderedTTL uint64 txManager *unorderedtx.Manager env appmodule.Environment + sha256Cost uint64 } -func NewUnorderedTxDecorator(maxTTL uint64, m *unorderedtx.Manager, env appmodule.Environment) *UnorderedTxDecorator { +func NewUnorderedTxDecorator(maxTTL uint64, m *unorderedtx.Manager, env appmodule.Environment, gasCost uint64) *UnorderedTxDecorator { return &UnorderedTxDecorator{ maxUnOrderedTTL: maxTTL, txManager: m, env: env, + sha256Cost: gasCost, } } @@ -62,13 +78,27 @@ func (d *UnorderedTxDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, ne return ctx, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "unordered tx ttl exceeds %d", d.maxUnOrderedTTL) } - txHash := sha256.Sum256(ctx.TxBytes()) + // consume gas in all exec modes to avoid gas estimation discrepancies + if err := d.env.GasService.GasMeter(ctx).Consume(d.sha256Cost, "consume gas for calculating tx hash"); err != nil { + return ctx, errorsmod.Wrap(sdkerrors.ErrOutOfGas, "out of gas") + } + + // Avoid checking for duplicates and creating the identifier in simulation mode + // This is done to avoid sha256 computation in simulation mode + if d.env.TransactionService.ExecMode(ctx) == transaction.ExecModeSimulate { + return next(ctx, tx, false) + } + + // calculate the tx hash + txHash, err := TxIdentifier(ttl, tx) + if err != nil { + return ctx, err + } // check for duplicates if d.txManager.Contains(txHash) { return ctx, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "tx %X is duplicated") } - if d.env.TransactionService.ExecMode(ctx) == transaction.ExecModeFinalize { // a new tx included in the block, add the hash to the unordered tx manager d.txManager.Add(txHash, ttl) @@ -76,3 +106,46 @@ func (d *UnorderedTxDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, ne return next(ctx, tx, false) } + +// TxIdentifier returns a unique identifier for a transaction that is intended to be unordered. +func TxIdentifier(timeout uint64, tx sdk.Tx) ([32]byte, error) { + feetx := tx.(sdk.FeeTx) + if feetx.GetFee().IsZero() { + return [32]byte{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "unordered transaction must have a fee") + } + + buf := bufPool.Get().(*bytes.Buffer) + // Make sure to reset the buffer + buf.Reset() + defer bufPool.Put(buf) + + // Use the buffer + for _, msg := range tx.GetMsgs() { + // loop through the messages and write them to the buffer + // encoding the msg to bytes makes it deterministic within the state machine. + // Malleability is not a concern here because the state machine will encode the transaction deterministically. + bz, err := proto.Marshal(msg) + if err != nil { + return [32]byte{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "failed to marshal message") + } + + if _, err := buf.Write(bz); err != nil { + return [32]byte{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "failed to write message to buffer") + } + } + + // write the timeout height to the buffer + if err := binary.Write(buf, binary.LittleEndian, timeout); err != nil { + return [32]byte{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "failed to write timeout_height to buffer") + } + + // write gas to the buffer + if err := binary.Write(buf, binary.LittleEndian, feetx.GetGas()); err != nil { + return [32]byte{}, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "failed to write unordered to buffer") + } + + txHash := sha256.Sum256(buf.Bytes()) + + // Return the Buffer to the pool + return txHash, nil +} diff --git a/x/auth/ante/unordered_test.go b/x/auth/ante/unordered_test.go index c64a267f4a..7a1db02f27 100644 --- a/x/auth/ante/unordered_test.go +++ b/x/auth/ante/unordered_test.go @@ -1,11 +1,11 @@ package ante_test import ( - "crypto/sha256" "testing" "github.com/stretchr/testify/require" + storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/auth/ante" "cosmossdk.io/x/auth/ante/unorderedtx" @@ -15,6 +15,8 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" ) +const gasConsumed = uint64(25) + func TestUnorderedTxDecorator_OrderedTx(t *testing.T) { txm := unorderedtx.NewManager(t.TempDir()) defer func() { @@ -25,7 +27,7 @@ func TestUnorderedTxDecorator_OrderedTx(t *testing.T) { suite := SetupTestSuite(t, false) - chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment())) + chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost)) tx, txBz := genUnorderedTx(t, false, 0) ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100) @@ -44,7 +46,7 @@ func TestUnorderedTxDecorator_UnorderedTx_NoTTL(t *testing.T) { suite := SetupTestSuite(t, false) - chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment())) + chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost)) tx, txBz := genUnorderedTx(t, true, 0) ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100) @@ -63,7 +65,7 @@ func TestUnorderedTxDecorator_UnorderedTx_InvalidTTL(t *testing.T) { suite := SetupTestSuite(t, false) - chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment())) + chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost)) tx, txBz := genUnorderedTx(t, true, 100+unorderedtx.DefaultMaxUnOrderedTTL+1) ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100) @@ -82,13 +84,14 @@ func TestUnorderedTxDecorator_UnorderedTx_AlreadyExists(t *testing.T) { suite := SetupTestSuite(t, false) - chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment())) + chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost)) tx, txBz := genUnorderedTx(t, true, 150) - ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100) + ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100).WithGasMeter(storetypes.NewGasMeter(gasConsumed)) - txHash := sha256.Sum256(txBz) - txm.Add(txHash, 150) + bz := [32]byte{} + copy(bz[:], txBz[:32]) + txm.Add(bz, 150) _, err := chain(ctx, tx, false) require.Error(t, err) @@ -104,10 +107,10 @@ func TestUnorderedTxDecorator_UnorderedTx_ValidCheckTx(t *testing.T) { suite := SetupTestSuite(t, false) - chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment())) + chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost)) tx, txBz := genUnorderedTx(t, true, 150) - ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100).WithExecMode(sdk.ExecModeCheck) + ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100).WithExecMode(sdk.ExecModeCheck).WithGasMeter(storetypes.NewGasMeter(gasConsumed)) _, err := chain(ctx, tx, false) require.NoError(t, err) @@ -123,16 +126,18 @@ func TestUnorderedTxDecorator_UnorderedTx_ValidDeliverTx(t *testing.T) { suite := SetupTestSuite(t, false) - chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment())) + chain := sdk.ChainAnteDecorators(ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, txm, suite.accountKeeper.GetEnvironment(), ante.DefaultSha256Cost)) tx, txBz := genUnorderedTx(t, true, 150) - ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100).WithExecMode(sdk.ExecModeFinalize) + ctx := sdk.Context{}.WithTxBytes(txBz).WithBlockHeight(100).WithExecMode(sdk.ExecModeFinalize).WithGasMeter(storetypes.NewGasMeter(gasConsumed)) _, err := chain(ctx, tx, false) require.NoError(t, err) - txHash := sha256.Sum256(txBz) - require.True(t, txm.Contains(txHash)) + bz := [32]byte{} + copy(bz[:], txBz[:32]) + + require.True(t, txm.Contains(bz)) } func genUnorderedTx(t *testing.T, unordered bool, ttl uint64) (sdk.Tx, []byte) { @@ -159,8 +164,9 @@ func genUnorderedTx(t *testing.T, unordered bool, ttl uint64) (sdk.Tx, []byte) { tx, err := s.CreateTestTx(s.ctx, privKeys, accNums, accSeqs, s.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT) require.NoError(t, err) - txBz, err := s.encCfg.TxConfig.TxEncoder()(tx) + txBz, err := ante.TxIdentifier(ttl, tx) + require.NoError(t, err) - return tx, txBz + return tx, txBz[:] } diff --git a/x/authz/go.mod b/x/authz/go.mod index be512f1ed4..1109855902 100644 --- a/x/authz/go.mod +++ b/x/authz/go.mod @@ -3,12 +3,10 @@ module cosmossdk.io/x/authz go 1.22.2 require ( - buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect cosmossdk.io/api v0.7.5 cosmossdk.io/core v0.12.1-0.20231114100755-569e3ff6a0d7 cosmossdk.io/depinject v1.0.0-alpha.4 cosmossdk.io/errors v1.0.1 - cosmossdk.io/log v1.3.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc cosmossdk.io/x/bank v0.0.0-20240226161501-23359a0b6d91 @@ -168,6 +166,8 @@ require ( ) require ( + buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 // indirect + cosmossdk.io/log v1.3.1 // indirect cosmossdk.io/schema v0.1.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect ) @@ -182,6 +182,8 @@ replace ( cosmossdk.io/core/testing => ../../core/testing cosmossdk.io/depinject => ../../depinject cosmossdk.io/log => ../../log + cosmossdk.io/logger => ../../logger + cosmossdk.io/store => ../../store cosmossdk.io/x/accounts => ../accounts cosmossdk.io/x/auth => ../auth cosmossdk.io/x/bank => ../bank diff --git a/x/authz/go.sum b/x/authz/go.sum index 0b0081734c..af1f81c0e2 100644 --- a/x/authz/go.sum +++ b/x/authz/go.sum @@ -10,8 +10,6 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/schema v0.1.1 h1:I0M6pgI7R10nq+/HCQfbO6BsGBZA8sQy+duR1Y3aKcA= cosmossdk.io/schema v0.1.1/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ= -cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg= -cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= diff --git a/x/authz/keeper/genesis_test.go b/x/authz/keeper/genesis_test.go index 42d289a5a1..46887c5865 100644 --- a/x/authz/keeper/genesis_test.go +++ b/x/authz/keeper/genesis_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/suite" "cosmossdk.io/core/header" - "cosmossdk.io/log" + "cosmossdk.io/core/log" sdkmath "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/authz/keeper" diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index 154dee4f5b..5a94064637 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - "github.com/cosmos/gogoproto/proto" + gogoproto "github.com/cosmos/gogoproto/proto" "cosmossdk.io/core/appmodule" corecontext "cosmossdk.io/core/context" @@ -65,7 +65,7 @@ func (k Keeper) update(ctx context.Context, grantee, granter sdk.AccAddress, upd return authz.ErrNoAuthorizationFound } - msg, ok := updated.(proto.Message) + msg, ok := updated.(gogoproto.Message) if !ok { return sdkerrors.ErrPackAny.Wrapf("cannot proto marshal %T", updated) } diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 35589d1fe9..3cda4e1132 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/suite" "cosmossdk.io/core/header" - "cosmossdk.io/log" + "cosmossdk.io/core/log" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/authz" authzkeeper "cosmossdk.io/x/authz/keeper" diff --git a/x/authz/migrations/v2/store_test.go b/x/authz/migrations/v2/store_test.go index fe328faae8..0f5cd17359 100644 --- a/x/authz/migrations/v2/store_test.go +++ b/x/authz/migrations/v2/store_test.go @@ -8,7 +8,7 @@ import ( govtypes "cosmossdk.io/api/cosmos/gov/v1beta1" "cosmossdk.io/core/header" - "cosmossdk.io/log" + "cosmossdk.io/core/log" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/authz" v2 "cosmossdk.io/x/authz/migrations/v2" diff --git a/x/authz/module/abci_test.go b/x/authz/module/abci_test.go index e241edb3c6..131063f48a 100644 --- a/x/authz/module/abci_test.go +++ b/x/authz/module/abci_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "cosmossdk.io/core/header" - "cosmossdk.io/log" + "cosmossdk.io/core/log" storetypes "cosmossdk.io/store/types" authtypes "cosmossdk.io/x/auth/types" "cosmossdk.io/x/authz"