From 9c3d039e58cb826d718ce4726b07248b278a409a Mon Sep 17 00:00:00 2001 From: codchen Date: Thu, 30 Mar 2023 19:48:50 -0700 Subject: [PATCH] Reject proposal if max block gas is exceeded (#674) * Reject proposal if max block gas is exceeded * fix test * fix test --- app/app.go | 29 +++++++++++++++++++++++++++++ app/app_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/app/app.go b/app/app.go index 4361f3812a..d77259f756 100644 --- a/app/app.go +++ b/app/app.go @@ -943,6 +943,13 @@ func (app *App) ClearOptimisticProcessingInfo() { } func (app *App) ProcessProposalHandler(ctx sdk.Context, req *abci.RequestProcessProposal) (*abci.ResponseProcessProposal, error) { + // TODO: this check decodes transactions which is redone in subsequent processing. We might be able to optimize performance + // by recording the decoding results and avoid decoding again later on. + if !app.checkTotalBlockGasWanted(ctx, req.Txs) { + return &abci.ResponseProcessProposal{ + Status: abci.ResponseProcessProposal_REJECT, + }, nil + } if app.optimisticProcessingInfo == nil { completionSignal := make(chan struct{}, 1) optimisticProcessingInfo := &OptimisticProcessingInfo{ @@ -1468,6 +1475,28 @@ func (app *App) RegisterTendermintService(clientCtx client.Context) { tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) } +func (app *App) checkTotalBlockGasWanted(ctx sdk.Context, txs [][]byte) bool { + totalGasWanted := uint64(0) + for _, tx := range txs { + decoded, err := app.txDecoder(tx) + if err != nil { + // such tx will not be processed and thus won't consume gas. Skipping + continue + } + feeTx, ok := decoded.(sdk.FeeTx) + if !ok { + // such tx will not be processed and thus won't consume gas. Skipping + continue + } + totalGasWanted += feeTx.GetGas() + if totalGasWanted > uint64(ctx.ConsensusParams().Block.MaxGas) { + // early return + return false + } + } + return true +} + // GetMaccPerms returns a copy of the module account permissions func GetMaccPerms() map[string][]string { dupMaccPerms := make(map[string][]string) diff --git a/app/app_test.go b/app/app_test.go index 0501aab8fe..c19b5277e0 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -15,6 +15,7 @@ import ( oracletypes "github.com/sei-protocol/sei-chain/x/oracle/types" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/proto/tendermint/types" ) func TestEmptyBlockIdempotency(t *testing.T) { @@ -267,3 +268,26 @@ func TestProcessOracleAndOtherTxsSuccess(t *testing.T) { require.Equal(t, 2, len(txResults)) } + +func TestInvalidProposalWithExcessiveGasWanted(t *testing.T) { + tm := time.Now().UTC() + valPub := secp256k1.GenPrivKey().PubKey() + + testWrapper := app.NewTestWrapper(t, tm, valPub) + ap := testWrapper.App + ctx := testWrapper.Ctx.WithConsensusParams(&types.ConsensusParams{ + Block: &types.BlockParams{MaxGas: 10}, + }) + emptyTxBuilder := app.MakeEncodingConfig().TxConfig.NewTxBuilder() + txEncoder := app.MakeEncodingConfig().TxConfig.TxEncoder() + emptyTxBuilder.SetGasLimit(10) + emptyTx, _ := txEncoder(emptyTxBuilder.GetTx()) + + badProposal := abci.RequestProcessProposal{ + Txs: [][]byte{emptyTx, emptyTx}, + Height: 1, + } + res, err := ap.ProcessProposalHandler(ctx, &badProposal) + require.Nil(t, err) + require.Equal(t, abci.ResponseProcessProposal_REJECT, res.Status) +}