Skip to content

Commit dbfa5bc

Browse files
committed
Transaction simulation service
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
1 parent 854d35b commit dbfa5bc

File tree

38 files changed

+424
-98
lines changed

38 files changed

+424
-98
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
- Add blob transaction support to `eth_call` [#6661](https://github.com/hyperledger/besu/pull/6661)
2222
- Add blobs to `eth_feeHistory` [#6679](https://github.com/hyperledger/besu/pull/6679)
2323
- Refactor and extend `TransactionPoolValidatorService` [#6636](https://github.com/hyperledger/besu/pull/6636)
24+
- Introduce `TransactionSimulationService` [#6686](https://github.com/hyperledger/besu/pull/6686)
2425

2526
### Bug fixes
2627

acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ public NodeRequests nodeRequests() {
436436

437437
nodeRequests =
438438
new NodeRequests(
439+
web3jService,
439440
new JsonRpc2_0Web3j(web3jService, 2000, Async.defaultExecutorService()),
440441
new CliqueRequestFactory(web3jService),
441442
new BftRequestFactory(web3jService, bftType),

acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.hyperledger.besu.cryptoservices.KeyPairSecurityModule;
2929
import org.hyperledger.besu.cryptoservices.NodeKey;
3030
import org.hyperledger.besu.ethereum.GasLimitCalculator;
31+
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
3132
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
3233
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters;
3334
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
@@ -37,30 +38,35 @@
3738
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
3839
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
3940
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
41+
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
4042
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
4143
import org.hyperledger.besu.evm.internal.EvmConfiguration;
4244
import org.hyperledger.besu.metrics.MetricsSystemFactory;
4345
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
4446
import org.hyperledger.besu.plugin.data.EnodeURL;
4547
import org.hyperledger.besu.plugin.services.BesuConfiguration;
4648
import org.hyperledger.besu.plugin.services.BesuEvents;
49+
import org.hyperledger.besu.plugin.services.BlockchainService;
4750
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
4851
import org.hyperledger.besu.plugin.services.RpcEndpointService;
4952
import org.hyperledger.besu.plugin.services.SecurityModuleService;
5053
import org.hyperledger.besu.plugin.services.StorageService;
5154
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
5255
import org.hyperledger.besu.plugin.services.TransactionSelectionService;
56+
import org.hyperledger.besu.plugin.services.TransactionSimulationService;
5357
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
5458
import org.hyperledger.besu.services.BesuConfigurationImpl;
5559
import org.hyperledger.besu.services.BesuEventsImpl;
5660
import org.hyperledger.besu.services.BesuPluginContextImpl;
61+
import org.hyperledger.besu.services.BlockchainServiceImpl;
5762
import org.hyperledger.besu.services.PermissioningServiceImpl;
5863
import org.hyperledger.besu.services.PicoCLIOptionsImpl;
5964
import org.hyperledger.besu.services.RpcEndpointServiceImpl;
6065
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
6166
import org.hyperledger.besu.services.StorageServiceImpl;
6267
import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl;
6368
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
69+
import org.hyperledger.besu.services.TransactionSimulationServiceImpl;
6470

6571
import java.io.File;
6672
import java.nio.file.Path;
@@ -92,18 +98,27 @@ private BesuPluginContextImpl buildPluginContext(
9298
final BesuNode node,
9399
final StorageServiceImpl storageService,
94100
final SecurityModuleServiceImpl securityModuleService,
101+
final TransactionSimulationServiceImpl transactionSimulationServiceImpl,
95102
final TransactionSelectionServiceImpl transactionSelectionServiceImpl,
103+
final TransactionPoolValidatorServiceImpl transactionPoolValidatorServiceImpl,
104+
final BlockchainServiceImpl blockchainServiceImpl,
105+
final RpcEndpointServiceImpl rpcEndpointServiceImpl,
96106
final BesuConfiguration commonPluginConfiguration) {
97107
final CommandLine commandLine = new CommandLine(CommandSpec.create());
98108
final BesuPluginContextImpl besuPluginContext = new BesuPluginContextImpl();
99109
besuPluginContext.addService(StorageService.class, storageService);
100110
besuPluginContext.addService(SecurityModuleService.class, securityModuleService);
101111
besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
102-
besuPluginContext.addService(RpcEndpointService.class, new RpcEndpointServiceImpl());
112+
besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl);
103113
besuPluginContext.addService(
104114
TransactionSelectionService.class, transactionSelectionServiceImpl);
105115
besuPluginContext.addService(
106-
TransactionPoolValidatorService.class, new TransactionPoolValidatorServiceImpl());
116+
TransactionPoolValidatorService.class, transactionPoolValidatorServiceImpl);
117+
besuPluginContext.addService(
118+
TransactionSimulationService.class, transactionSimulationServiceImpl);
119+
besuPluginContext.addService(BlockchainService.class, blockchainServiceImpl);
120+
besuPluginContext.addService(BesuConfiguration.class, commonPluginConfiguration);
121+
107122
final Path pluginsPath;
108123
final String pluginDir = System.getProperty("besu.plugins.dir");
109124
if (pluginDir == null || pluginDir.isEmpty()) {
@@ -120,9 +135,6 @@ private BesuPluginContextImpl buildPluginContext(
120135
besuPluginContext.registerPlugins(pluginsPath);
121136

122137
commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0]));
123-
124-
besuPluginContext.addService(BesuConfiguration.class, commonPluginConfiguration);
125-
126138
// register built-in plugins
127139
new RocksDBPlugin().register(besuPluginContext);
128140

@@ -143,8 +155,14 @@ public void startNode(final BesuNode node) {
143155

144156
final StorageServiceImpl storageService = new StorageServiceImpl();
145157
final SecurityModuleServiceImpl securityModuleService = new SecurityModuleServiceImpl();
158+
final TransactionSimulationServiceImpl transactionSimulationServiceImpl =
159+
new TransactionSimulationServiceImpl();
146160
final TransactionSelectionServiceImpl transactionSelectionServiceImpl =
147161
new TransactionSelectionServiceImpl();
162+
final TransactionPoolValidatorServiceImpl transactionPoolValidatorServiceImpl =
163+
new TransactionPoolValidatorServiceImpl();
164+
final BlockchainServiceImpl blockchainServiceImpl = new BlockchainServiceImpl();
165+
final RpcEndpointServiceImpl rpcEndpointServiceImpl = new RpcEndpointServiceImpl();
148166
final Path dataDir = node.homeDirectory();
149167
final BesuConfigurationImpl commonPluginConfiguration = new BesuConfigurationImpl();
150168
final var miningParameters =
@@ -165,7 +183,11 @@ public void startNode(final BesuNode node) {
165183
node,
166184
storageService,
167185
securityModuleService,
186+
transactionSimulationServiceImpl,
168187
transactionSelectionServiceImpl,
188+
transactionPoolValidatorServiceImpl,
189+
blockchainServiceImpl,
190+
rpcEndpointServiceImpl,
169191
commonPluginConfiguration));
170192

171193
GlobalOpenTelemetry.resetForTest();
@@ -199,6 +221,7 @@ public void startNode(final BesuNode node) {
199221
ImmutableTransactionPoolConfiguration.builder()
200222
.from(node.getTransactionPoolConfiguration())
201223
.strictTransactionReplayProtectionEnabled(node.isStrictTxReplayProtectionEnabled())
224+
.transactionPoolValidatorService(transactionPoolValidatorServiceImpl)
202225
.build();
203226

204227
final int maxPeers = 25;
@@ -232,6 +255,10 @@ public void startNode(final BesuNode node) {
232255

233256
final BesuController besuController = builder.build();
234257

258+
initTransactionSimulationService(
259+
transactionSimulationServiceImpl, besuController, node.getApiConfiguration());
260+
initBlockchainService(blockchainServiceImpl, besuController);
261+
235262
final RunnerBuilder runnerBuilder = new RunnerBuilder();
236263
runnerBuilder.permissioningConfiguration(node.getPermissioningConfiguration());
237264
runnerBuilder.apiConfiguration(node.getApiConfiguration());
@@ -261,7 +288,7 @@ public void startNode(final BesuNode node) {
261288
.besuPluginContext(new BesuPluginContextImpl())
262289
.autoLogBloomCaching(false)
263290
.storageProvider(storageProvider)
264-
.rpcEndpointService(new RpcEndpointServiceImpl());
291+
.rpcEndpointService(rpcEndpointServiceImpl);
265292
node.engineRpcConfiguration().ifPresent(runnerBuilder::engineJsonRpcConfiguration);
266293

267294
final Runner runner = runnerBuilder.build();
@@ -285,6 +312,25 @@ public void startNode(final BesuNode node) {
285312
MDC.remove("node");
286313
}
287314

315+
private void initBlockchainService(
316+
final BlockchainServiceImpl blockchainServiceImpl, final BesuController besuController) {
317+
blockchainServiceImpl.init(
318+
besuController.getProtocolContext(), besuController.getProtocolSchedule());
319+
}
320+
321+
private void initTransactionSimulationService(
322+
final TransactionSimulationServiceImpl transactionSimulationService,
323+
final BesuController besuController,
324+
final ApiConfiguration apiConfiguration) {
325+
transactionSimulationService.init(
326+
besuController.getProtocolContext().getBlockchain(),
327+
new TransactionSimulator(
328+
besuController.getProtocolContext().getBlockchain(),
329+
besuController.getProtocolContext().getWorldStateArchive(),
330+
besuController.getProtocolSchedule(),
331+
apiConfiguration.getGasCap()));
332+
}
333+
288334
@Override
289335
public void stopNode(final BesuNode node) {
290336
final BesuPluginContextImpl pluginContext = besuPluginContextMap.remove(node);

acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.util.ArrayList;
5050
import java.util.List;
5151
import java.util.Optional;
52+
import java.util.Set;
5253
import java.util.function.UnaryOperator;
5354

5455
import io.vertx.core.Vertx;
@@ -376,17 +377,27 @@ public BesuNode createCliqueNode(final String name) throws IOException {
376377

377378
public BesuNode createCliqueNode(final String name, final CliqueOptions cliqueOptions)
378379
throws IOException {
379-
return createCliqueNodeWithExtraCliOptions(name, cliqueOptions, List.of());
380+
return createCliqueNodeWithExtraCliOptionsAndRpcApis(name, cliqueOptions, List.of());
380381
}
381382

382-
public BesuNode createCliqueNodeWithExtraCliOptions(
383+
public BesuNode createCliqueNodeWithExtraCliOptionsAndRpcApis(
383384
final String name, final CliqueOptions cliqueOptions, final List<String> extraCliOptions)
384385
throws IOException {
386+
return createCliqueNodeWithExtraCliOptionsAndRpcApis(
387+
name, cliqueOptions, extraCliOptions, Set.of());
388+
}
389+
390+
public BesuNode createCliqueNodeWithExtraCliOptionsAndRpcApis(
391+
final String name,
392+
final CliqueOptions cliqueOptions,
393+
final List<String> extraCliOptions,
394+
final Set<String> extraRpcApis)
395+
throws IOException {
385396
return create(
386397
new BesuNodeConfigurationBuilder()
387398
.name(name)
388399
.miningEnabled()
389-
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig())
400+
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig(extraRpcApis))
390401
.webSocketConfiguration(node.createWebSocketEnabledConfig())
391402
.devMode(false)
392403
.jsonRpcTxPool()
@@ -584,7 +595,7 @@ public BesuNode createCliqueNodeWithValidators(final String name, final String..
584595
new BesuNodeConfigurationBuilder()
585596
.name(name)
586597
.miningEnabled()
587-
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig())
598+
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig(Set.of()))
588599
.webSocketConfiguration(node.createWebSocketEnabledConfig())
589600
.jsonRpcTxPool()
590601
.devMode(false)

acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/NodeConfigurationFactory.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
import java.util.ArrayList;
3131
import java.util.Arrays;
3232
import java.util.Collection;
33+
import java.util.HashSet;
3334
import java.util.List;
3435
import java.util.Optional;
36+
import java.util.Set;
3537

3638
public class NodeConfigurationFactory {
3739

@@ -44,8 +46,10 @@ public Optional<String> createGenesisConfigForValidators(
4446
return genesisConfigProvider.create(nodes);
4547
}
4648

47-
public JsonRpcConfiguration createJsonRpcWithCliqueEnabledConfig() {
48-
return createJsonRpcWithRpcApiEnabledConfig(CLIQUE.name());
49+
public JsonRpcConfiguration createJsonRpcWithCliqueEnabledConfig(final Set<String> extraRpcApis) {
50+
final var enabledApis = new HashSet<>(extraRpcApis);
51+
enabledApis.add(CLIQUE.name());
52+
return createJsonRpcWithRpcApiEnabledConfig(enabledApis.toArray(String[]::new));
4953
}
5054

5155
public JsonRpcConfiguration createJsonRpcWithIbft2EnabledConfig(final boolean minerEnabled) {

acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/NodeRequests.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@
2727
import java.util.Optional;
2828

2929
import org.web3j.protocol.Web3j;
30+
import org.web3j.protocol.Web3jService;
3031
import org.web3j.protocol.websocket.WebSocketService;
3132

3233
public class NodeRequests {
33-
34+
private final Web3jService web3jService;
3435
private final Web3j netEth;
3536
private final CliqueRequestFactory clique;
3637
private final BftRequestFactory bft;
@@ -44,6 +45,7 @@ public class NodeRequests {
4445
private final TxPoolRequestFactory txPool;
4546

4647
public NodeRequests(
48+
final Web3jService web3jService,
4749
final Web3j netEth,
4850
final CliqueRequestFactory clique,
4951
final BftRequestFactory bft,
@@ -55,6 +57,7 @@ public NodeRequests(
5557
final TxPoolRequestFactory txPool,
5658
final Optional<WebSocketService> websocketService,
5759
final LoginRequestFactory login) {
60+
this.web3jService = web3jService;
5861
this.netEth = netEth;
5962
this.clique = clique;
6063
this.bft = bft;
@@ -116,4 +119,8 @@ public void shutdown() {
116119
netEth.shutdown();
117120
websocketService.ifPresent(WebSocketService::close);
118121
}
122+
123+
public Web3jService getWeb3jService() {
124+
return web3jService;
125+
}
119126
}

besu/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ jar {
2828
}
2929

3030
dependencies {
31+
api project(':datatypes')
32+
3133
api 'org.slf4j:slf4j-api'
3234

3335
implementation project(':config')

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
140140
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
141141
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
142+
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
142143
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
143144
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
144145
import org.hyperledger.besu.evm.precompile.AbstractAltBnPrecompiledContract;
@@ -167,6 +168,7 @@
167168
import org.hyperledger.besu.plugin.services.TraceService;
168169
import org.hyperledger.besu.plugin.services.TransactionPoolValidatorService;
169170
import org.hyperledger.besu.plugin.services.TransactionSelectionService;
171+
import org.hyperledger.besu.plugin.services.TransactionSimulationService;
170172
import org.hyperledger.besu.plugin.services.exception.StorageException;
171173
import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
172174
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
@@ -187,6 +189,7 @@
187189
import org.hyperledger.besu.services.TraceServiceImpl;
188190
import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl;
189191
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
192+
import org.hyperledger.besu.services.TransactionSimulationServiceImpl;
190193
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
191194
import org.hyperledger.besu.util.InvalidConfigurationException;
192195
import org.hyperledger.besu.util.LogConfigurator;
@@ -370,6 +373,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
370373

371374
private final TransactionSelectionServiceImpl transactionSelectionServiceImpl;
372375
private final TransactionPoolValidatorServiceImpl transactionValidatorServiceImpl;
376+
private final TransactionSimulationServiceImpl transactionSimulationServiceImpl;
373377
private final BlockchainServiceImpl blockchainServiceImpl;
374378

375379
static class P2PDiscoveryOptionGroup {
@@ -956,6 +960,7 @@ public BesuCommand(
956960
new RpcEndpointServiceImpl(),
957961
new TransactionSelectionServiceImpl(),
958962
new TransactionPoolValidatorServiceImpl(),
963+
new TransactionSimulationServiceImpl(),
959964
new BlockchainServiceImpl());
960965
}
961966

@@ -978,6 +983,7 @@ public BesuCommand(
978983
* @param rpcEndpointServiceImpl instance of RpcEndpointServiceImpl
979984
* @param transactionSelectionServiceImpl instance of TransactionSelectionServiceImpl
980985
* @param transactionValidatorServiceImpl instance of TransactionValidatorServiceImpl
986+
* @param transactionSimulationServiceImpl instance of TransactionSimulationServiceImpl
981987
* @param blockchainServiceImpl instance of BlockchainServiceImpl
982988
*/
983989
@VisibleForTesting
@@ -998,6 +1004,7 @@ protected BesuCommand(
9981004
final RpcEndpointServiceImpl rpcEndpointServiceImpl,
9991005
final TransactionSelectionServiceImpl transactionSelectionServiceImpl,
10001006
final TransactionPoolValidatorServiceImpl transactionValidatorServiceImpl,
1007+
final TransactionSimulationServiceImpl transactionSimulationServiceImpl,
10011008
final BlockchainServiceImpl blockchainServiceImpl) {
10021009
this.besuComponent = besuComponent;
10031010
this.logger = besuComponent.getBesuCommandLogger();
@@ -1018,6 +1025,7 @@ protected BesuCommand(
10181025
this.rpcEndpointServiceImpl = rpcEndpointServiceImpl;
10191026
this.transactionSelectionServiceImpl = transactionSelectionServiceImpl;
10201027
this.transactionValidatorServiceImpl = transactionValidatorServiceImpl;
1028+
this.transactionSimulationServiceImpl = transactionSimulationServiceImpl;
10211029
this.blockchainServiceImpl = blockchainServiceImpl;
10221030
}
10231031

@@ -1210,6 +1218,8 @@ private void preparePlugins() {
12101218
TransactionSelectionService.class, transactionSelectionServiceImpl);
12111219
besuPluginContext.addService(
12121220
TransactionPoolValidatorService.class, transactionValidatorServiceImpl);
1221+
besuPluginContext.addService(
1222+
TransactionSimulationService.class, transactionSimulationServiceImpl);
12131223
besuPluginContext.addService(BlockchainService.class, blockchainServiceImpl);
12141224

12151225
// register built-in plugins
@@ -1293,6 +1303,13 @@ private Runner buildRunner() {
12931303
private void startPlugins() {
12941304
blockchainServiceImpl.init(
12951305
besuController.getProtocolContext(), besuController.getProtocolSchedule());
1306+
transactionSimulationServiceImpl.init(
1307+
besuController.getProtocolContext().getBlockchain(),
1308+
new TransactionSimulator(
1309+
besuController.getProtocolContext().getBlockchain(),
1310+
besuController.getProtocolContext().getWorldStateArchive(),
1311+
besuController.getProtocolSchedule(),
1312+
apiConfiguration.getGasCap()));
12961313

12971314
besuPluginContext.addService(
12981315
BesuEvents.class,

0 commit comments

Comments
 (0)