Skip to content

Commit d7d50d3

Browse files
Gabriel-Trintinaliagfukushima
authored andcommitted
New cli options to limit rewards return by eth_feeHistory (besu-eth#6202)
Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net> Signed-off-by: Gabriel Fukushima <gabrielfukushima@gmail.com>
1 parent 0774a15 commit d7d50d3

File tree

15 files changed

+323
-30
lines changed

15 files changed

+323
-30
lines changed

besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,29 @@ static class PermissionsOptionGroup {
12171217
description = "Maximum gas price for eth_gasPrice (default: ${DEFAULT-VALUE})")
12181218
private final Long apiGasPriceMax = 500_000_000_000L;
12191219

1220+
@CommandLine.Option(
1221+
names = {"--api-priority-fee-limiting-enabled"},
1222+
hidden = true,
1223+
description =
1224+
"Set to enable priority fee limit in eth_feeHistory (default: ${DEFAULT-VALUE})")
1225+
private final Boolean apiPriorityFeeLimitingEnabled = false;
1226+
1227+
@CommandLine.Option(
1228+
names = {"--api-priority-fee-lower-bound-coefficient"},
1229+
hidden = true,
1230+
description =
1231+
"Coefficient for setting the lower limit of minimum priority fee in eth_feeHistory (default: ${DEFAULT-VALUE})")
1232+
private final Long apiPriorityFeeLowerBoundCoefficient =
1233+
ApiConfiguration.DEFAULT_LOWER_BOUND_PRIORITY_FEE_COEFFICIENT;
1234+
1235+
@CommandLine.Option(
1236+
names = {"--api-priority-fee-upper-bound-coefficient"},
1237+
hidden = true,
1238+
description =
1239+
"Coefficient for setting the upper limit of minimum priority fee in eth_feeHistory (default: ${DEFAULT-VALUE})")
1240+
private final Long apiPriorityFeeUpperBoundCoefficient =
1241+
ApiConfiguration.DEFAULT_UPPER_BOUND_PRIORITY_FEE_COEFFICIENT;
1242+
12201243
@CommandLine.Option(
12211244
names = {"--static-nodes-file"},
12221245
paramLabel = MANDATORY_FILE_FORMAT_HELP,
@@ -1875,6 +1898,17 @@ private void validateDnsOptionsParams() {
18751898
}
18761899
}
18771900

1901+
private void checkApiOptionsDependencies() {
1902+
CommandLineUtils.checkOptionDependencies(
1903+
logger,
1904+
commandLine,
1905+
"--api-priority-fee-limiting-enabled",
1906+
!apiPriorityFeeLimitingEnabled,
1907+
asList(
1908+
"--api-priority-fee-upper-bound-coefficient",
1909+
"--api-priority-fee-lower-bound-coefficient"));
1910+
}
1911+
18781912
private void ensureValidPeerBoundParams() {
18791913
maxPeers = p2PDiscoveryOptionGroup.maxPeers;
18801914
peersLowerBound = unstableNetworkingOptions.toDomainObject().getPeerLowerBound();
@@ -2485,15 +2519,28 @@ && rpcWsAuthenticationCredentialsFile() == null
24852519
}
24862520

24872521
private ApiConfiguration apiConfiguration() {
2488-
return ImmutableApiConfiguration.builder()
2489-
.gasPriceBlocks(apiGasPriceBlocks)
2490-
.gasPricePercentile(apiGasPricePercentile)
2491-
.gasPriceMinSupplier(
2492-
getMiningParameters().getMinTransactionGasPrice().getAsBigInteger()::longValueExact)
2493-
.gasPriceMax(apiGasPriceMax)
2494-
.maxLogsRange(rpcMaxLogsRange)
2495-
.gasCap(rpcGasCap)
2496-
.build();
2522+
checkApiOptionsDependencies();
2523+
var builder =
2524+
ImmutableApiConfiguration.builder()
2525+
.gasPriceBlocks(apiGasPriceBlocks)
2526+
.gasPricePercentile(apiGasPricePercentile)
2527+
.gasPriceMinSupplier(
2528+
getMiningParameters().getMinTransactionGasPrice().getAsBigInteger()::longValueExact)
2529+
.gasPriceMax(apiGasPriceMax)
2530+
.maxLogsRange(rpcMaxLogsRange)
2531+
.gasCap(rpcGasCap)
2532+
.isPriorityFeeLimitingEnabled(apiPriorityFeeLimitingEnabled);
2533+
if (apiPriorityFeeLimitingEnabled) {
2534+
if (apiPriorityFeeLowerBoundCoefficient > apiPriorityFeeUpperBoundCoefficient) {
2535+
throw new ParameterException(
2536+
this.commandLine,
2537+
"--api-priority-fee-lower-bound-coefficient cannot be greater than the value of --api-priority-fee-upper-bound-coefficient");
2538+
}
2539+
builder
2540+
.lowerBoundPriorityFeeCoefficient(apiPriorityFeeLowerBoundCoefficient)
2541+
.upperBoundPriorityFeeCoefficient(apiPriorityFeeUpperBoundCoefficient);
2542+
}
2543+
return builder.build();
24972544
}
24982545

24992546
/**

besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,77 @@ public void rpcGasCapOptionMustBeUsed() {
16091609
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
16101610
}
16111611

1612+
@Test
1613+
public void apiPriorityFeeLimitingEnabledOptionMustBeUsed() {
1614+
parseCommand("--api-priority-fee-limiting-enabled");
1615+
verify(mockRunnerBuilder).apiConfiguration(apiConfigurationCaptor.capture());
1616+
verify(mockRunnerBuilder).build();
1617+
assertThat(apiConfigurationCaptor.getValue())
1618+
.isEqualTo(ImmutableApiConfiguration.builder().isPriorityFeeLimitingEnabled(true).build());
1619+
1620+
assertThat(commandOutput.toString(UTF_8)).isEmpty();
1621+
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
1622+
}
1623+
1624+
@Test
1625+
public void apiPriorityFeeLowerBoundCoefficientOptionMustBeUsed() {
1626+
final long lowerBound = 150L;
1627+
parseCommand(
1628+
"--api-priority-fee-lower-bound-coefficient",
1629+
Long.toString(lowerBound),
1630+
"--api-priority-fee-limiting-enabled");
1631+
verify(mockRunnerBuilder).apiConfiguration(apiConfigurationCaptor.capture());
1632+
verify(mockRunnerBuilder).build();
1633+
assertThat(apiConfigurationCaptor.getValue())
1634+
.isEqualTo(
1635+
ImmutableApiConfiguration.builder()
1636+
.lowerBoundPriorityFeeCoefficient(lowerBound)
1637+
.isPriorityFeeLimitingEnabled(true)
1638+
.build());
1639+
1640+
assertThat(commandOutput.toString(UTF_8)).isEmpty();
1641+
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
1642+
}
1643+
1644+
@Test
1645+
public void
1646+
apiPriorityFeeLowerBoundCoefficients_MustNotBeGreaterThan_apiPriorityFeeUpperBoundCoefficient() {
1647+
final long lowerBound = 200L;
1648+
final long upperBound = 100L;
1649+
1650+
parseCommand(
1651+
"--api-priority-fee-limiting-enabled",
1652+
"--api-priority-fee-lower-bound-coefficient",
1653+
Long.toString(lowerBound),
1654+
"--api-priority-fee-upper-bound-coefficient",
1655+
Long.toString(upperBound));
1656+
Mockito.verifyNoInteractions(mockRunnerBuilder);
1657+
assertThat(commandOutput.toString(UTF_8)).isEmpty();
1658+
assertThat(commandErrorOutput.toString(UTF_8))
1659+
.contains(
1660+
"--api-priority-fee-lower-bound-coefficient cannot be greater than the value of --api-priority-fee-upper-bound-coefficient");
1661+
}
1662+
1663+
@Test
1664+
public void apiPriorityFeeUpperBoundCoefficientsOptionMustBeUsed() {
1665+
final long upperBound = 200L;
1666+
parseCommand(
1667+
"--api-priority-fee-upper-bound-coefficient",
1668+
Long.toString(upperBound),
1669+
"--api-priority-fee-limiting-enabled");
1670+
verify(mockRunnerBuilder).apiConfiguration(apiConfigurationCaptor.capture());
1671+
verify(mockRunnerBuilder).build();
1672+
assertThat(apiConfigurationCaptor.getValue())
1673+
.isEqualTo(
1674+
ImmutableApiConfiguration.builder()
1675+
.upperBoundPriorityFeeCoefficient(upperBound)
1676+
.isPriorityFeeLimitingEnabled(true)
1677+
.build());
1678+
1679+
assertThat(commandOutput.toString(UTF_8)).isEmpty();
1680+
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
1681+
}
1682+
16121683
@Test
16131684
public void p2pPeerUpperBound_without_p2pPeerLowerBound_shouldSetLowerBoundEqualToUpperBound() {
16141685

consensus/common/src/main/java/org/hyperledger/besu/consensus/common/MigratingMiningCoordinator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public Wei getMinTransactionGasPrice() {
103103
return activeMiningCoordinator.getMinTransactionGasPrice();
104104
}
105105

106+
@Override
107+
public Wei getMinPriorityFeePerGas() {
108+
return activeMiningCoordinator.getMinPriorityFeePerGas();
109+
}
110+
106111
@Override
107112
public void setExtraData(final Bytes extraData) {
108113
activeMiningCoordinator.setExtraData(extraData);

consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftBlockCreatorFactory.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ public Wei getMinTransactionGasPrice() {
147147
return miningParameters.getMinTransactionGasPrice();
148148
}
149149

150+
/**
151+
* Gets min priority fee per gas
152+
*
153+
* @return min priority fee per gas
154+
*/
155+
public Wei getMinPriorityFeePerGas() {
156+
return miningParameters.getMinPriorityFeePerGas();
157+
}
158+
150159
/**
151160
* Create extra data bytes.
152161
*

consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftMiningCoordinator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ public Wei getMinTransactionGasPrice() {
148148
return blockCreatorFactory.getMinTransactionGasPrice();
149149
}
150150

151+
@Override
152+
public Wei getMinPriorityFeePerGas() {
153+
return blockCreatorFactory.getMinPriorityFeePerGas();
154+
}
155+
151156
@Override
152157
public void setExtraData(final Bytes extraData) {
153158
blockCreatorFactory.setExtraData(extraData);

consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ public Wei getMinTransactionGasPrice() {
211211
return miningParameters.getMinTransactionGasPrice();
212212
}
213213

214+
@Override
215+
public Wei getMinPriorityFeePerGas() {
216+
return miningParameters.getMinPriorityFeePerGas();
217+
}
218+
214219
@Override
215220
public void setExtraData(final Bytes extraData) {
216221
this.miningParameters.setExtraData(extraData);

consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/TransitionCoordinator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ public Wei getMinTransactionGasPrice() {
101101
return dispatchFunctionAccordingToMergeState(MiningCoordinator::getMinTransactionGasPrice);
102102
}
103103

104+
@Override
105+
public Wei getMinPriorityFeePerGas() {
106+
return dispatchFunctionAccordingToMergeState(MiningCoordinator::getMinPriorityFeePerGas);
107+
}
108+
104109
@Override
105110
public void setExtraData(final Bytes extraData) {
106111
miningCoordinator.setExtraData(extraData);

ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
@Value.Style(allParameters = true)
2525
public abstract class ApiConfiguration {
2626

27+
public static final long DEFAULT_LOWER_BOUND_PRIORITY_FEE_COEFFICIENT = 0L;
28+
public static final long DEFAULT_UPPER_BOUND_PRIORITY_FEE_COEFFICIENT = Long.MAX_VALUE;
29+
2730
@Value.Default
2831
public long getGasPriceBlocks() {
2932
return 100;
@@ -59,4 +62,19 @@ public Long getMaxLogsRange() {
5962
public Long getGasCap() {
6063
return 0L;
6164
}
65+
66+
@Value.Default
67+
public boolean isPriorityFeeLimitingEnabled() {
68+
return false;
69+
}
70+
71+
@Value.Default
72+
public Long getLowerBoundPriorityFeeCoefficient() {
73+
return DEFAULT_LOWER_BOUND_PRIORITY_FEE_COEFFICIENT;
74+
}
75+
76+
@Value.Default
77+
public Long getUpperBoundPriorityFeeCoefficient() {
78+
return DEFAULT_UPPER_BOUND_PRIORITY_FEE_COEFFICIENT;
79+
}
6280
}

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

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.hyperledger.besu.datatypes.Hash;
2020
import org.hyperledger.besu.datatypes.Wei;
21+
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
2122
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
2223
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
2324
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
@@ -28,6 +29,7 @@
2829
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
2930
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.FeeHistory;
3031
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.ImmutableFeeHistory;
32+
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
3133
import org.hyperledger.besu.ethereum.chain.Blockchain;
3234
import org.hyperledger.besu.ethereum.core.Block;
3335
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -53,14 +55,22 @@
5355
public class EthFeeHistory implements JsonRpcMethod {
5456
private final ProtocolSchedule protocolSchedule;
5557
private final Blockchain blockchain;
58+
private final MiningCoordinator miningCoordinator;
59+
private final ApiConfiguration apiConfiguration;
5660
private final Cache<RewardCacheKey, List<Wei>> cache;
5761
private static final int MAXIMUM_CACHE_SIZE = 100_000;
5862

5963
record RewardCacheKey(Hash blockHash, List<Double> rewardPercentiles) {}
6064

61-
public EthFeeHistory(final ProtocolSchedule protocolSchedule, final Blockchain blockchain) {
65+
public EthFeeHistory(
66+
final ProtocolSchedule protocolSchedule,
67+
final Blockchain blockchain,
68+
final MiningCoordinator miningCoordinator,
69+
final ApiConfiguration apiConfiguration) {
6270
this.protocolSchedule = protocolSchedule;
6371
this.blockchain = blockchain;
72+
this.miningCoordinator = miningCoordinator;
73+
this.apiConfiguration = apiConfiguration;
6474
this.cache = Caffeine.newBuilder().maximumSize(MAXIMUM_CACHE_SIZE).build();
6575
}
6676

@@ -203,7 +213,16 @@ public List<Wei> computeRewards(final List<Double> rewardPercentiles, final Bloc
203213
final List<Long> transactionsGasUsed = calculateTransactionsGasUsed(block);
204214
final List<TransactionInfo> transactionsInfo =
205215
generateTransactionsInfo(transactions, transactionsGasUsed, baseFee);
206-
return calculateRewards(rewardPercentiles, block, transactionsInfo);
216+
217+
var realRewards = calculateRewards(rewardPercentiles, block, transactionsInfo);
218+
219+
// If the priority fee boundary is set, return the bounded rewards. Otherwise, return the real
220+
// rewards.
221+
if (apiConfiguration.isPriorityFeeLimitingEnabled()) {
222+
return boundRewards(realRewards);
223+
} else {
224+
return realRewards;
225+
}
207226
}
208227

209228
private List<Wei> calculateRewards(
@@ -235,6 +254,46 @@ private List<Wei> calculateRewards(
235254
return rewards;
236255
}
237256

257+
/**
258+
* This method returns a list of bounded rewards.
259+
*
260+
* @param rewards The list of rewards to be bounded.
261+
* @return The list of bounded rewards.
262+
*/
263+
private List<Wei> boundRewards(final List<Wei> rewards) {
264+
Wei minPriorityFee = miningCoordinator.getMinPriorityFeePerGas();
265+
Wei lowerBound =
266+
minPriorityFee.multiply(apiConfiguration.getLowerBoundPriorityFeeCoefficient()).divide(100);
267+
Wei upperBound =
268+
minPriorityFee.multiply(apiConfiguration.getUpperBoundPriorityFeeCoefficient()).divide(100);
269+
270+
return rewards.stream().map(reward -> boundReward(reward, lowerBound, upperBound)).toList();
271+
}
272+
273+
/**
274+
* This method bounds the reward between a lower and upper limit.
275+
*
276+
* @param reward The reward to be bounded.
277+
* @param lowerBound The lower limit for the reward.
278+
* @param upperBound The upper limit for the reward.
279+
* @return The bounded reward.
280+
*/
281+
private Wei boundReward(final Wei reward, final Wei lowerBound, final Wei upperBound) {
282+
283+
// If the reward is less than the lower bound, return the lower bound.
284+
if (reward.compareTo(lowerBound) <= 0) {
285+
return lowerBound;
286+
}
287+
288+
// If the reward is greater than the upper bound, return the upper bound.
289+
if (reward.compareTo(upperBound) > 0) {
290+
return upperBound;
291+
}
292+
293+
// If the reward is within the bounds, return the reward as is.
294+
return reward;
295+
}
296+
238297
private List<Long> calculateTransactionsGasUsed(final Block block) {
239298
final List<Long> transactionsGasUsed = new ArrayList<>();
240299
long cumulativeGasUsed = 0L;

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,11 @@ protected Map<String, JsonRpcMethod> create() {
130130
blockchainQueries.getWorldStateArchive(),
131131
protocolSchedule,
132132
apiConfiguration.getGasCap())),
133-
new EthFeeHistory(protocolSchedule, blockchainQueries.getBlockchain()),
133+
new EthFeeHistory(
134+
protocolSchedule,
135+
blockchainQueries.getBlockchain(),
136+
miningCoordinator,
137+
apiConfiguration),
134138
new EthGetCode(blockchainQueries),
135139
new EthGetLogs(blockchainQueries, apiConfiguration.getMaxLogsRange()),
136140
new EthGetProof(blockchainQueries),

0 commit comments

Comments
 (0)