Skip to content

Commit 2360908

Browse files
matktgfukushima
andauthored
worldstate refactor (#6209)
* worldstate storage refactor Signed-off-by: Karim TAAM <karim.t2am@gmail.com> Signed-off-by: Gabriel Fukushima <gabrielfukushima@gmail.com> Co-authored-by: Gabriel Fukushima <gabrielfukushima@gmail.com>
1 parent c622213 commit 2360908

File tree

105 files changed

+1800
-1244
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+1800
-1244
lines changed

besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/BackupState.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
2828
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
2929
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
30-
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
30+
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
3131
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
3232

3333
import java.io.File;
@@ -81,15 +81,19 @@ public void run() {
8181

8282
final BesuController besuController = createBesuController();
8383
final MutableBlockchain blockchain = besuController.getProtocolContext().getBlockchain();
84-
final WorldStateStorage worldStateStorage =
84+
final ForestWorldStateKeyValueStorage forestWorldStateKeyValueStorage =
8585
((ForestWorldStateArchive) besuController.getProtocolContext().getWorldStateArchive())
8686
.getWorldStateStorage();
8787
final EthScheduler scheduler = new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem());
8888
try {
8989
final long targetBlock = Math.min(blockchain.getChainHeadBlockNumber(), this.block);
9090
final StateBackupService backup =
9191
new StateBackupService(
92-
BesuInfo.version(), blockchain, backupDir.toPath(), scheduler, worldStateStorage);
92+
BesuInfo.version(),
93+
blockchain,
94+
backupDir.toPath(),
95+
scheduler,
96+
forestWorldStateKeyValueStorage);
9397
final BackupStatus status = backup.requestBackup(targetBlock, compress, Optional.empty());
9498

9599
final double refValue = Math.pow(2, 256) / 100.0d;

besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/RestoreState.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
import org.hyperledger.besu.ethereum.trie.PersistVisitor;
3838
import org.hyperledger.besu.ethereum.trie.RestoreVisitor;
3939
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
40+
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
4041
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
41-
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
4242
import org.hyperledger.besu.util.io.RollingFileReader;
4343

4444
import java.io.IOException;
@@ -83,7 +83,7 @@ public class RestoreState implements Runnable {
8383
private long trieNodeCount;
8484
private boolean compressed;
8585
private BesuController besuController;
86-
private WorldStateStorage.Updater updater;
86+
private ForestWorldStateKeyValueStorage.Updater updater;
8787

8888
private Path accountFileName(final int fileNumber, final boolean compressed) {
8989
return StateBackupService.accountFileName(backupDir, targetBlock, fileNumber, compressed);
@@ -249,10 +249,10 @@ private void newWorldStateUpdater() {
249249
if (updater != null) {
250250
updater.commit();
251251
}
252-
final WorldStateStorage worldStateStorage =
252+
final ForestWorldStateKeyValueStorage worldStateKeyValueStorage =
253253
((ForestWorldStateArchive) besuController.getProtocolContext().getWorldStateArchive())
254254
.getWorldStateStorage();
255-
updater = worldStateStorage.updater();
255+
updater = worldStateKeyValueStorage.updater();
256256
}
257257

258258
private void maybeCommitUpdater() {
@@ -263,20 +263,20 @@ private void maybeCommitUpdater() {
263263

264264
private void updateCode(final Bytes code) {
265265
maybeCommitUpdater();
266-
updater.putCode(null, code);
266+
updater.putCode(code);
267267
}
268268

269269
private void updateAccountState(final Bytes32 key, final Bytes value) {
270270
maybeCommitUpdater();
271271
// restore by path not supported
272-
updater.putAccountStateTrieNode(null, key, value);
272+
updater.putAccountStateTrieNode(key, value);
273273
trieNodeCount++;
274274
}
275275

276276
private void updateAccountStorage(final Bytes32 key, final Bytes value) {
277277
maybeCommitUpdater();
278278
// restore by path not supported
279-
updater.putAccountStorageTrieNode(null, null, key, value);
279+
updater.putAccountStorageTrieNode(key, value);
280280
trieNodeCount++;
281281
}
282282

besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,9 @@
9292
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
9393
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
9494
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
95+
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
9596
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
96-
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
97+
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
9798
import org.hyperledger.besu.evm.internal.EvmConfiguration;
9899
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
99100
import org.hyperledger.besu.plugin.services.MetricsSystem;
@@ -559,8 +560,8 @@ public BesuController build() {
559560

560561
final VariablesStorage variablesStorage = storageProvider.createVariablesStorage();
561562

562-
final WorldStateStorage worldStateStorage =
563-
storageProvider.createWorldStateStorage(dataStorageConfiguration);
563+
final WorldStateStorageCoordinator worldStateStorageCoordinator =
564+
storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration);
564565

565566
final BlockchainStorage blockchainStorage =
566567
storageProvider.createBlockchainStorage(protocolSchedule, variablesStorage);
@@ -580,7 +581,7 @@ public BesuController build() {
580581
.orElseGet(() -> new CachedMerkleTrieLoader(metricsSystem));
581582

582583
final WorldStateArchive worldStateArchive =
583-
createWorldStateArchive(worldStateStorage, blockchain, cachedMerkleTrieLoader);
584+
createWorldStateArchive(worldStateStorageCoordinator, blockchain, cachedMerkleTrieLoader);
584585

585586
if (blockchain.getChainHeadBlockNumber() < 1) {
586587
genesisState.writeStateTo(worldStateArchive.getMutable());
@@ -707,7 +708,7 @@ public BesuController build() {
707708
final Synchronizer synchronizer =
708709
createSynchronizer(
709710
protocolSchedule,
710-
worldStateStorage,
711+
worldStateStorageCoordinator,
711712
protocolContext,
712713
maybePruner,
713714
ethContext,
@@ -739,8 +740,10 @@ public BesuController build() {
739740
&& DataStorageFormat.BONSAI.equals(dataStorageConfiguration.getDataStorageFormat())) {
740741
final TrieLogManager trieLogManager =
741742
((BonsaiWorldStateProvider) worldStateArchive).getTrieLogManager();
743+
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
744+
worldStateStorageCoordinator.getStrategy(BonsaiWorldStateKeyValueStorage.class);
742745
final TrieLogPruner trieLogPruner =
743-
createTrieLogPruner(worldStateStorage, blockchain, scheduler);
746+
createTrieLogPruner(worldStateKeyValueStorage, blockchain, scheduler);
744747
trieLogManager.subscribe(trieLogPruner);
745748
}
746749

@@ -773,7 +776,7 @@ public BesuController build() {
773776
}
774777

775778
private TrieLogPruner createTrieLogPruner(
776-
final WorldStateStorage worldStateStorage,
779+
final WorldStateKeyValueStorage worldStateStorage,
777780
final Blockchain blockchain,
778781
final EthScheduler scheduler) {
779782
final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get();
@@ -796,7 +799,7 @@ private TrieLogPruner createTrieLogPruner(
796799
* Create synchronizer synchronizer.
797800
*
798801
* @param protocolSchedule the protocol schedule
799-
* @param worldStateStorage the world state storage
802+
* @param worldStateStorageCoordinator the world state storage
800803
* @param protocolContext the protocol context
801804
* @param maybePruner the maybe pruner
802805
* @param ethContext the eth context
@@ -807,7 +810,7 @@ private TrieLogPruner createTrieLogPruner(
807810
*/
808811
protected Synchronizer createSynchronizer(
809812
final ProtocolSchedule protocolSchedule,
810-
final WorldStateStorage worldStateStorage,
813+
final WorldStateStorageCoordinator worldStateStorageCoordinator,
811814
final ProtocolContext protocolContext,
812815
final Optional<Pruner> maybePruner,
813816
final EthContext ethContext,
@@ -819,7 +822,7 @@ protected Synchronizer createSynchronizer(
819822
syncConfig,
820823
protocolSchedule,
821824
protocolContext,
822-
worldStateStorage,
825+
worldStateStorageCoordinator,
823826
ethProtocolManager.getBlockBroadcaster(),
824827
maybePruner,
825828
ethContext,
@@ -1042,21 +1045,26 @@ private Optional<SnapProtocolManager> createSnapProtocolManager(
10421045
}
10431046

10441047
WorldStateArchive createWorldStateArchive(
1045-
final WorldStateStorage worldStateStorage,
1048+
final WorldStateStorageCoordinator worldStateStorageCoordinator,
10461049
final Blockchain blockchain,
10471050
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
10481051
return switch (dataStorageConfiguration.getDataStorageFormat()) {
1049-
case BONSAI -> new BonsaiWorldStateProvider(
1050-
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
1051-
blockchain,
1052-
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
1053-
cachedMerkleTrieLoader,
1054-
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
1055-
evmConfiguration);
1052+
case BONSAI -> {
1053+
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
1054+
worldStateStorageCoordinator.getStrategy(BonsaiWorldStateKeyValueStorage.class);
1055+
yield new BonsaiWorldStateProvider(
1056+
worldStateKeyValueStorage,
1057+
blockchain,
1058+
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
1059+
cachedMerkleTrieLoader,
1060+
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
1061+
evmConfiguration);
1062+
}
10561063
case FOREST -> {
10571064
final WorldStatePreimageStorage preimageStorage =
10581065
storageProvider.createWorldStatePreimageStorage();
1059-
yield new ForestWorldStateArchive(worldStateStorage, preimageStorage, evmConfiguration);
1066+
yield new ForestWorldStateArchive(
1067+
worldStateStorageCoordinator, preimageStorage, evmConfiguration);
10601068
}
10611069
};
10621070
}

besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
5757
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
5858
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
59-
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
59+
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
6060
import org.hyperledger.besu.evm.internal.EvmConfiguration;
6161
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
6262
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
@@ -217,7 +217,7 @@ protected PluginServiceFactory createAdditionalPluginServices(
217217
@Override
218218
protected Synchronizer createSynchronizer(
219219
final ProtocolSchedule protocolSchedule,
220-
final WorldStateStorage worldStateStorage,
220+
final WorldStateStorageCoordinator worldStateStorageCoordinator,
221221
final ProtocolContext protocolContext,
222222
final Optional<Pruner> maybePruner,
223223
final EthContext ethContext,
@@ -229,7 +229,7 @@ protected Synchronizer createSynchronizer(
229229
(DefaultSynchronizer)
230230
super.createSynchronizer(
231231
protocolSchedule,
232-
worldStateStorage,
232+
worldStateStorageCoordinator,
233233
protocolContext,
234234
maybePruner,
235235
ethContext,

besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@
4747
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
4848
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
4949
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
50+
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
5051
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
5152
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
5253
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
5354
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
54-
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
55+
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
5556
import org.hyperledger.besu.evm.internal.EvmConfiguration;
5657
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
5758
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
@@ -89,7 +90,6 @@ public class BesuControllerBuilderTest {
8990
@Mock Clock clock;
9091
@Mock StorageProvider storageProvider;
9192
@Mock GasLimitCalculator gasLimitCalculator;
92-
@Mock WorldStateStorage worldStateStorage;
9393
@Mock WorldStateArchive worldStateArchive;
9494
@Mock BonsaiWorldStateKeyValueStorage bonsaiWorldStateStorage;
9595
@Mock WorldStatePreimageStorage worldStatePreimageStorage;
@@ -105,6 +105,12 @@ public class BesuControllerBuilderTest {
105105

106106
@BeforeEach
107107
public void setup() {
108+
109+
final ForestWorldStateKeyValueStorage worldStateKeyValueStorage =
110+
mock(ForestWorldStateKeyValueStorage.class);
111+
final WorldStateStorageCoordinator worldStateStorageCoordinator =
112+
new WorldStateStorageCoordinator(worldStateKeyValueStorage);
113+
108114
when(genesisConfigFile.getParentHash()).thenReturn(Hash.ZERO.toHexString());
109115
when(genesisConfigFile.getDifficulty()).thenReturn(Bytes.of(0).toHexString());
110116
when(genesisConfigFile.getExtraData()).thenReturn(Bytes.EMPTY.toHexString());
@@ -132,17 +138,21 @@ public void setup() {
132138

133139
lenient()
134140
.when(
135-
storageProvider.createWorldStateStorage(DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
136-
.thenReturn(worldStateStorage);
141+
storageProvider.createWorldStateStorageCoordinator(
142+
DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
143+
.thenReturn(worldStateStorageCoordinator);
137144
lenient()
138145
.when(storageProvider.createWorldStatePreimageStorage())
139146
.thenReturn(worldStatePreimageStorage);
140147

141-
lenient().when(worldStateStorage.isWorldStateAvailable(any(), any())).thenReturn(true);
148+
lenient().when(worldStateKeyValueStorage.isWorldStateAvailable(any())).thenReturn(true);
142149
lenient()
143150
.when(worldStatePreimageStorage.updater())
144151
.thenReturn(mock(WorldStatePreimageStorage.Updater.class));
145-
lenient().when(worldStateStorage.updater()).thenReturn(mock(WorldStateStorage.Updater.class));
152+
lenient()
153+
.when(worldStateKeyValueStorage.updater())
154+
.thenReturn(mock(ForestWorldStateKeyValueStorage.Updater.class));
155+
146156
besuControllerBuilder = spy(visitWithMockConfigs(new MainnetBesuControllerBuilder()));
147157
}
148158

@@ -167,18 +177,23 @@ BesuControllerBuilder visitWithMockConfigs(final BesuControllerBuilder builder)
167177

168178
@Test
169179
public void shouldDisablePruningIfBonsaiIsEnabled() {
180+
DataStorageConfiguration dataStorageConfiguration =
181+
ImmutableDataStorageConfiguration.builder()
182+
.dataStorageFormat(DataStorageFormat.BONSAI)
183+
.bonsaiMaxLayersToLoad(DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD)
184+
.build();
170185
BonsaiWorldState mockWorldState = mock(BonsaiWorldState.class, Answers.RETURNS_DEEP_STUBS);
171186
doReturn(worldStateArchive)
172187
.when(besuControllerBuilder)
173188
.createWorldStateArchive(
174-
any(WorldStateStorage.class), any(Blockchain.class), any(CachedMerkleTrieLoader.class));
189+
any(WorldStateStorageCoordinator.class),
190+
any(Blockchain.class),
191+
any(CachedMerkleTrieLoader.class));
175192
doReturn(mockWorldState).when(worldStateArchive).getMutable();
193+
when(storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration))
194+
.thenReturn(new WorldStateStorageCoordinator(bonsaiWorldStateStorage));
195+
besuControllerBuilder.isPruningEnabled(true).dataStorageConfiguration(dataStorageConfiguration);
176196

177-
when(storageProvider.createWorldStateStorage(DataStorageConfiguration.DEFAULT_BONSAI_CONFIG))
178-
.thenReturn(bonsaiWorldStateStorage);
179-
besuControllerBuilder
180-
.isPruningEnabled(true)
181-
.dataStorageConfiguration(DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
182197
besuControllerBuilder.build();
183198

184199
verify(storageProvider, never())

besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@
5252
import org.hyperledger.besu.ethereum.storage.StorageProvider;
5353
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
5454
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
55+
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
5556
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
5657
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
5758
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
58-
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
59+
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
5960
import org.hyperledger.besu.evm.internal.EvmConfiguration;
6061
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
6162
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
@@ -99,7 +100,6 @@ public class MergeBesuControllerBuilderTest {
99100
@Mock Clock clock;
100101
@Mock StorageProvider storageProvider;
101102
@Mock GasLimitCalculator gasLimitCalculator;
102-
@Mock WorldStateStorage worldStateStorage;
103103
@Mock WorldStatePreimageStorage worldStatePreimageStorage;
104104

105105
BigInteger networkId = BigInteger.ONE;
@@ -113,6 +113,12 @@ public class MergeBesuControllerBuilderTest {
113113

114114
@BeforeEach
115115
public void setup() {
116+
117+
final ForestWorldStateKeyValueStorage worldStateKeyValueStorage =
118+
mock(ForestWorldStateKeyValueStorage.class);
119+
final WorldStateStorageCoordinator worldStateStorageCoordinator =
120+
new WorldStateStorageCoordinator(worldStateKeyValueStorage);
121+
116122
lenient().when(genesisConfigFile.getParentHash()).thenReturn(Hash.ZERO.toHexString());
117123
lenient().when(genesisConfigFile.getDifficulty()).thenReturn(Bytes.of(0).toHexString());
118124
lenient().when(genesisConfigFile.getExtraData()).thenReturn(Bytes.EMPTY.toHexString());
@@ -146,17 +152,20 @@ public void setup() {
146152

147153
lenient()
148154
.when(
149-
storageProvider.createWorldStateStorage(DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
150-
.thenReturn(worldStateStorage);
155+
storageProvider.createWorldStateStorageCoordinator(
156+
DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
157+
.thenReturn(worldStateStorageCoordinator);
151158
lenient()
152159
.when(storageProvider.createWorldStatePreimageStorage())
153160
.thenReturn(worldStatePreimageStorage);
154161

155-
lenient().when(worldStateStorage.isWorldStateAvailable(any(), any())).thenReturn(true);
162+
lenient().when(worldStateKeyValueStorage.isWorldStateAvailable(any())).thenReturn(true);
156163
lenient()
157164
.when(worldStatePreimageStorage.updater())
158165
.thenReturn(mock(WorldStatePreimageStorage.Updater.class));
159-
lenient().when(worldStateStorage.updater()).thenReturn(mock(WorldStateStorage.Updater.class));
166+
lenient()
167+
.when(worldStateKeyValueStorage.updater())
168+
.thenReturn(mock(ForestWorldStateKeyValueStorage.Updater.class));
160169
lenient().when(miningParameters.getTargetGasLimit()).thenReturn(OptionalLong.empty());
161170

162171
besuControllerBuilder = visitWithMockConfigs(new MergeBesuControllerBuilder());

0 commit comments

Comments
 (0)