Skip to content

Commit 1e5fb00

Browse files
authored
update rpc gas cap default to 50M (#8251)
* update rpc gas cap default to 50M Signed-off-by: Sally MacFarlane <[email protected]> --------- Signed-off-by: Sally MacFarlane <[email protected]>
1 parent 28dd49e commit 1e5fb00

File tree

5 files changed

+114
-30
lines changed

5 files changed

+114
-30
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44
### Breaking Changes
5+
- `rpc-gas-cap` default value has changed from 0 (unlimited) to 50M. If you require `rpc-gas-cap` greater than 50M, you'll need to set that explicitly. [#8251](https://github.com/hyperledger/besu/issues/8251)
56
### Upcoming Breaking Changes
67
- `MetricSystem::createLabelledGauge` is deprecated and will be removed in a future release, replace it with `MetricSystem::createLabelledSuppliedGauge`
78
- k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release. Use docker or none instead.
@@ -16,6 +17,7 @@
1617
- Fast Sync
1718
### Additions and Improvements
1819
- Add a tx selector to skip txs from the same sender after the first not selected [#8216](https://github.com/hyperledger/besu/pull/8216)
20+
- `rpc-gas-cap` default value has changed from 0 (unlimited) to 50M [#8251](https://github.com/hyperledger/besu/issues/8251)
1921

2022
#### Prague
2123
- Add timestamps to enable Prague hardfork on Sepolia and Holesky test networks [#8163](https://github.com/hyperledger/besu/pull/8163)

besu/src/main/java/org/hyperledger/besu/cli/options/ApiConfigurationOptions.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public ApiConfigurationOptions() {}
8181
names = {"--rpc-gas-cap"},
8282
description =
8383
"Specifies the gasLimit cap for transaction simulation RPC methods. Must be >=0. 0 specifies no limit (default: ${DEFAULT-VALUE})")
84-
private final Long rpcGasCap = 0L;
84+
private final Long rpcGasCap = ApiConfiguration.DEFAULT_GAS_CAP;
8585

8686
@CommandLine.Option(
8787
names = {"--rpc-max-trace-filter-range"},

besu/src/test/java/org/hyperledger/besu/cli/options/ApiConfigurationOptionsTest.java

+34-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static org.mockito.Mockito.verify;
2020

2121
import org.hyperledger.besu.cli.CommandTestAbstract;
22+
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
2223
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
2324

2425
import org.junit.jupiter.api.Test;
@@ -111,7 +112,7 @@ public void rpcMaxLogsRangeOptionMustBeUsed() {
111112
verify(mockRunnerBuilder).build();
112113

113114
assertThat(apiConfigurationCaptor.getValue())
114-
.isEqualTo(ImmutableApiConfiguration.builder().maxLogsRange((rpcMaxLogsRange)).build());
115+
.isEqualTo(ImmutableApiConfiguration.builder().maxLogsRange(rpcMaxLogsRange).build());
115116

116117
assertThat(commandOutput.toString(UTF_8)).isEmpty();
117118
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
@@ -126,7 +127,37 @@ public void rpcGasCapOptionMustBeUsed() {
126127
verify(mockRunnerBuilder).build();
127128

128129
assertThat(apiConfigurationCaptor.getValue())
129-
.isEqualTo(ImmutableApiConfiguration.builder().gasCap((rpcGasCap)).build());
130+
.isEqualTo(ImmutableApiConfiguration.builder().gasCap(rpcGasCap).build());
131+
132+
assertThat(commandOutput.toString(UTF_8)).isEmpty();
133+
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
134+
}
135+
136+
@Test
137+
public void rpcGasCapDefault() {
138+
parseCommand();
139+
140+
verify(mockRunnerBuilder).apiConfiguration(apiConfigurationCaptor.capture());
141+
verify(mockRunnerBuilder).build();
142+
143+
assertThat(apiConfigurationCaptor.getValue())
144+
.isEqualTo(
145+
ImmutableApiConfiguration.builder().gasCap(ApiConfiguration.DEFAULT_GAS_CAP).build());
146+
147+
assertThat(commandOutput.toString(UTF_8)).isEmpty();
148+
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
149+
}
150+
151+
@Test
152+
public void rpcGasCapAcceptsZero() {
153+
final long rpcGasCap = 0L;
154+
parseCommand("--rpc-gas-cap", Long.toString(rpcGasCap));
155+
156+
verify(mockRunnerBuilder).apiConfiguration(apiConfigurationCaptor.capture());
157+
verify(mockRunnerBuilder).build();
158+
159+
assertThat(apiConfigurationCaptor.getValue())
160+
.isEqualTo(ImmutableApiConfiguration.builder().gasCap(rpcGasCap).build());
130161

131162
assertThat(commandOutput.toString(UTF_8)).isEmpty();
132163
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
@@ -143,7 +174,7 @@ public void rpcMaxTraceFilterOptionMustBeUsed() {
143174
assertThat(apiConfigurationCaptor.getValue())
144175
.isEqualTo(
145176
ImmutableApiConfiguration.builder()
146-
.maxTraceFilterRange((rpcMaxTraceFilterOption))
177+
.maxTraceFilterRange(rpcMaxTraceFilterOption)
147178
.build());
148179

149180
assertThat(commandOutput.toString(UTF_8)).isEmpty();

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ public abstract class ApiConfiguration {
3838
*/
3939
public static final long DEFAULT_UPPER_BOUND_GAS_AND_PRIORITY_FEE_COEFFICIENT = Long.MAX_VALUE;
4040

41+
/** The default gas cap used for transaction simulation */
42+
public static final long DEFAULT_GAS_CAP = 50_000_000L;
43+
4144
/** Constructs a new ApiConfiguration with default values. */
4245
protected ApiConfiguration() {}
4346

@@ -93,13 +96,13 @@ public Long getMaxLogsRange() {
9396
}
9497

9598
/**
96-
* Returns the gas cap. Default value is 0.
99+
* Returns the gas cap. Default value is 50M.
97100
*
98101
* @return the gas cap
99102
*/
100103
@Value.Default
101104
public Long getGasCap() {
102-
return 0L;
105+
return DEFAULT_GAS_CAP;
103106
}
104107

105108
/**

ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java

+72-24
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.hyperledger.besu.datatypes.Wei;
3838
import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter;
3939
import org.hyperledger.besu.ethereum.GasLimitCalculator;
40+
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
4041
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter.JsonCallParameterBuilder;
4142
import org.hyperledger.besu.ethereum.chain.Blockchain;
4243
import org.hyperledger.besu.ethereum.core.BlobTestFixture;
@@ -93,8 +94,9 @@ public class TransactionSimulatorTest {
9394
Address.fromHexString("0x0000000000000000000000000000000000000000");
9495
private static final long GAS_CAP = 500000L;
9596
private static final long TRANSFER_GAS_LIMIT = 21000L;
96-
private TransactionSimulator transactionSimulator;
97+
private TransactionSimulator uncappedTransactionSimulator;
9798
private TransactionSimulator cappedTransactionSimulator;
99+
private TransactionSimulator defaultCappedTransactionSimulator;
98100

99101
@Mock private Blockchain blockchain;
100102
@Mock private WorldStateArchive worldStateArchive;
@@ -107,12 +109,22 @@ public class TransactionSimulatorTest {
107109
@BeforeEach
108110
public void setUp() {
109111
final var miningConfiguration = MiningConfiguration.newDefault().setCoinbase(Address.ZERO);
110-
this.transactionSimulator =
112+
// rpc gas cap 0 means unlimited
113+
this.uncappedTransactionSimulator =
111114
new TransactionSimulator(
112115
blockchain, worldStateArchive, protocolSchedule, miningConfiguration, 0);
116+
// capped at a lower limit
113117
this.cappedTransactionSimulator =
114118
new TransactionSimulator(
115119
blockchain, worldStateArchive, protocolSchedule, miningConfiguration, GAS_CAP);
120+
// capped at default limit
121+
this.defaultCappedTransactionSimulator =
122+
new TransactionSimulator(
123+
blockchain,
124+
worldStateArchive,
125+
protocolSchedule,
126+
miningConfiguration,
127+
ApiConfiguration.DEFAULT_GAS_CAP);
116128
}
117129

118130
@Test
@@ -174,7 +186,7 @@ public void shouldReturnEmptyWhenBlockDoesNotExist() {
174186
when(blockchain.getBlockHeader(eq(1L))).thenReturn(Optional.empty());
175187

176188
final Optional<TransactionSimulatorResult> result =
177-
transactionSimulator.process(legacyTransactionCallParameterBuilder().build(), 1L);
189+
uncappedTransactionSimulator.process(legacyTransactionCallParameterBuilder().build(), 1L);
178190

179191
assertThat(result.isPresent()).isFalse();
180192
}
@@ -203,7 +215,7 @@ public void shouldReturnSuccessfulResultWhenProcessingIsSuccessful() {
203215
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
204216

205217
final Optional<TransactionSimulatorResult> result =
206-
transactionSimulator.process(callParameter, 1L);
218+
uncappedTransactionSimulator.process(callParameter, 1L);
207219

208220
assertThat(result.get().isSuccessful()).isTrue();
209221
verifyTransactionWasProcessed(expectedTransaction);
@@ -234,12 +246,12 @@ public void simulateOnPendingBlockWorks() {
234246
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
235247

236248
final Optional<TransactionSimulatorResult> result =
237-
transactionSimulator.processOnPending(
249+
uncappedTransactionSimulator.processOnPending(
238250
callParameter,
239251
Optional.empty(),
240252
TransactionValidationParams.transactionSimulator(),
241253
NO_TRACING,
242-
transactionSimulator.simulatePendingBlockHeader());
254+
uncappedTransactionSimulator.simulatePendingBlockHeader());
243255

244256
assertThat(result.get().isSuccessful()).isTrue();
245257
verifyTransactionWasProcessed(expectedTransaction);
@@ -269,7 +281,7 @@ public void shouldSetGasPriceToZeroWhenExceedingBalanceAllowed() {
269281
.build();
270282
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
271283

272-
transactionSimulator.process(
284+
uncappedTransactionSimulator.process(
273285
callParameter,
274286
ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(true).build(),
275287
NO_TRACING,
@@ -306,7 +318,7 @@ public void shouldSetFeePerGasToZeroWhenExceedingBalanceAllowed() {
306318

307319
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
308320

309-
transactionSimulator.process(
321+
uncappedTransactionSimulator.process(
310322
callParameter,
311323
ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(true).build(),
312324
NO_TRACING,
@@ -340,7 +352,7 @@ public void shouldNotSetGasPriceToZeroWhenExceedingBalanceIsNotAllowed() {
340352

341353
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
342354

343-
transactionSimulator.process(
355+
uncappedTransactionSimulator.process(
344356
callParameter,
345357
ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(false).build(),
346358
NO_TRACING,
@@ -376,7 +388,7 @@ public void shouldNotSetFeePerGasToZeroWhenExceedingBalanceIsNotAllowed() {
376388
.build();
377389
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
378390

379-
transactionSimulator.process(
391+
uncappedTransactionSimulator.process(
380392
callParameter,
381393
ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(false).build(),
382394
NO_TRACING,
@@ -409,7 +421,7 @@ public void shouldUseDefaultValuesWhenMissingOptionalFields() {
409421
.build();
410422
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
411423

412-
transactionSimulator.process(callParameter, 1L);
424+
uncappedTransactionSimulator.process(callParameter, 1L);
413425

414426
verifyTransactionWasProcessed(expectedTransaction);
415427
}
@@ -438,7 +450,7 @@ public void shouldUseZeroNonceWhenAccountDoesNotExist() {
438450
.build();
439451
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
440452

441-
transactionSimulator.process(callParameter, 1L);
453+
uncappedTransactionSimulator.process(callParameter, 1L);
442454

443455
verifyTransactionWasProcessed(expectedTransaction);
444456
}
@@ -472,7 +484,7 @@ public void shouldUseSpecifiedNonceWhenProvided() {
472484
.build();
473485
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
474486

475-
transactionSimulator.process(callParameter, 1L);
487+
uncappedTransactionSimulator.process(callParameter, 1L);
476488
verifyTransactionWasProcessed(expectedTransaction);
477489
}
478490

@@ -501,7 +513,7 @@ public void shouldReturnFailureResultWhenProcessingFails() {
501513
mockProcessorStatusForTransaction(expectedTransaction, Status.FAILED);
502514

503515
final Optional<TransactionSimulatorResult> result =
504-
transactionSimulator.process(callParameter, 1L);
516+
uncappedTransactionSimulator.process(callParameter, 1L);
505517

506518
assertThat(result.get().isSuccessful()).isFalse();
507519
verifyTransactionWasProcessed(expectedTransaction);
@@ -512,7 +524,8 @@ public void shouldReturnEmptyWhenBlockDoesNotExistByHash() {
512524
when(blockchain.getBlockHeader(eq(Hash.ZERO))).thenReturn(Optional.empty());
513525

514526
final Optional<TransactionSimulatorResult> result =
515-
transactionSimulator.process(legacyTransactionCallParameterBuilder().build(), Hash.ZERO);
527+
uncappedTransactionSimulator.process(
528+
legacyTransactionCallParameterBuilder().build(), Hash.ZERO);
516529

517530
assertThat(result.isPresent()).isFalse();
518531
}
@@ -542,7 +555,7 @@ public void shouldReturnSuccessfulResultWhenProcessingIsSuccessfulByHash() {
542555
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
543556

544557
final Optional<TransactionSimulatorResult> result =
545-
transactionSimulator.process(callParameter, blockHeader.getBlockHash());
558+
uncappedTransactionSimulator.process(callParameter, blockHeader.getBlockHash());
546559

547560
assertThat(result.get().isSuccessful()).isTrue();
548561
verifyTransactionWasProcessed(expectedTransaction);
@@ -572,7 +585,7 @@ public void shouldUseDefaultValuesWhenMissingOptionalFieldsByHash() {
572585
.build();
573586
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
574587

575-
transactionSimulator.process(callParameter, blockHeader.getBlockHash());
588+
uncappedTransactionSimulator.process(callParameter, blockHeader.getBlockHash());
576589

577590
verifyTransactionWasProcessed(expectedTransaction);
578591
}
@@ -601,7 +614,7 @@ public void shouldUseZeroNonceWhenAccountDoesNotExistByHash() {
601614
.build();
602615
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
603616

604-
transactionSimulator.process(callParameter, blockHeader.getBlockHash());
617+
uncappedTransactionSimulator.process(callParameter, blockHeader.getBlockHash());
605618

606619
verifyTransactionWasProcessed(expectedTransaction);
607620
}
@@ -631,7 +644,7 @@ public void shouldReturnFailureResultWhenProcessingFailsByHash() {
631644
mockProcessorStatusForTransaction(expectedTransaction, Status.FAILED);
632645

633646
final Optional<TransactionSimulatorResult> result =
634-
transactionSimulator.process(callParameter, blockHeader.getBlockHash());
647+
uncappedTransactionSimulator.process(callParameter, blockHeader.getBlockHash());
635648

636649
assertThat(result.get().isSuccessful()).isFalse();
637650
verifyTransactionWasProcessed(expectedTransaction);
@@ -662,7 +675,7 @@ public void shouldReturnSuccessfulResultWhenEip1559TransactionProcessingIsSucces
662675
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
663676

664677
final Optional<TransactionSimulatorResult> result =
665-
transactionSimulator.process(callParameter, 1L);
678+
uncappedTransactionSimulator.process(callParameter, 1L);
666679

667680
assertThat(result.get().isSuccessful()).isTrue();
668681
verifyTransactionWasProcessed(expectedTransaction);
@@ -735,7 +748,7 @@ public void shouldUseProvidedGasLimitWhenBelowRpcCapGas() {
735748
}
736749

737750
@Test
738-
public void shouldUseRpcGasCapWhenGasLimitNoPresent() {
751+
public void shouldUseRpcGasCapWhenGasLimitNotPresent() {
739752
// generate call parameters that do not specify a gas limit,
740753
// expect the rpc gas cap to be used for simulation
741754

@@ -769,6 +782,41 @@ public void shouldUseRpcGasCapWhenGasLimitNoPresent() {
769782
verifyTransactionWasProcessed(expectedTransaction);
770783
}
771784

785+
@Test
786+
public void shouldUseDefaultRpcGasCapWhenGasLimitNotPresent() {
787+
// generate call parameters that do not specify a gas limit,
788+
// expect the default rpc gas cap to be used for simulation
789+
790+
final CallParameter callParameter =
791+
eip1559TransactionCallParameterBuilder().withGas(-1L).build();
792+
793+
mockBlockchainAndWorldState(callParameter);
794+
mockProtocolSpecForProcessWithWorldUpdater();
795+
796+
final Transaction expectedTransaction =
797+
Transaction.builder()
798+
.type(TransactionType.EIP1559)
799+
.chainId(BigInteger.ONE)
800+
.nonce(1L)
801+
.gasLimit(callParameter.getGasLimit())
802+
.maxFeePerGas(callParameter.getMaxFeePerGas().orElseThrow())
803+
.maxPriorityFeePerGas(callParameter.getMaxPriorityFeePerGas().orElseThrow())
804+
.to(callParameter.getTo())
805+
.sender(callParameter.getFrom())
806+
.value(callParameter.getValue())
807+
.payload(callParameter.getPayload())
808+
.signature(FAKE_SIGNATURE)
809+
.gasLimit(ApiConfiguration.DEFAULT_GAS_CAP)
810+
.build();
811+
812+
// call process with original transaction
813+
defaultCappedTransactionSimulator.process(
814+
callParameter, TransactionValidationParams.transactionSimulator(), NO_TRACING, 1L);
815+
816+
// expect transaction with the original gas limit to be processed
817+
verifyTransactionWasProcessed(expectedTransaction);
818+
}
819+
772820
@Test
773821
public void shouldReturnSuccessfulResultWhenBlobTransactionProcessingIsSuccessful() {
774822
final CallParameter callParameter = blobTransactionCallParameter();
@@ -780,7 +828,7 @@ public void shouldReturnSuccessfulResultWhenBlobTransactionProcessingIsSuccessfu
780828
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
781829

782830
final Optional<TransactionSimulatorResult> result =
783-
transactionSimulator.process(callParameter, 1L);
831+
uncappedTransactionSimulator.process(callParameter, 1L);
784832

785833
assertThat(result.get().isSuccessful()).isTrue();
786834
verifyTransactionWasProcessed(expectedTransaction);
@@ -797,7 +845,7 @@ public void shouldReturnFailureResultWhenBlobTransactionProcessingFails() {
797845
mockProcessorStatusForTransaction(expectedTransaction, Status.FAILED);
798846

799847
final Optional<TransactionSimulatorResult> result =
800-
transactionSimulator.process(callParameter, 1L);
848+
uncappedTransactionSimulator.process(callParameter, 1L);
801849

802850
assertThat(result.get().isSuccessful()).isFalse();
803851
verifyTransactionWasProcessed(expectedTransaction);
@@ -980,7 +1028,7 @@ public void shouldSimulateLegacyTransactionWhenBaseFeeNotZero() {
9801028
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);
9811029

9821030
final Optional<TransactionSimulatorResult> result =
983-
transactionSimulator.process(callParameter, 1L);
1031+
uncappedTransactionSimulator.process(callParameter, 1L);
9841032

9851033
verifyTransactionWasProcessed(expectedTransaction);
9861034
assertThat(result.get().isSuccessful()).isTrue();

0 commit comments

Comments
 (0)