storage format refactor for preparing verkle trie integration (#6721)

Splitting Bonsai code: This commit aims to divide Bonsai into two packages

- Common Classes with a Prefix: The common part will include classes prefixed with "DiffBased." These classes are designed to provide a base for both Bonsai and any future storage format that might use this diff-based approach.

- Bonsai's Specifics: Bonsai will retain its unique features in its own package. This means that while it shares the diff-based infrastructure with the common part, it also has its own specific functionalities that are not shared with other storage format.

- Extension to Verkle: this modification add the possibility of adding "Verkle" as a new storage format based on the diff-based architecture. Like Bonsai, Verkle would use the common diff-based classes but also have its own specific features.

---------

Signed-off-by: Karim TAAM <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
pull/6832/head develop
Karim TAAM 8 months ago committed by GitHub
parent 7e46889817
commit f2c2512ef6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelper.java
  2. 4
      besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogSubCommand.java
  3. 8
      besu/src/main/java/org/hyperledger/besu/components/BesuComponent.java
  4. 23
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  5. 6
      besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java
  6. 8
      besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java
  7. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java
  8. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java
  9. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java
  10. 18
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java
  11. 185
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiAccount.java
  12. 145
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java
  13. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedMerkleTrieLoader.java
  14. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedMerkleTrieLoaderModule.java
  15. 60
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java
  16. 18
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java
  17. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiPreImageProxy.java
  18. 14
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java
  19. 188
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiWorldStateKeyValueStorage.java
  20. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiWorldStateLayerStorage.java
  21. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/flat/FullFlatDbStrategy.java
  22. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/flat/PartialFlatDbStrategy.java
  23. 19
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/trielog/TrieLogFactoryImpl.java
  24. 361
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java
  25. 98
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java
  26. 206
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedAccount.java
  27. 25
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedValue.java
  28. 171
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java
  29. 25
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/StorageSubscriber.java
  30. 97
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java
  31. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldView.java
  32. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedLayeredWorldStateKeyValueStorage.java
  33. 21
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedSnapshotWorldStateKeyValueStorage.java
  34. 234
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedWorldStateKeyValueStorage.java
  35. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/flat/AccountHashCodeStorageStrategy.java
  36. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/flat/CodeHashCodeStorageStrategy.java
  37. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/flat/CodeStorageStrategy.java
  38. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/flat/FlatDbStrategy.java
  39. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/flat/FlatDbStrategyProvider.java
  40. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/NoOpTrieLogManager.java
  41. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogAddedEvent.java
  42. 50
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogLayer.java
  43. 23
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java
  44. 12
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java
  45. 334
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java
  46. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldView.java
  47. 339
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java
  48. 49
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/preload/AccountConsumingMap.java
  49. 21
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/preload/Consumer.java
  50. 53
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/preload/StorageConsumingMap.java
  51. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateStorageCoordinator.java
  52. 12
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java
  53. 2
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TrieGenerator.java
  54. 6
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java
  55. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java
  56. 12
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiCachedMerkleTrieLoaderTest.java
  57. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java
  58. 36
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProviderTest.java
  59. 12
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java
  60. 12
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java
  61. 4
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiWorldStateKeyValueStorageTest.java
  62. 3
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/trielog/TrieLogFactoryTests.java
  63. 9
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/trielog/TrieLogManagerTests.java
  64. 7
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/trielog/TrieLogPrunerTest.java
  65. 30
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java
  66. 4
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/flat/FlatDbStrategyProviderTest.java
  67. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogLayerTests.java
  68. 1
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/forest/storage/ForestKeyValueStorageWorldStateStorageTest.java
  69. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java
  70. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java
  71. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/PersistDataStep.java
  72. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapWorldDownloadState.java
  73. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapWorldStateDownloader.java
  74. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/AccountRangeDataRequest.java
  75. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/StorageRangeDataRequest.java
  76. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/AccountFlatDatabaseHealingRangeRequest.java
  77. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/StorageFlatDatabaseHealingRangeRequest.java
  78. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointSyncChainDownloaderTest.java
  79. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastDownloaderFactoryTest.java
  80. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloaderTest.java
  81. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldDownloadStateTest.java
  82. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/LoadLocalDataStepTest.java
  83. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/AccountHealingTrackingTest.java
  84. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/PersistDataStepTest.java
  85. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapWorldDownloadStateTest.java
  86. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/TaskGenerator.java
  87. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/AccountFlatDatabaseHealingRangeRequestTest.java
  88. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/StorageFlatDatabaseHealingRangeRequestTest.java
  89. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/StorageTrieNodeHealingRequestTest.java
  90. 18
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestUpdateAccumulator.java
  91. 58
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java
  92. 12
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldStateStorage.java

@ -27,9 +27,9 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import java.io.File;

@ -25,8 +25,8 @@ import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;

@ -19,8 +19,8 @@ package org.hyperledger.besu.components;
import org.hyperledger.besu.cli.BesuCommand;
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoaderModule;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoaderModule;
import org.hyperledger.besu.metrics.MetricsSystemModule;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.services.BesuPluginContextImpl;
@ -37,7 +37,7 @@ import org.slf4j.Logger;
modules = {
BesuCommandModule.class,
MetricsSystemModule.class,
CachedMerkleTrieLoaderModule.class,
BonsaiCachedMerkleTrieLoaderModule.class,
BesuPluginContextModule.class,
BlobCacheModule.class
})
@ -55,7 +55,7 @@ public interface BesuComponent {
*
* @return CachedMerkleTrieLoader
*/
CachedMerkleTrieLoader getCachedMerkleTrieLoader();
BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader();
/**
* a metrics system that is observable by a Prometheus or OTEL metrics collection subsystem

@ -81,11 +81,11 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
import org.hyperledger.besu.ethereum.trie.forest.pruner.MarkSweepPruner;
import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner;
@ -576,13 +576,14 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
dataDirectory.toString(),
numberOfBlocksToCache);
final CachedMerkleTrieLoader cachedMerkleTrieLoader =
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
besuComponent
.map(BesuComponent::getCachedMerkleTrieLoader)
.orElseGet(() -> new CachedMerkleTrieLoader(metricsSystem));
.orElseGet(() -> new BonsaiCachedMerkleTrieLoader(metricsSystem));
final WorldStateArchive worldStateArchive =
createWorldStateArchive(worldStateStorageCoordinator, blockchain, cachedMerkleTrieLoader);
createWorldStateArchive(
worldStateStorageCoordinator, blockchain, bonsaiCachedMerkleTrieLoader);
if (blockchain.getChainHeadBlockNumber() < 1) {
genesisState.writeStateTo(worldStateArchive.getMutable());
@ -1048,7 +1049,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
WorldStateArchive createWorldStateArchive(
final WorldStateStorageCoordinator worldStateStorageCoordinator,
final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader) {
return switch (dataStorageConfiguration.getDataStorageFormat()) {
case BONSAI -> {
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
@ -1057,7 +1058,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
worldStateKeyValueStorage,
blockchain,
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
cachedMerkleTrieLoader,
bonsaiCachedMerkleTrieLoader,
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
evmConfiguration);
}
@ -1067,6 +1068,8 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
yield new ForestWorldStateArchive(
worldStateStorageCoordinator, preimageStorage, evmConfiguration);
}
default -> throw new IllegalStateException(
"Unexpected value: " + dataStorageConfiguration.getDataStorageFormat());
};
}

@ -31,9 +31,9 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;

@ -43,9 +43,9 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.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;
@ -189,7 +189,7 @@ public class BesuControllerBuilderTest {
.createWorldStateArchive(
any(WorldStateStorageCoordinator.class),
any(Blockchain.class),
any(CachedMerkleTrieLoader.class));
any(BonsaiCachedMerkleTrieLoader.class));
doReturn(mockWorldState).when(worldStateArchive).getMutable();
when(storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration))
.thenReturn(new WorldStateStorageCoordinator(bonsaiWorldStateStorage));

@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.AccountState;

@ -31,8 +31,8 @@ import org.hyperledger.besu.ethereum.core.Withdrawal;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;

@ -19,7 +19,7 @@ import org.hyperledger.besu.ethereum.chain.VariablesStorage;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -19,11 +19,11 @@ package org.hyperledger.besu.ethereum.trie.common;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.NoOpCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.NoOpTrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.NoOpBonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
@ -59,8 +59,8 @@ public class GenesisWorldStateProvider {
* @return a mutable world state for the Genesis block
*/
private static MutableWorldState createGenesisBonsaiWorldState() {
final CachedMerkleTrieLoader cachedMerkleTrieLoader =
new CachedMerkleTrieLoader(new NoOpMetricsSystem());
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage =
new BonsaiWorldStateKeyValueStorage(
new KeyValueStorageProvider(
@ -71,8 +71,8 @@ public class GenesisWorldStateProvider {
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
return new BonsaiWorldState(
bonsaiWorldStateKeyValueStorage,
cachedMerkleTrieLoader,
new NoOpCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage),
bonsaiCachedMerkleTrieLoader,
new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage),
new NoOpTrieLogManager(),
EvmConfiguration.DEFAULT);
}

@ -14,48 +14,34 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
import org.hyperledger.besu.evm.ModificationNotAllowedException;
import org.hyperledger.besu.evm.account.AccountStorageEntry;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
import java.util.HashMap;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Objects;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
public class BonsaiAccount implements MutableAccount, AccountValue {
private final BonsaiWorldView context;
private boolean immutable;
private final Address address;
private final Hash addressHash;
private Hash codeHash;
private long nonce;
private Wei balance;
public class BonsaiAccount extends DiffBasedAccount {
private Hash storageRoot;
private Bytes code;
private final Map<UInt256, UInt256> updatedStorage = new HashMap<>();
public BonsaiAccount(
final BonsaiWorldView context,
final DiffBasedWorldView context,
final Address address,
final Hash addressHash,
final long nonce,
@ -63,31 +49,24 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
final Hash storageRoot,
final Hash codeHash,
final boolean mutable) {
this.context = context;
this.address = address;
this.addressHash = addressHash;
this.nonce = nonce;
this.balance = balance;
super(context, address, addressHash, nonce, balance, codeHash, mutable);
this.storageRoot = storageRoot;
this.codeHash = codeHash;
this.immutable = !mutable;
}
public BonsaiAccount(
final BonsaiWorldView context,
final DiffBasedWorldView context,
final Address address,
final AccountValue stateTrieAccount,
final boolean mutable) {
this(
super(
context,
address,
address.addressHash(),
stateTrieAccount.getNonce(),
stateTrieAccount.getBalance(),
stateTrieAccount.getStorageRoot(),
stateTrieAccount.getCodeHash(),
mutable);
this.storageRoot = stateTrieAccount.getStorageRoot();
}
public BonsaiAccount(final BonsaiAccount toCopy) {
@ -95,37 +74,35 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
}
public BonsaiAccount(
final BonsaiAccount toCopy, final BonsaiWorldView context, final boolean mutable) {
this.context = context;
this.address = toCopy.address;
this.addressHash = toCopy.addressHash;
this.nonce = toCopy.nonce;
this.balance = toCopy.balance;
final BonsaiAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
super(
context,
toCopy.address,
toCopy.addressHash,
toCopy.nonce,
toCopy.balance,
toCopy.codeHash,
mutable);
this.storageRoot = toCopy.storageRoot;
this.codeHash = toCopy.codeHash;
this.code = toCopy.code;
updatedStorage.putAll(toCopy.updatedStorage);
this.immutable = !mutable;
}
public BonsaiAccount(
final BonsaiWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) {
this.context = context;
this.address = tracked.getAddress();
this.addressHash = tracked.getAddressHash();
this.nonce = tracked.getNonce();
this.balance = tracked.getBalance();
final DiffBasedWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) {
super(
context,
tracked.getAddress(),
tracked.getAddressHash(),
tracked.getNonce(),
tracked.getBalance(),
tracked.getCodeHash(),
true);
this.storageRoot = Hash.EMPTY_TRIE_HASH;
this.codeHash = tracked.getCodeHash();
this.code = tracked.getCode();
updatedStorage.putAll(tracked.getUpdatedStorage());
this.immutable = false;
}
public static BonsaiAccount fromRLP(
final BonsaiWorldView context,
final DiffBasedWorldView context,
final Address address,
final Bytes encoded,
final boolean mutable)
@ -144,88 +121,11 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
context, address, address.addressHash(), nonce, balance, storageRoot, codeHash, mutable);
}
@Override
public Address getAddress() {
return address;
}
@Override
public Hash getAddressHash() {
return addressHash;
}
@Override
public long getNonce() {
return nonce;
}
@Override
public void setNonce(final long value) {
if (immutable) {
throw new ModificationNotAllowedException();
}
nonce = value;
}
@Override
public Wei getBalance() {
return balance;
}
@Override
public void setBalance(final Wei value) {
if (immutable) {
throw new ModificationNotAllowedException();
}
balance = value;
}
@Override
public Bytes getCode() {
if (code == null) {
code = context.getCode(address, codeHash).orElse(Bytes.EMPTY);
}
return code;
}
@Override
public void setCode(final Bytes code) {
if (immutable) {
throw new ModificationNotAllowedException();
}
this.code = code;
if (code == null || code.isEmpty()) {
this.codeHash = Hash.EMPTY;
} else {
this.codeHash = Hash.hash(code);
}
}
@Override
public Hash getCodeHash() {
return codeHash;
}
@Override
public UInt256 getStorageValue(final UInt256 key) {
return context.getStorageValue(address, key);
}
@Override
public UInt256 getOriginalStorageValue(final UInt256 key) {
return context.getPriorStorageValue(address, key);
}
@Override
public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
final Bytes32 startKeyHash, final int limit) {
return context.getWorldStateStorage().storageEntriesFrom(this.addressHash, startKeyHash, limit);
}
public Bytes serializeAccount() {
final BytesValueRLPOutput out = new BytesValueRLPOutput();
writeTo(out);
return out.encoded();
return ((BonsaiWorldStateKeyValueStorage) context.getWorldStateStorage())
.storageEntriesFrom(this.addressHash, startKeyHash, limit);
}
@Override
@ -240,24 +140,6 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
out.endList();
}
@Override
public void setStorageValue(final UInt256 key, final UInt256 value) {
if (immutable) {
throw new ModificationNotAllowedException();
}
updatedStorage.put(key, value);
}
@Override
public void clearStorage() {
updatedStorage.clear();
}
@Override
public Map<UInt256, UInt256> getUpdatedStorage() {
return updatedStorage;
}
@Override
public Hash getStorageRoot() {
return storageRoot;
@ -270,11 +152,6 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
this.storageRoot = storageRoot;
}
@Override
public void becomeImmutable() {
immutable = true;
}
@Override
public String toString() {
return "AccountState{"

@ -0,0 +1,145 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.plugin.BesuContext;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import com.google.common.annotations.VisibleForTesting;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateProvider.class);
private final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader;
public BonsaiWorldStateProvider(
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final Blockchain blockchain,
final Optional<Long> maxLayersToLoad,
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
final BesuContext pluginContext,
final EvmConfiguration evmConfiguration) {
super(worldStateKeyValueStorage, blockchain, maxLayersToLoad, pluginContext);
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
provideCachedWorldStorageManager(
new BonsaiCachedWorldStorageManager(this, worldStateKeyValueStorage));
loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration));
}
@VisibleForTesting
BonsaiWorldStateProvider(
final BonsaiCachedWorldStorageManager bonsaiCachedWorldStorageManager,
final TrieLogManager trieLogManager,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final Blockchain blockchain,
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
final EvmConfiguration evmConfiguration) {
super(worldStateKeyValueStorage, blockchain, trieLogManager);
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
provideCachedWorldStorageManager(bonsaiCachedWorldStorageManager);
loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration));
}
public BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader() {
return bonsaiCachedMerkleTrieLoader;
}
private BonsaiWorldStateKeyValueStorage getWorldStateKeyValueStorage() {
return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage;
}
/**
* Prepares the state healing process for a given address and location. It prepares the state
* healing, including retrieving data from storage, identifying invalid slots or nodes, removing
* account and slot from the state trie, and committing the changes. Finally, it downgrades the
* world state storage to partial flat database mode.
*/
public void prepareStateHealing(final Address address, final Bytes location) {
final Set<Bytes> keysToDelete = new HashSet<>();
final BonsaiWorldStateKeyValueStorage.Updater updater =
getWorldStateKeyValueStorage().updater();
final Hash accountHash = address.addressHash();
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
new StoredMerklePatriciaTrie<>(
(l, h) -> {
final Optional<Bytes> node =
getWorldStateKeyValueStorage().getAccountStateTrieNode(l, h);
if (node.isPresent()) {
keysToDelete.add(l);
}
return node;
},
persistedState.getWorldStateRootHash(),
Function.identity(),
Function.identity());
try {
accountTrie
.get(accountHash)
.map(RLP::input)
.map(StateTrieAccountValue::readFrom)
.ifPresent(
account -> {
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
new StoredMerklePatriciaTrie<>(
(l, h) -> {
Optional<Bytes> node =
getWorldStateKeyValueStorage()
.getAccountStorageTrieNode(accountHash, l, h);
if (node.isPresent()) {
keysToDelete.add(Bytes.concatenate(accountHash, l));
}
return node;
},
account.getStorageRoot(),
Function.identity(),
Function.identity());
try {
storageTrie.getPath(location);
} catch (Exception eA) {
LOG.warn("Invalid slot found for account {} at location {}", address, location);
// ignore
}
});
} catch (Exception eA) {
LOG.warn("Invalid node for account {} at location {}", address, location);
// ignore
}
keysToDelete.forEach(updater::removeAccountStateTrieNode);
updater.commit();
getWorldStateKeyValueStorage().downgradeToPartialFlatDbMode();
}
}

