Skip to content

Commit e200e11

Browse files
authored
Implement percentiles array size limit for eth_feeHistory (#8748)
* implement percentiles array size limit for eth_feeHistory Signed-off-by: garyschulte <[email protected]>
1 parent cccc25d commit e200e11

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#### Fusaka Devnet
99
- EIP-7825 - Transaction gas limit cap [#8700](https://github.com/hyperledger/besu/pull/8700)
1010
- EIP-7823 - Modexp upper bounds [#8632](https://github.com/hyperledger/besu/pull/8632)
11+
- implement rewardPercentile cap in eth_feeHistory [#8748](https://github.com/hyperledger/besu/pull/8748)
1112

1213
### Bug fixes
1314

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public class EthFeeHistory implements JsonRpcMethod {
6767
private final ApiConfiguration apiConfiguration;
6868
private final Cache<RewardCacheKey, List<Wei>> cache;
6969
private static final int MAXIMUM_CACHE_SIZE = 100_000;
70+
private static final int MAXIMUM_QUERY_PERCENTILES = 100;
7071

7172
record RewardCacheKey(Hash blockHash, List<Double> rewardPercentiles) {}
7273

@@ -139,8 +140,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext request) {
139140
final List<Double> gasUsedRatios = getGasUsedRatios(blockHeaderRange);
140141
final List<Double> blobGasUsedRatios = getBlobGasUsedRatios(blockHeaderRange);
141142
final Optional<List<List<Wei>>> maybeRewards =
142-
maybeRewardPercentiles.map(
143-
percentiles -> getRewards(percentiles, blockHeaderRange, nextBaseFee));
143+
maybeRewardPercentiles
144+
.filter(list -> list.size() <= MAXIMUM_QUERY_PERCENTILES)
145+
.map(percentiles -> getRewards(percentiles, blockHeaderRange, nextBaseFee));
144146
return new JsonRpcSuccessResponse(
145147
requestId,
146148
createFeeHistoryResult(

ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistoryTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
import java.util.Collections;
6262
import java.util.List;
6363
import java.util.Optional;
64+
import java.util.stream.Collectors;
65+
import java.util.stream.IntStream;
6466
import java.util.stream.Stream;
6567

6668
import org.apache.tuweni.bytes.Bytes;
@@ -368,6 +370,48 @@ public void allZeroPercentilesForZeroBlock() {
368370
assertThat(result.getReward()).isEqualTo(List.of(List.of("0x0")));
369371
}
370372

373+
@Test
374+
public void assertMaximumPercentilesArraySize() {
375+
final ProtocolSpec londonSpec = mock(ProtocolSpec.class);
376+
when(londonSpec.getFeeMarket()).thenReturn(FeeMarket.london(5));
377+
final BlockDataGenerator.BlockOptions blockOptions = BlockDataGenerator.BlockOptions.create();
378+
blockOptions.hasTransactions(false);
379+
blockOptions.setParentHash(blockchain.getChainHeadHash());
380+
blockOptions.setBlockNumber(11);
381+
final Block emptyBlock = gen.block(blockOptions);
382+
blockchain.appendBlock(emptyBlock, gen.receipts(emptyBlock));
383+
when(protocolSchedule.getForNextBlockHeader(
384+
eq(blockchain.getChainHeadHeader()),
385+
eq(blockchain.getChainHeadHeader().getTimestamp())))
386+
.thenReturn(londonSpec);
387+
388+
double[] biglist = new double[500];
389+
Arrays.fill(biglist, 1d);
390+
List<Double> oversizeRewardPercentiles =
391+
Arrays.stream(biglist).boxed().collect(Collectors.toList());
392+
393+
List<Double> maxRewardPercentiles =
394+
IntStream.rangeClosed(1, 100)
395+
.mapToDouble(i -> i / 100d)
396+
.boxed()
397+
.collect(Collectors.toList());
398+
399+
// assert we return no percentiles for array sizes > 100
400+
final FeeHistory.FeeHistoryResult result =
401+
(FeeHistory.FeeHistoryResult)
402+
((JsonRpcSuccessResponse) feeHistoryRequest("0x1", "latest", oversizeRewardPercentiles))
403+
.getResult();
404+
assertThat(result.getReward()).isNull();
405+
406+
// assert we will return percentiles for array sizes <= 100
407+
final FeeHistory.FeeHistoryResult resultOk =
408+
(FeeHistory.FeeHistoryResult)
409+
((JsonRpcSuccessResponse) feeHistoryRequest("0x1", "latest", maxRewardPercentiles))
410+
.getResult();
411+
assertThat(resultOk.getReward()).isNotNull();
412+
assertThat(resultOk.getReward().get(0).size()).isEqualTo(100);
413+
}
414+
371415
private void assertFeeMetadataSize(final Object feeObject, final int blockCount) {
372416
assertThat(((ImmutableFeeHistoryResult) feeObject).getBaseFeePerGas().size())
373417
.isEqualTo(blockCount + 1);

0 commit comments

Comments
 (0)