Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

worldstate refactor #6209

Merged
merged 32 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
657a78e
worldstate storage refactor
matkt Nov 28, 2023
6d4a4bb
fix unit tests
matkt Nov 28, 2023
d8a411e
fix unit tests
matkt Nov 28, 2023
e9558d3
fix unit tests
matkt Nov 29, 2023
18e1899
merge main
matkt Dec 19, 2023
4a3ea8a
merge main
matkt Dec 19, 2023
a368a35
fix tests
matkt Dec 20, 2023
ccdb980
merge main
matkt Jan 9, 2024
41fc466
fix review
matkt Jan 10, 2024
513734f
Merge branch 'main' into feature/worldstate-refactor
matkt Jan 10, 2024
61e985b
Merge branch 'main' into feature/worldstate-refactor
matkt Jan 12, 2024
9f4cd99
Merge branch 'main' into feature/worldstate-refactor
matkt Jan 16, 2024
772efd7
merge main
matkt Jan 19, 2024
78f64f2
Merge branch 'main' into feature/worldstate-refactor
matkt Jan 19, 2024
36ee939
merge main
matkt Jan 25, 2024
d0ed277
fix build
matkt Jan 25, 2024
93f0476
Merge branch 'main' into feature/worldstate-refactor
matkt Jan 25, 2024
6620e1d
Merge branch 'main' into feature/worldstate-refactor
matkt Jan 29, 2024
1ca3362
Merge branch 'main' into feature/worldstate-refactor
matkt Jan 31, 2024
44df1e9
merge main
matkt Mar 1, 2024
e3ae5d1
fix ref tests
matkt Mar 1, 2024
9dfadc4
fix tests
matkt Mar 1, 2024
0f24e3a
fix build
matkt Mar 1, 2024
3f34e01
fix build
matkt Mar 1, 2024
bb66627
fix failed tests
matkt Mar 6, 2024
fadc9c4
Merge branch 'main' into feature/worldstate-refactor
matkt Mar 7, 2024
228a794
fix test to use BonsaiWSKVStorage
gfukushima Mar 8, 2024
7824da4
Merge branch 'main' into feature/worldstate-refactor
gfukushima Mar 8, 2024
b9ffdcf
spotless
gfukushima Mar 8, 2024
4e045c6
Merge remote-tracking branch 'matkt/feature/worldstate-refactor' into…
gfukushima Mar 8, 2024
47e97c0
Merge branch 'main' into feature/worldstate-refactor
matkt Mar 8, 2024
574fac1
fiw review
matkt Mar 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;

import java.io.File;
Expand Down Expand Up @@ -81,15 +81,19 @@ public void run() {

final BesuController besuController = createBesuController();
final MutableBlockchain blockchain = besuController.getProtocolContext().getBlockchain();
final WorldStateStorage worldStateStorage =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this has been an undocumented experimental feature for 3 years. we should get rid of it. probably in a different PR

final ForestWorldStateKeyValueStorage forestWorldStateKeyValueStorage =
((ForestWorldStateArchive) besuController.getProtocolContext().getWorldStateArchive())
.getWorldStateStorage();
final EthScheduler scheduler = new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem());
try {
final long targetBlock = Math.min(blockchain.getChainHeadBlockNumber(), this.block);
final StateBackupService backup =
new StateBackupService(
BesuInfo.version(), blockchain, backupDir.toPath(), scheduler, worldStateStorage);
BesuInfo.version(),
blockchain,
backupDir.toPath(),
scheduler,
forestWorldStateKeyValueStorage);
final BackupStatus status = backup.requestBackup(targetBlock, compress, Optional.empty());

final double refValue = Math.pow(2, 256) / 100.0d;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
import org.hyperledger.besu.ethereum.trie.PersistVisitor;
import org.hyperledger.besu.ethereum.trie.RestoreVisitor;
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.util.io.RollingFileReader;

