diff --git a/CHANGELOG.md b/CHANGELOG.md index 23cc7aa5b1d2..62b9b9d02246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (baseapp) [#20107](https://github.com/cosmos/cosmos-sdk/pull/20107) Avoid header height overwrite block height. * (cli) [#20020](https://github.com/cosmos/cosmos-sdk/pull/20020) Make bootstrap-state command support both new and legacy genesis format. * [#507](https://github.com/crypto-org-chain/cosmos-sdk/pull/507) mempool respect gas wanted returned by ante handler +* [#744](https://github.com/crypto-org-chain/cosmos-sdk/pull/744) Pass raw transactions to tx executor so it can do pre-estimations. ### Bug Fixes diff --git a/baseapp/abci.go b/baseapp/abci.go index 1b0c12394299..3d3b6f11926e 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -842,8 +842,8 @@ func (app *BaseApp) internalFinalizeBlock(ctx context.Context, req *abci.Request func (app *BaseApp) executeTxs(ctx context.Context, txs [][]byte) ([]*abci.ExecTxResult, error) { if app.txExecutor != nil { - return app.txExecutor(ctx, len(txs), app.finalizeBlockState.ms, func(i int, ms storetypes.MultiStore, incarnationCache map[string]any) *abci.ExecTxResult { - return app.deliverTxWithMultiStore(txs[i], i, ms, incarnationCache) + return app.txExecutor(ctx, txs, app.finalizeBlockState.ms, func(i int, memTx sdk.Tx, ms storetypes.MultiStore, incarnationCache map[string]any) *abci.ExecTxResult { + return app.deliverTxWithMultiStore(txs[i], memTx, i, ms, incarnationCache) }) } @@ -851,8 +851,8 @@ func (app *BaseApp) executeTxs(ctx context.Context, txs [][]byte) ([]*abci.ExecT for i, rawTx := range txs { var response *abci.ExecTxResult - if _, err := app.txDecoder(rawTx); err == nil { - response = app.deliverTx(rawTx, i) + if memTx, err := app.txDecoder(rawTx); err == nil { + response = app.deliverTx(rawTx, memTx, i) } else { // In the case where a transaction included in a block proposal is malformed, // we still want to return a default response to comet. This is because comet diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 492cd79050ae..55e0aa8469b3 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -764,11 +764,11 @@ func (app *BaseApp) beginBlock(_ *abci.RequestFinalizeBlock) (sdk.BeginBlock, er return resp, nil } -func (app *BaseApp) deliverTx(tx []byte, txIndex int) *abci.ExecTxResult { - return app.deliverTxWithMultiStore(tx, txIndex, nil, nil) +func (app *BaseApp) deliverTx(tx []byte, memTx sdk.Tx, txIndex int) *abci.ExecTxResult { + return app.deliverTxWithMultiStore(tx, memTx, txIndex, nil, nil) } -func (app *BaseApp) deliverTxWithMultiStore(tx []byte, txIndex int, txMultiStore storetypes.MultiStore, incarnationCache map[string]any) *abci.ExecTxResult { +func (app *BaseApp) deliverTxWithMultiStore(tx []byte, memTx sdk.Tx, txIndex int, txMultiStore storetypes.MultiStore, incarnationCache map[string]any) *abci.ExecTxResult { gInfo := sdk.GasInfo{} resultStr := "successful" @@ -781,7 +781,7 @@ func (app *BaseApp) deliverTxWithMultiStore(tx []byte, txIndex int, txMultiStore telemetry.SetGauge(float32(gInfo.GasWanted), "tx", "gas", "wanted") }() - gInfo, result, anteEvents, err := app.runTxWithMultiStore(execModeFinalize, tx, txIndex, txMultiStore, incarnationCache) + gInfo, result, anteEvents, err := app.runTxWithMultiStore(execModeFinalize, tx, memTx, txIndex, txMultiStore, incarnationCache) if err != nil { resultStr = "failed" resp = sdkerrors.ResponseExecTxResultWithEvents( @@ -839,10 +839,17 @@ func (app *BaseApp) endBlock(_ context.Context) (sdk.EndBlock, error) { // returned if the tx does not run out of gas and if all the messages are valid // and execute successfully. An error is returned otherwise. func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { - return app.runTxWithMultiStore(mode, txBytes, -1, nil, nil) + return app.runTxWithMultiStore(mode, txBytes, nil, -1, nil, nil) } -func (app *BaseApp) runTxWithMultiStore(mode execMode, txBytes []byte, txIndex int, txMultiStore storetypes.MultiStore, incarnationCache map[string]any) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { +func (app *BaseApp) runTxWithMultiStore( + mode execMode, + txBytes []byte, + tx sdk.Tx, + txIndex int, + txMultiStore storetypes.MultiStore, + incarnationCache map[string]any, +) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is // determined by the GasMeter. We need access to the context to get the gas // meter, so we initialize upfront. @@ -894,9 +901,11 @@ func (app *BaseApp) runTxWithMultiStore(mode execMode, txBytes []byte, txIndex i defer consumeBlockGas() } - tx, err := app.txDecoder(txBytes) - if err != nil { - return sdk.GasInfo{}, nil, nil, err + if tx == nil { + tx, err = app.txDecoder(txBytes) + if err != nil { + return sdk.GasInfo{}, nil, nil, err + } } msgs := tx.GetMsgs() diff --git a/baseapp/genesis.go b/baseapp/genesis.go index e9f611772e08..562bdca3b276 100644 --- a/baseapp/genesis.go +++ b/baseapp/genesis.go @@ -13,7 +13,7 @@ var _ genesis.TxHandler = (*BaseApp)(nil) // ExecuteGenesisTx implements genesis.GenesisState from // cosmossdk.io/core/genesis to set initial state in genesis func (ba BaseApp) ExecuteGenesisTx(tx []byte) error { - res := ba.deliverTx(tx, -1) + res := ba.deliverTx(tx, nil, -1) if res.Code != types.CodeTypeOK { return errors.New(res.Log) diff --git a/baseapp/txexecutor.go b/baseapp/txexecutor.go index 82649036dba0..b09c204e06c0 100644 --- a/baseapp/txexecutor.go +++ b/baseapp/txexecutor.go @@ -4,13 +4,14 @@ import ( "context" abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" "cosmossdk.io/store/types" ) type TxExecutor func( ctx context.Context, - blockSize int, + block [][]byte, cms types.MultiStore, - deliverTxWithMultiStore func(int, types.MultiStore, map[string]any) *abci.ExecTxResult, + deliverTxWithMultiStore func(int, sdk.Tx, types.MultiStore, map[string]any) *abci.ExecTxResult, ) ([]*abci.ExecTxResult, error)