Skip to content

Commit 23b8ebb

Browse files
fab-10jflo
authored andcommitted
Add WorldStateService to the plugin API (besu-eth#9024)
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> Signed-off-by: jflo <justin+github@florentine.us>
1 parent e83681c commit 23b8ebb

File tree

10 files changed

+252
-2
lines changed

10 files changed

+252
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- Add option to trace reference tests during execution [#8878](https://github.com/hyperledger/besu/pull/8878)
1818
- Expose methods to query hardfork by block header or for the next block in the Plugin API [#8909](https://github.com/hyperledger/besu/pull/8909)
1919
- Generate distribution dependencies catalog [#8987](https://github.com/hyperledger/besu/pull/8987)
20+
- Add `WorldStateService` to the plugin API [#9024](https://github.com/hyperledger/besu/pull/9024)
2021

2122
#### Performance
2223
- Improve the sync performance by not RLP decoding bodies during sync. This means we are using less memory and CPU, allowing us to increase the parallelism of the download pipeline, which has been increased from 4 to 8. Can be reduced again with `--Xsynchronizer-downloader-parallelism=4` [#8959]

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import org.hyperledger.besu.plugin.services.TransactionSelectionService;
7777
import org.hyperledger.besu.plugin.services.TransactionSimulationService;
7878
import org.hyperledger.besu.plugin.services.TransactionValidatorService;
79+
import org.hyperledger.besu.plugin.services.WorldStateService;
7980
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
8081
import org.hyperledger.besu.plugin.services.mining.MiningService;
8182
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
@@ -97,6 +98,7 @@
9798
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
9899
import org.hyperledger.besu.services.TransactionSimulationServiceImpl;
99100
import org.hyperledger.besu.services.TransactionValidatorServiceImpl;
101+
import org.hyperledger.besu.services.WorldStateServiceImpl;
100102
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
101103

102104
import java.io.File;
@@ -275,6 +277,9 @@ private void loadAdditionalServices(
275277
new TransactionPoolServiceImpl(besuController.getTransactionPool()));
276278
besuPluginContext.addService(
277279
MiningService.class, new MiningServiceImpl(besuController.getMiningCoordinator()));
280+
besuPluginContext.addService(
281+
WorldStateService.class,
282+
new WorldStateServiceImpl(besuController.getProtocolContext().getWorldStateArchive()));
278283
}
279284

280285
private void killRunner(final String name) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ public BesuNode createQbftPluginsNode(
566566
.devMode(false)
567567
.jsonRpcTxPool()
568568
.genesisConfigProvider(GenesisConfigurationFactory::createQbftLondonGenesisConfig)
569+
.dataStorageConfiguration(DataStorageConfiguration.DEFAULT_BONSAI_CONFIG)
569570
.build());
570571
}
571572

acceptance-tests/test-plugins/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ dependencies {
88
implementation project(':ethereum:core')
99
implementation project(':ethereum:rlp')
1010
implementation project(':ethereum:api')
11+
implementation project(':evm')
1112
implementation project(':plugin-api')
1213
implementation 'com.google.auto.service:auto-service'
1314
implementation 'info.picocli:picocli'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.tests.acceptance.plugins;
16+
17+
import static java.nio.charset.StandardCharsets.UTF_8;
18+
19+
import org.hyperledger.besu.datatypes.Address;
20+
import org.hyperledger.besu.datatypes.Wei;
21+
import org.hyperledger.besu.plugin.BesuPlugin;
22+
import org.hyperledger.besu.plugin.ServiceManager;
23+
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
24+
import org.hyperledger.besu.plugin.services.WorldStateService;
25+
26+
import java.io.File;
27+
import java.io.IOException;
28+
import java.nio.file.Files;
29+
30+
import com.google.auto.service.AutoService;
31+
import org.slf4j.Logger;
32+
import org.slf4j.LoggerFactory;
33+
import picocli.CommandLine;
34+
35+
@AutoService(BesuPlugin.class)
36+
public class TestWorldStateServicePlugin implements BesuPlugin {
37+
private static final Logger LOG = LoggerFactory.getLogger(TestWorldStateServicePlugin.class);
38+
private ServiceManager serviceManager;
39+
private File callbackDir;
40+
41+
@CommandLine.Option(names = "--plugin-world-state-service-test-enabled")
42+
boolean enabled = false;
43+
44+
@Override
45+
public void register(final ServiceManager serviceManager) {
46+
LOG.info("Registering TestWorldStateServicePlugin");
47+
this.serviceManager = serviceManager;
48+
serviceManager
49+
.getService(PicoCLIOptions.class)
50+
.orElseThrow()
51+
.addPicoCLIOptions("world-state-service", this);
52+
callbackDir = new File(System.getProperty("besu.plugins.dir", "plugins"));
53+
}
54+
55+
@Override
56+
public void start() {
57+
if (enabled) {
58+
LOG.info("Starting TestWorldStateServicePlugin");
59+
60+
try {
61+
final var worldStateService =
62+
serviceManager.getService(WorldStateService.class).orElseThrow();
63+
64+
final var account =
65+
worldStateService
66+
.getWorldView()
67+
.get(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"));
68+
final var balance = account.getBalance();
69+
writeBalance(balance);
70+
} catch (Exception e) {
71+
LOG.error("Error in TestWorldStateServicePlugin", e);
72+
throw new RuntimeException(e);
73+
}
74+
}
75+
}
76+
77+
@Override
78+
public void stop() {}
79+
80+
private void writeBalance(final Wei balance) {
81+
try {
82+
final File callbackFile = new File(callbackDir, "TestWorldStateServicePlugin.txt");
83+
if (!callbackFile.getParentFile().exists()) {
84+
callbackFile.getParentFile().mkdirs();
85+
callbackFile.getParentFile().deleteOnExit();
86+
}
87+
88+
final var content = balance.toHexString();
89+
90+
Files.write(callbackFile.toPath(), content.getBytes(UTF_8));
91+
callbackFile.deleteOnExit();
92+
} catch (final IOException ioe) {
93+
throw new RuntimeException(ioe);
94+
}
95+
}
96+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.tests.acceptance.plugins;
16+
17+
import org.hyperledger.besu.datatypes.Address;
18+
import org.hyperledger.besu.datatypes.Wei;
19+
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
20+
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
21+
import org.hyperledger.besu.tests.acceptance.dsl.blockchain.Amount;
22+
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
23+
24+
import java.io.IOException;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import java.util.Collections;
28+
29+
import org.junit.jupiter.api.BeforeEach;
30+
import org.junit.jupiter.api.Test;
31+
32+
public class WorldStateServicePluginTest extends AcceptanceTestBase {
33+
private BesuNode pluginNode;
34+
35+
@BeforeEach
36+
public void setUp() throws Exception {
37+
pluginNode =
38+
besu.createQbftPluginsNode(
39+
"pluginNode",
40+
Collections.singletonList("testPlugins"),
41+
Collections.singletonList("--plugin-world-state-service-test-enabled=true"));
42+
43+
cluster.start(pluginNode);
44+
}
45+
46+
@Test
47+
public void balanceFromPluginIsCorrect() throws IOException {
48+
final Path resultFile =
49+
pluginNode.homeDirectory().resolve("plugins/TestWorldStateServicePlugin.txt");
50+
waitForFile(resultFile);
51+
final var fileContents = Files.readString(resultFile);
52+
final var balanceFromPlugin = Wei.fromHexString(fileContents);
53+
54+
final Account account =
55+
Account.create(
56+
ethTransactions, Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"));
57+
cluster.verify(account.balanceEquals(Amount.wei(balanceFromPlugin.getAsBigInteger())));
58+
}
59+
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
import org.hyperledger.besu.plugin.services.TransactionSelectionService;
161161
import org.hyperledger.besu.plugin.services.TransactionSimulationService;
162162
import org.hyperledger.besu.plugin.services.TransactionValidatorService;
163+
import org.hyperledger.besu.plugin.services.WorldStateService;
163164
import org.hyperledger.besu.plugin.services.exception.StorageException;
164165
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
165166
import org.hyperledger.besu.plugin.services.mining.MiningService;
@@ -190,6 +191,7 @@
190191
import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
191192
import org.hyperledger.besu.services.TransactionSimulationServiceImpl;
192193
import org.hyperledger.besu.services.TransactionValidatorServiceImpl;
194+
import org.hyperledger.besu.services.WorldStateServiceImpl;
193195
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
194196
import org.hyperledger.besu.util.BesuVersionUtils;
195197
import org.hyperledger.besu.util.EphemeryGenesisUpdater;
@@ -1243,7 +1245,9 @@ private void startPlugins(final Runner runner) {
12431245
besuController.getProtocolContext().getBadBlockManager()));
12441246
besuPluginContext.addService(MetricsSystem.class, getMetricsSystem());
12451247

1246-
besuPluginContext.addService(BlockchainService.class, blockchainServiceImpl);
1248+
besuPluginContext.addService(
1249+
WorldStateService.class,
1250+
new WorldStateServiceImpl(besuController.getProtocolContext().getWorldStateArchive()));
12471251

12481252
besuPluginContext.addService(
12491253
SynchronizationService.class,
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright contributors to Hyperledger Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.services;
16+
17+
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
18+
import org.hyperledger.besu.evm.worldstate.WorldView;
19+
import org.hyperledger.besu.plugin.Unstable;
20+
import org.hyperledger.besu.plugin.services.WorldStateService;
21+
22+
/**
23+
* Implementation of the {@link WorldStateService} that provides access to Besu's world state.
24+
*
25+
* <p>This implementation delegates world state operations to the underlying {@link
26+
* WorldStateArchive}.
27+
*/
28+
@Unstable
29+
public class WorldStateServiceImpl implements WorldStateService {
30+
private final WorldStateArchive worldStateArchive;
31+
32+
/**
33+
* Constructs a new WorldStateServiceImpl.
34+
*
35+
* @param worldStateArchive The world state archive that provides access to world state data
36+
*/
37+
public WorldStateServiceImpl(final WorldStateArchive worldStateArchive) {
38+
this.worldStateArchive = worldStateArchive;
39+
}
40+
41+
/**
42+
* {@inheritDoc}
43+
*
44+
* <p>Returns a view of the current world state by delegating to the underlying world state
45+
* archive.
46+
*
47+
* @return A view of the current world state
48+
*/
49+
@Override
50+
public WorldView getWorldView() {
51+
return worldStateArchive.getWorldState();
52+
}
53+
}

plugin-api/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Calculated : ${currentHash}
7171
tasks.register('checkAPIChanges', FileStateChecker) {
7272
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
7373
files = sourceSets.main.allJava.files
74-
knownHash = 'K53ycFTZR4uqRPa1c5WS1HYGisvxJu65zeaGAwfQ5uw='
74+
knownHash = 'JOV0yKVExHLhhiBc5ta2oidTIjUVgBdWw4E7u/qNseM='
7575
}
7676
check.dependsOn('checkAPIChanges')
7777

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright contributors to Hyperledger Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.plugin.services;
16+
17+
import org.hyperledger.besu.evm.worldstate.WorldView;
18+
import org.hyperledger.besu.plugin.Unstable;
19+
20+
/** A service that plugin can use to access world state */
21+
@Unstable
22+
public interface WorldStateService extends BesuService {
23+
24+
/**
25+
* Returns a view of the head world state.
26+
*
27+
* @return the head world view
28+
*/
29+
WorldView getWorldView();
30+
}

0 commit comments

Comments
 (0)