@ -13,14 +13,15 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
@ -37,8 +38,7 @@ import io.prometheus.client.guava.cache.CacheMetricsCollector;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
public class CachedMerkleTrieLoader
implements BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
public class BonsaiCachedMerkleTrieLoader implements StorageSubscriber {
private static final int ACCOUNT_CACHE_SIZE = 100_000;
private static final int STORAGE_CACHE_SIZE = 200_000;
@ -47,7 +47,7 @@ public class CachedMerkleTrieLoader
private final Cache<Bytes, Bytes> storageNodes =
CacheBuilder.newBuilder().recordStats().maximumSize(STORAGE_CACHE_SIZE).build();
public CachedMerkleTrieLoader(final ObservableMetricsSystem metricsSystem) {
public BonsaiCachedMerkleTrieLoader(final ObservableMetricsSystem metricsSystem) {
CacheMetricsCollector cacheMetrics = new CacheMetricsCollector();
cacheMetrics.addCache("accountsNodes", accountNodes);

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
@ -21,11 +21,11 @@ import dagger.Module;
import dagger.Provides;
@Module
public class CachedMerkleTrieLoaderModule {
public class BonsaiCachedMerkleTrieLoaderModule {
@Provides
CachedMerkleTrieLoader provideCachedMerkleTrieLoaderModule(
BonsaiCachedMerkleTrieLoader provideCachedMerkleTrieLoaderModule(
final ObservableMetricsSystem metricsSystem) {
return new CachedMerkleTrieLoader(metricsSystem);
return new BonsaiCachedMerkleTrieLoader(metricsSystem);
}
}

@ -0,0 +1,60 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager {
public BonsaiCachedWorldStorageManager(
final BonsaiWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
super(archive, worldStateKeyValueStorage);
}
@Override
public DiffBasedWorldState createWorldState(
final DiffBasedWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final EvmConfiguration evmConfiguration) {
return new BonsaiWorldState(
(BonsaiWorldStateProvider) archive,
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage,
evmConfiguration);
}
@Override
public DiffBasedWorldStateKeyValueStorage createLayeredKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
return new BonsaiWorldStateLayerStorage(
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage);
}
@Override
public DiffBasedWorldStateKeyValueStorage createSnapshotKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
return new BonsaiSnapshotWorldStateKeyValueStorage(
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage);
}
}

@ -12,19 +12,19 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import java.util.Optional;
import java.util.function.Function;
public class NoOpCachedWorldStorageManager extends CachedWorldStorageManager {
public class NoOpBonsaiCachedWorldStorageManager extends BonsaiCachedWorldStorageManager {
public NoOpCachedWorldStorageManager(
public NoOpBonsaiCachedWorldStorageManager(
final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage) {
super(null, bonsaiWorldStateKeyValueStorage);
}
@ -33,7 +33,7 @@ public class NoOpCachedWorldStorageManager extends CachedWorldStorageManager {
public synchronized void addCachedLayer(
final BlockHeader blockHeader,
final Hash worldStateRootHash,
final BonsaiWorldState forWorldState) {
final DiffBasedWorldState forWorldState) {
// no cache
}
@ -43,17 +43,17 @@ public class NoOpCachedWorldStorageManager extends CachedWorldStorageManager {
}
@Override
public Optional<BonsaiWorldState> getWorldState(final Hash blockHash) {
public Optional<DiffBasedWorldState> getWorldState(final Hash blockHash) {
return Optional.empty();
}
@Override
public Optional<BonsaiWorldState> getNearestWorldState(final BlockHeader blockHeader) {
public Optional<DiffBasedWorldState> getNearestWorldState(final BlockHeader blockHeader) {
return Optional.empty();
}
@Override
public Optional<BonsaiWorldState> getHeadWorldState(
public Optional<DiffBasedWorldState> getHeadWorldState(
final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) {
return Optional.empty();
}

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;

@ -13,11 +13,12 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SnappableKeyValueStorage;
@ -32,7 +33,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKeyValueStorage
implements BonsaiStorageSubscriber {
implements DiffBasedSnapshotWorldStateKeyValueStorage, StorageSubscriber {
protected final BonsaiWorldStateKeyValueStorage parentWorldStateStorage;
private static final Logger LOG =
@ -53,9 +54,9 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
final BonsaiWorldStateKeyValueStorage worldStateStorageKeyValueStorage) {
this(
worldStateStorageKeyValueStorage,
((SnappableKeyValueStorage) worldStateStorageKeyValueStorage.composedWorldStateStorage)
((SnappableKeyValueStorage) worldStateStorageKeyValueStorage.getComposedWorldStateStorage())
.takeSnapshot(),
worldStateStorageKeyValueStorage.trieLogStorage);
worldStateStorageKeyValueStorage.getTrieLogStorage());
}
private boolean isClosedGet() {
@ -207,7 +208,7 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
protected synchronized void doClose() throws Exception {
if (!isClosedGet()) {
// alert any subscribers we are closing:
subscribers.forEach(BonsaiStorageSubscriber::onCloseStorage);
subscribers.forEach(StorageSubscriber::onCloseStorage);
// close all of the SnappedKeyValueStorages:
composedWorldStateStorage.close();
@ -220,6 +221,7 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
}
}
@Override
public BonsaiWorldStateKeyValueStorage getParentWorldStateStorage() {
return parentWorldStateStorage;
}

@ -12,7 +12,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
@ -24,8 +24,9 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FlatDbStrategyProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategyProvider;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
@ -37,52 +38,28 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
import org.hyperledger.besu.util.Subscribers;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorage, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateKeyValueStorage.class);
// 0x776f726c64526f6f74
public static final byte[] WORLD_ROOT_HASH_KEY = "worldRoot".getBytes(StandardCharsets.UTF_8);
// 0x776f726c64426c6f636b48617368
public static final byte[] WORLD_BLOCK_HASH_KEY =
"worldBlockHash".getBytes(StandardCharsets.UTF_8);
public class BonsaiWorldStateKeyValueStorage extends DiffBasedWorldStateKeyValueStorage
implements WorldStateKeyValueStorage {
protected final FlatDbStrategyProvider flatDbStrategyProvider;
protected final SegmentedKeyValueStorage composedWorldStateStorage;
protected final KeyValueStorage trieLogStorage;
private final AtomicBoolean shouldClose = new AtomicBoolean(false);
protected final AtomicBoolean isClosed = new AtomicBoolean(false);
protected final Subscribers<BonsaiStorageSubscriber> subscribers = Subscribers.create();
public BonsaiWorldStateKeyValueStorage(
final StorageProvider provider,
final MetricsSystem metricsSystem,
final DataStorageConfiguration dataStorageConfiguration) {
this.composedWorldStateStorage =
super(
provider.getStorageBySegmentIdentifiers(
List.of(
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE));
this.trieLogStorage =
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE);
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE)),
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE));
this.flatDbStrategyProvider =
new FlatDbStrategyProvider(metricsSystem, dataStorageConfiguration);
flatDbStrategyProvider.loadFlatDbStrategy(composedWorldStateStorage);
@ -92,9 +69,8 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
final FlatDbStrategyProvider flatDbStrategyProvider,
final SegmentedKeyValueStorage composedWorldStateStorage,
final KeyValueStorage trieLogStorage) {
super(composedWorldStateStorage, trieLogStorage);
this.flatDbStrategyProvider = flatDbStrategyProvider;
this.composedWorldStateStorage = composedWorldStateStorage;
this.trieLogStorage = trieLogStorage;
}
@Override
@ -102,6 +78,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return DataStorageFormat.BONSAI;
}
@Override
public FlatDbMode getFlatDbMode() {
return flatDbStrategyProvider.getFlatDbMode();
}
@ -155,31 +132,6 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
.map(Bytes::wrap);
}
public Optional<byte[]> getTrieLog(final Hash blockHash) {
return trieLogStorage.get(blockHash.toArrayUnsafe());
}
public Stream<byte[]> streamTrieLogKeys(final long limit) {
return trieLogStorage.streamKeys().limit(limit);
}
public Optional<Bytes> getStateTrieNode(final Bytes location) {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, location.toArrayUnsafe())
.map(Bytes::wrap);
}
public Optional<Bytes> getWorldStateRootHash() {
return composedWorldStateStorage.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY).map(Bytes::wrap);
}
public Optional<Hash> getWorldStateBlockHash() {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY)
.map(Bytes32::wrap)
.map(Hash::wrap);
}
public Optional<Bytes> getStorageValueByStorageSlotKey(
final Hash accountHash, final StorageSlotKey storageSlotKey) {
return getStorageValueByStorageSlotKey(
@ -209,34 +161,11 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateStorage);
}
public Map<Bytes32, Bytes> streamFlatAccounts(
final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
return flatDbStrategyProvider
.getFlatDbStrategy(composedWorldStateStorage)
.streamAccountFlatDatabase(composedWorldStateStorage, startKeyHash, endKeyHash, max);
}
public Map<Bytes32, Bytes> streamFlatStorages(
final Hash accountHash, final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
return flatDbStrategyProvider
.getFlatDbStrategy(composedWorldStateStorage)
.streamStorageFlatDatabase(
composedWorldStateStorage, accountHash, startKeyHash, endKeyHash, max);
}
public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
final Hash addressHash, final Bytes32 startKeyHash, final int limit) {
throw new RuntimeException("Bonsai Tries does not currently support enumerating storage");
}
public boolean isWorldStateAvailable(final Bytes32 rootHash, final Hash blockHash) {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY)
.map(Bytes32::wrap)
.map(hash -> hash.equals(rootHash) || trieLogStorage.containsKey(blockHash.toArrayUnsafe()))
.orElse(false);
}
public void upgradeToFullFlatDbMode() {
flatDbStrategyProvider.upgradeToFullFlatDbMode(composedWorldStateStorage);
}
@ -247,26 +176,14 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
@Override
public void clear() {
subscribers.forEach(BonsaiStorageSubscriber::onClearStorage);
flatDbStrategyProvider
.getFlatDbStrategy(composedWorldStateStorage)
.clearAll(composedWorldStateStorage);
composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE);
trieLogStorage.clear();
super.clear();
flatDbStrategyProvider.loadFlatDbStrategy(
composedWorldStateStorage); // force reload of flat db reader strategy
}
public void clearTrieLog() {
subscribers.forEach(BonsaiStorageSubscriber::onClearTrieLog);
trieLogStorage.clear();
}
public void clearFlatDatabase() {
subscribers.forEach(BonsaiStorageSubscriber::onClearFlatDatabaseStorage);
flatDbStrategyProvider
.getFlatDbStrategy(composedWorldStateStorage)
.resetOnResync(composedWorldStateStorage);
@Override
public FlatDbStrategy getFlatDbStrategy() {
return flatDbStrategyProvider.getFlatDbStrategy(composedWorldStateStorage);
}
@Override
@ -277,20 +194,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
flatDbStrategyProvider.getFlatDbStrategy(composedWorldStateStorage));
}
public boolean pruneTrieLog(final Hash blockHash) {
try {
return trieLogStorage.tryDelete(blockHash.toArrayUnsafe());
} catch (Exception e) {
LOG.error("Error pruning trie log for block hash {}", blockHash, e);
return false;
}
}
public FlatDbStrategy getFlatDbStrategy() {
return flatDbStrategyProvider.getFlatDbStrategy(composedWorldStateStorage);
}
public static class Updater implements WorldStateKeyValueStorage.Updater {
public static class Updater implements DiffBasedWorldStateKeyValueStorage.Updater {
private final SegmentedKeyValueStorageTransaction composedWorldStateTransaction;
private final KeyValueStorageTransaction trieLogStorageTransaction;
@ -340,6 +244,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return this;
}
@Override
public Updater saveWorldState(final Bytes blockHash, final Bytes32 nodeHash, final Bytes node) {
composedWorldStateTransaction.put(
TRIE_BRANCH_STORAGE, Bytes.EMPTY.toArrayUnsafe(), node.toArrayUnsafe());
@ -392,10 +297,12 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateTransaction, accountHash, slotHash);
}
@Override
public SegmentedKeyValueStorageTransaction getWorldStateTransaction() {
return composedWorldStateTransaction;
}
@Override
public KeyValueStorageTransaction getTrieLogStorageTransaction() {
return trieLogStorageTransaction;
}
@ -407,65 +314,10 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateTransaction.commit();
}
@Override
public void rollback() {
composedWorldStateTransaction.rollback();
trieLogStorageTransaction.rollback();
}
}
@Override
public synchronized void close() throws Exception {
// when the storage clears, close
shouldClose.set(true);
tryClose();
}
public synchronized long subscribe(final BonsaiStorageSubscriber sub) {
if (isClosed.get()) {
throw new RuntimeException("Storage is marked to close or has already closed");
}
return subscribers.subscribe(sub);
}
public synchronized void unSubscribe(final long id) {
subscribers.unsubscribe(id);
try {
tryClose();
} catch (Exception e) {
LOG.atWarn()
.setMessage("exception while trying to close : {}")
.addArgument(e::getMessage)
.log();
}
}
protected synchronized void tryClose() throws Exception {
if (shouldClose.get() && subscribers.getSubscriberCount() < 1) {
doClose();
}
}
protected synchronized void doClose() throws Exception {
if (!isClosed.get()) {
// alert any subscribers we are closing:
subscribers.forEach(BonsaiStorageSubscriber::onCloseStorage);
// close all of the KeyValueStorages:
composedWorldStateStorage.close();
trieLogStorage.close();
// set storage closed
isClosed.set(true);
}
}
public interface BonsaiStorageSubscriber {
default void onClearStorage() {}
default void onClearFlatDatabaseStorage() {}
default void onClearTrieLog() {}
default void onCloseStorage() {}
}
}