import java.io.IOException;
Expand Down Expand Up @@ -83,7 +83,7 @@ public class RestoreState implements Runnable {
private long trieNodeCount;
private boolean compressed;
private BesuController besuController;
private WorldStateStorage.Updater updater;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same, non-blocking. forest is deprecated and we should deprecate these commands too

private ForestWorldStateKeyValueStorage.Updater updater;

private Path accountFileName(final int fileNumber, final boolean compressed) {
return StateBackupService.accountFileName(backupDir, targetBlock, fileNumber, compressed);
Expand Down Expand Up @@ -249,10 +249,10 @@ private void newWorldStateUpdater() {
if (updater != null) {
updater.commit();
}
final WorldStateStorage worldStateStorage =
final ForestWorldStateKeyValueStorage worldStateKeyValueStorage =
((ForestWorldStateArchive) besuController.getProtocolContext().getWorldStateArchive())
.getWorldStateStorage();
updater = worldStateStorage.updater();
updater = worldStateKeyValueStorage.updater();
}

private void maybeCommitUpdater() {
Expand All @@ -263,20 +263,20 @@ private void maybeCommitUpdater() {

private void updateCode(final Bytes code) {
maybeCommitUpdater();
updater.putCode(null, code);
updater.putCode(code);
}

private void updateAccountState(final Bytes32 key, final Bytes value) {
maybeCommitUpdater();
// restore by path not supported
updater.putAccountStateTrieNode(null, key, value);
updater.putAccountStateTrieNode(key, value);
trieNodeCount++;
}

private void updateAccountStorage(final Bytes32 key, final Bytes value) {
maybeCommitUpdater();
// restore by path not supported
updater.putAccountStorageTrieNode(null, null, key, value);
updater.putAccountStorageTrieNode(key, value);
trieNodeCount++;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.MetricsSystem;
Expand Down Expand Up @@ -559,8 +560,8 @@ public BesuController build() {

final VariablesStorage variablesStorage = storageProvider.createVariablesStorage();

final WorldStateStorage worldStateStorage =
storageProvider.createWorldStateStorage(dataStorageConfiguration);
final WorldStateStorageCoordinator worldStateStorageCoordinator =
storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration);

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

final WorldStateArchive worldStateArchive =
createWorldStateArchive(worldStateStorage, blockchain, cachedMerkleTrieLoader);
createWorldStateArchive(worldStateStorageCoordinator, blockchain, cachedMerkleTrieLoader);

if (blockchain.getChainHeadBlockNumber() < 1) {
genesisState.writeStateTo(worldStateArchive.getMutable());
Expand Down Expand Up @@ -707,7 +708,7 @@ public BesuController build() {
final Synchronizer synchronizer =
createSynchronizer(
protocolSchedule,
worldStateStorage,
worldStateStorageCoordinator,
protocolContext,
maybePruner,
ethContext,
Expand Down Expand Up @@ -739,8 +740,10 @@ public BesuController build() {
&& DataStorageFormat.BONSAI.equals(dataStorageConfiguration.getDataStorageFormat())) {
final TrieLogManager trieLogManager =
((BonsaiWorldStateProvider) worldStateArchive).getTrieLogManager();
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
worldStateStorageCoordinator.getStrategy(BonsaiWorldStateKeyValueStorage.class);
final TrieLogPruner trieLogPruner =
createTrieLogPruner(worldStateStorage, blockchain, scheduler);
createTrieLogPruner(worldStateKeyValueStorage, blockchain, scheduler);
trieLogManager.subscribe(trieLogPruner);
}

Expand Down Expand Up @@ -773,7 +776,7 @@ public BesuController build() {
}

private TrieLogPruner createTrieLogPruner(
final WorldStateStorage worldStateStorage,
final WorldStateKeyValueStorage worldStateStorage,
final Blockchain blockchain,
final EthScheduler scheduler) {
final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get();
Expand All @@ -796,7 +799,7 @@ private TrieLogPruner createTrieLogPruner(
* Create synchronizer synchronizer.
*
* @param protocolSchedule the protocol schedule
* @param worldStateStorage the world state storage
* @param worldStateStorageCoordinator the world state storage
* @param protocolContext the protocol context
* @param maybePruner the maybe pruner
* @param ethContext the eth context
Expand All @@ -807,7 +810,7 @@ private TrieLogPruner createTrieLogPruner(
*/
protected Synchronizer createSynchronizer(
final ProtocolSchedule protocolSchedule,
final WorldStateStorage worldStateStorage,
final WorldStateStorageCoordinator worldStateStorageCoordinator,
final ProtocolContext protocolContext,
final Optional<Pruner> maybePruner,
final EthContext ethContext,
Expand All @@ -819,7 +822,7 @@ protected Synchronizer createSynchronizer(
syncConfig,
protocolSchedule,
protocolContext,
worldStateStorage,
worldStateStorageCoordinator,
ethProtocolManager.getBlockBroadcaster(),
maybePruner,
ethContext,
Expand Down Expand Up @@ -1042,21 +1045,26 @@ private Optional<SnapProtocolManager> createSnapProtocolManager(
}

WorldStateArchive createWorldStateArchive(
final WorldStateStorage worldStateStorage,
final WorldStateStorageCoordinator worldStateStorageCoordinator,
final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
return switch (dataStorageConfiguration.getDataStorageFormat()) {
case BONSAI -> new BonsaiWorldStateProvider(
(BonsaiWorldStateKeyValueStorage) worldStateStorage,
blockchain,
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
cachedMerkleTrieLoader,
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
evmConfiguration);
case BONSAI -> {
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
worldStateStorageCoordinator.getStrategy(BonsaiWorldStateKeyValueStorage.class);
yield new BonsaiWorldStateProvider(
worldStateKeyValueStorage,
blockchain,
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
cachedMerkleTrieLoader,
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
evmConfiguration);
}
case FOREST -> {
final WorldStatePreimageStorage preimageStorage =
storageProvider.createWorldStatePreimageStorage();
yield new ForestWorldStateArchive(worldStateStorage, preimageStorage, evmConfiguration);
yield new ForestWorldStateArchive(
worldStateStorageCoordinator, preimageStorage, evmConfiguration);
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider;
Expand Down Expand Up @@ -217,7 +217,7 @@ protected PluginServiceFactory createAdditionalPluginServices(
@Override
protected Synchronizer createSynchronizer(
final ProtocolSchedule protocolSchedule,
final WorldStateStorage worldStateStorage,
final WorldStateStorageCoordinator worldStateStorageCoordinator,
final ProtocolContext protocolContext,
final Optional<Pruner> maybePruner,
final EthContext ethContext,
Expand All @@ -229,7 +229,7 @@ protected Synchronizer createSynchronizer(
(DefaultSynchronizer)
super.createSynchronizer(
protocolSchedule,
worldStateStorage,
worldStateStorageCoordinator,
protocolContext,
maybePruner,
ethContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
Expand Down Expand Up @@ -89,7 +90,6 @@ public class BesuControllerBuilderTest {
@Mock Clock clock;
@Mock StorageProvider storageProvider;
@Mock GasLimitCalculator gasLimitCalculator;
@Mock WorldStateStorage worldStateStorage;
@Mock WorldStateArchive worldStateArchive;
@Mock BonsaiWorldStateKeyValueStorage bonsaiWorldStateStorage;
@Mock WorldStatePreimageStorage worldStatePreimageStorage;
Expand All @@ -105,6 +105,12 @@ public class BesuControllerBuilderTest {

@BeforeEach
public void setup() {

final ForestWorldStateKeyValueStorage worldStateKeyValueStorage =
mock(ForestWorldStateKeyValueStorage.class);
final WorldStateStorageCoordinator worldStateStorageCoordinator =
new WorldStateStorageCoordinator(worldStateKeyValueStorage);

when(genesisConfigFile.getParentHash()).thenReturn(Hash.ZERO.toHexString());
when(genesisConfigFile.getDifficulty()).thenReturn(Bytes.of(0).toHexString());
when(genesisConfigFile.getExtraData()).thenReturn(Bytes.EMPTY.toHexString());
Expand Down Expand Up @@ -132,17 +138,21 @@ public void setup() {

lenient()
.when(
storageProvider.createWorldStateStorage(DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
.thenReturn(worldStateStorage);
storageProvider.createWorldStateStorageCoordinator(
DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
.thenReturn(worldStateStorageCoordinator);
lenient()
.when(storageProvider.createWorldStatePreimageStorage())
.thenReturn(worldStatePreimageStorage);

lenient().when(worldStateStorage.isWorldStateAvailable(any(), any())).thenReturn(true);
lenient().when(worldStateKeyValueStorage.isWorldStateAvailable(any())).thenReturn(true);
lenient()
.when(worldStatePreimageStorage.updater())
.thenReturn(mock(WorldStatePreimageStorage.Updater.class));
lenient().when(worldStateStorage.updater()).thenReturn(mock(WorldStateStorage.Updater.class));
lenient()
.when(worldStateKeyValueStorage.updater())
.thenReturn(mock(ForestWorldStateKeyValueStorage.Updater.class));

besuControllerBuilder = spy(visitWithMockConfigs(new MainnetBesuControllerBuilder()));
}

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

@Test
public void shouldDisablePruningIfBonsaiIsEnabled() {
DataStorageConfiguration dataStorageConfiguration =
ImmutableDataStorageConfiguration.builder()
.dataStorageFormat(DataStorageFormat.BONSAI)
.bonsaiMaxLayersToLoad(DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD)
.build();
BonsaiWorldState mockWorldState = mock(BonsaiWorldState.class, Answers.RETURNS_DEEP_STUBS);
doReturn(worldStateArchive)
.when(besuControllerBuilder)
.createWorldStateArchive(
any(WorldStateStorage.class), any(Blockchain.class), any(CachedMerkleTrieLoader.class));
any(WorldStateStorageCoordinator.class),
any(Blockchain.class),
any(CachedMerkleTrieLoader.class));
doReturn(mockWorldState).when(worldStateArchive).getMutable();
when(storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration))
.thenReturn(new WorldStateStorageCoordinator(bonsaiWorldStateStorage));
besuControllerBuilder.isPruningEnabled(true).dataStorageConfiguration(dataStorageConfiguration);

when(storageProvider.createWorldStateStorage(DataStorageConfiguration.DEFAULT_BONSAI_CONFIG))
.thenReturn(bonsaiWorldStateStorage);
besuControllerBuilder
.isPruningEnabled(true)
.dataStorageConfiguration(DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
besuControllerBuilder.build();

verify(storageProvider, never())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
Expand Down Expand Up @@ -99,7 +100,6 @@ public class MergeBesuControllerBuilderTest {
@Mock Clock clock;
@Mock StorageProvider storageProvider;
@Mock GasLimitCalculator gasLimitCalculator;
@Mock WorldStateStorage worldStateStorage;
@Mock WorldStatePreimageStorage worldStatePreimageStorage;

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

@BeforeEach
public void setup() {

final ForestWorldStateKeyValueStorage worldStateKeyValueStorage =
mock(ForestWorldStateKeyValueStorage.class);
final WorldStateStorageCoordinator worldStateStorageCoordinator =
new WorldStateStorageCoordinator(worldStateKeyValueStorage);

lenient().when(genesisConfigFile.getParentHash()).thenReturn(Hash.ZERO.toHexString());
lenient().when(genesisConfigFile.getDifficulty()).thenReturn(Bytes.of(0).toHexString());
lenient().when(genesisConfigFile.getExtraData()).thenReturn(Bytes.EMPTY.toHexString());
Expand Down Expand Up @@ -146,17 +152,20 @@ public void setup() {

lenient()
.when(
storageProvider.createWorldStateStorage(DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
.thenReturn(worldStateStorage);
storageProvider.createWorldStateStorageCoordinator(
DataStorageConfiguration.DEFAULT_FOREST_CONFIG))
.thenReturn(worldStateStorageCoordinator);
lenient()
.when(storageProvider.createWorldStatePreimageStorage())
.thenReturn(worldStatePreimageStorage);

lenient().when(worldStateStorage.isWorldStateAvailable(any(), any())).thenReturn(true);
lenient().when(worldStateKeyValueStorage.isWorldStateAvailable(any())).thenReturn(true);
lenient()
.when(worldStatePreimageStorage.updater())
.thenReturn(mock(WorldStatePreimageStorage.Updater.class));
lenient().when(worldStateStorage.updater()).thenReturn(mock(WorldStateStorage.Updater.class));
lenient()
.when(worldStateKeyValueStorage.updater())
.thenReturn(mock(ForestWorldStateKeyValueStorage.Updater.class));
lenient().when(miningParameters.getTargetGasLimit()).thenReturn(OptionalLong.empty());

besuControllerBuilder = visitWithMockConfigs(new MergeBesuControllerBuilder());
Expand Down
Loading
Loading