From a5d5af0d321a825df2f9084f204ccc8bcca1e738 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Wed, 22 Nov 2023 01:15:52 +1100 Subject: [PATCH] Add `rpc-gas-cap` via transaction simulator (#6156) * Add `rpc-gas-cap` to enable user to cap gasLimit of certain RPC methods Signed-off-by: Gabriel Fukushima --------- Signed-off-by: Gabriel Fukushima --- CHANGELOG.md | 2 + .../org/hyperledger/besu/RunnerBuilder.java | 17 ++- .../org/hyperledger/besu/cli/BesuCommand.java | 7 ++ .../controller/QbftBesuControllerBuilder.java | 2 +- .../hyperledger/besu/RunnerBuilderTest.java | 6 ++ .../java/org/hyperledger/besu/RunnerTest.java | 3 +- .../hyperledger/besu/cli/BesuCommandTest.java | 14 +++ .../besu/cli/CommandTestAbstract.java | 2 +- .../src/test/resources/everything_config.toml | 1 + .../qbft/support/TestContextBuilder.java | 2 +- .../jsonrpc/JsonRpcTestMethodsFactory.java | 1 + .../api/graphql/GraphQLContextType.java | 3 +- .../pojoadapter/BlockAdapterBase.java | 4 +- .../pojoadapter/PendingStateAdapter.java | 4 +- .../jsonrpc/methods/DebugJsonRpcMethods.java | 10 +- .../jsonrpc/methods/EthJsonRpcMethods.java | 14 ++- .../methods/JsonRpcMethodsFactory.java | 11 +- .../jsonrpc/methods/TraceJsonRpcMethods.java | 17 ++- .../AbstractEthGraphQLHttpServiceTest.java | 4 +- .../AbstractJsonRpcHttpServiceTest.java | 1 + .../JsonRpcHttpServiceHostAllowlistTest.java | 1 + .../jsonrpc/JsonRpcHttpServiceLoginTest.java | 1 + .../JsonRpcHttpServiceRpcApisTest.java | 2 + .../jsonrpc/JsonRpcHttpServiceTestBase.java | 1 + .../JsonRpcHttpServiceTlsClientAuthTest.java | 1 + ...RpcHttpServiceTlsMisconfigurationTest.java | 1 + .../jsonrpc/JsonRpcHttpServiceTlsTest.java | 1 + .../websocket/WebSocketServiceLoginTest.java | 1 + .../transaction/TransactionSimulator.java | 17 ++- .../transaction/TransactionSimulatorTest.java | 102 ++++++++++++++++-- ...rtContractPermissioningControllerTest.java | 3 +- ...rtContractPermissioningControllerTest.java | 3 +- 32 files changed, 221 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0b2387fcb4..4a4d3138d39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ - Transactions that takes too long to evaluate, during block creation, are dropped from the txpool [#6163](https://github.com/hyperledger/besu/pull/6163) - New option `tx-pool-min-gas-price` to set a lower bound when accepting txs to the pool [#6098](https://github.com/hyperledger/besu/pull/6098) - Allow a transaction selection plugin to specify custom selection results [#6190](https://github.com/hyperledger/besu/pull/6190) +- Add `rpc-gas-cap` to allow users to set gas limit to the RPC methods used to simulate transactions[#6156](https://github.com/hyperledger/besu/pull/6156) + ## 23.10.2 diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index 12ec2f3d849..2628729d750 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -192,6 +192,7 @@ public class RunnerBuilder { private JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private boolean legacyForkIdEnabled; private Optional rpcMaxLogsRange; + private Optional rpcGasCap; private Optional enodeDnsConfiguration; /** @@ -585,6 +586,16 @@ public RunnerBuilder rpcMaxLogsRange(final Long rpcMaxLogsRange) { this.rpcMaxLogsRange = rpcMaxLogsRange > 0 ? Optional.of(rpcMaxLogsRange) : Optional.empty(); return this; } + /** + * Add Rpc gasLimit cap . + * + * @param rpcGasCap the rpc gas limit cap for transaction simulation methods + * @return the runner builder + */ + public RunnerBuilder rpcGasCap(final Long rpcGasCap) { + this.rpcGasCap = rpcGasCap > 0 ? Optional.of(rpcGasCap) : Optional.empty(); + return this; + } /** * Add enode DNS configuration @@ -661,7 +672,7 @@ public Runner build() { final TransactionSimulator transactionSimulator = new TransactionSimulator( - context.getBlockchain(), context.getWorldStateArchive(), protocolSchedule); + context.getBlockchain(), context.getWorldStateArchive(), protocolSchedule, rpcGasCap); final Bytes localNodeId = nodeKey.getPublicKey().getEncodedBytes(); final Optional nodePermissioningController = @@ -910,6 +921,7 @@ public Runner build() { graphQlContextMap.putIfAbsent(GraphQLContextType.SYNCHRONIZER, synchronizer); graphQlContextMap.putIfAbsent( GraphQLContextType.CHAIN_ID, protocolSchedule.getChainId().map(UInt256::valueOf)); + graphQlContextMap.putIfAbsent(GraphQLContextType.GAS_CAP, rpcGasCap); final GraphQL graphQL; try { graphQL = GraphQLProvider.buildGraphQL(fetchers); @@ -1240,7 +1252,8 @@ private Map jsonRpcMethods( besuController.getProtocolManager().ethContext().getEthPeers(), consensusEngineServer, rpcMaxLogsRange, - enodeDnsConfiguration); + enodeDnsConfiguration, + rpcGasCap); methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis)); final var pluginMethods = diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 9cfc44c57b5..71eeb507f89 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -1230,6 +1230,12 @@ static class PermissionsOptionGroup { "Specifies the maximum number of blocks to retrieve logs from via RPC. Must be >=0. 0 specifies no limit (default: ${DEFAULT-VALUE})") private final Long rpcMaxLogsRange = 5000L; + @CommandLine.Option( + names = {"--rpc-gas-cap"}, + description = + "Specifies the gasLimit cap for transaction simulation RPC methods. Must be >=0. 0 specifies no limit (default: ${DEFAULT-VALUE})") + private final Long rpcGasCap = 0L; + @CommandLine.Option( names = {"--cache-last-blocks"}, description = "Specifies the number of last blocks to cache (default: ${DEFAULT-VALUE})") @@ -2948,6 +2954,7 @@ private Runner synchronize( .storageProvider(keyValueStorageProvider(keyValueStorageName)) .rpcEndpointService(rpcEndpointServiceImpl) .rpcMaxLogsRange(rpcMaxLogsRange) + .rpcGasCap(rpcGasCap) .enodeDnsConfiguration(getEnodeDnsConfiguration()) .build(); diff --git a/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java index 38e14eec0db..dee56b6902a 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java @@ -367,7 +367,7 @@ protected BftContext createConsensusContext( blockchain, epochManager, bftBlockInterface().get(), validatorOverrides); final TransactionSimulator transactionSimulator = - new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule); + new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule, Optional.empty()); transactionValidatorProvider = new TransactionValidatorProvider( blockchain, new ValidatorContractController(transactionSimulator), qbftForksSchedule); diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java index 6db9f68efad..bbea5cb1a6a 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerBuilderTest.java @@ -167,6 +167,7 @@ public void enodeUrlShouldHaveAdvertisedHostWhenDiscoveryDisabled() { .dataDir(dataDir.getRoot()) .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) + .rpcGasCap(50_000_000L) .build(); runner.startEthereumMainLoop(); @@ -211,6 +212,7 @@ public void movingAcrossProtocolSpecsUpdatesNodeRecord() { .dataDir(dataDir.getRoot()) .storageProvider(storageProvider) .rpcEndpointService(new RpcEndpointServiceImpl()) + .rpcGasCap(50_000_000L) .build(); runner.startEthereumMainLoop(); @@ -270,6 +272,7 @@ public void whenEngineApiAddedListensOnDefaultPort() { .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) + .rpcGasCap(50_000_000L) .build(); assertThat(runner.getJsonRpcPort()).isPresent(); @@ -312,6 +315,7 @@ public void whenEngineApiAddedWebSocketReadyOnSamePort() { .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) + .rpcGasCap(50_000_000L) .build(); assertThat(runner.getEngineJsonRpcPort()).isPresent(); @@ -353,6 +357,7 @@ public void whenEngineApiAddedEthSubscribeAvailable() { .storageProvider(mock(KeyValueStorageProvider.class, RETURNS_DEEP_STUBS)) .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) + .rpcGasCap(50_000_000L) .build(); assertThat(runner.getEngineJsonRpcPort()).isPresent(); @@ -396,6 +401,7 @@ public void noEngineApiNoServiceForMethods() { .rpcEndpointService(new RpcEndpointServiceImpl()) .besuPluginContext(mock(BesuPluginContextImpl.class)) .networkingConfiguration(NetworkingConfiguration.create()) + .rpcGasCap(50_000_000L) .build(); assertThat(runner.getJsonRpcPort()).isPresent(); diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index 43a4d2cd963..880bc8b652e 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -192,7 +192,8 @@ private void syncFromGenesis(final SyncMode mode, final GenesisConfigFile genesi .permissioningService(new PermissioningServiceImpl()) .staticNodes(emptySet()) .storageProvider(new InMemoryKeyValueStorageProvider()) - .rpcEndpointService(new RpcEndpointServiceImpl()); + .rpcEndpointService(new RpcEndpointServiceImpl()) + .rpcGasCap(50_000_000L); Runner runnerBehind = null; final Runner runnerAhead = diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 204245f92c7..4b861b99038 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -1587,6 +1587,20 @@ public void rpcMaxLogsRangeOptionMustBeUsed() { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } + @Test + public void rpcGasCapOptionMustBeUsed() { + final long rpcGasCap = 150L; + parseCommand("--rpc-gas-cap", Long.toString(rpcGasCap)); + + verify(mockRunnerBuilder).rpcGasCap(longArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); + + assertThat(longArgumentCaptor.getValue()).isEqualTo(rpcGasCap); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + @Test public void p2pPeerUpperBound_without_p2pPeerLowerBound_shouldSetLowerBoundEqualToUpperBound() { diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index 23e458552d9..ab71fdd546c 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -197,7 +197,6 @@ public abstract class CommandTestAbstract { @Captor protected ArgumentCaptor stringArgumentCaptor; @Captor protected ArgumentCaptor intArgumentCaptor; @Captor protected ArgumentCaptor longArgumentCaptor; - @Captor protected ArgumentCaptor floatCaptor; @Captor protected ArgumentCaptor ethNetworkConfigArgumentCaptor; @Captor protected ArgumentCaptor syncConfigurationCaptor; @Captor protected ArgumentCaptor jsonRpcConfigArgumentCaptor; @@ -315,6 +314,7 @@ public void initMocks() throws Exception { when(mockRunnerBuilder.legacyForkId(anyBoolean())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.rpcMaxLogsRange(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.enodeDnsConfiguration(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.rpcGasCap(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.build()).thenReturn(mockRunner); final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance(); diff --git a/besu/src/test/resources/everything_config.toml b/besu/src/test/resources/everything_config.toml index 085a8ad444f..be337272e97 100644 --- a/besu/src/test/resources/everything_config.toml +++ b/besu/src/test/resources/everything_config.toml @@ -89,6 +89,7 @@ rpc-http-max-request-content-length = 5242880 rpc-max-logs-range=100 json-pretty-print-enabled=false cache-last-blocks=512 +rpc-gas-cap = 50000000 # PRIVACY TLS privacy-tls-enabled=false diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java index b5b0a26bd62..d298bb1366a 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java +++ b/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java @@ -414,7 +414,7 @@ private static ControllerAndState createControllerAndFinalState( final BftValidatorOverrides validatorOverrides = convertBftForks(qbftForks); final TransactionSimulator transactionSimulator = - new TransactionSimulator(blockChain, worldStateArchive, protocolSchedule); + new TransactionSimulator(blockChain, worldStateArchive, protocolSchedule, Optional.empty()); final BlockValidatorProvider blockValidatorProvider = BlockValidatorProvider.forkingValidatorProvider( diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java index fd6ca9a1313..d3162154474 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java @@ -188,6 +188,7 @@ public Map methods() { ethPeers, Vertx.vertx(new VertxOptions().setWorkerPoolSize(1)), Optional.empty(), + Optional.empty(), Optional.empty()); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java index f4a693eaa43..d7975335657 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java @@ -22,5 +22,6 @@ public enum GraphQLContextType { MINING_COORDINATOR, SYNCHRONIZER, IS_ALIVE_HANDLER, - CHAIN_ID + CHAIN_ID, + GAS_CAP } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java index 6d3884e61c0..20716d95ef2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java @@ -209,10 +209,10 @@ private Optional executeCall(final DataFetchingEnvironment environme final ProtocolSchedule protocolSchedule = environment.getGraphQlContext().get(GraphQLContextType.PROTOCOL_SCHEDULE); final long bn = header.getNumber(); - + final Optional gasCap = environment.getGraphQlContext().get(GraphQLContextType.GAS_CAP); final TransactionSimulator transactionSimulator = new TransactionSimulator( - query.getBlockchain(), query.getWorldStateArchive(), protocolSchedule); + query.getBlockchain(), query.getWorldStateArchive(), protocolSchedule, gasCap); long gasParam = -1; Wei gasPriceParam = null; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java index b070b5d6b93..a57d2e2f2d5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java @@ -92,10 +92,10 @@ public Optional getCall(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final ProtocolSchedule protocolSchedule = environment.getGraphQlContext().get(GraphQLContextType.PROTOCOL_SCHEDULE); - + final Optional gasCap = environment.getGraphQlContext().get(GraphQLContextType.GAS_CAP); final TransactionSimulator transactionSimulator = new TransactionSimulator( - query.getBlockchain(), query.getWorldStateArchive(), protocolSchedule); + query.getBlockchain(), query.getWorldStateArchive(), protocolSchedule, gasCap); long gasParam = -1; Wei gasPriceParam = null; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java index b70e7720a0d..74a5e216b15 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java @@ -51,6 +51,7 @@ import java.nio.file.Path; import java.util.Map; +import java.util.Optional; public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { @@ -64,6 +65,8 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { private final Synchronizer synchronizer; private final Path dataDir; + private final Optional gasCap; + DebugJsonRpcMethods( final BlockchainQueries blockchainQueries, final ProtocolContext protocolContext, @@ -71,7 +74,8 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { final ObservableMetricsSystem metricsSystem, final TransactionPool transactionPool, final Synchronizer synchronizer, - final Path dataDir) { + final Path dataDir, + final Optional gasCap) { this.blockchainQueries = blockchainQueries; this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; @@ -79,6 +83,7 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { this.transactionPool = transactionPool; this.synchronizer = synchronizer; this.dataDir = dataDir; + this.gasCap = gasCap; } @Override @@ -122,6 +127,7 @@ protected Map create() { new TransactionSimulator( blockchainQueries.getBlockchain(), blockchainQueries.getWorldStateArchive(), - protocolSchedule))); + protocolSchedule, + gasCap))); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java index b3ca5514d7b..8053b4e5aca 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java @@ -87,6 +87,7 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods { private final MiningCoordinator miningCoordinator; private final Set supportedCapabilities; private final Optional maxLogRange; + private final Optional gasCap; public EthJsonRpcMethods( final BlockchainQueries blockchainQueries, @@ -96,7 +97,8 @@ public EthJsonRpcMethods( final TransactionPool transactionPool, final MiningCoordinator miningCoordinator, final Set supportedCapabilities, - final Optional maxLogRange) { + final Optional maxLogRange, + final Optional gasCap) { this.blockchainQueries = blockchainQueries; this.synchronizer = synchronizer; this.protocolSchedule = protocolSchedule; @@ -105,6 +107,7 @@ public EthJsonRpcMethods( this.miningCoordinator = miningCoordinator; this.supportedCapabilities = supportedCapabilities; this.maxLogRange = maxLogRange; + this.gasCap = gasCap; } @Override @@ -128,7 +131,8 @@ protected Map create() { new TransactionSimulator( blockchainQueries.getBlockchain(), blockchainQueries.getWorldStateArchive(), - protocolSchedule)), + protocolSchedule, + gasCap)), new EthFeeHistory(protocolSchedule, blockchainQueries.getBlockchain()), new EthGetCode(blockchainQueries), new EthGetLogs(blockchainQueries, maxLogRange), @@ -157,13 +161,15 @@ protected Map create() { new TransactionSimulator( blockchainQueries.getBlockchain(), blockchainQueries.getWorldStateArchive(), - protocolSchedule)), + protocolSchedule, + gasCap)), new EthCreateAccessList( blockchainQueries, new TransactionSimulator( blockchainQueries.getBlockchain(), blockchainQueries.getWorldStateArchive(), - protocolSchedule)), + protocolSchedule, + gasCap)), new EthMining(miningCoordinator), new EthCoinbase(miningCoordinator), new EthProtocolVersion(supportedCapabilities), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index c8a7ccb7529..b9fbb79fd8c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -80,7 +80,8 @@ public Map methods( final EthPeers ethPeers, final Vertx consensusEngineServer, final Optional maxLogRange, - final Optional enodeDnsConfiguration) { + final Optional enodeDnsConfiguration, + final Optional gasCap) { final Map enabled = new HashMap<>(); if (!rpcApis.isEmpty()) { final JsonRpcMethod modules = new RpcModules(rpcApis); @@ -104,7 +105,8 @@ public Map methods( metricsSystem, transactionPool, synchronizer, - dataDir), + dataDir, + gasCap), new EeaJsonRpcMethods( blockchainQueries, protocolSchedule, transactionPool, privacyParameters), new ExecutionEngineJsonRpcMethods( @@ -121,7 +123,8 @@ public Map methods( transactionPool, miningCoordinator, supportedCapabilities, - maxLogRange), + maxLogRange, + gasCap), new NetJsonRpcMethods( p2pNetwork, networkId, @@ -139,7 +142,7 @@ public Map methods( new PrivxJsonRpcMethods( blockchainQueries, protocolSchedule, transactionPool, privacyParameters), new Web3JsonRpcMethods(clientVersion), - new TraceJsonRpcMethods(blockchainQueries, protocolSchedule), + new TraceJsonRpcMethods(blockchainQueries, protocolSchedule, gasCap), new TxPoolJsonRpcMethods(transactionPool), new PluginsJsonRpcMethods(namedPlugins)); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java index 88c6db1dd4d..3041af4f17b 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java @@ -31,16 +31,22 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import java.util.Map; +import java.util.Optional; public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods { private final BlockchainQueries blockchainQueries; private final ProtocolSchedule protocolSchedule; + private final Optional gasCap; + TraceJsonRpcMethods( - final BlockchainQueries blockchainQueries, final ProtocolSchedule protocolSchedule) { + final BlockchainQueries blockchainQueries, + final ProtocolSchedule protocolSchedule, + final Optional gasCap) { this.blockchainQueries = blockchainQueries; this.protocolSchedule = protocolSchedule; + this.gasCap = gasCap; } @Override @@ -65,20 +71,23 @@ protected Map create() { new TransactionSimulator( blockchainQueries.getBlockchain(), blockchainQueries.getWorldStateArchive(), - protocolSchedule)), + protocolSchedule, + gasCap)), new TraceCallMany( blockchainQueries, protocolSchedule, new TransactionSimulator( blockchainQueries.getBlockchain(), blockchainQueries.getWorldStateArchive(), - protocolSchedule)), + protocolSchedule, + gasCap)), new TraceRawTransaction( protocolSchedule, blockchainQueries, new TransactionSimulator( blockchainQueries.getBlockchain(), blockchainQueries.getWorldStateArchive(), - protocolSchedule))); + protocolSchedule, + gasCap))); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java index 08da73a87cf..27a5ec92be7 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java @@ -143,7 +143,9 @@ public void setupTest() throws Exception { GraphQLContextType.MINING_COORDINATOR, miningCoordinatorMock, GraphQLContextType.SYNCHRONIZER, - synchronizerMock), + synchronizerMock, + GraphQLContextType.GAS_CAP, + Optional.empty()), Mockito.mock(EthScheduler.class)); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java index c48d5d2b10c..7ab708b50bb 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java @@ -191,6 +191,7 @@ protected Map getRpcMethods( mock(EthPeers.class), syncVertx, Optional.empty(), + Optional.empty(), Optional.empty()); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java index 208c3d5779b..dcbb2f9d12c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java @@ -128,6 +128,7 @@ public void initServerAndClient() throws Exception { mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java index d86bcbd81c0..420cbd184ec 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java @@ -157,6 +157,7 @@ public static void initServerAndClient() throws Exception { mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(); jwtAuth = service.authenticationService.get().getJwtAuthProvider(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java index fcbb2116c9a..1109d575d44 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java @@ -230,6 +230,7 @@ private JsonRpcHttpService createJsonRpcHttpServiceWithRpcApis(final JsonRpcConf mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( @@ -340,6 +341,7 @@ private JsonRpcHttpService createJsonRpcHttpService( mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java index 8299cf70aa1..082c10c0e8d 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java @@ -136,6 +136,7 @@ public static void initServerAndClient() throws Exception { ethPeersMock, vertx, Optional.empty(), + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(createLimitedJsonRpcConfig()); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java index 2cefd7633e8..a973046e2da 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java @@ -141,6 +141,7 @@ public void initServer() throws Exception { mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); System.setProperty("javax.net.ssl.trustStore", CLIENT_AS_CA_CERT.getKeyStoreFile().toString()); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java index c6e4a933ea0..257832a8243 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java @@ -130,6 +130,7 @@ public void beforeEach() { mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java index 3fffd3561f0..877c85bd856 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java @@ -131,6 +131,7 @@ public void initServer() throws Exception { mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); service = createJsonRpcHttpService(createJsonRpcConfig()); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java index 072c493d696..e999b198602 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java @@ -192,6 +192,7 @@ public void before() throws URISyntaxException { mock(EthPeers.class), vertx, Optional.empty(), + Optional.empty(), Optional.empty())); websocketMethods.putAll(rpcMethods); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index 4906378e9f2..537049c3613 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -48,6 +48,8 @@ import com.google.common.base.Suppliers; import org.apache.tuweni.bytes.Bytes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /* * Used to process transactions for eth_call and eth_estimateGas. @@ -56,6 +58,7 @@ * blockchain or to estimate the transaction gas cost. */ public class TransactionSimulator { + private static final Logger LOG = LoggerFactory.getLogger(TransactionSimulator.class); private static final Supplier SIGNATURE_ALGORITHM = Suppliers.memoize(SignatureAlgorithmFactory::getInstance); @@ -76,14 +79,17 @@ public class TransactionSimulator { private final Blockchain blockchain; private final WorldStateArchive worldStateArchive; private final ProtocolSchedule protocolSchedule; + private final Optional rpcGasCap; public TransactionSimulator( final Blockchain blockchain, final WorldStateArchive worldStateArchive, - final ProtocolSchedule protocolSchedule) { + final ProtocolSchedule protocolSchedule, + final Optional rpcGasCap) { this.blockchain = blockchain; this.worldStateArchive = worldStateArchive; this.protocolSchedule = protocolSchedule; + this.rpcGasCap = rpcGasCap; } public Optional process( @@ -207,10 +213,17 @@ public Optional processWithWorldUpdater( final Account sender = updater.get(senderAddress); final long nonce = sender != null ? sender.getNonce() : 0L; - final long gasLimit = + long gasLimit = callParams.getGasLimit() >= 0 ? callParams.getGasLimit() : blockHeaderToProcess.getGasLimit(); + if (rpcGasCap.isPresent()) { + final long gasCap = rpcGasCap.get(); + if (gasCap < gasLimit) { + gasLimit = gasCap; + LOG.info("Capping gasLimit to " + gasCap); + } + } final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO; final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java index 2b523beacb6..5447adb0b9d 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java @@ -40,6 +40,7 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult.Status; @@ -75,8 +76,9 @@ public class TransactionSimulatorTest { private static final Address DEFAULT_FROM = Address.fromHexString("0x0000000000000000000000000000000000000000"); - + private static final long GASCAP = 500L; private TransactionSimulator transactionSimulator; + private TransactionSimulator cappedTransactionSimulator; @Mock private Blockchain blockchain; @Mock private WorldStateArchive worldStateArchive; @@ -84,13 +86,15 @@ public class TransactionSimulatorTest { @Mock private ProtocolSchedule protocolSchedule; @Mock private ProtocolSpec protocolSpec; @Mock private MainnetTransactionProcessor transactionProcessor; - private final BlockHeaderTestFixture blockHeaderTestFixture = new BlockHeaderTestFixture(); @BeforeEach public void setUp() { this.transactionSimulator = - new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule); + new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule, Optional.empty()); + this.cappedTransactionSimulator = + new TransactionSimulator( + blockchain, worldStateArchive, protocolSchedule, Optional.of(GASCAP)); } @Test @@ -156,7 +160,6 @@ public void shouldSetGasPriceToZeroWhenExceedingBalanceAllowed() { .payload(callParameter.getPayload()) .signature(FAKE_SIGNATURE) .build(); - mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL); transactionSimulator.process( @@ -260,7 +263,6 @@ public void shouldNotSetFeePerGasToZeroWhenExceedingBalanceIsNotAllowed() { .payload(callParameter.getPayload()) .signature(FAKE_SIGNATURE) .build(); - mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL); transactionSimulator.process( @@ -523,6 +525,82 @@ public void shouldReturnSuccessfulResultWhenEip1559TransactionProcessingIsSucces verifyTransactionWasProcessed(expectedTransaction); } + @Test + public void shouldCapGasLimitWhenOriginalTransactionExceedsGasCap() { + final CallParameter callParameter = + eip1559TransactionCallParameter(Wei.ZERO, Wei.ZERO, GASCAP + 1); + + final BlockHeader blockHeader = mockBlockHeader(Hash.ZERO, 1L, Wei.ONE); + + mockBlockchainForBlockHeader(blockHeader); + mockWorldStateForAccount(blockHeader, callParameter.getFrom(), 1L); + + final Transaction expectedTransaction = + Transaction.builder() + .type(TransactionType.EIP1559) + .chainId(BigInteger.ONE) + .nonce(1L) + .gasLimit(GASCAP) + .maxFeePerGas(callParameter.getMaxFeePerGas().orElseThrow()) + .maxPriorityFeePerGas(callParameter.getMaxPriorityFeePerGas().orElseThrow()) + .to(callParameter.getTo()) + .sender(callParameter.getFrom()) + .value(callParameter.getValue()) + .payload(callParameter.getPayload()) + .signature(FAKE_SIGNATURE) + .build(); + + mockProtocolSpecForProcessWithWorldUpdater(); + + // call process with original transaction + cappedTransactionSimulator.process( + callParameter, + TransactionValidationParams.transactionSimulator(), + OperationTracer.NO_TRACING, + 1L); + + // expect overwritten transaction to be processed + verifyTransactionWasProcessed(expectedTransaction); + } + + @Test + public void shouldKeepOriginalGasLimitWhenCapIsHigherThanOriginalValue() { + // generate a transaction with a gas limit that is lower than the gas cap + final CallParameter callParameter = + eip1559TransactionCallParameter(Wei.ZERO, Wei.ZERO, GASCAP - 1); + + final BlockHeader blockHeader = mockBlockHeader(Hash.ZERO, 1L, Wei.ONE); + + mockBlockchainForBlockHeader(blockHeader); + mockWorldStateForAccount(blockHeader, callParameter.getFrom(), 1L); + mockProtocolSpecForProcessWithWorldUpdater(); + + final Transaction expectedTransaction = + Transaction.builder() + .type(TransactionType.EIP1559) + .chainId(BigInteger.ONE) + .nonce(1L) + .gasLimit(callParameter.getGasLimit()) + .maxFeePerGas(callParameter.getMaxFeePerGas().orElseThrow()) + .maxPriorityFeePerGas(callParameter.getMaxPriorityFeePerGas().orElseThrow()) + .to(callParameter.getTo()) + .sender(callParameter.getFrom()) + .value(callParameter.getValue()) + .payload(callParameter.getPayload()) + .signature(FAKE_SIGNATURE) + .build(); + + // call process with original transaction + cappedTransactionSimulator.process( + callParameter, + TransactionValidationParams.transactionSimulator(), + OperationTracer.NO_TRACING, + 1L); + + // expect transaction with the original gas limit to be processed + verifyTransactionWasProcessed(expectedTransaction); + } + private void mockWorldStateForAccount( final BlockHeader blockHeader, final Address address, final long nonce) { final Account account = mock(Account.class); @@ -558,8 +636,7 @@ private void mockBlockchainForBlockHeader(final BlockHeader blockHeader) { .thenReturn(Optional.of(blockHeader)); } - private void mockProcessorStatusForTransaction( - final Transaction transaction, final Status status) { + private void mockProtocolSpecForProcessWithWorldUpdater() { final BlockHeaderFunctions blockHeaderFunctions = mock(BlockHeaderFunctions.class); when(protocolSchedule.getChainId()).thenReturn(Optional.of(BigInteger.ONE)); when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); @@ -567,7 +644,11 @@ private void mockProcessorStatusForTransaction( when(protocolSpec.getMiningBeneficiaryCalculator()).thenReturn(BlockHeader::getCoinbase); when(protocolSpec.getBlockHeaderFunctions()).thenReturn(blockHeaderFunctions); when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0)); + } + private void mockProcessorStatusForTransaction( + final Transaction transaction, final Status status) { + mockProtocolSpecForProcessWithWorldUpdater(); final TransactionProcessingResult result = mock(TransactionProcessingResult.class); switch (status) { case SUCCESSFUL: @@ -628,10 +709,15 @@ private CallParameter eip1559TransactionCallParameter() { private CallParameter eip1559TransactionCallParameter( final Wei maxFeePerGas, final Wei maxPriorityFeePerGas) { + return eip1559TransactionCallParameter(maxFeePerGas, maxPriorityFeePerGas, 0L); + } + + private CallParameter eip1559TransactionCallParameter( + final Wei maxFeePerGas, final Wei maxPriorityFeePerGas, final long gasLimit) { return new CallParameter( Address.fromHexString("0x0"), Address.fromHexString("0x0"), - 0, + gasLimit, Wei.of(0), Optional.of(maxFeePerGas), Optional.of(maxPriorityFeePerGas), diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java index 788b4b8c01c..b3724998e86 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java @@ -38,6 +38,7 @@ import org.hyperledger.besu.plugin.services.metrics.Counter; import java.io.IOException; +import java.util.Optional; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.io.Resources; @@ -70,7 +71,7 @@ private NodeSmartContractPermissioningController setupController( genesisState.writeStateTo(worldArchive.getMutable()); final TransactionSimulator ts = - new TransactionSimulator(blockchain, worldArchive, protocolSchedule); + new TransactionSimulator(blockchain, worldArchive, protocolSchedule, Optional.empty()); final Address contractAddress = Address.fromHexString(contractAddressString); when(metricsSystem.createCounter( diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java index 7140ba2fc82..4b71def609a 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java @@ -41,6 +41,7 @@ import java.io.IOException; import java.math.BigInteger; +import java.util.Optional; import com.google.common.io.Resources; import org.apache.tuweni.bytes.Bytes; @@ -71,7 +72,7 @@ private TransactionSmartContractPermissioningController setupController( genesisState.writeStateTo(worldArchive.getMutable()); final TransactionSimulator ts = - new TransactionSimulator(blockchain, worldArchive, protocolSchedule); + new TransactionSimulator(blockchain, worldArchive, protocolSchedule, Optional.empty()); final Address contractAddress = Address.fromHexString(contractAddressString); when(metricsSystem.createCounter(