@ -13,21 +13,22 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SnappedKeyValueStorage;
import org.hyperledger.besu.services.kvstore.LayeredKeyValueStorage;
public class BonsaiWorldStateLayerStorage extends BonsaiSnapshotWorldStateKeyValueStorage
implements BonsaiStorageSubscriber {
implements DiffBasedLayeredWorldStateKeyValueStorage, StorageSubscriber {
public BonsaiWorldStateLayerStorage(final BonsaiWorldStateKeyValueStorage parent) {
this(
new LayeredKeyValueStorage(parent.composedWorldStateStorage),
parent.trieLogStorage,
new LayeredKeyValueStorage(parent.getComposedWorldStateStorage()),
parent.getTrieLogStorage(),
parent);
}

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
@ -21,6 +21,8 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIden
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.NodeLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.CodeStorageStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
@ -21,6 +21,8 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIden
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.NodeLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.CodeStorageStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.trie.patricia.StoredNodeFactory;
import org.hyperledger.besu.metrics.BesuMetricCategory;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;
@ -23,7 +23,8 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
@ -150,7 +151,7 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final TrieLogLayer newLayer = new TrieLogLayer();
input.enterList();
newLayer.blockHash = Hash.wrap(input.readBytes32());
newLayer.setBlockHash(Hash.wrap(input.readBytes32()));
while (!input.isEndOfCurrentList()) {
input.enterList();
@ -164,7 +165,9 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final StateTrieAccountValue newValue = nullOrValue(input, StateTrieAccountValue::readFrom);
final boolean isCleared = getOptionalIsCleared(input);
input.leaveList();
newLayer.accounts.put(address, new BonsaiValue<>(oldValue, newValue, isCleared));
newLayer
.getAccountChanges()
.put(address, new DiffBasedValue<>(oldValue, newValue, isCleared));
}
if (input.nextIsNull()) {
@ -175,13 +178,13 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final Bytes newCode = nullOrValue(input, RLPInput::readBytes);
final boolean isCleared = getOptionalIsCleared(input);
input.leaveList();
newLayer.code.put(address, new BonsaiValue<>(oldCode, newCode, isCleared));
newLayer.getCodeChanges().put(address, new DiffBasedValue<>(oldCode, newCode, isCleared));
}
if (input.nextIsNull()) {
input.skipNext();
} else {
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageChanges = new TreeMap<>();
final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageChanges = new TreeMap<>();
input.enterList();
while (!input.isEndOfCurrentList()) {
input.enterList();
@ -190,11 +193,11 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final UInt256 oldValue = nullOrValue(input, RLPInput::readUInt256Scalar);
final UInt256 newValue = nullOrValue(input, RLPInput::readUInt256Scalar);
final boolean isCleared = getOptionalIsCleared(input);
storageChanges.put(storageSlotKey, new BonsaiValue<>(oldValue, newValue, isCleared));
storageChanges.put(storageSlotKey, new DiffBasedValue<>(oldValue, newValue, isCleared));
input.leaveList();
}
input.leaveList();
newLayer.storage.put(address, storageChanges);
newLayer.getStorageChanges().put(address, storageChanges);
}
// TODO add trie nodes

@ -14,39 +14,33 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView.encodeTrieValue;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView.encodeTrieValue;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.NodeLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator.StorageConsumingMap;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
@ -63,24 +57,10 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.rlp.RLP;
import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiWorldState
implements MutableWorldState, BonsaiWorldView, BonsaiStorageSubscriber {
public class BonsaiWorldState extends DiffBasedWorldState {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldState.class);
protected BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
protected final CachedMerkleTrieLoader cachedMerkleTrieLoader;
protected final CachedWorldStorageManager cachedWorldStorageManager;
protected final TrieLogManager trieLogManager;
private BonsaiWorldStateUpdateAccumulator accumulator;
protected Hash worldStateRootHash;
Hash worldStateBlockHash;
private boolean isFrozen;
protected final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader;
public BonsaiWorldState(
final BonsaiWorldStateProvider archive,
@ -96,90 +76,39 @@ public class BonsaiWorldState
public BonsaiWorldState(
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final CachedWorldStorageManager cachedWorldStorageManager,
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager,
final EvmConfiguration evmConfiguration) {
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.worldStateRootHash =
Hash.wrap(
Bytes32.wrap(
worldStateKeyValueStorage.getWorldStateRootHash().orElse(getEmptyTrieHash())));
this.worldStateBlockHash =
Hash.wrap(
Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
this.accumulator =
super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager);
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
this.setAccumulator(
new BonsaiWorldStateUpdateAccumulator(
this,
(addr, value) ->
cachedMerkleTrieLoader.preLoadAccount(
getWorldStateStorage(), worldStateRootHash, addr),
bonsaiCachedMerkleTrieLoader.preLoadAccount(
worldStateKeyValueStorage, worldStateRootHash, addr),
(addr, value) ->
cachedMerkleTrieLoader.preLoadStorageSlot(getWorldStateStorage(), addr, value),
evmConfiguration);
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
this.cachedWorldStorageManager = cachedWorldStorageManager;
this.trieLogManager = trieLogManager;
}
/**
* Override the accumulator solves the chicken-egg problem of needing a worldstate reference
* (this) when construction the Accumulator.
*
* @param accumulator accumulator to use.
*/
public void setAccumulator(final BonsaiWorldStateUpdateAccumulator accumulator) {
this.accumulator = accumulator;
}
/**
* Returns the world state block hash of this world state
*
* @return the world state block hash.
*/
public Hash getWorldStateBlockHash() {
return worldStateBlockHash;
}
/**
* Returns the world state root hash of this world state
*
* @return the world state root hash.
*/
public Hash getWorldStateRootHash() {
return worldStateRootHash;
bonsaiCachedMerkleTrieLoader.preLoadStorageSlot(
getWorldStateStorage(), addr, value),
evmConfiguration));
}
@Override
public boolean isPersisted() {
return isPersisted(worldStateKeyValueStorage);
}
private boolean isPersisted(final WorldStateKeyValueStorage worldStateKeyValueStorage) {
return !(worldStateKeyValueStorage instanceof BonsaiSnapshotWorldStateKeyValueStorage);
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage;
}
@Override
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
return worldStateKeyValueStorage.getCode(codeHash, address.addressHash());
protected Hash calculateRootHash(
final Optional<DiffBasedWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final DiffBasedWorldStateUpdateAccumulator<?> worldStateUpdater) {
return internalCalculateRootHash(
maybeStateUpdater.map(BonsaiWorldStateKeyValueStorage.Updater.class::cast),
(BonsaiWorldStateUpdateAccumulator) worldStateUpdater);
}
/**
* Reset the worldState to this block header
*
* @param blockHeader block to use
*/
public void resetWorldStateTo(final BlockHeader blockHeader) {
worldStateBlockHash = blockHeader.getBlockHash();
worldStateRootHash = blockHeader.getStateRoot();
}
@Override
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
return worldStateKeyValueStorage;
}
private Hash calculateRootHash(
private Hash internalCalculateRootHash(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
@ -187,7 +116,7 @@ public class BonsaiWorldState
// This must be done before updating the accounts so
// that we can get the storage state hash
Stream<Map.Entry<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>>
Stream<Map.Entry<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>>
storageStream = worldStateUpdater.getStorageToUpdate().entrySet().stream();
if (maybeStateUpdater.isEmpty()) {
storageStream =
@ -205,8 +134,8 @@ public class BonsaiWorldState
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
createTrie(
(location, hash) ->
cachedMerkleTrieLoader.getAccountStateTrieNode(
worldStateKeyValueStorage, location, hash),
bonsaiCachedMerkleTrieLoader.getAccountStateTrieNode(
getWorldStateStorage(), location, hash),
worldStateRootHash);
// for manicured tries and composting, collect branches here (not implemented)
@ -231,10 +160,10 @@ public class BonsaiWorldState
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie) {
for (final Map.Entry<Address, BonsaiValue<BonsaiAccount>> accountUpdate :
for (final Map.Entry<Address, DiffBasedValue<BonsaiAccount>> accountUpdate :
worldStateUpdater.getAccountsToUpdate().entrySet()) {
final Bytes accountKey = accountUpdate.getKey();
final BonsaiValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue();
final DiffBasedValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue();
final BonsaiAccount updatedAccount = bonsaiValue.getUpdated();
try {
if (updatedAccount == null) {
@ -264,7 +193,7 @@ public class BonsaiWorldState
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
maybeStateUpdater.ifPresent(
bonsaiUpdater -> {
for (final Map.Entry<Address, BonsaiValue<Bytes>> codeUpdate :
for (final Map.Entry<Address, DiffBasedValue<Bytes>> codeUpdate :
worldStateUpdater.getCodeToUpdate().entrySet()) {
final Bytes updatedCode = codeUpdate.getValue().getUpdated();
final Hash accountHash = codeUpdate.getKey().addressHash();
@ -294,12 +223,12 @@ public class BonsaiWorldState
private void updateAccountStorageState(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>
final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
storageAccountUpdate) {
final Address updatedAddress = storageAccountUpdate.getKey();
final Hash updatedAddressHash = updatedAddress.addressHash();
if (worldStateUpdater.getAccountsToUpdate().containsKey(updatedAddress)) {
final BonsaiValue<BonsaiAccount> accountValue =
final DiffBasedValue<BonsaiAccount> accountValue =
worldStateUpdater.getAccountsToUpdate().get(updatedAddress);
final BonsaiAccount accountOriginal = accountValue.getPrior();
final Hash storageRoot =
@ -310,12 +239,12 @@ public class BonsaiWorldState
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
createTrie(
(location, key) ->
cachedMerkleTrieLoader.getAccountStorageTrieNode(
worldStateKeyValueStorage, updatedAddressHash, location, key),
bonsaiCachedMerkleTrieLoader.getAccountStorageTrieNode(
getWorldStateStorage(), updatedAddressHash, location, key),
storageRoot);
// for manicured tries and composting, collect branches here (not implemented)
for (final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> storageUpdate :
for (final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> storageUpdate :
storageAccountUpdate.getValue().entrySet()) {
final Hash slotHash = storageUpdate.getKey().getSlotHash();
final UInt256 updatedStorage = storageUpdate.getValue().getUpdated();
@ -360,11 +289,10 @@ public class BonsaiWorldState
private void clearStorage(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
for (final Address address : worldStateUpdater.getStorageToClear()) {
// because we are clearing persisted values we need the account root as persisted
final BonsaiAccount oldAccount =
worldStateKeyValueStorage
getWorldStateStorage()
.getAccount(address.addressHash())
.map(bytes -> BonsaiAccount.fromRLP(BonsaiWorldState.this, address, bytes, true))
.orElse(null);
@ -379,7 +307,7 @@ public class BonsaiWorldState
(location, key) -> getStorageTrieNode(addressHash, location, key),
oldAccount.getStorageRoot());
try {
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> storageToDelete =
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> storageToDelete =
worldStateUpdater.getStorageToUpdate().get(address);
Map<Bytes32, Bytes> entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256);
while (!entriesToDelete.isEmpty()) {
@ -394,7 +322,7 @@ public class BonsaiWorldState
address.addressHash(), storageSlotKey.getSlotHash()));
storageToDelete
.computeIfAbsent(
storageSlotKey, key -> new BonsaiValue<>(slotValue, null, true))
storageSlotKey, key -> new DiffBasedValue<>(slotValue, null, true))
.setPrior(slotValue);
});
entriesToDelete.keySet().forEach(storageTrie::remove);
@ -412,138 +340,6 @@ public class BonsaiWorldState
}
}
@Override
public void persist(final BlockHeader blockHeader) {
final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader);
LOG.atDebug()
.setMessage("Persist world state for block {}")
.addArgument(maybeBlockHeader)
.log();
final BonsaiWorldStateUpdateAccumulator localCopy = accumulator.copy();
boolean success = false;
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater =
worldStateKeyValueStorage.updater();
Runnable saveTrieLog = () -> {};
try {
final Hash newWorldStateRootHash =
calculateRootHash(isFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator);
// if we are persisted with a block header, and the prior state is the parent
// then persist the TrieLog for that transition.
// If specified but not a direct descendant simply store the new block hash.
if (blockHeader != null) {
verifyWorldStateRoot(newWorldStateRootHash, blockHeader);
saveTrieLog =
() -> {
trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this);
// not save a frozen state in the cache
if (!isFrozen) {
cachedWorldStorageManager.addCachedLayer(blockHeader, newWorldStateRootHash, this);
}
};
stateUpdater
.getWorldStateTransaction()
.put(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY, blockHeader.getHash().toArrayUnsafe());
worldStateBlockHash = blockHeader.getHash();
} else {
stateUpdater.getWorldStateTransaction().remove(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY);
worldStateBlockHash = null;
}
stateUpdater
.getWorldStateTransaction()
.put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, newWorldStateRootHash.toArrayUnsafe());
worldStateRootHash = newWorldStateRootHash;
success = true;
} finally {
if (success) {
stateUpdater.commit();
accumulator.reset();
saveTrieLog.run();
} else {
stateUpdater.rollback();
accumulator.reset();
}
}
}
protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) {
if (!calculatedStateRoot.equals(header.getStateRoot())) {
throw new RuntimeException(
"World State Root does not match expected value, header "
+ header.getStateRoot().toHexString()
+ " calculated "
+ calculatedStateRoot.toHexString());
}
}
@Override
public WorldUpdater updater() {
return accumulator;
}
@Override
public Hash rootHash() {
if (isFrozen && accumulator.isAccumulatorStateChanged()) {
worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy());
accumulator.resetAccumulatorStateChanged();
}
return Hash.wrap(worldStateRootHash);
}
static final KeyValueStorageTransaction noOpTx =
new KeyValueStorageTransaction() {
@Override
public void put(final byte[] key, final byte[] value) {
// no-op
}
@Override
public void remove(final byte[] key) {
// no-op
}
@Override
public void commit() throws StorageException {
// no-op
}
@Override
public void rollback() {
// no-op
}
};
static final SegmentedKeyValueStorageTransaction noOpSegmentedTx =
new SegmentedKeyValueStorageTransaction() {
@Override
public void put(
final SegmentIdentifier segmentIdentifier, final byte[] key, final byte[] value) {
// no-op
}
@Override
public void remove(final SegmentIdentifier segmentIdentifier, final byte[] key) {
// no-op
}
@Override
public void commit() throws StorageException {
// no-op
}
@Override
public void rollback() {
// no-op
}
};
@Override
public Hash frontierRootHash() {
return calculateRootHash(
@ -553,25 +349,28 @@ public class BonsaiWorldState
accumulator.copy());
}
public Hash blockHash() {
return worldStateBlockHash;
}
@Override
public Stream<StreamableAccount> streamAccounts(final Bytes32 startKeyHash, final int limit) {
throw new RuntimeException("Bonsai Tries do not provide account streaming.");
public MutableWorldState freeze() {
this.isFrozen = true;
this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage());
return this;
}
@Override
public Account get(final Address address) {
return worldStateKeyValueStorage
return getWorldStateStorage()
.getAccount(address.addressHash())
.map(bytes -> BonsaiAccount.fromRLP(accumulator, address, bytes, true))
.orElse(null);
}
@Override
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
return getWorldStateStorage().getCode(codeHash, address.addressHash());
}
protected Optional<Bytes> getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) {
return worldStateKeyValueStorage.getAccountStateTrieNode(location, nodeHash);
return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash);
}
private void writeTrieNode(
@ -584,7 +383,7 @@ public class BonsaiWorldState
protected Optional<Bytes> getStorageTrieNode(
final Hash accountHash, final Bytes location, final Bytes32 nodeHash) {
return worldStateKeyValueStorage.getAccountStorageTrieNode(accountHash, location, nodeHash);
return getWorldStateStorage().getAccountStorageTrieNode(accountHash, location, nodeHash);
}
private void writeStorageTrieNode(
@ -605,7 +404,7 @@ public class BonsaiWorldState
@Override
public Optional<UInt256> getStorageValueByStorageSlotKey(
final Address address, final StorageSlotKey storageSlotKey) {
return worldStateKeyValueStorage
return getWorldStateStorage()
.getStorageValueByStorageSlotKey(address.addressHash(), storageSlotKey)
.map(UInt256::fromBytes);
}
@ -614,7 +413,7 @@ public class BonsaiWorldState
final Supplier<Optional<Hash>> storageRootSupplier,
final Address address,
final StorageSlotKey storageSlotKey) {
return worldStateKeyValueStorage
return getWorldStateStorage()
.getStorageValueByStorageSlotKey(storageRootSupplier, address.addressHash(), storageSlotKey)
.map(UInt256::fromBytes);
}
@ -632,50 +431,18 @@ public class BonsaiWorldState
return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE);
}
@Override
public MutableWorldState freeze() {
this.isFrozen = true;
this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(worldStateKeyValueStorage);
return this;
}
private StoredMerklePatriciaTrie<Bytes, Bytes> createTrie(
final NodeLoader nodeLoader, final Bytes32 rootHash) {
return new StoredMerklePatriciaTrie<>(
nodeLoader, rootHash, Function.identity(), Function.identity());
}
@Override
public void close() {
try {
if (!isPersisted()) {
this.worldStateKeyValueStorage.close();
if (isFrozen) {
closeFrozenStorage();
}
}
} catch (Exception e) {
// no op
}
}
private void closeFrozenStorage() {
try {
final BonsaiWorldStateLayerStorage worldStateLayerStorage =
(BonsaiWorldStateLayerStorage) worldStateKeyValueStorage;
if (!isPersisted(worldStateLayerStorage.getParentWorldStateStorage())) {
worldStateLayerStorage.getParentWorldStateStorage().close();
}
} catch (Exception e) {
// no op
}
}
protected Hash hashAndSavePreImage(final Bytes value) {
// by default do not save has preImages
return Hash.hash(value);
}
@Override
protected Hash getEmptyTrieHash() {
return Hash.EMPTY_TRIE_HASH;
}

@ -0,0 +1,98 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview;
import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.Consumer;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
public class BonsaiWorldStateUpdateAccumulator
extends DiffBasedWorldStateUpdateAccumulator<BonsaiAccount> {
public BonsaiWorldStateUpdateAccumulator(
final DiffBasedWorldView world,
final Consumer<DiffBasedValue<BonsaiAccount>> accountPreloader,
final Consumer<StorageSlotKey> storagePreloader,
final EvmConfiguration evmConfiguration) {
super(world, accountPreloader, storagePreloader, evmConfiguration);
}
@Override
public DiffBasedWorldStateUpdateAccumulator<BonsaiAccount> copy() {
final BonsaiWorldStateUpdateAccumulator copy =
new BonsaiWorldStateUpdateAccumulator(
wrappedWorldView(),
getAccountPreloader(),
getStoragePreloader(),
getEvmConfiguration());
copy.cloneFromUpdater(this);
return copy;
}
@Override
protected BonsaiAccount copyAccount(final BonsaiAccount account) {
return new BonsaiAccount(account);
}
@Override
protected BonsaiAccount copyAccount(
final BonsaiAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
return new BonsaiAccount(toCopy, context, mutable);
}
@Override
protected BonsaiAccount createAccount(
final DiffBasedWorldView context,
final Address address,
final AccountValue stateTrieAccount,
final boolean mutable) {
return new BonsaiAccount(context, address, stateTrieAccount, mutable);
}
@Override
protected BonsaiAccount createAccount(
final DiffBasedWorldView context,
final Address address,
final Hash addressHash,
final long nonce,
final Wei balance,
final Hash storageRoot,
final Hash codeHash,
final boolean mutable) {
return new BonsaiAccount(
context, address, addressHash, nonce, balance, storageRoot, codeHash, mutable);
}
@Override
protected BonsaiAccount createAccount(
final DiffBasedWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) {
return new BonsaiAccount(context, tracked);
}
@Override
protected void assertCloseEnoughForDiffing(
final BonsaiAccount source, final AccountValue account, final String context) {
BonsaiAccount.assertCloseEnoughForDiffing(source, account, context);
}
}

@ -0,0 +1,206 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common;
import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
import org.hyperledger.besu.evm.ModificationNotAllowedException;
import org.hyperledger.besu.evm.account.MutableAccount;
import java.util.HashMap;
import java.util.Map;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
public abstract class DiffBasedAccount implements MutableAccount, AccountValue {
protected final DiffBasedWorldView context;
protected boolean immutable;
protected final Address address;
protected final Hash addressHash;
protected Hash codeHash;
protected long nonce;
protected Wei balance;
protected Bytes code;
protected final Map<UInt256, UInt256> updatedStorage = new HashMap<>();
public DiffBasedAccount(
final DiffBasedWorldView context,
final Address address,
final Hash addressHash,
final long nonce,
final Wei balance,
final Hash codeHash,
final boolean mutable) {
this.context = context;
this.address = address;
this.addressHash = addressHash;
this.nonce = nonce;
this.balance = balance;
this.codeHash = codeHash;
this.immutable = !mutable;
}
public DiffBasedAccount(
final DiffBasedWorldView context,
final Address address,
final AccountValue stateTrieAccount,
final boolean mutable) {
this(
context,
address,
address.addressHash(),
stateTrieAccount.getNonce(),
stateTrieAccount.getBalance(),
stateTrieAccount.getCodeHash(),
mutable);
}
public DiffBasedAccount(
final DiffBasedAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
this.context = context;
this.address = toCopy.address;
this.addressHash = toCopy.addressHash;
this.nonce = toCopy.nonce;
this.balance = toCopy.balance;
this.codeHash = toCopy.codeHash;
this.code = toCopy.code;
updatedStorage.putAll(toCopy.updatedStorage);
this.immutable = !mutable;
}
@Override
public Address getAddress() {
return address;
}
@Override
public Hash getAddressHash() {
return addressHash;
}
@Override
public long getNonce() {
return nonce;
}
@Override
public void setNonce(final long value) {
if (immutable) {
throw new ModificationNotAllowedException();
}
nonce = value;
}
@Override
public Wei getBalance() {
return balance;
}
@Override
public void setBalance(final Wei value) {
if (immutable) {
throw new ModificationNotAllowedException();
}
balance = value;
}
@Override
public Bytes getCode() {
if (code == null) {
code = context.getCode(address, codeHash).orElse(Bytes.EMPTY);
}
return code;
}
@Override
public void setCode(final Bytes code) {
if (immutable) {
throw new ModificationNotAllowedException();
}
this.code = code;
if (code == null || code.isEmpty()) {
this.codeHash = Hash.EMPTY;
} else {
this.codeHash = Hash.hash(code);
}
}
@Override
public Hash getCodeHash() {
return codeHash;
}
@Override
public UInt256 getStorageValue(final UInt256 key) {
return context.getStorageValue(address, key);
}
@Override
public UInt256 getOriginalStorageValue(final UInt256 key) {
return context.getPriorStorageValue(address, key);
}
public Bytes serializeAccount() {
final BytesValueRLPOutput out = new BytesValueRLPOutput();
writeTo(out);
return out.encoded();
}
@Override
public void setStorageValue(final UInt256 key, final UInt256 value) {
if (immutable) {
throw new ModificationNotAllowedException();
}
updatedStorage.put(key, value);
}
@Override
public void clearStorage() {
updatedStorage.clear();
}
@Override
public Map<UInt256, UInt256> getUpdatedStorage() {
return updatedStorage;
}
@Override
public void becomeImmutable() {
immutable = true;
}
@Override
public String toString() {
return "AccountState{"
+ "address="
+ address
+ ", nonce="
+ nonce
+ ", balance="
+ balance
+ ", codeHash="
+ codeHash
+ '}';
}
}

@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@ -11,38 +11,37 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.common;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
public class DiffBasedValue<T> implements TrieLog.LogTuple<T> {
private T prior;
private T updated;
private boolean lastStepCleared;
private boolean clearedAtLeastOnce;
public BonsaiValue(final T prior, final T updated) {
public DiffBasedValue(final T prior, final T updated) {
this.prior = prior;
this.updated = updated;
this.lastStepCleared = false;
this.clearedAtLeastOnce = false;
}
public BonsaiValue(final T prior, final T updated, final boolean lastStepCleared) {
public DiffBasedValue(final T prior, final T updated, final boolean lastStepCleared) {
this.prior = prior;
this.updated = updated;
this.lastStepCleared = lastStepCleared;
this.clearedAtLeastOnce = lastStepCleared;
}
public BonsaiValue(
public DiffBasedValue(
final T prior,
final T updated,
final boolean lastStepCleared,
@ -63,12 +62,12 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
return updated;
}
public BonsaiValue<T> setPrior(final T prior) {
public DiffBasedValue<T> setPrior(final T prior) {
this.prior = prior;
return this;
}
public BonsaiValue<T> setUpdated(final T updated) {
public DiffBasedValue<T> setUpdated(final T updated) {
this.lastStepCleared = updated == null;
if (lastStepCleared) {
this.clearedAtLeastOnce = true;
@ -94,7 +93,7 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
@Override
public String toString() {
return "BonsaiValue{"
return "DiffBasedValue{"
+ "prior="
+ prior
+ ", updated="
@ -112,7 +111,7 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
if (o == null || getClass() != o.getClass()) {
return false;
}
BonsaiValue<?> that = (BonsaiValue<?>) o;
DiffBasedValue<?> that = (DiffBasedValue<?>) o;
return new EqualsBuilder()
.append(lastStepCleared, that.lastStepCleared)
.append(prior, that.prior)
@ -129,7 +128,7 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
.toHashCode();
}
public BonsaiValue<T> copy() {
return new BonsaiValue<T>(prior, updated, lastStepCleared, clearedAtLeastOnce);
public DiffBasedValue<T> copy() {
return new DiffBasedValue<T>(prior, updated, lastStepCleared, clearedAtLeastOnce);
}
}

@ -14,9 +14,7 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
import static org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager.RETAINED_LAYERS;
package org.hyperledger.besu.ethereum.trie.diffbased.common;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
@ -25,91 +23,75 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.proof.WorldStateProof;
import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.plugin.BesuContext;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import com.google.common.annotations.VisibleForTesting;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiWorldStateProvider implements WorldStateArchive {
public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
private static final Logger LOG = LoggerFactory.getLogger(DiffBasedWorldStateProvider.class);
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateProvider.class);
protected final Blockchain blockchain;
private final Blockchain blockchain;
protected final TrieLogManager trieLogManager;
protected DiffBasedCachedWorldStorageManager cachedWorldStorageManager;
protected DiffBasedWorldState persistedState;
private final CachedWorldStorageManager cachedWorldStorageManager;
private final TrieLogManager trieLogManager;
private final BonsaiWorldState persistedState;
private final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
private final CachedMerkleTrieLoader cachedMerkleTrieLoader;
protected final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage;
public BonsaiWorldStateProvider(
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
public DiffBasedWorldStateProvider(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final Blockchain blockchain,
final Optional<Long> maxLayersToLoad,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final BesuContext pluginContext,
final EvmConfiguration evmConfiguration) {
final BesuContext pluginContext) {
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.cachedWorldStorageManager = new CachedWorldStorageManager(this, worldStateKeyValueStorage);
// TODO: de-dup constructors
this.trieLogManager =
new TrieLogManager(
blockchain,
worldStateKeyValueStorage,
maxLayersToLoad.orElse(RETAINED_LAYERS),
maxLayersToLoad.orElse(DiffBasedCachedWorldStorageManager.RETAINED_LAYERS),
pluginContext);
this.blockchain = blockchain;
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
this.persistedState = new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration);
blockchain
.getBlockHeader(persistedState.getWorldStateBlockHash())
.ifPresent(
blockHeader ->
this.cachedWorldStorageManager.addCachedLayer(
blockHeader, persistedState.getWorldStateRootHash(), persistedState));
}
@VisibleForTesting
BonsaiWorldStateProvider(
final CachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
public DiffBasedWorldStateProvider(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final EvmConfiguration evmConfiguration) {
this.cachedWorldStorageManager = cachedWorldStorageManager;
final TrieLogManager trieLogManager) {
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
// TODO: de-dup constructors
this.trieLogManager = trieLogManager;
this.blockchain = blockchain;
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.persistedState = new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration);
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
}
protected void provideCachedWorldStorageManager(
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager) {
this.cachedWorldStorageManager = cachedWorldStorageManager;
}
protected void loadPersistedState(final DiffBasedWorldState persistedState) {
this.persistedState = persistedState;
blockchain
.getBlockHeader(persistedState.getWorldStateBlockHash())
.ifPresent(
@ -158,9 +140,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
.getWorldState(blockHeader.getHash())
.or(() -> cachedWorldStorageManager.getNearestWorldState(blockHeader))
.or(() -> cachedWorldStorageManager.getHeadWorldState(blockchain::getBlockHeader))
.flatMap(
bonsaiWorldState ->
rollMutableStateToBlockHash(bonsaiWorldState, blockHeader.getHash()))
.flatMap(worldState -> rollMutableStateToBlockHash(worldState, blockHeader.getHash()))
.map(MutableWorldState::freeze);
}
}
@ -172,7 +152,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
}
Optional<MutableWorldState> rollMutableStateToBlockHash(
final BonsaiWorldState mutableState, final Hash blockHash) {
final DiffBasedWorldState mutableState, final Hash blockHash) {
if (blockHash.equals(mutableState.blockHash())) {
return Optional.of(mutableState);
} else {
@ -221,19 +201,19 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
}
// attempt the state rolling
final BonsaiWorldStateUpdateAccumulator bonsaiUpdater =
(BonsaiWorldStateUpdateAccumulator) mutableState.updater();
final DiffBasedWorldStateUpdateAccumulator<?> diffBasedUpdater =
(DiffBasedWorldStateUpdateAccumulator<?>) mutableState.updater();
try {
for (final TrieLog rollBack : rollBacks) {
LOG.debug("Attempting Rollback of {}", rollBack.getBlockHash());
bonsaiUpdater.rollBack(rollBack);
diffBasedUpdater.rollBack(rollBack);
}
for (int i = rollForwards.size() - 1; i >= 0; i--) {
final var forward = rollForwards.get(i);
LOG.debug("Attempting Rollforward of {}", rollForwards.get(i).getBlockHash());
bonsaiUpdater.rollForward(forward);
diffBasedUpdater.rollForward(forward);
}
bonsaiUpdater.commit();
diffBasedUpdater.commit();
mutableState.persist(blockchain.getBlockHeader(blockHash).get());
@ -247,7 +227,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
throw re;
} catch (final Exception e) {
// if we fail we must clean up the updater
bonsaiUpdater.reset();
diffBasedUpdater.reset();
LOG.debug(
"State rolling failed on "
+ mutableState.getWorldStateStorage().getClass().getSimpleName()
@ -269,80 +249,16 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
}
}
public CachedMerkleTrieLoader getCachedMerkleTrieLoader() {
return cachedMerkleTrieLoader;
}
@Override
public MutableWorldState getMutable() {
return persistedState;
}
/**
* Prepares the state healing process for a given address and location. It prepares the state
* healing, including retrieving data from storage, identifying invalid slots or nodes, removing
* account and slot from the state trie, and committing the changes. Finally, it downgrades the
* world state storage to partial flat database mode.
*/
public void prepareStateHealing(final Address address, final Bytes location) {
final Set<Bytes> keysToDelete = new HashSet<>();
final BonsaiWorldStateKeyValueStorage.Updater updater = worldStateKeyValueStorage.updater();
final Hash accountHash = address.addressHash();
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
new StoredMerklePatriciaTrie<>(
(l, h) -> {
final Optional<Bytes> node = worldStateKeyValueStorage.getAccountStateTrieNode(l, h);
if (node.isPresent()) {
keysToDelete.add(l);
}
return node;
},
persistedState.getWorldStateRootHash(),
Function.identity(),
Function.identity());
try {
accountTrie
.get(accountHash)
.map(RLP::input)
.map(StateTrieAccountValue::readFrom)
.ifPresent(
account -> {
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
new StoredMerklePatriciaTrie<>(
(l, h) -> {
Optional<Bytes> node =
worldStateKeyValueStorage.getAccountStorageTrieNode(
accountHash, l, h);
if (node.isPresent()) {
keysToDelete.add(Bytes.concatenate(accountHash, l));
}
return node;
},
account.getStorageRoot(),
Function.identity(),
Function.identity());
try {
storageTrie.getPath(location);
} catch (Exception eA) {
LOG.warn("Invalid slot found for account {} at location {}", address, location);
// ignore
}
});
} catch (Exception eA) {
LOG.warn("Invalid node for account {} at location {}", address, location);
// ignore
}
keysToDelete.forEach(bytes -> updater.removeAccountStateTrieNode(bytes));
updater.commit();
worldStateKeyValueStorage.downgradeToPartialFlatDbMode();
}
public TrieLogManager getTrieLogManager() {
return trieLogManager;
}
public CachedWorldStorageManager getCachedWorldStorageManager() {
public DiffBasedCachedWorldStorageManager getCachedWorldStorageManager() {
return cachedWorldStorageManager;
}
@ -360,7 +276,8 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
final Address accountAddress,
final List<UInt256> accountStorageKeys,
final Function<Optional<WorldStateProof>, ? extends Optional<U>> mapper) {
try (BonsaiWorldState ws = (BonsaiWorldState) getMutable(blockHeader, false).orElse(null)) {
try (DiffBasedWorldState ws =
(DiffBasedWorldState) getMutable(blockHeader, false).orElse(null)) {
if (ws != null) {
final WorldStateProofProvider worldStateProofProvider =
new WorldStateProofProvider(

@ -0,0 +1,25 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common;
public interface StorageSubscriber {
default void onClearStorage() {}
default void onClearFlatDatabaseStorage() {}
default void onClearTrieLog() {}
default void onCloseStorage() {}
}

@ -12,15 +12,15 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
package org.hyperledger.besu.ethereum.trie.diffbased.common.cache;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.ArrayList;
@ -35,20 +35,20 @@ import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CachedWorldStorageManager
implements BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
public abstract class DiffBasedCachedWorldStorageManager implements StorageSubscriber {
public static final long RETAINED_LAYERS = 512; // at least 256 + typical rollbacks
private static final Logger LOG = LoggerFactory.getLogger(CachedWorldStorageManager.class);
private final BonsaiWorldStateProvider archive;
private static final Logger LOG =
LoggerFactory.getLogger(DiffBasedCachedWorldStorageManager.class);
private final DiffBasedWorldStateProvider archive;
private final EvmConfiguration evmConfiguration;
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
private final Map<Bytes32, CachedBonsaiWorldView> cachedWorldStatesByHash;
private final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
private final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash;
private CachedWorldStorageManager(
final BonsaiWorldStateProvider archive,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final Map<Bytes32, CachedBonsaiWorldView> cachedWorldStatesByHash,
private DiffBasedCachedWorldStorageManager(
final DiffBasedWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash,
final EvmConfiguration evmConfiguration) {
worldStateKeyValueStorage.subscribe(this);
this.rootWorldStateStorage = worldStateKeyValueStorage;
@ -57,32 +57,32 @@ public class CachedWorldStorageManager
this.evmConfiguration = evmConfiguration;
}
public CachedWorldStorageManager(
final BonsaiWorldStateProvider archive,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage) {
public DiffBasedCachedWorldStorageManager(
final DiffBasedWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
this(archive, worldStateKeyValueStorage, new ConcurrentHashMap<>(), EvmConfiguration.DEFAULT);
}
public synchronized void addCachedLayer(
final BlockHeader blockHeader,
final Hash worldStateRootHash,
final BonsaiWorldState forWorldState) {
final Optional<CachedBonsaiWorldView> cachedBonsaiWorldView =
final DiffBasedWorldState forWorldState) {
final Optional<DiffBasedCachedWorldView> cachedDiffBasedWorldView =
Optional.ofNullable(this.cachedWorldStatesByHash.get(blockHeader.getBlockHash()));
if (cachedBonsaiWorldView.isPresent()) {
if (cachedDiffBasedWorldView.isPresent()) {
// only replace if it is a layered storage
if (forWorldState.isPersisted()
&& cachedBonsaiWorldView.get().getWorldStateStorage()
instanceof BonsaiWorldStateLayerStorage) {
&& cachedDiffBasedWorldView.get().getWorldStateStorage()
instanceof DiffBasedLayeredWorldStateKeyValueStorage) {
LOG.atDebug()
.setMessage("updating layered world state for block {}, state root hash {}")
.addArgument(blockHeader::toLogString)
.addArgument(worldStateRootHash::toShortHexString)
.log();
cachedBonsaiWorldView
cachedDiffBasedWorldView
.get()
.updateWorldStateStorage(
new BonsaiSnapshotWorldStateKeyValueStorage(forWorldState.getWorldStateStorage()));
createSnapshotKeyValueStorage(forWorldState.getWorldStateStorage()));
}
} else {
LOG.atDebug()
@ -93,16 +93,16 @@ public class CachedWorldStorageManager
if (forWorldState.isPersisted()) {
cachedWorldStatesByHash.put(
blockHeader.getHash(),
new CachedBonsaiWorldView(
blockHeader,
new BonsaiSnapshotWorldStateKeyValueStorage(forWorldState.getWorldStateStorage())));
new DiffBasedCachedWorldView(
blockHeader, createSnapshotKeyValueStorage(forWorldState.getWorldStateStorage())));
} else {
// otherwise, add the layer to the cache
cachedWorldStatesByHash.put(
blockHeader.getHash(),
new CachedBonsaiWorldView(
new DiffBasedCachedWorldView(
blockHeader,
((BonsaiWorldStateLayerStorage) forWorldState.getWorldStateStorage()).clone()));
((DiffBasedLayeredWorldStateKeyValueStorage) forWorldState.getWorldStateStorage())
.clone()));
}
}
scrubCachedLayers(blockHeader.getNumber());
@ -122,15 +122,15 @@ public class CachedWorldStorageManager
}
}
public Optional<BonsaiWorldState> getWorldState(final Hash blockHash) {
public Optional<DiffBasedWorldState> getWorldState(final Hash blockHash) {
if (cachedWorldStatesByHash.containsKey(blockHash)) {
// return a new worldstate using worldstate storage and an isolated copy of the updater
return Optional.ofNullable(cachedWorldStatesByHash.get(blockHash))
.map(
cached ->
new BonsaiWorldState(
createWorldState(
archive,
new BonsaiWorldStateLayerStorage(cached.getWorldStateStorage()),
createLayeredKeyValueStorage(cached.getWorldStateStorage()),
evmConfiguration));
}
LOG.atDebug()
@ -141,7 +141,7 @@ public class CachedWorldStorageManager
return Optional.empty();
}
public Optional<BonsaiWorldState> getNearestWorldState(final BlockHeader blockHeader) {
public Optional<DiffBasedWorldState> getNearestWorldState(final BlockHeader blockHeader) {
LOG.atDebug()
.setMessage("getting nearest worldstate for {}")
.addArgument(blockHeader.toLogString())
@ -149,7 +149,7 @@ public class CachedWorldStorageManager
return Optional.ofNullable(
cachedWorldStatesByHash.get(blockHeader.getParentHash())) // search parent block
.map(CachedBonsaiWorldView::getWorldStateStorage)
.map(DiffBasedCachedWorldView::getWorldStateStorage)
.or(
() -> {
// or else search the nearest state in the cache
@ -158,22 +158,22 @@ public class CachedWorldStorageManager
.addArgument(blockHeader.toLogString())
.log();
final List<CachedBonsaiWorldView> cachedBonsaiWorldViews =
final List<DiffBasedCachedWorldView> cachedDiffBasedWorldViews =
new ArrayList<>(cachedWorldStatesByHash.values());
return cachedBonsaiWorldViews.stream()
return cachedDiffBasedWorldViews.stream()
.sorted(
Comparator.comparingLong(
view -> Math.abs(blockHeader.getNumber() - view.getBlockNumber())))
.map(CachedBonsaiWorldView::getWorldStateStorage)
.map(DiffBasedCachedWorldView::getWorldStateStorage)
.findFirst();
})
.map(
storage ->
new BonsaiWorldState( // wrap the state in a layered worldstate
archive, new BonsaiWorldStateLayerStorage(storage), evmConfiguration));
createWorldState( // wrap the state in a layered worldstate
archive, createLayeredKeyValueStorage(storage), evmConfiguration));
}
public Optional<BonsaiWorldState> getHeadWorldState(
public Optional<DiffBasedWorldState> getHeadWorldState(
final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) {
LOG.atDebug().setMessage("getting head worldstate").log();
@ -187,7 +187,7 @@ public class CachedWorldStorageManager
addCachedLayer(
blockHeader,
blockHeader.getStateRoot(),
new BonsaiWorldState(archive, rootWorldStateStorage, evmConfiguration));
createWorldState(archive, rootWorldStateStorage, evmConfiguration));
return getWorldState(blockHeader.getHash());
});
}
@ -219,4 +219,15 @@ public class CachedWorldStorageManager
public void onCloseStorage() {
this.cachedWorldStatesByHash.clear();
}
public abstract DiffBasedWorldState createWorldState(
final DiffBasedWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final EvmConfiguration evmConfiguration);
public abstract DiffBasedWorldStateKeyValueStorage createLayeredKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage);
public abstract DiffBasedWorldStateKeyValueStorage createSnapshotKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage);
}

@ -13,30 +13,30 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
package org.hyperledger.besu.ethereum.trie.diffbased.common.cache;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CachedBonsaiWorldView
implements BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
private BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
public class DiffBasedCachedWorldView implements StorageSubscriber {
private DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage;
private final BlockHeader blockHeader;
private long worldViewSubscriberId;
private static final Logger LOG = LoggerFactory.getLogger(CachedBonsaiWorldView.class);
private static final Logger LOG = LoggerFactory.getLogger(DiffBasedCachedWorldView.class);
public CachedBonsaiWorldView(
final BlockHeader blockHeader, final BonsaiWorldStateKeyValueStorage worldView) {
public DiffBasedCachedWorldView(
final BlockHeader blockHeader, final DiffBasedWorldStateKeyValueStorage worldView) {
this.blockHeader = blockHeader;
this.worldStateKeyValueStorage = worldView;
this.worldViewSubscriberId = worldStateKeyValueStorage.subscribe(this);
}
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
public DiffBasedWorldStateKeyValueStorage getWorldStateStorage() {
return worldStateKeyValueStorage;
}
@ -58,10 +58,10 @@ public class CachedBonsaiWorldView
}
public synchronized void updateWorldStateStorage(
final BonsaiWorldStateKeyValueStorage newWorldStateStorage) {
final DiffBasedWorldStateKeyValueStorage newWorldStateStorage) {
long newSubscriberId = newWorldStateStorage.subscribe(this);
this.worldStateKeyValueStorage.unSubscribe(this.worldViewSubscriberId);
BonsaiWorldStateKeyValueStorage oldWorldStateStorage = this.worldStateKeyValueStorage;
final DiffBasedWorldStateKeyValueStorage oldWorldStateStorage = this.worldStateKeyValueStorage;
this.worldStateKeyValueStorage = newWorldStateStorage;
this.worldViewSubscriberId = newSubscriberId;
try {

@ -0,0 +1,22 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage;
public interface DiffBasedLayeredWorldStateKeyValueStorage
extends DiffBasedSnapshotWorldStateKeyValueStorage {
DiffBasedWorldStateKeyValueStorage clone();
}

@ -0,0 +1,21 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage;
public interface DiffBasedSnapshotWorldStateKeyValueStorage {
DiffBasedWorldStateKeyValueStorage getParentWorldStateStorage();
}

@ -0,0 +1,234 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
import org.hyperledger.besu.util.Subscribers;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class DiffBasedWorldStateKeyValueStorage
implements WorldStateKeyValueStorage, AutoCloseable {
private static final Logger LOG =
LoggerFactory.getLogger(DiffBasedWorldStateKeyValueStorage.class);
// 0x776f726c64526f6f74
public static final byte[] WORLD_ROOT_HASH_KEY = "worldRoot".getBytes(StandardCharsets.UTF_8);
// 0x776f726c64426c6f636b48617368
public static final byte[] WORLD_BLOCK_HASH_KEY =
"worldBlockHash".getBytes(StandardCharsets.UTF_8);
private final AtomicBoolean shouldClose = new AtomicBoolean(false);
protected final AtomicBoolean isClosed = new AtomicBoolean(false);
protected final Subscribers<StorageSubscriber> subscribers = Subscribers.create();
protected final SegmentedKeyValueStorage composedWorldStateStorage;
protected final KeyValueStorage trieLogStorage;
public DiffBasedWorldStateKeyValueStorage(final StorageProvider provider) {
this.composedWorldStateStorage =
provider.getStorageBySegmentIdentifiers(
List.of(
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE));
this.trieLogStorage =
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE);
}
public DiffBasedWorldStateKeyValueStorage(
final SegmentedKeyValueStorage composedWorldStateStorage,
final KeyValueStorage trieLogStorage) {
this.composedWorldStateStorage = composedWorldStateStorage;
this.trieLogStorage = trieLogStorage;
}
public abstract FlatDbMode getFlatDbMode();
public abstract FlatDbStrategy getFlatDbStrategy();
@Override
public abstract DataStorageFormat getDataStorageFormat();
public SegmentedKeyValueStorage getComposedWorldStateStorage() {
return composedWorldStateStorage;
}
public KeyValueStorage getTrieLogStorage() {
return trieLogStorage;
}
public Optional<byte[]> getTrieLog(final Hash blockHash) {
return trieLogStorage.get(blockHash.toArrayUnsafe());
}
public Stream<byte[]> streamTrieLogKeys(final long limit) {
return trieLogStorage.streamKeys().limit(limit);
}
public Optional<Bytes> getStateTrieNode(final Bytes location) {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, location.toArrayUnsafe())
.map(Bytes::wrap);
}
public Optional<Bytes> getWorldStateRootHash() {
return composedWorldStateStorage.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY).map(Bytes::wrap);
}
public Optional<Hash> getWorldStateBlockHash() {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY)
.map(Bytes32::wrap)
.map(Hash::wrap);
}
public Map<Bytes32, Bytes> streamFlatAccounts(
final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
return getFlatDbStrategy()
.streamAccountFlatDatabase(composedWorldStateStorage, startKeyHash, endKeyHash, max);
}
public Map<Bytes32, Bytes> streamFlatStorages(
final Hash accountHash, final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
return getFlatDbStrategy()
.streamStorageFlatDatabase(
composedWorldStateStorage, accountHash, startKeyHash, endKeyHash, max);
}
public boolean isWorldStateAvailable(final Bytes32 rootHash, final Hash blockHash) {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY)
.map(Bytes32::wrap)
.map(hash -> hash.equals(rootHash) || trieLogStorage.containsKey(blockHash.toArrayUnsafe()))
.orElse(false);
}
@Override
public void clear() {
subscribers.forEach(StorageSubscriber::onClearStorage);
getFlatDbStrategy().clearAll(composedWorldStateStorage);
composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE);
trieLogStorage.clear();
}
public void clearTrieLog() {
subscribers.forEach(StorageSubscriber::onClearTrieLog);
trieLogStorage.clear();
}
public void clearFlatDatabase() {
subscribers.forEach(StorageSubscriber::onClearFlatDatabaseStorage);
getFlatDbStrategy().resetOnResync(composedWorldStateStorage);
}
@Override
public abstract Updater updater();
public boolean pruneTrieLog(final Hash blockHash) {
try {
return trieLogStorage.tryDelete(blockHash.toArrayUnsafe());
} catch (Exception e) {
LOG.error("Error pruning trie log for block hash {}", blockHash, e);
return false;
}
}
@Override
public synchronized void close() throws Exception {
// when the storage clears, close
shouldClose.set(true);
tryClose();
}
public synchronized long subscribe(final StorageSubscriber sub) {
if (isClosed.get()) {
throw new RuntimeException("Storage is marked to close or has already closed");
}
return subscribers.subscribe(sub);
}
public synchronized void unSubscribe(final long id) {
subscribers.unsubscribe(id);
try {
tryClose();
} catch (Exception e) {
LOG.atWarn()
.setMessage("exception while trying to close : {}")
.addArgument(e::getMessage)
.log();
}
}
protected synchronized void tryClose() throws Exception {
if (shouldClose.get() && subscribers.getSubscriberCount() < 1) {
doClose();
}
}
protected synchronized void doClose() throws Exception {
if (!isClosed.get()) {
// alert any subscribers we are closing:
subscribers.forEach(StorageSubscriber::onCloseStorage);
// close all of the KeyValueStorages:
composedWorldStateStorage.close();
trieLogStorage.close();
// set storage closed
isClosed.set(true);
}
}
public interface Updater extends WorldStateKeyValueStorage.Updater {
DiffBasedWorldStateKeyValueStorage.Updater saveWorldState(
final Bytes blockHash, final Bytes32 nodeHash, final Bytes node);
SegmentedKeyValueStorageTransaction getWorldStateTransaction();
KeyValueStorageTransaction getTrieLogStorageTransaction();
@Override
void commit();
void rollback();
}
}

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;

@ -13,11 +13,13 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FullFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.PartialFlatDbStrategy;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.plugin.services.MetricsSystem;

@ -12,12 +12,12 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import java.util.Optional;
@ -30,10 +30,10 @@ public class NoOpTrieLogManager extends TrieLogManager {
@Override
public synchronized void saveTrieLog(
final BonsaiWorldStateUpdateAccumulator localUpdater,
final DiffBasedWorldStateUpdateAccumulator<?> localUpdater,
final Hash forWorldStateRootHash,
final BlockHeader forBlockHeader,
final BonsaiWorldState forWorldState) {
final DiffBasedWorldState forWorldState) {
// notify trie log added observers, synchronously
TrieLog trieLog = trieLogFactory.create(localUpdater, forBlockHeader);
trieLogObservers.forEach(o -> o.onTrieLogAdded(new TrieLogAddedEvent(trieLog)));

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent;

@ -14,7 +14,7 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
import static com.google.common.base.Preconditions.checkState;
@ -22,7 +22,7 @@ import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import java.util.HashMap;
@ -49,21 +49,21 @@ public class TrieLogLayer implements TrieLog {
protected Hash blockHash;
protected Optional<Long> blockNumber = Optional.empty();
Map<Address, BonsaiValue<AccountValue>> getAccounts() {
Map<Address, DiffBasedValue<AccountValue>> getAccounts() {
return accounts;
}
Map<Address, BonsaiValue<Bytes>> getCode() {
Map<Address, DiffBasedValue<Bytes>> getCode() {
return code;
}
Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> getStorage() {
Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> getStorage() {
return storage;
}
protected final Map<Address, BonsaiValue<AccountValue>> accounts;
protected final Map<Address, BonsaiValue<Bytes>> code;
protected final Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> storage;
protected final Map<Address, DiffBasedValue<AccountValue>> accounts;
protected final Map<Address, DiffBasedValue<Bytes>> code;
protected final Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> storage;
protected boolean frozen = false;
public TrieLogLayer() {
@ -104,14 +104,14 @@ public class TrieLogLayer implements TrieLog {
public TrieLogLayer addAccountChange(
final Address address, final AccountValue oldValue, final AccountValue newValue) {
checkState(!frozen, "Layer is Frozen");
accounts.put(address, new BonsaiValue<>(oldValue, newValue));
accounts.put(address, new DiffBasedValue<>(oldValue, newValue));
return this;
}
public TrieLogLayer addCodeChange(
final Address address, final Bytes oldValue, final Bytes newValue, final Hash blockHash) {
checkState(!frozen, "Layer is Frozen");
code.put(address, new BonsaiValue<>(oldValue, newValue, newValue == null));
code.put(address, new DiffBasedValue<>(oldValue, newValue, newValue == null));
return this;
}
@ -123,22 +123,22 @@ public class TrieLogLayer implements TrieLog {
checkState(!frozen, "Layer is Frozen");
storage
.computeIfAbsent(address, a -> new TreeMap<>())
.put(slot, new BonsaiValue<>(oldValue, newValue));
.put(slot, new DiffBasedValue<>(oldValue, newValue));
return this;
}
@Override
public Map<Address, BonsaiValue<AccountValue>> getAccountChanges() {
public Map<Address, DiffBasedValue<AccountValue>> getAccountChanges() {
return accounts;
}
@Override
public Map<Address, BonsaiValue<Bytes>> getCodeChanges() {
public Map<Address, DiffBasedValue<Bytes>> getCodeChanges() {
return code;
}
@Override
public Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> getStorageChanges() {
public Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> getStorageChanges() {
return storage;
}
@ -147,18 +147,18 @@ public class TrieLogLayer implements TrieLog {
}
@Override
public Map<StorageSlotKey, BonsaiValue<UInt256>> getStorageChanges(final Address address) {
public Map<StorageSlotKey, DiffBasedValue<UInt256>> getStorageChanges(final Address address) {
return storage.getOrDefault(address, Map.of());
}
@Override
public Optional<Bytes> getPriorCode(final Address address) {
return Optional.ofNullable(code.get(address)).map(BonsaiValue::getPrior);
return Optional.ofNullable(code.get(address)).map(DiffBasedValue::getPrior);
}
@Override
public Optional<Bytes> getCode(final Address address) {
return Optional.ofNullable(code.get(address)).map(BonsaiValue::getUpdated);
return Optional.ofNullable(code.get(address)).map(DiffBasedValue::getUpdated);
}
@Override
@ -166,7 +166,7 @@ public class TrieLogLayer implements TrieLog {
final Address address, final StorageSlotKey storageSlotKey) {
return Optional.ofNullable(storage.get(address))
.map(i -> i.get(storageSlotKey))
.map(BonsaiValue::getPrior);
.map(DiffBasedValue::getPrior);
}
@Override
@ -174,24 +174,24 @@ public class TrieLogLayer implements TrieLog {
final Address address, final StorageSlotKey storageSlotKey) {
return Optional.ofNullable(storage.get(address))
.map(i -> i.get(storageSlotKey))
.map(BonsaiValue::getUpdated);
.map(DiffBasedValue::getUpdated);
}
@Override
public Optional<AccountValue> getPriorAccount(final Address address) {
return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getPrior);
return Optional.ofNullable(accounts.get(address)).map(DiffBasedValue::getPrior);
}
@Override
public Optional<AccountValue> getAccount(final Address address) {
return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getUpdated);
return Optional.ofNullable(accounts.get(address)).map(DiffBasedValue::getUpdated);
}
public String dump() {
final StringBuilder sb = new StringBuilder();
sb.append("TrieLog{" + "blockHash=").append(blockHash).append(frozen).append('}');
sb.append("accounts\n");
for (final Map.Entry<Address, BonsaiValue<AccountValue>> account : accounts.entrySet()) {
for (final Map.Entry<Address, DiffBasedValue<AccountValue>> account : accounts.entrySet()) {
sb.append(" : ").append(account.getKey()).append("\n");
if (Objects.equals(account.getValue().getPrior(), account.getValue().getUpdated())) {
sb.append(" = ").append(account.getValue().getUpdated()).append("\n");
@ -201,7 +201,7 @@ public class TrieLogLayer implements TrieLog {
}
}
sb.append("code").append("\n");
for (final Map.Entry<Address, BonsaiValue<Bytes>> code : code.entrySet()) {
for (final Map.Entry<Address, DiffBasedValue<Bytes>> code : code.entrySet()) {
sb.append(" : ").append(code.getKey()).append("\n");
if (Objects.equals(code.getValue().getPrior(), code.getValue().getUpdated())) {
sb.append(" = ").append(code.getValue().getPrior()).append("\n");
@ -211,10 +211,10 @@ public class TrieLogLayer implements TrieLog {
}
}
sb.append("Storage").append("\n");
for (final Map.Entry<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> storage :
for (final Map.Entry<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> storage :
storage.entrySet()) {
sb.append(" : ").append(storage.getKey()).append("\n");
for (final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> slot :
for (final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> slot :
storage.getValue().entrySet()) {
final UInt256 originalValue = slot.getValue().getPrior();
final UInt256 updatedValue = slot.getValue().getUpdated();

@ -13,14 +13,15 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.plugin.BesuContext;
import org.hyperledger.besu.plugin.services.TrieLogService;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
@ -41,7 +42,7 @@ public class TrieLogManager {
private static final Logger LOG = LoggerFactory.getLogger(TrieLogManager.class);
public static final long LOG_RANGE_LIMIT = 1000; // restrict trielog range queries to 1k logs
protected final Blockchain blockchain;
protected final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
protected final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
protected final long maxLayersToLoad;
protected final Subscribers<TrieLogEvent.TrieLogObserver> trieLogObservers = Subscribers.create();
@ -50,7 +51,7 @@ public class TrieLogManager {
public TrieLogManager(
final Blockchain blockchain,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final long maxLayersToLoad,
final BesuContext pluginContext) {
this.blockchain = blockchain;
@ -60,15 +61,15 @@ public class TrieLogManager {
}
public synchronized void saveTrieLog(
final BonsaiWorldStateUpdateAccumulator localUpdater,
final DiffBasedWorldStateUpdateAccumulator<?> localUpdater,
final Hash forWorldStateRootHash,
final BlockHeader forBlockHeader,
final BonsaiWorldState forWorldState) {
final DiffBasedWorldState forWorldState) {
// do not overwrite a trielog layer that already exists in the database.
// if it's only in memory we need to save it
// for example, in case of reorg we don't replace a trielog layer
if (rootWorldStateStorage.getTrieLog(forBlockHeader.getHash()).isEmpty()) {
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater =
final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater =
forWorldState.getWorldStateStorage().updater();
boolean success = false;
try {
@ -90,7 +91,7 @@ public class TrieLogManager {
}
private TrieLog prepareTrieLog(
final BlockHeader blockHeader, final BonsaiWorldStateUpdateAccumulator localUpdater) {
final BlockHeader blockHeader, final DiffBasedWorldStateUpdateAccumulator<?> localUpdater) {
LOG.atDebug()
.setMessage("Adding layered world state for {}")
.addArgument(blockHeader::toLogString)
@ -104,7 +105,7 @@ public class TrieLogManager {
final BlockHeader blockHeader,
final Hash worldStateRootHash,
final TrieLog trieLog,
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater) {
final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater) {
LOG.atDebug()
.setMessage("Persisting trie log for block hash {} and world state root {}")
.addArgument(blockHeader::toLogString)

@ -13,13 +13,13 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent;
import java.util.Comparator;
@ -41,7 +41,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
private final int pruningLimit;
private final int loadingLimit;
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
private final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
private final Blockchain blockchain;
private final Consumer<Runnable> executeAsync;
private final long numBlocksToRetain;
@ -51,7 +51,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
TreeMultimap.create(Comparator.reverseOrder(), Comparator.naturalOrder());
public TrieLogPruner(
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage,
final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage,
final Blockchain blockchain,
final Consumer<Runnable> executeAsync,
final long numBlocksToRetain,
@ -100,7 +100,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
}
}
void addToPruneQueue(final long blockNumber, final Hash blockHash) {
public void addToPruneQueue(final long blockNumber, final Hash blockHash) {
LOG.atTrace()
.setMessage("adding trie log to queue for later pruning blockNumber {}; blockHash {}")
.addArgument(blockNumber)
@ -109,7 +109,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
trieLogBlocksAndForksByDescendingBlockNumber.put(blockNumber, blockHash);
}
int pruneFromQueue() {
public int pruneFromQueue() {
final long retainAboveThisBlock = blockchain.getChainHeadBlockNumber() - numBlocksToRetain;
final Optional<Hash> finalized = blockchain.getFinalized();
if (requireFinalizedBlock && finalized.isEmpty()) {

@ -0,0 +1,334 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
import java.util.Optional;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class DiffBasedWorldState
implements MutableWorldState, DiffBasedWorldView, StorageSubscriber {
private static final Logger LOG = LoggerFactory.getLogger(DiffBasedWorldState.class);
protected DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage;
protected final DiffBasedCachedWorldStorageManager cachedWorldStorageManager;
protected final TrieLogManager trieLogManager;
protected DiffBasedWorldStateUpdateAccumulator<?> accumulator;
protected Hash worldStateRootHash;
protected Hash worldStateBlockHash;
protected boolean isFrozen;
protected DiffBasedWorldState(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager) {
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.worldStateRootHash =
Hash.wrap(
Bytes32.wrap(
worldStateKeyValueStorage.getWorldStateRootHash().orElse(getEmptyTrieHash())));
this.worldStateBlockHash =
Hash.wrap(
Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
this.cachedWorldStorageManager = cachedWorldStorageManager;
this.trieLogManager = trieLogManager;
}
/**
* Having a protected method to override the accumulator solves the chicken-egg problem of needing
* a worldstate reference (this) when construction the Accumulator.
*
* @param accumulator accumulator to use.
*/
public void setAccumulator(final DiffBasedWorldStateUpdateAccumulator<?> accumulator) {
this.accumulator = accumulator;
}
/**
* Returns the world state block hash of this world state
*
* @return the world state block hash.
*/
public Hash getWorldStateBlockHash() {
return worldStateBlockHash;
}
/**
* Returns the world state root hash of this world state
*
* @return the world state root hash.
*/
public Hash getWorldStateRootHash() {
return worldStateRootHash;
}
@Override
public boolean isPersisted() {
return isPersisted(worldStateKeyValueStorage);
}
private boolean isPersisted(final WorldStateKeyValueStorage worldStateKeyValueStorage) {
return !(worldStateKeyValueStorage instanceof DiffBasedSnapshotWorldStateKeyValueStorage);
}
/**
* Reset the worldState to this block header
*
* @param blockHeader block to use
*/
public void resetWorldStateTo(final BlockHeader blockHeader) {
worldStateBlockHash = blockHeader.getBlockHash();
worldStateRootHash = blockHeader.getStateRoot();
}
@Override
public DiffBasedWorldStateKeyValueStorage getWorldStateStorage() {
return worldStateKeyValueStorage;
}
public DiffBasedWorldStateUpdateAccumulator<?> getAccumulator() {
return accumulator;
}
@Override
public void persist(final BlockHeader blockHeader) {
final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader);
LOG.atDebug()
.setMessage("Persist world state for block {}")
.addArgument(maybeBlockHeader)
.log();
final DiffBasedWorldStateUpdateAccumulator<?> localCopy = accumulator.copy();
boolean success = false;
final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater =
worldStateKeyValueStorage.updater();
Runnable saveTrieLog = () -> {};
try {
final Hash newWorldStateRootHash =
calculateRootHash(isFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator);
// if we are persisted with a block header, and the prior state is the parent
// then persist the TrieLog for that transition.
// If specified but not a direct descendant simply store the new block hash.
if (blockHeader != null) {
verifyWorldStateRoot(newWorldStateRootHash, blockHeader);
saveTrieLog =
() -> {
trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this);
// not save a frozen state in the cache
if (!isFrozen) {
cachedWorldStorageManager.addCachedLayer(blockHeader, newWorldStateRootHash, this);
}
};
stateUpdater
.getWorldStateTransaction()
.put(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY, blockHeader.getHash().toArrayUnsafe());
worldStateBlockHash = blockHeader.getHash();
} else {
stateUpdater.getWorldStateTransaction().remove(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY);
worldStateBlockHash = null;
}
stateUpdater
.getWorldStateTransaction()
.put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, newWorldStateRootHash.toArrayUnsafe());
worldStateRootHash = newWorldStateRootHash;
success = true;
} finally {
if (success) {
stateUpdater.commit();
accumulator.reset();
saveTrieLog.run();
} else {
stateUpdater.rollback();
accumulator.reset();
}
}
}
protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) {
if (!calculatedStateRoot.equals(header.getStateRoot())) {
throw new RuntimeException(
"World State Root does not match expected value, header "
+ header.getStateRoot().toHexString()
+ " calculated "
+ calculatedStateRoot.toHexString());
}
}
@Override
public WorldUpdater updater() {
return accumulator;
}
@Override
public Hash rootHash() {
if (isFrozen && accumulator.isAccumulatorStateChanged()) {
worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy());
accumulator.resetAccumulatorStateChanged();
}
return Hash.wrap(worldStateRootHash);
}
protected static final KeyValueStorageTransaction noOpTx =
new KeyValueStorageTransaction() {
@Override
public void put(final byte[] key, final byte[] value) {
// no-op
}
@Override
public void remove(final byte[] key) {
// no-op
}
@Override
public void commit() throws StorageException {
// no-op
}
@Override
public void rollback() {
// no-op
}
};
protected static final SegmentedKeyValueStorageTransaction noOpSegmentedTx =
new SegmentedKeyValueStorageTransaction() {
@Override
public void put(
final SegmentIdentifier segmentIdentifier, final byte[] key, final byte[] value) {
// no-op
}
@Override
public void remove(final SegmentIdentifier segmentIdentifier, final byte[] key) {
// no-op
}
@Override
public void commit() throws StorageException {
// no-op
}
@Override
public void rollback() {
// no-op
}
};
public Hash blockHash() {
return worldStateBlockHash;
}
@Override
public Stream<StreamableAccount> streamAccounts(final Bytes32 startKeyHash, final int limit) {
throw new RuntimeException("storage format do not provide account streaming.");
}
@Override
public UInt256 getPriorStorageValue(final Address address, final UInt256 storageKey) {
return getStorageValue(address, storageKey);
}
@Override
public void close() {
try {
if (!isPersisted()) {
this.worldStateKeyValueStorage.close();
if (isFrozen) {
closeFrozenStorage();
}
}
} catch (Exception e) {
// no op
}
}
private void closeFrozenStorage() {
try {
final DiffBasedLayeredWorldStateKeyValueStorage worldStateLayerStorage =
(DiffBasedLayeredWorldStateKeyValueStorage) worldStateKeyValueStorage;
if (!isPersisted(worldStateLayerStorage.getParentWorldStateStorage())) {
worldStateLayerStorage.getParentWorldStateStorage().close();
}
} catch (Exception e) {
// no op
}
}
@Override
public abstract Hash frontierRootHash();
@Override
public abstract MutableWorldState freeze();
@Override
public abstract Account get(final Address address);
@Override
public abstract UInt256 getStorageValue(final Address address, final UInt256 storageKey);
@Override
public abstract Optional<UInt256> getStorageValueByStorageSlotKey(
final Address address, final StorageSlotKey storageSlotKey);
@Override
public abstract Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash);
protected abstract Hash calculateRootHash(
final Optional<DiffBasedWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final DiffBasedWorldStateUpdateAccumulator<?> worldStateUpdater);
protected abstract Hash getEmptyTrieHash();
}

@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@ -11,16 +11,15 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.evm.worldstate.WorldView;
@ -31,7 +30,7 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
public interface BonsaiWorldView extends WorldView {
public interface DiffBasedWorldView extends WorldView {
Optional<Bytes> getCode(Address address, final Hash codeHash);
@ -59,7 +58,7 @@ public interface BonsaiWorldView extends WorldView {
boolean isPersisted();
BonsaiWorldStateKeyValueStorage getWorldStateStorage();
DiffBasedWorldStateKeyValueStorage getWorldStateStorage();
WorldUpdater updater();
}

@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@ -11,10 +11,9 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator;
import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;
@ -23,9 +22,14 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.AccountConsumingMap;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.Consumer;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
@ -44,42 +48,40 @@ import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import javax.annotation.Nonnull;
import com.google.common.collect.ForwardingMap;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiWorldStateUpdateAccumulator
extends AbstractWorldUpdater<BonsaiWorldView, BonsaiAccount>
implements BonsaiWorldView, TrieLogAccumulator {
@SuppressWarnings("unchecked")
public abstract class DiffBasedWorldStateUpdateAccumulator<ACCOUNT extends DiffBasedAccount>
extends AbstractWorldUpdater<DiffBasedWorldView, ACCOUNT>
implements DiffBasedWorldView, TrieLogAccumulator {
private static final Logger LOG =
LoggerFactory.getLogger(BonsaiWorldStateUpdateAccumulator.class);
protected final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader;
LoggerFactory.getLogger(DiffBasedWorldStateUpdateAccumulator.class);
protected final Consumer<DiffBasedValue<ACCOUNT>> accountPreloader;
protected final Consumer<StorageSlotKey> storagePreloader;
private final AccountConsumingMap<BonsaiValue<BonsaiAccount>> accountsToUpdate;
private final Map<Address, BonsaiValue<Bytes>> codeToUpdate = new ConcurrentHashMap<>();
private final AccountConsumingMap<DiffBasedValue<ACCOUNT>> accountsToUpdate;
private final Map<Address, DiffBasedValue<Bytes>> codeToUpdate = new ConcurrentHashMap<>();
private final Set<Address> storageToClear = Collections.synchronizedSet(new HashSet<>());
protected final EvmConfiguration evmConfiguration;
// storage sub mapped by _hashed_ key. This is because in self_destruct calls we need to
// enumerate the old storage and delete it. Those are trie stored by hashed key by spec and the
// alternative was to keep a giant pre-image cache of the entire trie.
private final Map<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>
private final Map<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
storageToUpdate = new ConcurrentHashMap<>();
private final Map<UInt256, Hash> storageKeyHashLookup = new ConcurrentHashMap<>();
protected boolean isAccumulatorStateChanged;
public BonsaiWorldStateUpdateAccumulator(
final BonsaiWorldView world,
final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader,
public DiffBasedWorldStateUpdateAccumulator(
final DiffBasedWorldView world,
final Consumer<DiffBasedValue<ACCOUNT>> accountPreloader,
final Consumer<StorageSlotKey> storagePreloader,
final EvmConfiguration evmConfiguration) {
super(world, evmConfiguration);
@ -90,15 +92,7 @@ public class BonsaiWorldStateUpdateAccumulator
this.evmConfiguration = evmConfiguration;
}
public BonsaiWorldStateUpdateAccumulator copy() {
final BonsaiWorldStateUpdateAccumulator copy =
new BonsaiWorldStateUpdateAccumulator(
wrappedWorldView(), accountPreloader, storagePreloader, evmConfiguration);
copy.cloneFromUpdater(this);
return copy;
}
void cloneFromUpdater(final BonsaiWorldStateUpdateAccumulator source) {
protected void cloneFromUpdater(final DiffBasedWorldStateUpdateAccumulator<ACCOUNT> source) {
accountsToUpdate.putAll(source.getAccountsToUpdate());
codeToUpdate.putAll(source.codeToUpdate);
storageToClear.addAll(source.storageToClear);
@ -108,14 +102,25 @@ public class BonsaiWorldStateUpdateAccumulator
this.isAccumulatorStateChanged = true;
}
protected Consumer<DiffBasedValue<ACCOUNT>> getAccountPreloader() {
return accountPreloader;
}
protected Consumer<StorageSlotKey> getStoragePreloader() {
return storagePreloader;
}
protected EvmConfiguration getEvmConfiguration() {
return evmConfiguration;
}
@Override
public Account get(final Address address) {
return super.get(address);
}
@Override
protected UpdateTrackingAccount<BonsaiAccount> track(
final UpdateTrackingAccount<BonsaiAccount> account) {
protected UpdateTrackingAccount<ACCOUNT> track(final UpdateTrackingAccount<ACCOUNT> account) {
return super.track(account);
}
@ -126,21 +131,21 @@ public class BonsaiWorldStateUpdateAccumulator
@Override
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address);
if (bonsaiValue == null) {
bonsaiValue = new BonsaiValue<>(null, null);
accountsToUpdate.put(address, bonsaiValue);
} else if (bonsaiValue.getUpdated() != null) {
if (bonsaiValue.getUpdated().isEmpty()) {
return track(new UpdateTrackingAccount<>(bonsaiValue.getUpdated()));
DiffBasedValue<ACCOUNT> diffBasedValue = accountsToUpdate.get(address);
if (diffBasedValue == null) {
diffBasedValue = new DiffBasedValue<>(null, null);
accountsToUpdate.put(address, diffBasedValue);
} else if (diffBasedValue.getUpdated() != null) {
if (diffBasedValue.getUpdated().isEmpty()) {
return track(new UpdateTrackingAccount<>(diffBasedValue.getUpdated()));
} else {
throw new IllegalStateException("Cannot create an account when one already exists");
}
}
final BonsaiAccount newAccount =
new BonsaiAccount(
final ACCOUNT newAccount =
createAccount(
this,
address,
hashAndSaveAccountPreImage(address),
@ -149,17 +154,17 @@ public class BonsaiWorldStateUpdateAccumulator
Hash.EMPTY_TRIE_HASH,
Hash.EMPTY,
true);
bonsaiValue.setUpdated(newAccount);
diffBasedValue.setUpdated(newAccount);
return track(new UpdateTrackingAccount<>(newAccount));
}
@Override
public Map<Address, BonsaiValue<BonsaiAccount>> getAccountsToUpdate() {
public Map<Address, DiffBasedValue<ACCOUNT>> getAccountsToUpdate() {
return accountsToUpdate;
}
@Override
public Map<Address, BonsaiValue<Bytes>> getCodeToUpdate() {
public Map<Address, DiffBasedValue<Bytes>> getCodeToUpdate() {
return codeToUpdate;
}
@ -168,40 +173,41 @@ public class BonsaiWorldStateUpdateAccumulator
}
@Override
public Map<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>
public Map<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
getStorageToUpdate() {
return storageToUpdate;
}
@Override
protected BonsaiAccount getForMutation(final Address address) {
return loadAccount(address, BonsaiValue::getUpdated);
protected ACCOUNT getForMutation(final Address address) {
return loadAccount(address, DiffBasedValue::getUpdated);
}
protected BonsaiAccount loadAccount(
final Address address,
final Function<BonsaiValue<BonsaiAccount>, BonsaiAccount> bonsaiAccountFunction) {
protected ACCOUNT loadAccount(
final Address address, final Function<DiffBasedValue<ACCOUNT>, ACCOUNT> accountFunction) {
try {
final BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address);
if (bonsaiValue == null) {
final DiffBasedValue<ACCOUNT> diffBasedValue = accountsToUpdate.get(address);
if (diffBasedValue == null) {
final Account account;
if (wrappedWorldView()
instanceof BonsaiWorldStateUpdateAccumulator bonsaiWorldStateUpdateAccumulator) {
account = bonsaiWorldStateUpdateAccumulator.loadAccount(address, bonsaiAccountFunction);
if (wrappedWorldView() instanceof DiffBasedWorldStateUpdateAccumulator) {
final DiffBasedWorldStateUpdateAccumulator<ACCOUNT> worldStateUpdateAccumulator =
(DiffBasedWorldStateUpdateAccumulator<ACCOUNT>) wrappedWorldView();
account = worldStateUpdateAccumulator.loadAccount(address, accountFunction);
} else {
account = wrappedWorldView().get(address);
}
if (account instanceof BonsaiAccount bonsaiAccount) {
BonsaiAccount mutableAccount = new BonsaiAccount(bonsaiAccount, this, true);
accountsToUpdate.put(address, new BonsaiValue<>(bonsaiAccount, mutableAccount));
if (account instanceof DiffBasedAccount diffBasedAccount) {
ACCOUNT mutableAccount = copyAccount((ACCOUNT) diffBasedAccount, this, true);
accountsToUpdate.put(
address, new DiffBasedValue<>((ACCOUNT) diffBasedAccount, mutableAccount));
return mutableAccount;
} else {
// add the empty read in accountsToUpdate
accountsToUpdate.put(address, new BonsaiValue<>(null, null));
accountsToUpdate.put(address, new DiffBasedValue<>(null, null));
return null;
}
} else {
return bonsaiAccountFunction.apply(bonsaiValue);
return accountFunction.apply(diffBasedValue);
}
} catch (MerkleTrieException e) {
// need to throw to trigger the heal
@ -229,12 +235,12 @@ public class BonsaiWorldStateUpdateAccumulator
public void commit() {
this.isAccumulatorStateChanged = true;
for (final Address deletedAddress : getDeletedAccounts()) {
final BonsaiValue<BonsaiAccount> accountValue =
final DiffBasedValue<ACCOUNT> accountValue =
accountsToUpdate.computeIfAbsent(
deletedAddress,
__ -> loadAccountFromParent(deletedAddress, new BonsaiValue<>(null, null, true)));
__ -> loadAccountFromParent(deletedAddress, new DiffBasedValue<>(null, null, true)));
storageToClear.add(deletedAddress);
final BonsaiValue<Bytes> codeValue = codeToUpdate.get(deletedAddress);
final DiffBasedValue<Bytes> codeValue = codeToUpdate.get(deletedAddress);
if (codeValue != null) {
codeValue.setUpdated(null).setCleared();
} else {
@ -242,26 +248,27 @@ public class BonsaiWorldStateUpdateAccumulator
.getCode(
deletedAddress,
Optional.ofNullable(accountValue)
.map(BonsaiValue::getPrior)
.map(BonsaiAccount::getCodeHash)
.map(DiffBasedValue::getPrior)
.map(DiffBasedAccount::getCodeHash)
.orElse(Hash.EMPTY))
.ifPresent(
deletedCode ->
codeToUpdate.put(deletedAddress, new BonsaiValue<>(deletedCode, null, true)));
codeToUpdate.put(
deletedAddress, new DiffBasedValue<>(deletedCode, null, true)));
}
// mark all updated storage as to be cleared
final Map<StorageSlotKey, BonsaiValue<UInt256>> deletedStorageUpdates =
final Map<StorageSlotKey, DiffBasedValue<UInt256>> deletedStorageUpdates =
storageToUpdate.computeIfAbsent(
deletedAddress,
k ->
new StorageConsumingMap<>(
deletedAddress, new ConcurrentHashMap<>(), storagePreloader));
final Iterator<Map.Entry<StorageSlotKey, BonsaiValue<UInt256>>> iter =
final Iterator<Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>>> iter =
deletedStorageUpdates.entrySet().iterator();
while (iter.hasNext()) {
final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> updateEntry = iter.next();
final BonsaiValue<UInt256> updatedSlot = updateEntry.getValue();
final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> updateEntry = iter.next();
final DiffBasedValue<UInt256> updatedSlot = updateEntry.getValue();
if (updatedSlot.getPrior() == null || updatedSlot.getPrior().isZero()) {
iter.remove();
} else {
@ -269,7 +276,7 @@ public class BonsaiWorldStateUpdateAccumulator
}
}
final BonsaiAccount originalValue = accountValue.getPrior();
final ACCOUNT originalValue = accountValue.getPrior();
if (originalValue != null) {
// Enumerate and delete addresses not updated
wrappedWorldView()
@ -280,7 +287,8 @@ public class BonsaiWorldStateUpdateAccumulator
new StorageSlotKey(Hash.wrap(keyHash), Optional.empty());
if (!deletedStorageUpdates.containsKey(storageSlotKey)) {
final UInt256 value = UInt256.fromBytes(RLP.decodeOne(entryValue));
deletedStorageUpdates.put(storageSlotKey, new BonsaiValue<>(value, null, true));
deletedStorageUpdates.put(
storageSlotKey, new DiffBasedValue<>(value, null, true));
}
});
}
@ -294,11 +302,11 @@ public class BonsaiWorldStateUpdateAccumulator
.forEach(
tracked -> {
final Address updatedAddress = tracked.getAddress();
final BonsaiAccount updatedAccount;
final BonsaiValue<BonsaiAccount> updatedAccountValue =
final ACCOUNT updatedAccount;
final DiffBasedValue<ACCOUNT> updatedAccountValue =
accountsToUpdate.get(updatedAddress);
final Map<StorageSlotKey, BonsaiValue<UInt256>> pendingStorageUpdates =
final Map<StorageSlotKey, DiffBasedValue<UInt256>> pendingStorageUpdates =
storageToUpdate.computeIfAbsent(
updatedAddress,
k ->
@ -311,12 +319,12 @@ public class BonsaiWorldStateUpdateAccumulator
}
if (tracked.getWrappedAccount() == null) {
updatedAccount = new BonsaiAccount(this, tracked);
updatedAccount = createAccount(this, tracked);
tracked.setWrappedAccount(updatedAccount);
if (updatedAccountValue == null) {
accountsToUpdate.put(updatedAddress, new BonsaiValue<>(null, updatedAccount));
accountsToUpdate.put(updatedAddress, new DiffBasedValue<>(null, updatedAccount));
codeToUpdate.put(
updatedAddress, new BonsaiValue<>(null, updatedAccount.getCode()));
updatedAddress, new DiffBasedValue<>(null, updatedAccount.getCode()));
} else {
updatedAccountValue.setUpdated(updatedAccount);
}
@ -334,17 +342,17 @@ public class BonsaiWorldStateUpdateAccumulator
}
if (tracked.codeWasUpdated()) {
final BonsaiValue<Bytes> pendingCode =
final DiffBasedValue<Bytes> pendingCode =
codeToUpdate.computeIfAbsent(
updatedAddress,
addr ->
new BonsaiValue<>(
new DiffBasedValue<>(
wrappedWorldView()
.getCode(
addr,
Optional.ofNullable(updatedAccountValue)
.map(BonsaiValue::getPrior)
.map(BonsaiAccount::getCodeHash)
.map(DiffBasedValue::getPrior)
.map(DiffBasedAccount::getCodeHash)
.orElse(Hash.EMPTY))
.orElse(null),
null));
@ -368,12 +376,11 @@ public class BonsaiWorldStateUpdateAccumulator
final StorageSlotKey slotKey =
new StorageSlotKey(hashAndSaveSlotPreImage(keyUInt), Optional.of(keyUInt));
final UInt256 value = storageUpdate.getValue();
final BonsaiValue<UInt256> pendingValue = pendingStorageUpdates.get(slotKey);
final DiffBasedValue<UInt256> pendingValue = pendingStorageUpdates.get(slotKey);
if (pendingValue == null) {
pendingStorageUpdates.put(
slotKey,
new BonsaiValue<>(
new DiffBasedValue<>(
updatedAccount.getOriginalStorageValue(keyUInt), value));
} else {
pendingValue.setUpdated(value);
@ -394,7 +401,7 @@ public class BonsaiWorldStateUpdateAccumulator
@Override
public Optional<Bytes> getCode(final Address address, final Hash codeHash) {
final BonsaiValue<Bytes> localCode = codeToUpdate.get(address);
final DiffBasedValue<Bytes> localCode = codeToUpdate.get(address);
if (localCode == null) {
final Optional<Bytes> code = wrappedWorldView().getCode(address, codeHash);
if (code.isEmpty() && !codeHash.equals(Hash.EMPTY)) {
@ -417,31 +424,26 @@ public class BonsaiWorldStateUpdateAccumulator
@Override
public Optional<UInt256> getStorageValueByStorageSlotKey(
final Address address, final StorageSlotKey storageSlotKey) {
final Map<StorageSlotKey, BonsaiValue<UInt256>> localAccountStorage =
final Map<StorageSlotKey, DiffBasedValue<UInt256>> localAccountStorage =
storageToUpdate.get(address);
if (localAccountStorage != null) {
final BonsaiValue<UInt256> value = localAccountStorage.get(storageSlotKey);
final DiffBasedValue<UInt256> value = localAccountStorage.get(storageSlotKey);
if (value != null) {
return Optional.ofNullable(value.getUpdated());
}
}
try {
final Optional<UInt256> valueUInt =
(wrappedWorldView() instanceof BonsaiWorldState bonsaiWorldState)
? bonsaiWorldState.getStorageValueByStorageSlotKey(
() ->
Optional.ofNullable(loadAccount(address, BonsaiValue::getPrior))
.map(BonsaiAccount::getStorageRoot),
address,
storageSlotKey)
(wrappedWorldView() instanceof DiffBasedWorldState worldState)
? worldState.getStorageValueByStorageSlotKey(address, storageSlotKey)
: wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey);
storageToUpdate
.computeIfAbsent(
address,
key ->
new StorageConsumingMap<>(address, new ConcurrentHashMap<>(), storagePreloader))
.put(storageSlotKey, new BonsaiValue<>(valueUInt.orElse(null), valueUInt.orElse(null)));
.put(
storageSlotKey, new DiffBasedValue<>(valueUInt.orElse(null), valueUInt.orElse(null)));
return valueUInt;
} catch (MerkleTrieException e) {
// need to throw to trigger the heal
@ -455,10 +457,10 @@ public class BonsaiWorldStateUpdateAccumulator
// TODO maybe log the read into the trie layer?
StorageSlotKey storageSlotKey =
new StorageSlotKey(hashAndSaveSlotPreImage(storageKey), Optional.of(storageKey));
final Map<StorageSlotKey, BonsaiValue<UInt256>> localAccountStorage =
final Map<StorageSlotKey, DiffBasedValue<UInt256>> localAccountStorage =
storageToUpdate.get(address);
if (localAccountStorage != null) {
final BonsaiValue<UInt256> value = localAccountStorage.get(storageSlotKey);
final DiffBasedValue<UInt256> value = localAccountStorage.get(storageSlotKey);
if (value != null) {
if (value.isLastStepCleared()) {
return UInt256.ZERO;
@ -482,11 +484,11 @@ public class BonsaiWorldStateUpdateAccumulator
@Override
public Map<Bytes32, Bytes> getAllAccountStorage(final Address address, final Hash rootHash) {
final Map<Bytes32, Bytes> results = wrappedWorldView().getAllAccountStorage(address, rootHash);
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> bonsaiValueStorage =
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> diffBasedValueStorage =
storageToUpdate.get(address);
if (bonsaiValueStorage != null) {
if (diffBasedValueStorage != null) {
// hash the key to match the implied storage interface of hashed slotKey
bonsaiValueStorage.forEach(
diffBasedValueStorage.forEach(
(key, value) -> results.put(key.getSlotHash(), value.getUpdated()));
}
return results;
@ -498,7 +500,7 @@ public class BonsaiWorldStateUpdateAccumulator
}
@Override
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
public DiffBasedWorldStateKeyValueStorage getWorldStateStorage() {
return wrappedWorldView().getWorldStateStorage();
}
@ -550,7 +552,7 @@ public class BonsaiWorldStateUpdateAccumulator
// non-change, a cached read.
return;
}
BonsaiValue<BonsaiAccount> accountValue = accountsToUpdate.get(address);
DiffBasedValue<ACCOUNT> accountValue = accountsToUpdate.get(address);
if (accountValue == null) {
accountValue = loadAccountFromParent(address, accountValue);
}
@ -558,7 +560,7 @@ public class BonsaiWorldStateUpdateAccumulator
if (expectedValue == null && replacementValue != null) {
accountsToUpdate.put(
address,
new BonsaiValue<>(null, new BonsaiAccount(this, address, replacementValue, true)));
new DiffBasedValue<>(null, createAccount(this, address, replacementValue, true)));
} else {
throw new IllegalStateException(
String.format(
@ -572,7 +574,7 @@ public class BonsaiWorldStateUpdateAccumulator
"Expected to create account, but the account exists. Address=%s", address));
}
} else {
BonsaiAccount.assertCloseEnoughForDiffing(
assertCloseEnoughForDiffing(
accountValue.getUpdated(),
expectedValue,
"Address=" + address + " Prior Value in Rolling Change");
@ -586,19 +588,18 @@ public class BonsaiWorldStateUpdateAccumulator
accountValue.setUpdated(null);
}
} else {
accountValue.setUpdated(
new BonsaiAccount(wrappedWorldView(), address, replacementValue, true));
accountValue.setUpdated(createAccount(wrappedWorldView(), address, replacementValue, true));
}
}
}
private BonsaiValue<BonsaiAccount> loadAccountFromParent(
final Address address, final BonsaiValue<BonsaiAccount> defaultValue) {
private DiffBasedValue<ACCOUNT> loadAccountFromParent(
final Address address, final DiffBasedValue<ACCOUNT> defaultValue) {
try {
final Account parentAccount = wrappedWorldView().get(address);
if (parentAccount instanceof BonsaiAccount account) {
final BonsaiValue<BonsaiAccount> loadedAccountValue =
new BonsaiValue<>(new BonsaiAccount(account), account);
if (parentAccount instanceof DiffBasedAccount account) {
final DiffBasedValue<ACCOUNT> loadedAccountValue =
new DiffBasedValue<>(copyAccount((ACCOUNT) account), ((ACCOUNT) account));
accountsToUpdate.put(address, loadedAccountValue);
return loadedAccountValue;
} else {
@ -617,7 +618,7 @@ public class BonsaiWorldStateUpdateAccumulator
// non-change, a cached read.
return;
}
BonsaiValue<Bytes> codeValue = codeToUpdate.get(address);
DiffBasedValue<Bytes> codeValue = codeToUpdate.get(address);
if (codeValue == null) {
final Bytes storedCode =
wrappedWorldView()
@ -625,14 +626,14 @@ public class BonsaiWorldStateUpdateAccumulator
address, Optional.ofNullable(expectedCode).map(Hash::hash).orElse(Hash.EMPTY))
.orElse(Bytes.EMPTY);
if (!storedCode.isEmpty()) {
codeValue = new BonsaiValue<>(storedCode, storedCode);
codeValue = new DiffBasedValue<>(storedCode, storedCode);
codeToUpdate.put(address, codeValue);
}
}
if (codeValue == null) {
if ((expectedCode == null || expectedCode.isEmpty()) && replacementCode != null) {
codeToUpdate.put(address, new BonsaiValue<>(null, replacementCode));
codeToUpdate.put(address, new DiffBasedValue<>(null, replacementCode));
} else {
throw new IllegalStateException(
String.format(
@ -660,10 +661,10 @@ public class BonsaiWorldStateUpdateAccumulator
}
}
private Map<StorageSlotKey, BonsaiValue<UInt256>> maybeCreateStorageMap(
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageMap, final Address address) {
private Map<StorageSlotKey, DiffBasedValue<UInt256>> maybeCreateStorageMap(
final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageMap, final Address address) {
if (storageMap == null) {
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> newMap =
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> newMap =
new StorageConsumingMap<>(address, new ConcurrentHashMap<>(), storagePreloader);
storageToUpdate.put(address, newMap);
return newMap;
@ -685,13 +686,13 @@ public class BonsaiWorldStateUpdateAccumulator
// corner case on deletes, non-change
return;
}
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageMap = storageToUpdate.get(address);
BonsaiValue<UInt256> slotValue = storageMap == null ? null : storageMap.get(storageSlotKey);
final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageMap = storageToUpdate.get(address);
DiffBasedValue<UInt256> slotValue = storageMap == null ? null : storageMap.get(storageSlotKey);
if (slotValue == null) {
final Optional<UInt256> storageValue =
wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey);
if (storageValue.isPresent()) {
slotValue = new BonsaiValue<>(storageValue.get(), storageValue.get());
slotValue = new DiffBasedValue<>(storageValue.get(), storageValue.get());
storageToUpdate
.computeIfAbsent(
address,
@ -703,7 +704,7 @@ public class BonsaiWorldStateUpdateAccumulator
if (slotValue == null) {
if ((expectedValue == null || expectedValue.isZero()) && replacementValue != null) {
maybeCreateStorageMap(storageMap, address)
.put(storageSlotKey, new BonsaiValue<>(null, replacementValue));
.put(storageSlotKey, new DiffBasedValue<>(null, replacementValue));
} else {
throw new IllegalStateException(
String.format(
@ -730,7 +731,7 @@ public class BonsaiWorldStateUpdateAccumulator
existingSlotValue == null ? "null" : existingSlotValue.toShortHexString()));
}
if (replacementValue == null && slotValue.getPrior() == null) {
final Map<StorageSlotKey, BonsaiValue<UInt256>> thisStorageUpdate =
final Map<StorageSlotKey, DiffBasedValue<UInt256>> thisStorageUpdate =
maybeCreateStorageMap(storageMap, address);
thisStorageUpdate.remove(storageSlotKey);
if (thisStorageUpdate.isEmpty()) {
@ -769,67 +770,6 @@ public class BonsaiWorldStateUpdateAccumulator
storageKeyHashLookup.clear();
}
public static class AccountConsumingMap<T> extends ForwardingMap<Address, T> {
private final ConcurrentMap<Address, T> accounts;
private final Consumer<T> consumer;
public AccountConsumingMap(
final ConcurrentMap<Address, T> accounts, final Consumer<T> consumer) {
this.accounts = accounts;
this.consumer = consumer;
}
@Override
public T put(@Nonnull final Address address, @Nonnull final T value) {
consumer.process(address, value);
return accounts.put(address, value);
}
public Consumer<T> getConsumer() {
return consumer;
}
@Override
protected Map<Address, T> delegate() {
return accounts;
}
}
public static class StorageConsumingMap<K, T> extends ForwardingMap<K, T> {
private final Address address;
private final ConcurrentMap<K, T> storages;
private final Consumer<K> consumer;
public StorageConsumingMap(
final Address address, final ConcurrentMap<K, T> storages, final Consumer<K> consumer) {
this.address = address;
this.storages = storages;
this.consumer = consumer;
}
@Override
public T put(@Nonnull final K slotKey, @Nonnull final T value) {
consumer.process(address, slotKey);
return storages.put(slotKey, value);
}
public Consumer<K> getConsumer() {
return consumer;
}
@Override
protected Map<K, T> delegate() {
return storages;
}
}
public interface Consumer<T> {
void process(final Address address, T value);
}
protected Hash hashAndSaveAccountPreImage(final Address address) {
// no need to save account preimage by default
return Hash.hash(address);
@ -843,4 +783,33 @@ public class BonsaiWorldStateUpdateAccumulator
}
return hash;
}
public abstract DiffBasedWorldStateUpdateAccumulator<ACCOUNT> copy();
protected abstract ACCOUNT copyAccount(final ACCOUNT account);
protected abstract ACCOUNT copyAccount(
final ACCOUNT toCopy, final DiffBasedWorldView context, final boolean mutable);
protected abstract ACCOUNT createAccount(
final DiffBasedWorldView context,
final Address address,
final AccountValue stateTrieAccount,
final boolean mutable);
protected abstract ACCOUNT createAccount(
final DiffBasedWorldView context,
final Address address,
final Hash addressHash,
final long nonce,
final Wei balance,
final Hash storageRoot,
final Hash codeHash,
final boolean mutable);
protected abstract ACCOUNT createAccount(
final DiffBasedWorldView context, final UpdateTrackingAccount<ACCOUNT> tracked);
protected abstract void assertCloseEnoughForDiffing(
final ACCOUNT source, final AccountValue account, final String context);
}

@ -0,0 +1,49 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload;
import org.hyperledger.besu.datatypes.Address;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import javax.annotation.Nonnull;
import com.google.common.collect.ForwardingMap;
public class AccountConsumingMap<T> extends ForwardingMap<Address, T> {
private final ConcurrentMap<Address, T> accounts;
private final Consumer<T> consumer;
public AccountConsumingMap(final ConcurrentMap<Address, T> accounts, final Consumer<T> consumer) {
this.accounts = accounts;
this.consumer = consumer;
}
@Override
public T put(@Nonnull final Address address, @Nonnull final T value) {
consumer.process(address, value);
return accounts.put(address, value);
}
public Consumer<T> getConsumer() {
return consumer;
}
@Override
protected Map<Address, T> delegate() {
return accounts;
}
}

@ -0,0 +1,21 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload;
import org.hyperledger.besu.datatypes.Address;
public interface Consumer<T> {
void process(final Address address, T value);
}

@ -0,0 +1,53 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload;
import org.hyperledger.besu.datatypes.Address;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import javax.annotation.Nonnull;
import com.google.common.collect.ForwardingMap;
public class StorageConsumingMap<K, T> extends ForwardingMap<K, T> {
private final Address address;
private final ConcurrentMap<K, T> storages;
private final Consumer<K> consumer;
public StorageConsumingMap(
final Address address, final ConcurrentMap<K, T> storages, final Consumer<K> consumer) {
this.address = address;
this.storages = storages;
this.consumer = consumer;
}
@Override
public T put(@Nonnull final K slotKey, @Nonnull final T value) {
consumer.process(address, slotKey);
return storages.put(slotKey, value);
}
public Consumer<K> getConsumer() {
return consumer;
}
@Override
protected Map<K, T> delegate() {
return storages;
}
}

@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.worldstate;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;

@ -25,9 +25,9 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKey
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState;
@ -95,15 +95,15 @@ public class InMemoryKeyValueStorageProvider extends KeyValueStorageProvider {
final Blockchain blockchain, final EvmConfiguration evmConfiguration) {
final InMemoryKeyValueStorageProvider inMemoryKeyValueStorageProvider =
new InMemoryKeyValueStorageProvider();
final CachedMerkleTrieLoader cachedMerkleTrieLoader =
new CachedMerkleTrieLoader(new NoOpMetricsSystem());
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
return new BonsaiWorldStateProvider(
(BonsaiWorldStateKeyValueStorage)
inMemoryKeyValueStorageProvider.createWorldStateStorage(
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
blockchain,
Optional.empty(),
cachedMerkleTrieLoader,
bonsaiCachedMerkleTrieLoader,
null,
evmConfiguration);
}

@ -20,7 +20,7 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -41,9 +41,9 @@ 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.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain;
import static org.mockito.ArgumentMatchers.any;
@ -66,8 +66,8 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
@ -159,7 +159,7 @@ public abstract class AbstractIsolationTests {
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage,
blockchain,
Optional.of(16L),
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
null,
EvmConfiguration.DEFAULT);
var ws = archive.getMutable();

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import static org.assertj.core.api.Assertions.assertThat;
@ -26,8 +26,8 @@ import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
@ -45,9 +45,9 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
class CachedMerkleTrieLoaderTest {
class BonsaiCachedMerkleTrieLoaderTest {
private CachedMerkleTrieLoader merkleTrieLoader;
private BonsaiCachedMerkleTrieLoader merkleTrieLoader;
private final StorageProvider storageProvider = new InMemoryKeyValueStorageProvider();
private final BonsaiWorldStateKeyValueStorage inMemoryWorldState =
Mockito.spy(
@ -69,7 +69,7 @@ class CachedMerkleTrieLoaderTest {
TrieGenerator.generateTrie(
worldStateStorageCoordinator,
accounts.stream().map(Address::addressHash).collect(Collectors.toList()));
merkleTrieLoader = new CachedMerkleTrieLoader(new NoOpMetricsSystem());
merkleTrieLoader = new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
}
@Test

@ -14,7 +14,7 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@ -13,13 +13,13 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.BLOCKCHAIN;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
@ -36,13 +36,13 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
@ -77,7 +77,7 @@ class BonsaiWorldStateProviderTest {
@Mock SegmentedKeyValueStorageTransaction segmentedKeyValueStorageTransaction;
BonsaiWorldStateProvider bonsaiWorldStateArchive;
@Mock CachedWorldStorageManager cachedWorldStorageManager;
@Mock BonsaiCachedWorldStorageManager cachedWorldStorageManager;
@Mock TrieLogManager trieLogManager;
@BeforeEach
@ -111,7 +111,7 @@ class BonsaiWorldStateProviderTest {
new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT);
assertThat(bonsaiWorldStateArchive.getMutable(chainHead, true))
@ -128,7 +128,7 @@ class BonsaiWorldStateProviderTest {
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
blockchain,
Optional.of(512L),
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
null,
EvmConfiguration.DEFAULT);
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
@ -150,7 +150,7 @@ class BonsaiWorldStateProviderTest {
new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT);
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
final BlockHeader chainHead = blockBuilder.number(511).buildHeader();
@ -185,7 +185,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
worldStateKeyValueStorage,
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
@ -214,7 +214,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
worldStateKeyValueStorage,
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
@ -254,7 +254,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
worldStateKeyValueStorage,
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
// initial persisted state hash key
@ -297,7 +297,7 @@ class BonsaiWorldStateProviderTest {
new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
// initial persisted state hash key

@ -14,7 +14,7 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@ -29,11 +29,11 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.internal.EvmConfiguration;

@ -14,7 +14,7 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import static com.google.common.base.Preconditions.checkArgument;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
@ -25,11 +25,11 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIden
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;

@ -12,11 +12,11 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@ -24,6 +24,7 @@ import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.spy;
@ -22,9 +22,10 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.concurrent.atomic.AtomicBoolean;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@ -26,7 +26,10 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import java.util.Optional;
import java.util.function.Consumer;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
@ -23,8 +23,8 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.HashMap;
@ -69,8 +69,8 @@ class BonsaiWorldStateTest {
@MethodSource("priorAndUpdatedEmptyAndNullBytes")
void codeUpdateDoesNothingWhenMarkedAsDeletedButAlreadyDeleted(
final Bytes prior, final Bytes updated) {
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
Map.of(Address.ZERO, new BonsaiValue<>(prior, updated));
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
Map.of(Address.ZERO, new DiffBasedValue<>(prior, updated));
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
@ -79,8 +79,8 @@ class BonsaiWorldStateTest {
@Test
void codeUpdateDoesNothingWhenAddingSameAsExistingValue() {
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
Map.of(Address.ZERO, new BonsaiValue<>(CODE, CODE));
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
Map.of(Address.ZERO, new DiffBasedValue<>(CODE, CODE));
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
@ -90,8 +90,8 @@ class BonsaiWorldStateTest {
@ParameterizedTest
@MethodSource("emptyAndNullBytes")
void removesCodeWhenMarkedAsDeleted(final Bytes updated) {
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
Map.of(Address.ZERO, new BonsaiValue<>(CODE, updated));
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
Map.of(Address.ZERO, new DiffBasedValue<>(CODE, updated));
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
@ -101,8 +101,8 @@ class BonsaiWorldStateTest {
@ParameterizedTest
@MethodSource("codeValueAndEmptyAndNullBytes")
void addsCodeForNewCodeValue(final Bytes prior) {
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
Map.of(ACCOUNT, new BonsaiValue<>(prior, CODE));
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
Map.of(ACCOUNT, new DiffBasedValue<>(prior, CODE));
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
@ -112,10 +112,10 @@ class BonsaiWorldStateTest {
@Test
void updateCodeForMultipleValues() {
final Map<Address, BonsaiValue<Bytes>> codeToUpdate = new HashMap<>();
codeToUpdate.put(Address.fromHexString("0x1"), new BonsaiValue<>(null, CODE));
codeToUpdate.put(Address.fromHexString("0x2"), new BonsaiValue<>(CODE, null));
codeToUpdate.put(Address.fromHexString("0x3"), new BonsaiValue<>(Bytes.of(9), CODE));
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate = new HashMap<>();
codeToUpdate.put(Address.fromHexString("0x1"), new DiffBasedValue<>(null, CODE));
codeToUpdate.put(Address.fromHexString("0x2"), new DiffBasedValue<>(CODE, null));
codeToUpdate.put(Address.fromHexString("0x3"), new DiffBasedValue<>(Bytes.of(9), CODE));
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);

@ -13,13 +13,15 @@
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FullFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.PartialFlatDbStrategy;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;

@ -66,6 +66,7 @@ public class ForestKeyValueStorageWorldStateStorageTest {
storage.updater().putCode(MerkleTrie.EMPTY_TRIE_NODE).putCode(Bytes.EMPTY).commit();
assertThat(storage.getCode(Hash.EMPTY_TRIE_HASH)).contains(MerkleTrie.EMPTY_TRIE_NODE);
assertThat(storage.getCode(Hash.EMPTY)).contains(Bytes.EMPTY);
}

@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.eth.sync.state.PendingBlocksManager;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.metrics.BesuMetricCategory;

@ -21,7 +21,7 @@ import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader;
import org.hyperledger.besu.ethereum.eth.sync.TrailingPeerRequirements;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import org.hyperledger.besu.services.tasks.TaskCollection;

@ -20,7 +20,7 @@ import static org.hyperledger.besu.ethereum.eth.sync.StorageExceptionManager.get
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.TrieNodeHealingRequest;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.plugin.services.exception.StorageException;

@ -30,7 +30,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.AccountFlatD
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.StorageFlatDatabaseHealingRangeRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldDownloadState;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -28,7 +28,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.AccountRangeDataR
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.plugin.services.MetricsSystem;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.trie.NodeUpdater;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.trie.CompactEncoding;
import org.hyperledger.besu.ethereum.trie.NodeUpdater;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -36,7 +36,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.ImmutableCheckpoint;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.worldstate.FastDownloaderFactory;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.worldstate.FastWorldState
import org.hyperledger.besu.ethereum.eth.sync.fastsync.worldstate.NodeDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -26,7 +26,7 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.eth.manager.task.EthTask;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -22,7 +22,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.trie.patricia.StoredNodeFactory;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;

@ -25,7 +25,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.AccountRangeDataR
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.BytecodeRequest;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.StorageRangeDataRequest;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -39,7 +39,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.BytecodeRequest;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
@ -51,6 +51,7 @@ public class TaskGenerator {
new InMemoryKeyValueStorageProvider(),
new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
final WorldStateStorageCoordinator worldStateStorageCoordinator =
new WorldStateStorageCoordinator(worldStateKeyValueStorage);

@ -29,7 +29,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeManager;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
@ -89,7 +89,6 @@ class StorageFlatDatabaseHealingRangeRequestTest {
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
worldStateStorageCoordinator = new WorldStateStorageCoordinator(worldStateKeyValueStorage);
proofProvider = new WorldStateProofProvider(worldStateStorageCoordinator);
trie =
TrieGenerator.generateTrie(
worldStateStorageCoordinator,

@ -21,7 +21,7 @@ import org.hyperledger.besu.ethereum.core.TrieGenerator;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;

@ -17,11 +17,13 @@ package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.Consumer;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.concurrent.ConcurrentHashMap;
@ -32,8 +34,8 @@ public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdate
private final BonsaiPreImageProxy preImageProxy;
public BonsaiReferenceTestUpdateAccumulator(
final BonsaiWorldView world,
final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader,
final DiffBasedWorldView world,
final Consumer<DiffBasedValue<BonsaiAccount>> accountPreloader,
final Consumer<StorageSlotKey> storagePreloader,
final BonsaiPreImageProxy preImageProxy,
final EvmConfiguration evmConfiguration) {
@ -65,7 +67,7 @@ public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdate
getStorageToUpdate()
.forEach(
(k, v) -> {
StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> newMap =
StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> newMap =
new StorageConsumingMap<>(k, new ConcurrentHashMap<>(), v.getConsumer());
v.forEach((key, value) -> newMap.put(key, value.copy()));
copy.getStorageToUpdate().put(k, newMap);

@ -18,16 +18,18 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.NoOpCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogAddedEvent;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.NoOpBonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@ -54,14 +56,14 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
protected BonsaiReferenceTestWorldState(
final BonsaiReferenceTestWorldStateStorage worldStateKeyValueStorage,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final CachedWorldStorageManager cachedWorldStorageManager,
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager,
final BonsaiPreImageProxy preImageProxy,
final EvmConfiguration evmConfiguration) {
super(
worldStateKeyValueStorage,
cachedMerkleTrieLoader,
bonsaiCachedMerkleTrieLoader,
cachedWorldStorageManager,
trieLogManager,
evmConfiguration);
@ -72,21 +74,21 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
new BonsaiReferenceTestUpdateAccumulator(
this,
(addr, value) ->
cachedMerkleTrieLoader.preLoadAccount(
bonsaiCachedMerkleTrieLoader.preLoadAccount(
getWorldStateStorage(), worldStateRootHash, addr),
(addr, value) ->
cachedMerkleTrieLoader.preLoadStorageSlot(getWorldStateStorage(), addr, value),
bonsaiCachedMerkleTrieLoader.preLoadStorageSlot(
getWorldStateStorage(), addr, value),
preImageProxy,
evmConfiguration));
}
@Override
public ReferenceTestWorldState copy() {
var layerCopy =
new BonsaiReferenceTestWorldStateStorage(worldStateKeyValueStorage, preImageProxy);
var layerCopy = new BonsaiReferenceTestWorldStateStorage(getWorldStateStorage(), preImageProxy);
return new BonsaiReferenceTestWorldState(
layerCopy,
cachedMerkleTrieLoader,
bonsaiCachedMerkleTrieLoader,
cachedWorldStorageManager,
trieLogManager,
preImageProxy,
@ -187,8 +189,9 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
private BonsaiWorldState createBonsaiWorldState(final boolean isFrozen) {
BonsaiWorldState bonsaiWorldState =
new BonsaiWorldState(
new BonsaiWorldStateLayerStorage(worldStateKeyValueStorage),
cachedMerkleTrieLoader,
new BonsaiWorldStateLayerStorage(
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage),
bonsaiCachedMerkleTrieLoader,
cachedWorldStorageManager,
trieLogManager,
evmConfiguration);
@ -209,8 +212,11 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
final Map<String, ReferenceTestWorldState.AccountMock> accounts,
final EvmConfiguration evmConfiguration) {
final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem();
final CachedMerkleTrieLoader cachedMerkleTrieLoader = new CachedMerkleTrieLoader(metricsSystem);
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
new BonsaiCachedMerkleTrieLoader(metricsSystem);
final TrieLogManager trieLogManager = new ReferenceTestsInMemoryTrieLogManager();
final BonsaiPreImageProxy preImageProxy =
new BonsaiPreImageProxy.BonsaiReferenceTestPreImageProxy();
@ -223,13 +229,13 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
final BonsaiReferenceTestWorldStateStorage worldStateKeyValueStorage =
new BonsaiReferenceTestWorldStateStorage(bonsaiWorldStateKeyValueStorage, preImageProxy);
final NoOpCachedWorldStorageManager noOpCachedWorldStorageManager =
new NoOpCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage);
final NoOpBonsaiCachedWorldStorageManager noOpCachedWorldStorageManager =
new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage);
final BonsaiReferenceTestWorldState worldState =
new BonsaiReferenceTestWorldState(
worldStateKeyValueStorage,
cachedMerkleTrieLoader,
bonsaiCachedMerkleTrieLoader,
noOpCachedWorldStorageManager,
trieLogManager,
preImageProxy,
@ -260,10 +266,10 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
@Override
public synchronized void saveTrieLog(
final BonsaiWorldStateUpdateAccumulator localUpdater,
final DiffBasedWorldStateUpdateAccumulator<?> localUpdater,
final Hash forWorldStateRootHash,
final BlockHeader forBlockHeader,
final BonsaiWorldState forWorldState) {
final DiffBasedWorldState forWorldState) {
// notify trie log added observers, synchronously
TrieLog trieLog = trieLogFactory.create(localUpdater, forBlockHeader);
trieLogCache.put(forBlockHeader.getHash(), trieLogFactory.serialize(trieLog));

@ -16,11 +16,11 @@ package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
import org.hyperledger.besu.evm.account.AccountStorageEntry;
import org.hyperledger.besu.evm.worldstate.WorldState;
@ -64,7 +64,7 @@ public class BonsaiReferenceTestWorldStateStorage extends BonsaiWorldStateLayerS
}
public Stream<WorldState.StreamableAccount> streamAccounts(
final BonsaiWorldView context, final Bytes32 startKeyHash, final int limit) {
final DiffBasedWorldView context, final Bytes32 startKeyHash, final int limit) {
return streamFlatAccounts(startKeyHash, UInt256.MAX_VALUE, limit)
.entrySet()
// map back to addresses using preImage provider:

Loading…
Cancel
Save