From b7f3994b6b605971f36d733cacd4e278fe618a30 Mon Sep 17 00:00:00 2001 From: "xingqiang.yuan" Date: Fri, 14 Apr 2023 13:47:24 +0800 Subject: [PATCH] add gas limit buffer to cmtx (#3105) * add gas limit buffer to cmtx * update --- libs/cosmos-sdk/baseapp/abci.go | 84 +++++++++++-------- .../config/dynamic_config_okchain.go | 5 ++ 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/libs/cosmos-sdk/baseapp/abci.go b/libs/cosmos-sdk/baseapp/abci.go index 9bbd4ba527..f8a2ea29b2 100644 --- a/libs/cosmos-sdk/baseapp/abci.go +++ b/libs/cosmos-sdk/baseapp/abci.go @@ -11,9 +11,6 @@ import ( "syscall" "time" - "github.com/spf13/viper" - "github.com/tendermint/go-amino" - "github.com/okex/exchain/app/rpc/simulator" "github.com/okex/exchain/libs/cosmos-sdk/codec" "github.com/okex/exchain/libs/cosmos-sdk/store/mpt" @@ -24,7 +21,10 @@ import ( "github.com/okex/exchain/libs/system/trace" "github.com/okex/exchain/libs/system/trace/persist" abci "github.com/okex/exchain/libs/tendermint/abci/types" + cfg "github.com/okex/exchain/libs/tendermint/config" tmtypes "github.com/okex/exchain/libs/tendermint/types" + "github.com/spf13/viper" + "github.com/tendermint/go-amino" ) // InitChain implements the ABCI interface. It runs the initialization logic @@ -410,7 +410,31 @@ func (app *BaseApp) Query(req abci.RequestQuery) abci.ResponseQuery { return sdkerrors.QueryResult(sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown query path")) } } -func handleSimulate(app *BaseApp, path []string, height int64, txBytes []byte, overrideBytes []byte) abci.ResponseQuery { + +func handleSimulateWithBuffer(app *BaseApp, path []string, height int64, txBytes []byte, overrideBytes []byte) abci.ResponseQuery { + simRes, shouldAddBuffer, err := handleSimulate(app, path, height, txBytes, overrideBytes) + if err != nil { + return sdkerrors.QueryResult(err) + } + if shouldAddBuffer { + buffer := cfg.DynamicConfig.GetGasLimitBuffer() + gasUsed := simRes.GasUsed + gasUsed += gasUsed * buffer / 100 + if gasUsed > SimulationGasLimit { + gasUsed = SimulationGasLimit + } + simRes.GasUsed = gasUsed + } + + return abci.ResponseQuery{ + Codespace: sdkerrors.RootCodespace, + Height: height, + Value: codec.Cdc.MustMarshalBinaryBare(simRes), + } + +} + +func handleSimulate(app *BaseApp, path []string, height int64, txBytes []byte, overrideBytes []byte) (sdk.SimulationResponse, bool, error) { // if path contains address, it means 'eth_estimateGas' the sender hasExtraPaths := len(path) > 2 var from string @@ -430,9 +454,16 @@ func handleSimulate(app *BaseApp, path []string, height int64, txBytes []byte, o if tx == nil { tx, err = app.txDecoder(txBytes) if err != nil { - return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to decode tx")) + return sdk.SimulationResponse{}, false, sdkerrors.Wrap(err, "failed to decode tx") } } + // if path contains mempool, it means to enable MaxGasUsedPerBlock + // return the actual gasUsed even though simulate tx failed + isMempoolSim := hasExtraPaths && path[2] == "mempool" + var shouldAddBuffer bool + if !isMempoolSim && tx.GetType() != types.EvmTxType { + shouldAddBuffer = true + } msgs := tx.GetMsgs() @@ -445,46 +476,32 @@ func handleSimulate(app *BaseApp, path []string, height int64, txBytes []byte, o } } if isPureWasm { - return handleSimulateWasm(height, txBytes, msgs) + res, err := handleSimulateWasm(height, txBytes, msgs) + return res, shouldAddBuffer, err } } gInfo, res, err := app.Simulate(txBytes, tx, height, overrideBytes, from) - - // if path contains mempool, it means to enable MaxGasUsedPerBlock - // return the actual gasUsed even though simulate tx failed - isMempoolSim := hasExtraPaths && path[2] == "mempool" if err != nil && !isMempoolSim { - return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to simulate tx")) + return sdk.SimulationResponse{}, false, sdkerrors.Wrap(err, "failed to simulate tx") } - simRes := sdk.SimulationResponse{ + return sdk.SimulationResponse{ GasInfo: gInfo, Result: res, - } - - return abci.ResponseQuery{ - Codespace: sdkerrors.RootCodespace, - Height: height, - Value: codec.Cdc.MustMarshalBinaryBare(simRes), - } + }, shouldAddBuffer, nil } -func handleSimulateWasm(height int64, txBytes []byte, msgs []sdk.Msg) (abciRes abci.ResponseQuery) { +func handleSimulateWasm(height int64, txBytes []byte, msgs []sdk.Msg) (simRes sdk.SimulationResponse, err error) { wasmSimulator := simulator.NewWasmSimulator() defer wasmSimulator.Release() defer func() { if r := recover(); r != nil { gasMeter := wasmSimulator.Context().GasMeter() - simRes := sdk.SimulationResponse{ + simRes = sdk.SimulationResponse{ GasInfo: sdk.GasInfo{ GasUsed: gasMeter.GasConsumed(), }, } - abciRes = abci.ResponseQuery{ - Codespace: sdkerrors.RootCodespace, - Height: height, - Value: codec.Cdc.MustMarshalBinaryBare(simRes), - } } }() @@ -492,28 +509,23 @@ func handleSimulateWasm(height int64, txBytes []byte, msgs []sdk.Msg) (abciRes a wasmSimulator.Context().GasMeter().ConsumeGas(uint64(10*len(txBytes)), "tx size cost") res, err := wasmSimulator.Simulate(msgs) if err != nil { - return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to simulate wasm tx")) + return sdk.SimulationResponse{}, sdkerrors.Wrap(err, "failed to simulate wasm tx") } gasMeter := wasmSimulator.Context().GasMeter() - simRes := sdk.SimulationResponse{ + return sdk.SimulationResponse{ GasInfo: sdk.GasInfo{ GasUsed: gasMeter.GasConsumed(), }, Result: res, - } - return abci.ResponseQuery{ - Codespace: sdkerrors.RootCodespace, - Height: height, - Value: codec.Cdc.MustMarshalBinaryBare(simRes), - } + }, nil } func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) abci.ResponseQuery { if len(path) >= 2 { switch path[1] { case "simulate": - return handleSimulate(app, path, req.Height, req.Data, nil) + return handleSimulateWithBuffer(app, path, req.Height, req.Data, nil) case "simulateWithOverrides": queryBytes := req.Data @@ -521,7 +533,7 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) abci.Res if err := json.Unmarshal(queryBytes, &queryData); err != nil { return sdkerrors.QueryResult(sdkerrors.Wrap(err, "failed to decode simulateOverrideData")) } - return handleSimulate(app, path, req.Height, queryData.TxBytes, queryData.OverridesBytes) + return handleSimulateWithBuffer(app, path, req.Height, queryData.TxBytes, queryData.OverridesBytes) case "trace": var queryParam sdk.QueryTraceTx diff --git a/libs/tendermint/config/dynamic_config_okchain.go b/libs/tendermint/config/dynamic_config_okchain.go index 288048994d..c69bea78a7 100644 --- a/libs/tendermint/config/dynamic_config_okchain.go +++ b/libs/tendermint/config/dynamic_config_okchain.go @@ -33,6 +33,7 @@ type IDynamicConfig interface { GetDynamicGpMode() int GetDynamicGpMaxTxNum() int64 GetDynamicGpMaxGasUsed() int64 + GetGasLimitBuffer() uint64 } var DynamicConfig IDynamicConfig = MockDynamicConfig{} @@ -185,3 +186,7 @@ func (d *MockDynamicConfig) SetDynamicGpMaxGasUsed(value int64) { func (d MockDynamicConfig) GetDynamicGpMaxGasUsed() int64 { return d.dynamicGpMaxGasUsed } + +func (d MockDynamicConfig) GetGasLimitBuffer() uint64 { + return 0 +}