From f0c1740ee8883474e4dcb6c83b0fb6226dd9139f Mon Sep 17 00:00:00 2001 From: boyuan-chen <46272347+boyuan-chen@users.noreply.github.com> Date: Thu, 19 Sep 2024 21:22:46 -0700 Subject: [PATCH] Add maxQueryLimit to feeHistory (#11973) Added a maxQueryLimit constant to define the maximum number of requested percentiles (set to 100). This implementation is the same as Geth: https://github.com/ethereum/go-ethereum/blob/a01e9742d997ea9e6cedfee41cba433433de9e10/eth/gasprice/feehistory.go#L245 Without this restriction, an attacker could submit a very large payload, causing Erigon to consume over 50GB of memory. --- eth/gasprice/feehistory.go | 5 +++++ eth/gasprice/feehistory_test.go | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go index ea773eef95f..53936737ebd 100644 --- a/eth/gasprice/feehistory.go +++ b/eth/gasprice/feehistory.go @@ -44,6 +44,8 @@ const ( // maxFeeHistory is the maximum number of blocks that can be retrieved for a // fee history request. maxFeeHistory = 1024 + // maxQueryLimit is the max number of requested percentiles. + maxQueryLimit = 100 ) // blockFees represents a single block for processing @@ -237,6 +239,9 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast oracle.log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory) blocks = maxFeeHistory } + if len(rewardPercentiles) > maxQueryLimit { + return libcommon.Big0, nil, nil, nil, fmt.Errorf("%w: over the query limit %d", ErrInvalidPercentile, maxQueryLimit) + } for i, p := range rewardPercentiles { if p < 0 || p > 100 { return libcommon.Big0, nil, nil, nil, nil, nil, fmt.Errorf("%w: %f", ErrInvalidPercentile, p) diff --git a/eth/gasprice/feehistory_test.go b/eth/gasprice/feehistory_test.go index 8207a89140d..fdd6b8df309 100644 --- a/eth/gasprice/feehistory_test.go +++ b/eth/gasprice/feehistory_test.go @@ -35,6 +35,11 @@ import ( func TestFeeHistory(t *testing.T) { + overMaxQuery := make([]float64, 101) + for i := 0; i < 101; i++ { + overMaxQuery[i] = float64(1) + } + var cases = []struct { pending bool maxHeader, maxBlock int @@ -57,6 +62,7 @@ func TestFeeHistory(t *testing.T) { {false, 20, 2, 100, 32, []float64{0, 10}, 31, 2, nil}, {false, 0, 0, 1, rpc.PendingBlockNumber, nil, 0, 0, nil}, {false, 0, 0, 2, rpc.PendingBlockNumber, nil, 32, 1, nil}, + {false, 0, 0, 10, 30, overMaxQuery, 0, 0, gasprice.ErrInvalidPercentile}, //{true, 0, 0, 2, rpc.PendingBlockNumber, nil, 32, 2, nil}, //{true, 0, 0, 2, rpc.PendingBlockNumber, []float64{0, 10}, 32, 2, nil}, }