add diffbased for bonsai

Signed-off-by: Karim Taam <karim.t2am@gmail.com>
pull/6920/head
Karim Taam 11 months ago
parent a368a353d8
commit 2ce37aea5e
  1. 8
      besu/src/main/java/org/hyperledger/besu/components/BesuComponent.java
  2. 16
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  3. 8
      besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java
  4. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/AccountAdapter.java
  5. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java
  6. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/storage/keyvalue/KeyValueStorageProvider.java
  7. 187
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiAccount.java
  8. 39
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java
  9. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedMerkleTrieLoader.java
  10. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedMerkleTrieLoaderModule.java
  11. 60
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java
  12. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiPreImageProxy.java
  13. 13
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java
  14. 182
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiWorldStateKeyValueStorage.java
  15. 13
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiWorldStateLayerStorage.java
  16. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/flat/FlatDbStrategy.java
  17. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/flat/FullFlatDbStrategy.java
  18. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/flat/PartialFlatDbStrategy.java
  19. 17
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/trielog/TrieLogFactoryImpl.java
  20. 359
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java
  21. 98
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java
  22. 219
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedAccount.java
  23. 14
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedValue.java
  24. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/StorageSubscriber.java
  25. 91
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java
  26. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldView.java
  27. 21
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedLayeredWorldStateKeyValueStorage.java
  28. 18
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedSnapshotWorldStateKeyValueStorage.java
  29. 246
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedWorldStateKeyValueStorage.java
  30. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogAddedEvent.java
  31. 50
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogLayer.java
  32. 23
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java
  33. 18
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogPruner.java
  34. 352
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java
  35. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldView.java
  36. 301
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java
  37. 50
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/preload/AccountConsumingMap.java
  38. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/preload/Consumer.java
  39. 54
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/preload/StorageConsumingMap.java
  40. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageFormat.java
  41. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/WorldStateStorageCoordinator.java
  42. 12
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/InMemoryKeyValueStorageProvider.java
  43. 2
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TrieGenerator.java
  44. 6
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java
  45. 9
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/AbstractIsolationTests.java
  46. 37
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/BonsaiWorldStateProviderTest.java
  47. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/CachedMerkleTrieLoaderTest.java
  48. 11
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/LogRollingTests.java
  49. 11
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/RollingImport.java
  50. 3
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/storage/BonsaiWorldStateKeyValueStorageTest.java
  51. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/TrieLogFactoryTests.java
  52. 1
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/TrieLogLayerTests.java
  53. 9
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/TrieLogManagerTests.java
  54. 3
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/bonsai/trielog/TrieLogPrunerTest.java
  55. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java
  56. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java
  57. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/PersistDataStep.java
  58. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapWorldDownloadState.java
  59. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapWorldStateDownloader.java
  60. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/AccountRangeDataRequest.java
  61. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/StorageRangeDataRequest.java
  62. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/AccountFlatDatabaseHealingRangeRequest.java
  63. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/StorageFlatDatabaseHealingRangeRequest.java
  64. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointSyncChainDownloaderTest.java
  65. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastDownloaderFactoryTest.java
  66. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloaderTest.java
  67. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldDownloadStateTest.java
  68. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/LoadLocalDataStepTest.java
  69. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/AccountHealingTrackingTest.java
  70. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapWorldDownloadStateTest.java
  71. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/AccountFlatDatabaseHealingRangeRequestTest.java
  72. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/StorageFlatDatabaseHealingRangeRequestTest.java
  73. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/request/heal/StorageTrieNodeHealingRequestTest.java
  74. 15
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestUpdateAccumulator.java
  75. 40
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java
  76. 12
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldStateStorage.java

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

@ -80,10 +80,10 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
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.bonsai.trielog.TrieLogPruner; 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.ForestWorldStateArchive;
import org.hyperledger.besu.ethereum.trie.forest.pruner.MarkSweepPruner; import org.hyperledger.besu.ethereum.trie.forest.pruner.MarkSweepPruner;
import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner; import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner;
@ -611,10 +611,10 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
dataDirectory.toString(), dataDirectory.toString(),
numberOfBlocksToCache); numberOfBlocksToCache);
final CachedMerkleTrieLoader cachedMerkleTrieLoader = final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader =
besuComponent besuComponent
.map(BesuComponent::getCachedMerkleTrieLoader) .map(BesuComponent::getCachedMerkleTrieLoader)
.orElseGet(() -> new CachedMerkleTrieLoader(metricsSystem)); .orElseGet(() -> new BonsaiCachedMerkleTrieLoader(metricsSystem));
final WorldStateArchive worldStateArchive = final WorldStateArchive worldStateArchive =
createWorldStateArchive(worldStateStorageCoordinator, blockchain, cachedMerkleTrieLoader); createWorldStateArchive(worldStateStorageCoordinator, blockchain, cachedMerkleTrieLoader);
@ -1065,7 +1065,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
WorldStateArchive createWorldStateArchive( WorldStateArchive createWorldStateArchive(
final WorldStateStorageCoordinator worldStateStorageCoordinator, final WorldStateStorageCoordinator worldStateStorageCoordinator,
final Blockchain blockchain, final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader) { final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader) {
return switch (dataStorageConfiguration.getDataStorageFormat()) { return switch (dataStorageConfiguration.getDataStorageFormat()) {
case BONSAI -> { case BONSAI -> {
final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get(); final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get();
@ -1099,6 +1099,8 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
yield new ForestWorldStateArchive( yield new ForestWorldStateArchive(
worldStateStorageCoordinator, preimageStorage, evmConfiguration); worldStateStorageCoordinator, preimageStorage, evmConfiguration);
} }
default -> throw new IllegalStateException(
"Unexpected value: " + dataStorageConfiguration.getDataStorageFormat());
}; };
} }

@ -42,9 +42,9 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
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.bonsai.worldview.BonsaiWorldState; 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.pruner.PrunerConfiguration;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
@ -174,7 +174,7 @@ public class BesuControllerBuilderTest {
.createWorldStateArchive( .createWorldStateArchive(
any(WorldStateStorageCoordinator.class), any(WorldStateStorageCoordinator.class),
any(Blockchain.class), any(Blockchain.class),
any(CachedMerkleTrieLoader.class)); any(BonsaiCachedMerkleTrieLoader.class));
doReturn(mockWorldState).when(worldStateArchive).getMutable(); doReturn(mockWorldState).when(worldStateArchive).getMutable();
when(storageProvider.createWorldStateStorageCoordinator(DataStorageFormat.BONSAI)) when(storageProvider.createWorldStateStorageCoordinator(DataStorageFormat.BONSAI))

@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter;
import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; 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.Account;
import org.hyperledger.besu.evm.account.AccountState; 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.privacy.storage.PrivateMetadataUpdater;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.tracing.OperationTracer;

@ -19,7 +19,7 @@ import org.hyperledger.besu.ethereum.chain.VariablesStorage;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.storage.StorageProvider; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -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.AccountValue;
import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei; 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.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPException; import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput; 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.ModificationNotAllowedException;
import org.hyperledger.besu.evm.account.AccountStorageEntry; import org.hyperledger.besu.evm.account.AccountStorageEntry;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount; import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
import java.util.HashMap;
import java.util.Map;
import java.util.NavigableMap; import java.util.NavigableMap;
import java.util.Objects; import java.util.Objects;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
public class BonsaiAccount implements MutableAccount, AccountValue { public class BonsaiAccount extends DiffBasedAccount {
private final BonsaiWorldView context;
private boolean immutable;
private final Address address;
private final Hash addressHash;
private Hash codeHash;
private long nonce;
private Wei balance;
private Hash storageRoot; private Hash storageRoot;
private Bytes code;
private final Map<UInt256, UInt256> updatedStorage = new HashMap<>();
public BonsaiAccount( public BonsaiAccount(
final BonsaiWorldView context, final DiffBasedWorldView context,
final Address address, final Address address,
final Hash addressHash, final Hash addressHash,
final long nonce, final long nonce,
@ -63,31 +49,24 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
final Hash storageRoot, final Hash storageRoot,
final Hash codeHash, final Hash codeHash,
final boolean mutable) { final boolean mutable) {
this.context = context; super(context, address, addressHash, nonce, balance, codeHash, !mutable);
this.address = address;
this.addressHash = addressHash;
this.nonce = nonce;
this.balance = balance;
this.storageRoot = storageRoot; this.storageRoot = storageRoot;
this.codeHash = codeHash;
this.immutable = !mutable;
} }
public BonsaiAccount( public BonsaiAccount(
final BonsaiWorldView context, final DiffBasedWorldView context,
final Address address, final Address address,
final AccountValue stateTrieAccount, final AccountValue stateTrieAccount,
final boolean mutable) { final boolean mutable) {
this( super(
context, context,
address, address,
address.addressHash(), address.addressHash(),
stateTrieAccount.getNonce(), stateTrieAccount.getNonce(),
stateTrieAccount.getBalance(), stateTrieAccount.getBalance(),
stateTrieAccount.getStorageRoot(),
stateTrieAccount.getCodeHash(), stateTrieAccount.getCodeHash(),
mutable); !mutable);
this.storageRoot = stateTrieAccount.getStorageRoot();
} }
public BonsaiAccount(final BonsaiAccount toCopy) { public BonsaiAccount(final BonsaiAccount toCopy) {
@ -95,37 +74,35 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
} }
public BonsaiAccount( public BonsaiAccount(
final BonsaiAccount toCopy, final BonsaiWorldView context, final boolean mutable) { final BonsaiAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
this.context = context; super(
this.address = toCopy.address; context,
this.addressHash = toCopy.addressHash; toCopy.address,
this.nonce = toCopy.nonce; toCopy.addressHash,
this.balance = toCopy.balance; toCopy.nonce,
toCopy.balance,
toCopy.codeHash,
!mutable);
this.storageRoot = toCopy.storageRoot; this.storageRoot = toCopy.storageRoot;
this.codeHash = toCopy.codeHash;
this.code = toCopy.code;
updatedStorage.putAll(toCopy.updatedStorage); updatedStorage.putAll(toCopy.updatedStorage);
this.immutable = !mutable;
} }
public BonsaiAccount( public BonsaiAccount(
final BonsaiWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) { final DiffBasedWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) {
this.context = context; super(
this.address = tracked.getAddress(); context,
this.addressHash = tracked.getAddressHash(); tracked.getAddress(),
this.nonce = tracked.getNonce(); tracked.getAddressHash(),
this.balance = tracked.getBalance(); tracked.getNonce(),
tracked.getBalance(),
tracked.getCodeHash(),
false);
this.storageRoot = Hash.EMPTY_TRIE_HASH; this.storageRoot = Hash.EMPTY_TRIE_HASH;
this.codeHash = tracked.getCodeHash();
this.code = tracked.getCode();
updatedStorage.putAll(tracked.getUpdatedStorage()); updatedStorage.putAll(tracked.getUpdatedStorage());
this.immutable = false;
} }
public static BonsaiAccount fromRLP( public static BonsaiAccount fromRLP(
final BonsaiWorldView context, final DiffBasedWorldView context,
final Address address, final Address address,
final Bytes encoded, final Bytes encoded,
final boolean mutable) final boolean mutable)
@ -144,88 +121,11 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
context, address, address.addressHash(), nonce, balance, storageRoot, codeHash, mutable); 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 @Override
public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom( public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
final Bytes32 startKeyHash, final int limit) { final Bytes32 startKeyHash, final int limit) {
return context.getWorldStateStorage().storageEntriesFrom(this.addressHash, startKeyHash, limit); return ((BonsaiWorldStateKeyValueStorage) context.getWorldStateStorage())
} .storageEntriesFrom(this.addressHash, startKeyHash, limit);
public Bytes serializeAccount() {
final BytesValueRLPOutput out = new BytesValueRLPOutput();
writeTo(out);
return out.encoded();
} }
@Override @Override
@ -240,24 +140,6 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
out.endList(); 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 @Override
public Hash getStorageRoot() { public Hash getStorageRoot() {
return storageRoot; return storageRoot;
@ -270,11 +152,6 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
this.storageRoot = storageRoot; this.storageRoot = storageRoot;
} }
@Override
public void becomeImmutable() {
immutable = true;
}
@Override @Override
public String toString() { public String toString() {
return "AccountState{" return "AccountState{"

@ -14,9 +14,7 @@
* *
*/ */
package org.hyperledger.besu.ethereum.trie.bonsai; package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
import static org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager.RETAINED_LAYERS;
import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
@ -27,13 +25,13 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProof;
import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider; import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
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.bonsai.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
@ -63,17 +61,17 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
private final Blockchain blockchain; private final Blockchain blockchain;
private final CachedWorldStorageManager cachedWorldStorageManager; private final BonsaiCachedWorldStorageManager cachedWorldStorageManager;
private final TrieLogManager trieLogManager; private final TrieLogManager trieLogManager;
private final BonsaiWorldState persistedState; private final BonsaiWorldState persistedState;
private final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage; private final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
private final CachedMerkleTrieLoader cachedMerkleTrieLoader; private final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader;
public BonsaiWorldStateProvider( public BonsaiWorldStateProvider(
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final Blockchain blockchain, final Blockchain blockchain,
final Optional<Long> maxLayersToLoad, final Optional<Long> maxLayersToLoad,
final CachedMerkleTrieLoader cachedMerkleTrieLoader, final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader,
final ObservableMetricsSystem metricsSystem, final ObservableMetricsSystem metricsSystem,
final BesuContext pluginContext, final BesuContext pluginContext,
final EvmConfiguration evmConfiguration, final EvmConfiguration evmConfiguration,
@ -81,13 +79,13 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
this.worldStateKeyValueStorage = worldStateKeyValueStorage; this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.cachedWorldStorageManager = this.cachedWorldStorageManager =
new CachedWorldStorageManager(this, worldStateKeyValueStorage, metricsSystem); new BonsaiCachedWorldStorageManager(this, worldStateKeyValueStorage, metricsSystem);
// TODO: de-dup constructors // TODO: de-dup constructors
this.trieLogManager = this.trieLogManager =
new TrieLogManager( new TrieLogManager(
blockchain, blockchain,
worldStateKeyValueStorage, worldStateKeyValueStorage,
maxLayersToLoad.orElse(RETAINED_LAYERS), maxLayersToLoad.orElse(BonsaiCachedWorldStorageManager.RETAINED_LAYERS),
pluginContext, pluginContext,
trieLogPruner); trieLogPruner);
this.blockchain = blockchain; this.blockchain = blockchain;
@ -103,11 +101,11 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
@VisibleForTesting @VisibleForTesting
BonsaiWorldStateProvider( BonsaiWorldStateProvider(
final CachedWorldStorageManager cachedWorldStorageManager, final BonsaiCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager, final TrieLogManager trieLogManager,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final Blockchain blockchain, final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader, final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration) {
this.cachedWorldStorageManager = cachedWorldStorageManager; this.cachedWorldStorageManager = cachedWorldStorageManager;
this.trieLogManager = trieLogManager; this.trieLogManager = trieLogManager;
@ -165,7 +163,8 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
.or(() -> cachedWorldStorageManager.getHeadWorldState(blockchain::getBlockHeader)) .or(() -> cachedWorldStorageManager.getHeadWorldState(blockchain::getBlockHeader))
.flatMap( .flatMap(
bonsaiWorldState -> bonsaiWorldState ->
rollMutableStateToBlockHash(bonsaiWorldState, blockHeader.getHash())) rollMutableStateToBlockHash(
(BonsaiWorldState) bonsaiWorldState, blockHeader.getHash()))
.map(MutableWorldState::freeze); .map(MutableWorldState::freeze);
} }
} }
@ -274,7 +273,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
} }
} }
public CachedMerkleTrieLoader getCachedMerkleTrieLoader() { public BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader() {
return cachedMerkleTrieLoader; return cachedMerkleTrieLoader;
} }
@ -347,7 +346,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
return trieLogManager; return trieLogManager;
} }
public CachedWorldStorageManager getCachedWorldStorageManager() { public BonsaiCachedWorldStorageManager getCachedWorldStorageManager() {
return cachedWorldStorageManager; return cachedWorldStorageManager;
} }

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

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0 * 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; import org.hyperledger.besu.metrics.ObservableMetricsSystem;
@ -21,11 +21,11 @@ import dagger.Module;
import dagger.Provides; import dagger.Provides;
@Module @Module
public class CachedMerkleTrieLoaderModule { public class BonsaiCachedMerkleTrieLoaderModule {
@Provides @Provides
CachedMerkleTrieLoader provideCachedMerkleTrieLoaderModule( BonsaiCachedMerkleTrieLoader provideCachedMerkleTrieLoaderModule(
final ObservableMetricsSystem metricsSystem) { 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.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;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager {
public BonsaiCachedWorldStorageManager(
final BonsaiWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final ObservableMetricsSystem metricsSystem) {
super(archive, worldStateKeyValueStorage, metricsSystem);
}
@Override
public DiffBasedWorldState<?> createWorldState(
final BonsaiWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final EvmConfiguration evmConfiguration) {
return new BonsaiWorldState(
archive, (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage, evmConfiguration);
}
@Override
public DiffBasedWorldStateKeyValueStorage createLayeredKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
return new BonsaiWorldStateLayerStorage(
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage);
}
@Override
public DiffBasedWorldStateKeyValueStorage createSnapshotKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final ObservableMetricsSystem metricsSystem) {
return new BonsaiSnapshotWorldStateKeyValueStorage(
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage, metricsSystem);
}
}

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0 * 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.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;

@ -13,11 +13,12 @@
* SPDX-License-Identifier: Apache-2.0 * 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.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey; 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.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
@ -33,7 +34,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKeyValueStorage public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKeyValueStorage
implements BonsaiStorageSubscriber { implements DiffBasedSnapshotWorldStateKeyValueStorage, StorageSubscriber {
protected final BonsaiWorldStateKeyValueStorage parentWorldStateStorage; protected final BonsaiWorldStateKeyValueStorage parentWorldStateStorage;
private static final Logger LOG = private static final Logger LOG =
@ -60,9 +61,9 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
final ObservableMetricsSystem metricsSystem) { final ObservableMetricsSystem metricsSystem) {
this( this(
worldStateKeyValueStorage, worldStateKeyValueStorage,
((SnappableKeyValueStorage) worldStateKeyValueStorage.composedWorldStateStorage) ((SnappableKeyValueStorage) worldStateKeyValueStorage.getComposedWorldStateStorage())
.takeSnapshot(), .takeSnapshot(),
worldStateKeyValueStorage.trieLogStorage, worldStateKeyValueStorage.getTrieLogStorage(),
metricsSystem); metricsSystem);
} }
@ -215,7 +216,7 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
protected synchronized void doClose() throws Exception { protected synchronized void doClose() throws Exception {
if (!isClosedGet()) { if (!isClosedGet()) {
// alert any subscribers we are closing: // alert any subscribers we are closing:
subscribers.forEach(BonsaiStorageSubscriber::onCloseStorage); subscribers.forEach(StorageSubscriber::onCloseStorage);
// close all of the SnappedKeyValueStorages: // close all of the SnappedKeyValueStorages:
composedWorldStateStorage.close(); composedWorldStateStorage.close();

@ -12,7 +12,7 @@
* *
* SPDX-License-Identifier: Apache-2.0 * 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_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
@ -24,9 +24,10 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FlatDbStrategy; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FullFlatDbStrategy; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FullFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.PartialFlatDbStrategy; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.PartialFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode; import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
@ -37,57 +38,34 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage; import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction; import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
import org.hyperledger.besu.util.Subscribers;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.NavigableMap; import java.util.NavigableMap;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorage, AutoCloseable { public class BonsaiWorldStateKeyValueStorage extends DiffBasedWorldStateKeyValueStorage
implements WorldStateKeyValueStorage {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateKeyValueStorage.class); 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);
// 0x666C61744462537461747573
public static final byte[] FLAT_DB_MODE = "flatDbStatus".getBytes(StandardCharsets.UTF_8); public static final byte[] FLAT_DB_MODE = "flatDbStatus".getBytes(StandardCharsets.UTF_8);
protected FlatDbMode flatDbMode; protected FlatDbMode flatDbMode;
protected FlatDbStrategy flatDbStrategy; protected FlatDbStrategy flatDbStrategy;
protected final SegmentedKeyValueStorage composedWorldStateStorage;
protected final KeyValueStorage trieLogStorage;
protected final ObservableMetricsSystem metricsSystem;
private final AtomicBoolean shouldClose = new AtomicBoolean(false);
protected final AtomicBoolean isClosed = new AtomicBoolean(false);
protected final Subscribers<BonsaiStorageSubscriber> subscribers = Subscribers.create();
public BonsaiWorldStateKeyValueStorage( public BonsaiWorldStateKeyValueStorage(
final StorageProvider provider, final ObservableMetricsSystem metricsSystem) { final StorageProvider provider, final ObservableMetricsSystem metricsSystem) {
this.composedWorldStateStorage = super(
provider.getStorageBySegmentIdentifiers( provider.getStorageBySegmentIdentifiers(
List.of( List.of(
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE)); ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE)),
this.trieLogStorage = provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE),
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE); metricsSystem);
this.metricsSystem = metricsSystem;
loadFlatDbStrategy(); loadFlatDbStrategy();
} }
@ -97,11 +75,9 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
final SegmentedKeyValueStorage composedWorldStateStorage, final SegmentedKeyValueStorage composedWorldStateStorage,
final KeyValueStorage trieLogStorage, final KeyValueStorage trieLogStorage,
final ObservableMetricsSystem metricsSystem) { final ObservableMetricsSystem metricsSystem) {
super(composedWorldStateStorage, trieLogStorage, metricsSystem);
this.flatDbMode = flatDbMode; this.flatDbMode = flatDbMode;
this.flatDbStrategy = flatDbStrategy; this.flatDbStrategy = flatDbStrategy;
this.composedWorldStateStorage = composedWorldStateStorage;
this.trieLogStorage = trieLogStorage;
this.metricsSystem = metricsSystem;
} }
private void loadFlatDbStrategy() { private void loadFlatDbStrategy() {
@ -131,6 +107,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return flatDbMode; return flatDbMode;
} }
@Override
public FlatDbStrategy getFlatDbStrategy() { public FlatDbStrategy getFlatDbStrategy() {
if (flatDbStrategy == null) { if (flatDbStrategy == null) {
loadFlatDbStrategy(); loadFlatDbStrategy();
@ -143,6 +120,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return DataStorageFormat.BONSAI; return DataStorageFormat.BONSAI;
} }
@Override
public FlatDbMode getFlatDbMode() { public FlatDbMode getFlatDbMode() {
return flatDbMode; return flatDbMode;
} }
@ -193,31 +171,6 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
.map(Bytes::wrap); .map(Bytes::wrap);
} }
public Optional<byte[]> getTrieLog(final Hash blockHash) {
return trieLogStorage.get(blockHash.toArrayUnsafe());
}
public Stream<byte[]> streamTrieLogKeys(final int 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( public Optional<Bytes> getStorageValueByStorageSlotKey(
final Hash accountHash, final StorageSlotKey storageSlotKey) { final Hash accountHash, final StorageSlotKey storageSlotKey) {
return getStorageValueByStorageSlotKey( return getStorageValueByStorageSlotKey(
@ -246,32 +199,11 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateStorage); composedWorldStateStorage);
} }
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 NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom( public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
final Hash addressHash, final Bytes32 startKeyHash, final int limit) { final Hash addressHash, final Bytes32 startKeyHash, final int limit) {
throw new RuntimeException("Bonsai Tries does not currently support enumerating storage"); 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() { public void upgradeToFullFlatDbMode() {
final SegmentedKeyValueStorageTransaction transaction = final SegmentedKeyValueStorageTransaction transaction =
composedWorldStateStorage.startTransaction(); composedWorldStateStorage.startTransaction();
@ -293,23 +225,10 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
@Override @Override
public void clear() { public void clear() {
subscribers.forEach(BonsaiStorageSubscriber::onClearStorage); super.clear();
getFlatDbStrategy().clearAll(composedWorldStateStorage);
composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE);
trieLogStorage.clear();
loadFlatDbStrategy(); // force reload of flat db reader strategy loadFlatDbStrategy(); // force reload of flat db reader strategy
} }
public void clearTrieLog() {
subscribers.forEach(BonsaiStorageSubscriber::onClearTrieLog);
trieLogStorage.clear();
}
public void clearFlatDatabase() {
subscribers.forEach(BonsaiStorageSubscriber::onClearFlatDatabaseStorage);
getFlatDbStrategy().resetOnResync(composedWorldStateStorage);
}
@Override @Override
public Updater updater() { public Updater updater() {
return new Updater( return new Updater(
@ -318,16 +237,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
flatDbStrategy); flatDbStrategy);
} }
public boolean pruneTrieLog(final Hash blockHash) { public static class Updater implements DiffBasedWorldStateKeyValueStorage.Updater {
try {
return trieLogStorage.tryDelete(blockHash.toArrayUnsafe());
} catch (Exception e) {
LOG.error("Error pruning trie log for block hash {}", blockHash, e);
return false;
}
}
public static class Updater implements WorldStateKeyValueStorage.Updater {
private final SegmentedKeyValueStorageTransaction composedWorldStateTransaction; private final SegmentedKeyValueStorageTransaction composedWorldStateTransaction;
private final KeyValueStorageTransaction trieLogStorageTransaction; private final KeyValueStorageTransaction trieLogStorageTransaction;
@ -377,6 +287,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return this; return this;
} }
@Override
public Updater saveWorldState(final Bytes blockHash, final Bytes32 nodeHash, final Bytes node) { public Updater saveWorldState(final Bytes blockHash, final Bytes32 nodeHash, final Bytes node) {
composedWorldStateTransaction.put( composedWorldStateTransaction.put(
TRIE_BRANCH_STORAGE, Bytes.EMPTY.toArrayUnsafe(), node.toArrayUnsafe()); TRIE_BRANCH_STORAGE, Bytes.EMPTY.toArrayUnsafe(), node.toArrayUnsafe());
@ -429,10 +340,12 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateTransaction, accountHash, slotHash); composedWorldStateTransaction, accountHash, slotHash);
} }
@Override
public SegmentedKeyValueStorageTransaction getWorldStateTransaction() { public SegmentedKeyValueStorageTransaction getWorldStateTransaction() {
return composedWorldStateTransaction; return composedWorldStateTransaction;
} }
@Override
public KeyValueStorageTransaction getTrieLogStorageTransaction() { public KeyValueStorageTransaction getTrieLogStorageTransaction() {
return trieLogStorageTransaction; return trieLogStorageTransaction;
} }
@ -444,65 +357,10 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateTransaction.commit(); composedWorldStateTransaction.commit();
} }
@Override
public void rollback() { public void rollback() {
composedWorldStateTransaction.rollback(); composedWorldStateTransaction.rollback();
trieLogStorageTransaction.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,9 +13,10 @@
* SPDX-License-Identifier: Apache-2.0 * 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.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
@ -23,14 +24,14 @@ import org.hyperledger.besu.plugin.services.storage.SnappedKeyValueStorage;
import org.hyperledger.besu.services.kvstore.LayeredKeyValueStorage; import org.hyperledger.besu.services.kvstore.LayeredKeyValueStorage;
public class BonsaiWorldStateLayerStorage extends BonsaiSnapshotWorldStateKeyValueStorage public class BonsaiWorldStateLayerStorage extends BonsaiSnapshotWorldStateKeyValueStorage
implements BonsaiStorageSubscriber { implements DiffBasedLayeredWorldStateKeyValueStorage, StorageSubscriber {
public BonsaiWorldStateLayerStorage(final BonsaiWorldStateKeyValueStorage parent) { public BonsaiWorldStateLayerStorage(final BonsaiWorldStateKeyValueStorage parent) {
this( this(
new LayeredKeyValueStorage(parent.composedWorldStateStorage), new LayeredKeyValueStorage(parent.getComposedWorldStateStorage()),
parent.trieLogStorage, parent.getTrieLogStorage(),
parent, parent,
parent.metricsSystem); parent.getMetricsSystem());
} }
public BonsaiWorldStateLayerStorage( public BonsaiWorldStateLayerStorage(

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0 * 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_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0 * 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_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0 * 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_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE; import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;

@ -13,7 +13,7 @@
* SPDX-License-Identifier: Apache-2.0 * 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.AccountValue;
import org.hyperledger.besu.datatypes.Address; 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.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput; 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.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.plugin.data.BlockHeader; import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog; import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
@ -150,7 +151,7 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final TrieLogLayer newLayer = new TrieLogLayer(); final TrieLogLayer newLayer = new TrieLogLayer();
input.enterList(); input.enterList();
newLayer.blockHash = Hash.wrap(input.readBytes32()); newLayer.setBlockHash(Hash.wrap(input.readBytes32()));
while (!input.isEndOfCurrentList()) { while (!input.isEndOfCurrentList()) {
input.enterList(); input.enterList();
@ -164,7 +165,7 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final StateTrieAccountValue newValue = nullOrValue(input, StateTrieAccountValue::readFrom); final StateTrieAccountValue newValue = nullOrValue(input, StateTrieAccountValue::readFrom);
final boolean isCleared = getOptionalIsCleared(input); final boolean isCleared = getOptionalIsCleared(input);
input.leaveList(); input.leaveList();
newLayer.accounts.put(address, new BonsaiValue<>(oldValue, newValue, isCleared)); newLayer.getAccountChanges().put(address, new DiffBasedValue<>(oldValue, newValue, isCleared));
} }
if (input.nextIsNull()) { if (input.nextIsNull()) {
@ -175,13 +176,13 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final Bytes newCode = nullOrValue(input, RLPInput::readBytes); final Bytes newCode = nullOrValue(input, RLPInput::readBytes);
final boolean isCleared = getOptionalIsCleared(input); final boolean isCleared = getOptionalIsCleared(input);
input.leaveList(); input.leaveList();
newLayer.code.put(address, new BonsaiValue<>(oldCode, newCode, isCleared)); newLayer.getCodeChanges().put(address, new DiffBasedValue<>(oldCode, newCode, isCleared));
} }
if (input.nextIsNull()) { if (input.nextIsNull()) {
input.skipNext(); input.skipNext();
} else { } else {
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageChanges = new TreeMap<>(); final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageChanges = new TreeMap<>();
input.enterList(); input.enterList();
while (!input.isEndOfCurrentList()) { while (!input.isEndOfCurrentList()) {
input.enterList(); input.enterList();
@ -190,11 +191,11 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
final UInt256 oldValue = nullOrValue(input, RLPInput::readUInt256Scalar); final UInt256 oldValue = nullOrValue(input, RLPInput::readUInt256Scalar);
final UInt256 newValue = nullOrValue(input, RLPInput::readUInt256Scalar); final UInt256 newValue = nullOrValue(input, RLPInput::readUInt256Scalar);
final boolean isCleared = getOptionalIsCleared(input); 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();
} }
input.leaveList(); input.leaveList();
newLayer.storage.put(address, storageChanges); newLayer.getStorageChanges().put(address, storageChanges);
} }
// TODO add trie nodes // 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.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.diffbased.common.worldview.DiffBasedWorldView.encodeTrieValue;
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 org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey; 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.core.MutableWorldState;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.NodeLoader; import org.hyperledger.besu.ethereum.trie.NodeLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber; import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator.StorageConsumingMap; 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.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.internal.EvmConfiguration; 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.SegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction; import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
@ -60,24 +54,10 @@ import javax.annotation.Nonnull;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiWorldState public class BonsaiWorldState extends DiffBasedWorldState<BonsaiWorldStateKeyValueStorage> {
implements MutableWorldState, BonsaiWorldView, BonsaiStorageSubscriber {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldState.class); protected final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader;
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;
public BonsaiWorldState( public BonsaiWorldState(
final BonsaiWorldStateProvider archive, final BonsaiWorldStateProvider archive,
@ -93,90 +73,33 @@ public class BonsaiWorldState
protected BonsaiWorldState( protected BonsaiWorldState(
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final CachedMerkleTrieLoader cachedMerkleTrieLoader, final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader,
final CachedWorldStorageManager cachedWorldStorageManager, final BonsaiCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager, final TrieLogManager trieLogManager,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration) {
this.worldStateKeyValueStorage = worldStateKeyValueStorage; super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager);
this.worldStateRootHash = this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
Hash.wrap( this.setAccumulator(
Bytes32.wrap(
worldStateKeyValueStorage.getWorldStateRootHash().orElse(getEmptyTrieHash())));
this.worldStateBlockHash =
Hash.wrap(
Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
this.accumulator =
new BonsaiWorldStateUpdateAccumulator( new BonsaiWorldStateUpdateAccumulator(
this, this,
(addr, value) -> (addr, value) ->
cachedMerkleTrieLoader.preLoadAccount( cachedMerkleTrieLoader.preLoadAccount(
getWorldStateStorage(), worldStateRootHash, addr), worldStateKeyValueStorage, worldStateRootHash, addr),
(addr, value) -> (addr, value) ->
cachedMerkleTrieLoader.preLoadStorageSlot(getWorldStateStorage(), addr, value), cachedMerkleTrieLoader.preLoadStorageSlot(worldStateKeyValueStorage, addr, value),
evmConfiguration); evmConfiguration));
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
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.
*/
protected 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;
}
@Override
public boolean isPersisted() {
return isPersisted(worldStateKeyValueStorage);
}
private boolean isPersisted(final WorldStateKeyValueStorage worldStateKeyValueStorage) {
return !(worldStateKeyValueStorage instanceof BonsaiSnapshotWorldStateKeyValueStorage);
}
@Override
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
return worldStateKeyValueStorage.getCode(codeHash, address.addressHash());
}
/**
* 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 @Override
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() { protected Hash calculateRootHash(
return worldStateKeyValueStorage; final Optional<DiffBasedWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final DiffBasedWorldStateUpdateAccumulator<?> worldStateUpdater) {
return internalCalculateRootHash(
maybeStateUpdater.map(BonsaiWorldStateKeyValueStorage.Updater.class::cast),
(BonsaiWorldStateUpdateAccumulator) worldStateUpdater);
} }
private Hash calculateRootHash( private Hash internalCalculateRootHash(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater, final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) { final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
@ -184,7 +107,7 @@ public class BonsaiWorldState
// This must be done before updating the accounts so // This must be done before updating the accounts so
// that we can get the storage state hash // 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(); storageStream = worldStateUpdater.getStorageToUpdate().entrySet().stream();
if (maybeStateUpdater.isEmpty()) { if (maybeStateUpdater.isEmpty()) {
storageStream = storageStream =
@ -203,7 +126,7 @@ public class BonsaiWorldState
createTrie( createTrie(
(location, hash) -> (location, hash) ->
cachedMerkleTrieLoader.getAccountStateTrieNode( cachedMerkleTrieLoader.getAccountStateTrieNode(
worldStateKeyValueStorage, location, hash), getWorldStateStorage(), location, hash),
worldStateRootHash); worldStateRootHash);
// for manicured tries and composting, collect branches here (not implemented) // for manicured tries and composting, collect branches here (not implemented)
@ -228,10 +151,10 @@ public class BonsaiWorldState
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater, final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater, final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie) { final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie) {
for (final Map.Entry<Address, BonsaiValue<BonsaiAccount>> accountUpdate : for (final Map.Entry<Address, DiffBasedValue<BonsaiAccount>> accountUpdate :
worldStateUpdater.getAccountsToUpdate().entrySet()) { worldStateUpdater.getAccountsToUpdate().entrySet()) {
final Bytes accountKey = accountUpdate.getKey(); final Bytes accountKey = accountUpdate.getKey();
final BonsaiValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue(); final DiffBasedValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue();
final BonsaiAccount updatedAccount = bonsaiValue.getUpdated(); final BonsaiAccount updatedAccount = bonsaiValue.getUpdated();
try { try {
if (updatedAccount == null) { if (updatedAccount == null) {
@ -260,7 +183,7 @@ public class BonsaiWorldState
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) { final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
maybeStateUpdater.ifPresent( maybeStateUpdater.ifPresent(
bonsaiUpdater -> { bonsaiUpdater -> {
for (final Map.Entry<Address, BonsaiValue<Bytes>> codeUpdate : for (final Map.Entry<Address, DiffBasedValue<Bytes>> codeUpdate :
worldStateUpdater.getCodeToUpdate().entrySet()) { worldStateUpdater.getCodeToUpdate().entrySet()) {
final Bytes updatedCode = codeUpdate.getValue().getUpdated(); final Bytes updatedCode = codeUpdate.getValue().getUpdated();
final Hash accountHash = codeUpdate.getKey().addressHash(); final Hash accountHash = codeUpdate.getKey().addressHash();
@ -276,12 +199,12 @@ public class BonsaiWorldState
private void updateAccountStorageState( private void updateAccountStorageState(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater, final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater, final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>> final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
storageAccountUpdate) { storageAccountUpdate) {
final Address updatedAddress = storageAccountUpdate.getKey(); final Address updatedAddress = storageAccountUpdate.getKey();
final Hash updatedAddressHash = updatedAddress.addressHash(); final Hash updatedAddressHash = updatedAddress.addressHash();
if (worldStateUpdater.getAccountsToUpdate().containsKey(updatedAddress)) { if (worldStateUpdater.getAccountsToUpdate().containsKey(updatedAddress)) {
final BonsaiValue<BonsaiAccount> accountValue = final DiffBasedValue<BonsaiAccount> accountValue =
worldStateUpdater.getAccountsToUpdate().get(updatedAddress); worldStateUpdater.getAccountsToUpdate().get(updatedAddress);
final BonsaiAccount accountOriginal = accountValue.getPrior(); final BonsaiAccount accountOriginal = accountValue.getPrior();
final Hash storageRoot = final Hash storageRoot =
@ -293,11 +216,11 @@ public class BonsaiWorldState
createTrie( createTrie(
(location, key) -> (location, key) ->
cachedMerkleTrieLoader.getAccountStorageTrieNode( cachedMerkleTrieLoader.getAccountStorageTrieNode(
worldStateKeyValueStorage, updatedAddressHash, location, key), getWorldStateStorage(), updatedAddressHash, location, key),
storageRoot); storageRoot);
// for manicured tries and composting, collect branches here (not implemented) // 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()) { storageAccountUpdate.getValue().entrySet()) {
final Hash slotHash = storageUpdate.getKey().getSlotHash(); final Hash slotHash = storageUpdate.getKey().getSlotHash();
final UInt256 updatedStorage = storageUpdate.getValue().getUpdated(); final UInt256 updatedStorage = storageUpdate.getValue().getUpdated();
@ -348,7 +271,7 @@ public class BonsaiWorldState
for (final Address address : worldStateUpdater.getStorageToClear()) { for (final Address address : worldStateUpdater.getStorageToClear()) {
// because we are clearing persisted values we need the account root as persisted // because we are clearing persisted values we need the account root as persisted
final BonsaiAccount oldAccount = final BonsaiAccount oldAccount =
worldStateKeyValueStorage getWorldStateStorage()
.getAccount(address.addressHash()) .getAccount(address.addressHash())
.map( .map(
bytes -> BonsaiAccount.fromRLP(BonsaiWorldState.this, address, bytes, true)) bytes -> BonsaiAccount.fromRLP(BonsaiWorldState.this, address, bytes, true))
@ -389,165 +312,27 @@ public class BonsaiWorldState
} }
@Override @Override
public void persist(final BlockHeader blockHeader) { public MutableWorldState freeze() {
final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader); this.isFrozen = true;
LOG.atDebug() this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage());
.setMessage("Persist world state for block {}") return this;
.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(
Optional.of(
new BonsaiWorldStateKeyValueStorage.Updater(
noOpSegmentedTx, noOpTx, worldStateKeyValueStorage.getFlatDbStrategy())),
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.");
} }
@Override @Override
public Account get(final Address address) { public Account get(final Address address) {
return worldStateKeyValueStorage return getWorldStateStorage()
.getAccount(address.addressHash()) .getAccount(address.addressHash())
.map(bytes -> BonsaiAccount.fromRLP(accumulator, address, bytes, true)) .map(bytes -> BonsaiAccount.fromRLP(accumulator, address, bytes, true))
.orElse(null); .orElse(null);
} }
@Override
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
return worldStateKeyValueStorage.getCode(codeHash, address.addressHash());
}
protected Optional<Bytes> getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) { protected Optional<Bytes> getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) {
return worldStateKeyValueStorage.getAccountStateTrieNode(location, nodeHash); return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash);
} }
protected void writeTrieNode( protected void writeTrieNode(
@ -560,7 +345,7 @@ public class BonsaiWorldState
protected Optional<Bytes> getStorageTrieNode( protected Optional<Bytes> getStorageTrieNode(
final Hash accountHash, final Bytes location, final Bytes32 nodeHash) { final Hash accountHash, final Bytes location, final Bytes32 nodeHash) {
return worldStateKeyValueStorage.getAccountStorageTrieNode(accountHash, location, nodeHash); return getWorldStateStorage().getAccountStorageTrieNode(accountHash, location, nodeHash);
} }
private void writeStorageTrieNode( private void writeStorageTrieNode(
@ -581,7 +366,7 @@ public class BonsaiWorldState
@Override @Override
public Optional<UInt256> getStorageValueByStorageSlotKey( public Optional<UInt256> getStorageValueByStorageSlotKey(
final Address address, final StorageSlotKey storageSlotKey) { final Address address, final StorageSlotKey storageSlotKey) {
return worldStateKeyValueStorage return getWorldStateStorage()
.getStorageValueByStorageSlotKey(address.addressHash(), storageSlotKey) .getStorageValueByStorageSlotKey(address.addressHash(), storageSlotKey)
.map(UInt256::fromBytes); .map(UInt256::fromBytes);
} }
@ -590,7 +375,7 @@ public class BonsaiWorldState
final Supplier<Optional<Hash>> storageRootSupplier, final Supplier<Optional<Hash>> storageRootSupplier,
final Address address, final Address address,
final StorageSlotKey storageSlotKey) { final StorageSlotKey storageSlotKey) {
return worldStateKeyValueStorage return getWorldStateStorage()
.getStorageValueByStorageSlotKey(storageRootSupplier, address.addressHash(), storageSlotKey) .getStorageValueByStorageSlotKey(storageRootSupplier, address.addressHash(), storageSlotKey)
.map(UInt256::fromBytes); .map(UInt256::fromBytes);
} }
@ -608,50 +393,18 @@ public class BonsaiWorldState
return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE); 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( private StoredMerklePatriciaTrie<Bytes, Bytes> createTrie(
final NodeLoader nodeLoader, final Bytes32 rootHash) { final NodeLoader nodeLoader, final Bytes32 rootHash) {
return new StoredMerklePatriciaTrie<>( return new StoredMerklePatriciaTrie<>(
nodeLoader, rootHash, Function.identity(), Function.identity()); 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) { protected Hash hashAndSavePreImage(final Bytes value) {
// by default do not save has preImages // by default do not save has preImages
return Hash.hash(value); return Hash.hash(value);
} }
@Override
protected Hash getEmptyTrieHash() { protected Hash getEmptyTrieHash() {
return Hash.EMPTY_TRIE_HASH; return Hash.EMPTY_TRIE_HASH;
} }

@ -0,0 +1,98 @@
/*
* Copyright ConsenSys AG.
*
* 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,219 @@
/*
* Copyright ConsenSys AG.
*
* 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.io.PrintWriter;
import java.io.StringWriter;
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;
private final String stack;
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;
StringWriter sw = new StringWriter();
new Exception().printStackTrace(new PrintWriter(sw));
stack = sw.toString();
}
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;
StringWriter sw = new StringWriter();
new Exception().printStackTrace(new PrintWriter(sw));
stack = sw.toString();
}
@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) {
System.out.println(stack);
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
+ '}';
}
}

@ -14,25 +14,25 @@
* *
*/ */
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.hyperledger.besu.plugin.services.trielogs.TrieLog;
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder; 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 prior;
private T updated; private T updated;
private boolean cleared; private boolean cleared;
public BonsaiValue(final T prior, final T updated) { public DiffBasedValue(final T prior, final T updated) {
this.prior = prior; this.prior = prior;
this.updated = updated; this.updated = updated;
this.cleared = false; this.cleared = false;
} }
public BonsaiValue(final T prior, final T updated, final boolean cleared) { public DiffBasedValue(final T prior, final T updated, final boolean cleared) {
this.prior = prior; this.prior = prior;
this.updated = updated; this.updated = updated;
this.cleared = cleared; this.cleared = cleared;
@ -48,12 +48,12 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
return updated; return updated;
} }
public BonsaiValue<T> setPrior(final T prior) { public DiffBasedValue<T> setPrior(final T prior) {
this.prior = prior; this.prior = prior;
return this; return this;
} }
public BonsaiValue<T> setUpdated(final T updated) { public DiffBasedValue<T> setUpdated(final T updated) {
this.cleared = updated == null; this.cleared = updated == null;
this.updated = updated; this.updated = updated;
return this; return this;
@ -88,7 +88,7 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
if (o == null || getClass() != o.getClass()) { if (o == null || getClass() != o.getClass()) {
return false; return false;
} }
BonsaiValue<?> that = (BonsaiValue<?>) o; DiffBasedValue<?> that = (DiffBasedValue<?>) o;
return new EqualsBuilder() return new EqualsBuilder()
.append(cleared, that.cleared) .append(cleared, that.cleared)
.append(prior, that.prior) .append(prior, that.prior)

@ -0,0 +1,11 @@
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,16 @@
* *
* SPDX-License-Identifier: Apache-2.0 * 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.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; 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 org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.ObservableMetricsSystem;
@ -36,21 +37,21 @@ import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class CachedWorldStorageManager public abstract class DiffBasedCachedWorldStorageManager implements StorageSubscriber {
implements BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
public static final long RETAINED_LAYERS = 512; // at least 256 + typical rollbacks public static final long RETAINED_LAYERS = 512; // at least 256 + typical rollbacks
private static final Logger LOG = LoggerFactory.getLogger(CachedWorldStorageManager.class); private static final Logger LOG =
LoggerFactory.getLogger(DiffBasedCachedWorldStorageManager.class);
private final BonsaiWorldStateProvider archive; private final BonsaiWorldStateProvider archive;
private final ObservableMetricsSystem metricsSystem; private final ObservableMetricsSystem metricsSystem;
private final EvmConfiguration evmConfiguration; private final EvmConfiguration evmConfiguration;
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage; private final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
private final Map<Bytes32, CachedBonsaiWorldView> cachedWorldStatesByHash; private final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash;
private CachedWorldStorageManager( private DiffBasedCachedWorldStorageManager(
final BonsaiWorldStateProvider archive, final BonsaiWorldStateProvider archive,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final Map<Bytes32, CachedBonsaiWorldView> cachedWorldStatesByHash, final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash,
final ObservableMetricsSystem metricsSystem, final ObservableMetricsSystem metricsSystem,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration) {
worldStateKeyValueStorage.subscribe(this); worldStateKeyValueStorage.subscribe(this);
@ -61,9 +62,9 @@ public class CachedWorldStorageManager
this.evmConfiguration = evmConfiguration; this.evmConfiguration = evmConfiguration;
} }
public CachedWorldStorageManager( public DiffBasedCachedWorldStorageManager(
final BonsaiWorldStateProvider archive, final BonsaiWorldStateProvider archive,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final ObservableMetricsSystem metricsSystem) { final ObservableMetricsSystem metricsSystem) {
this( this(
archive, archive,
@ -76,24 +77,23 @@ public class CachedWorldStorageManager
public synchronized void addCachedLayer( public synchronized void addCachedLayer(
final BlockHeader blockHeader, final BlockHeader blockHeader,
final Hash worldStateRootHash, final Hash worldStateRootHash,
final BonsaiWorldState forWorldState) { final DiffBasedWorldState<?> forWorldState) {
final Optional<CachedBonsaiWorldView> cachedBonsaiWorldView = final Optional<DiffBasedCachedWorldView> cachedDiffBasedWorldView =
Optional.ofNullable(this.cachedWorldStatesByHash.get(blockHeader.getBlockHash())); Optional.ofNullable(this.cachedWorldStatesByHash.get(blockHeader.getBlockHash()));
if (cachedBonsaiWorldView.isPresent()) { if (cachedDiffBasedWorldView.isPresent()) {
// only replace if it is a layered storage // only replace if it is a layered storage
if (forWorldState.isPersisted() if (forWorldState.isPersisted()
&& cachedBonsaiWorldView.get().getWorldStateStorage() && cachedDiffBasedWorldView.get().getWorldStateStorage()
instanceof BonsaiWorldStateLayerStorage) { instanceof BonsaiWorldStateLayerStorage) {
LOG.atDebug() LOG.atDebug()
.setMessage("updating layered world state for block {}, state root hash {}") .setMessage("updating layered world state for block {}, state root hash {}")
.addArgument(blockHeader::toLogString) .addArgument(blockHeader::toLogString)
.addArgument(worldStateRootHash::toShortHexString) .addArgument(worldStateRootHash::toShortHexString)
.log(); .log();
cachedBonsaiWorldView cachedDiffBasedWorldView
.get() .get()
.updateWorldStateStorage( .updateWorldStateStorage(
new BonsaiSnapshotWorldStateKeyValueStorage( createSnapshotKeyValueStorage(forWorldState.getWorldStateStorage(), metricsSystem));
forWorldState.getWorldStateStorage(), metricsSystem));
} }
} else { } else {
LOG.atDebug() LOG.atDebug()
@ -104,17 +104,18 @@ public class CachedWorldStorageManager
if (forWorldState.isPersisted()) { if (forWorldState.isPersisted()) {
cachedWorldStatesByHash.put( cachedWorldStatesByHash.put(
blockHeader.getHash(), blockHeader.getHash(),
new CachedBonsaiWorldView( new DiffBasedCachedWorldView(
blockHeader, blockHeader,
new BonsaiSnapshotWorldStateKeyValueStorage( createSnapshotKeyValueStorage(
forWorldState.getWorldStateStorage(), metricsSystem))); forWorldState.getWorldStateStorage(), metricsSystem)));
} else { } else {
// otherwise, add the layer to the cache // otherwise, add the layer to the cache
cachedWorldStatesByHash.put( cachedWorldStatesByHash.put(
blockHeader.getHash(), blockHeader.getHash(),
new CachedBonsaiWorldView( new DiffBasedCachedWorldView(
blockHeader, blockHeader,
((BonsaiWorldStateLayerStorage) forWorldState.getWorldStateStorage()).clone())); ((DiffBasedLayeredWorldStateKeyValueStorage) forWorldState.getWorldStateStorage())
.clone()));
} }
} }
scrubCachedLayers(blockHeader.getNumber()); scrubCachedLayers(blockHeader.getNumber());
@ -134,15 +135,15 @@ public class CachedWorldStorageManager
} }
} }
public Optional<BonsaiWorldState> getWorldState(final Hash blockHash) { public Optional<DiffBasedWorldState<?>> getWorldState(final Hash blockHash) {
if (cachedWorldStatesByHash.containsKey(blockHash)) { if (cachedWorldStatesByHash.containsKey(blockHash)) {
// return a new worldstate using worldstate storage and an isolated copy of the updater // return a new worldstate using worldstate storage and an isolated copy of the updater
return Optional.ofNullable(cachedWorldStatesByHash.get(blockHash)) return Optional.ofNullable(cachedWorldStatesByHash.get(blockHash))
.map( .map(
cached -> cached ->
new BonsaiWorldState( createWorldState(
archive, archive,
new BonsaiWorldStateLayerStorage(cached.getWorldStateStorage()), createLayeredKeyValueStorage(cached.getWorldStateStorage()),
evmConfiguration)); evmConfiguration));
} }
LOG.atDebug() LOG.atDebug()
@ -153,7 +154,7 @@ public class CachedWorldStorageManager
return Optional.empty(); return Optional.empty();
} }
public Optional<BonsaiWorldState> getNearestWorldState(final BlockHeader blockHeader) { public Optional<DiffBasedWorldState<?>> getNearestWorldState(final BlockHeader blockHeader) {
LOG.atDebug() LOG.atDebug()
.setMessage("getting nearest worldstate for {}") .setMessage("getting nearest worldstate for {}")
.addArgument(blockHeader.toLogString()) .addArgument(blockHeader.toLogString())
@ -161,7 +162,7 @@ public class CachedWorldStorageManager
return Optional.ofNullable( return Optional.ofNullable(
cachedWorldStatesByHash.get(blockHeader.getParentHash())) // search parent block cachedWorldStatesByHash.get(blockHeader.getParentHash())) // search parent block
.map(CachedBonsaiWorldView::getWorldStateStorage) .map(DiffBasedCachedWorldView::getWorldStateStorage)
.or( .or(
() -> { () -> {
// or else search the nearest state in the cache // or else search the nearest state in the cache
@ -170,22 +171,22 @@ public class CachedWorldStorageManager
.addArgument(blockHeader.toLogString()) .addArgument(blockHeader.toLogString())
.log(); .log();
final List<CachedBonsaiWorldView> cachedBonsaiWorldViews = final List<DiffBasedCachedWorldView> cachedDiffBasedWorldViews =
new ArrayList<>(cachedWorldStatesByHash.values()); new ArrayList<>(cachedWorldStatesByHash.values());
return cachedBonsaiWorldViews.stream() return cachedDiffBasedWorldViews.stream()
.sorted( .sorted(
Comparator.comparingLong( Comparator.comparingLong(
view -> Math.abs(blockHeader.getNumber() - view.getBlockNumber()))) view -> Math.abs(blockHeader.getNumber() - view.getBlockNumber())))
.map(CachedBonsaiWorldView::getWorldStateStorage) .map(DiffBasedCachedWorldView::getWorldStateStorage)
.findFirst(); .findFirst();
}) })
.map( .map(
storage -> storage ->
new BonsaiWorldState( // wrap the state in a layered worldstate createWorldState( // wrap the state in a layered worldstate
archive, new BonsaiWorldStateLayerStorage(storage), evmConfiguration)); archive, createLayeredKeyValueStorage(storage), evmConfiguration));
} }
public Optional<BonsaiWorldState> getHeadWorldState( public Optional<DiffBasedWorldState<?>> getHeadWorldState(
final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) { final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) {
LOG.atDebug().setMessage("getting head worldstate").log(); LOG.atDebug().setMessage("getting head worldstate").log();
@ -199,7 +200,7 @@ public class CachedWorldStorageManager
addCachedLayer( addCachedLayer(
blockHeader, blockHeader,
blockHeader.getStateRoot(), blockHeader.getStateRoot(),
new BonsaiWorldState(archive, rootWorldStateStorage, evmConfiguration)); createWorldState(archive, rootWorldStateStorage, evmConfiguration));
return getWorldState(blockHeader.getHash()); return getWorldState(blockHeader.getHash());
}); });
} }
@ -231,4 +232,16 @@ public class CachedWorldStorageManager
public void onCloseStorage() { public void onCloseStorage() {
this.cachedWorldStatesByHash.clear(); this.cachedWorldStatesByHash.clear();
} }
public abstract DiffBasedWorldState<?> createWorldState(
final BonsaiWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final EvmConfiguration evmConfiguration);
public abstract DiffBasedWorldStateKeyValueStorage createLayeredKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage);
public abstract DiffBasedWorldStateKeyValueStorage createSnapshotKeyValueStorage(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final ObservableMetricsSystem metricsSystem);
} }

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

@ -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 DiffBasedLayeredWorldStateKeyValueStorage {
DiffBasedWorldStateKeyValueStorage clone();
}

@ -0,0 +1,18 @@
/*
* 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 {}

@ -0,0 +1,246 @@
/*
* 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.bonsai.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
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 ObservableMetricsSystem metricsSystem;
protected final SegmentedKeyValueStorage composedWorldStateStorage;
protected final KeyValueStorage trieLogStorage;
public DiffBasedWorldStateKeyValueStorage(
final StorageProvider provider, final ObservableMetricsSystem metricsSystem) {
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);
this.metricsSystem = metricsSystem;
}
public DiffBasedWorldStateKeyValueStorage(
final SegmentedKeyValueStorage composedWorldStateStorage,
final KeyValueStorage trieLogStorage,
final ObservableMetricsSystem metricsSystem) {
this.composedWorldStateStorage = composedWorldStateStorage;
this.trieLogStorage = trieLogStorage;
this.metricsSystem = metricsSystem;
}
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 int 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();
}
}
public ObservableMetricsSystem getMetricsSystem() {
return metricsSystem;
}
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 * 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.TrieLog;
import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent; 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; 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.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey; 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 org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import java.util.HashMap; import java.util.HashMap;
@ -49,21 +49,21 @@ public class TrieLogLayer implements TrieLog {
protected Hash blockHash; protected Hash blockHash;
protected Optional<Long> blockNumber = Optional.empty(); protected Optional<Long> blockNumber = Optional.empty();
Map<Address, BonsaiValue<AccountValue>> getAccounts() { Map<Address, DiffBasedValue<AccountValue>> getAccounts() {
return accounts; return accounts;
} }
Map<Address, BonsaiValue<Bytes>> getCode() { Map<Address, DiffBasedValue<Bytes>> getCode() {
return code; return code;
} }
Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> getStorage() { Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> getStorage() {
return storage; return storage;
} }
protected final Map<Address, BonsaiValue<AccountValue>> accounts; protected final Map<Address, DiffBasedValue<AccountValue>> accounts;
protected final Map<Address, BonsaiValue<Bytes>> code; protected final Map<Address, DiffBasedValue<Bytes>> code;
protected final Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> storage; protected final Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> storage;
protected boolean frozen = false; protected boolean frozen = false;
public TrieLogLayer() { public TrieLogLayer() {
@ -104,14 +104,14 @@ public class TrieLogLayer implements TrieLog {
public TrieLogLayer addAccountChange( public TrieLogLayer addAccountChange(
final Address address, final AccountValue oldValue, final AccountValue newValue) { final Address address, final AccountValue oldValue, final AccountValue newValue) {
checkState(!frozen, "Layer is Frozen"); checkState(!frozen, "Layer is Frozen");
accounts.put(address, new BonsaiValue<>(oldValue, newValue)); accounts.put(address, new DiffBasedValue<>(oldValue, newValue));
return this; return this;
} }
public TrieLogLayer addCodeChange( public TrieLogLayer addCodeChange(
final Address address, final Bytes oldValue, final Bytes newValue, final Hash blockHash) { final Address address, final Bytes oldValue, final Bytes newValue, final Hash blockHash) {
checkState(!frozen, "Layer is Frozen"); 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; return this;
} }
@ -123,22 +123,22 @@ public class TrieLogLayer implements TrieLog {
checkState(!frozen, "Layer is Frozen"); checkState(!frozen, "Layer is Frozen");
storage storage
.computeIfAbsent(address, a -> new TreeMap<>()) .computeIfAbsent(address, a -> new TreeMap<>())
.put(slot, new BonsaiValue<>(oldValue, newValue)); .put(slot, new DiffBasedValue<>(oldValue, newValue));
return this; return this;
} }
@Override @Override
public Map<Address, BonsaiValue<AccountValue>> getAccountChanges() { public Map<Address, DiffBasedValue<AccountValue>> getAccountChanges() {
return accounts; return accounts;
} }
@Override @Override
public Map<Address, BonsaiValue<Bytes>> getCodeChanges() { public Map<Address, DiffBasedValue<Bytes>> getCodeChanges() {
return code; return code;
} }
@Override @Override
public Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> getStorageChanges() { public Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> getStorageChanges() {
return storage; return storage;
} }
@ -147,18 +147,18 @@ public class TrieLogLayer implements TrieLog {
} }
@Override @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()); return storage.getOrDefault(address, Map.of());
} }
@Override @Override
public Optional<Bytes> getPriorCode(final Address address) { 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 @Override
public Optional<Bytes> getCode(final Address address) { 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 @Override
@ -166,7 +166,7 @@ public class TrieLogLayer implements TrieLog {
final Address address, final StorageSlotKey storageSlotKey) { final Address address, final StorageSlotKey storageSlotKey) {
return Optional.ofNullable(storage.get(address)) return Optional.ofNullable(storage.get(address))
.map(i -> i.get(storageSlotKey)) .map(i -> i.get(storageSlotKey))
.map(BonsaiValue::getPrior); .map(DiffBasedValue::getPrior);
} }
@Override @Override
@ -174,24 +174,24 @@ public class TrieLogLayer implements TrieLog {
final Address address, final StorageSlotKey storageSlotKey) { final Address address, final StorageSlotKey storageSlotKey) {
return Optional.ofNullable(storage.get(address)) return Optional.ofNullable(storage.get(address))
.map(i -> i.get(storageSlotKey)) .map(i -> i.get(storageSlotKey))
.map(BonsaiValue::getUpdated); .map(DiffBasedValue::getUpdated);
} }
@Override @Override
public Optional<AccountValue> getPriorAccount(final Address address) { 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 @Override
public Optional<AccountValue> getAccount(final Address address) { 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() { public String dump() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("TrieLog{" + "blockHash=").append(blockHash).append(frozen).append('}'); sb.append("TrieLog{" + "blockHash=").append(blockHash).append(frozen).append('}');
sb.append("accounts\n"); 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"); sb.append(" : ").append(account.getKey()).append("\n");
if (Objects.equals(account.getValue().getPrior(), account.getValue().getUpdated())) { if (Objects.equals(account.getValue().getPrior(), account.getValue().getUpdated())) {
sb.append(" = ").append(account.getValue().getUpdated()).append("\n"); sb.append(" = ").append(account.getValue().getUpdated()).append("\n");
@ -201,7 +201,7 @@ public class TrieLogLayer implements TrieLog {
} }
} }
sb.append("code").append("\n"); 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"); sb.append(" : ").append(code.getKey()).append("\n");
if (Objects.equals(code.getValue().getPrior(), code.getValue().getUpdated())) { if (Objects.equals(code.getValue().getPrior(), code.getValue().getUpdated())) {
sb.append(" = ").append(code.getValue().getPrior()).append("\n"); sb.append(" = ").append(code.getValue().getPrior()).append("\n");
@ -211,10 +211,10 @@ public class TrieLogLayer implements TrieLog {
} }
} }
sb.append("Storage").append("\n"); 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()) { storage.entrySet()) {
sb.append(" : ").append(storage.getKey()).append("\n"); 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()) { storage.getValue().entrySet()) {
final UInt256 originalValue = slot.getValue().getPrior(); final UInt256 originalValue = slot.getValue().getPrior();
final UInt256 updatedValue = slot.getValue().getUpdated(); final UInt256 updatedValue = slot.getValue().getUpdated();

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

@ -13,13 +13,12 @@
* SPDX-License-Identifier: Apache-2.0 * 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.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import java.util.Comparator; import java.util.Comparator;
import java.util.Optional; import java.util.Optional;
@ -30,6 +29,7 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap; import com.google.common.collect.TreeMultimap;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -39,7 +39,7 @@ public class TrieLogPruner {
private final int pruningLimit; private final int pruningLimit;
private final int loadingLimit; private final int loadingLimit;
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage; private final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
private final Blockchain blockchain; private final Blockchain blockchain;
private final long numBlocksToRetain; private final long numBlocksToRetain;
private final boolean requireFinalizedBlock; private final boolean requireFinalizedBlock;
@ -48,7 +48,7 @@ public class TrieLogPruner {
TreeMultimap.create(Comparator.reverseOrder(), Comparator.naturalOrder()); TreeMultimap.create(Comparator.reverseOrder(), Comparator.naturalOrder());
public TrieLogPruner( public TrieLogPruner(
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage, final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage,
final Blockchain blockchain, final Blockchain blockchain,
final long numBlocksToRetain, final long numBlocksToRetain,
final int pruningLimit, final int pruningLimit,
@ -91,7 +91,7 @@ public class TrieLogPruner {
} }
} }
void addToPruneQueue(final long blockNumber, final Hash blockHash) { public void addToPruneQueue(final long blockNumber, final Hash blockHash) {
LOG.atTrace() LOG.atTrace()
.setMessage("adding trie log to queue for later pruning blockNumber {}; blockHash {}") .setMessage("adding trie log to queue for later pruning blockNumber {}; blockHash {}")
.addArgument(blockNumber) .addArgument(blockNumber)
@ -100,7 +100,7 @@ public class TrieLogPruner {
trieLogBlocksAndForksByDescendingBlockNumber.put(blockNumber, blockHash); trieLogBlocksAndForksByDescendingBlockNumber.put(blockNumber, blockHash);
} }
int pruneFromQueue() { public int pruneFromQueue() {
final long retainAboveThisBlock = blockchain.getChainHeadBlockNumber() - numBlocksToRetain; final long retainAboveThisBlock = blockchain.getChainHeadBlockNumber() - numBlocksToRetain;
final Optional<Hash> finalized = blockchain.getFinalized(); final Optional<Hash> finalized = blockchain.getFinalized();
if (requireFinalizedBlock && finalized.isEmpty()) { if (requireFinalizedBlock && finalized.isEmpty()) {
@ -168,7 +168,7 @@ public class TrieLogPruner {
public static class NoOpTrieLogPruner extends TrieLogPruner { public static class NoOpTrieLogPruner extends TrieLogPruner {
private NoOpTrieLogPruner( private NoOpTrieLogPruner(
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage, final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage,
final Blockchain blockchain, final Blockchain blockchain,
final long numBlocksToRetain, final long numBlocksToRetain,
final int pruningLimit) { final int pruningLimit) {
@ -181,12 +181,12 @@ public class TrieLogPruner {
} }
@Override @Override
void addToPruneQueue(final long blockNumber, final Hash blockHash) { public void addToPruneQueue(final long blockNumber, final Hash blockHash) {
// no-op // no-op
} }
@Override @Override
int pruneFromQueue() { public int pruneFromQueue() {
// no-op // no-op
return -1; return -1;
} }

@ -0,0 +1,352 @@
/*
* Copyright ConsenSys AG.
*
* 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 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.bonsai.cache.BonsaiCachedWorldStorageManager;
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.common.trielog.TrieLogManager;
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.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
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<
WORLDSTATE_STORAGE extends DiffBasedWorldStateKeyValueStorage>
implements MutableWorldState, DiffBasedWorldView, StorageSubscriber {
private static final Logger LOG = LoggerFactory.getLogger(DiffBasedWorldState.class);
protected WORLDSTATE_STORAGE worldStateKeyValueStorage;
protected final BonsaiCachedWorldStorageManager cachedWorldStorageManager;
protected final TrieLogManager trieLogManager;
protected BonsaiWorldStateUpdateAccumulator accumulator;
protected Hash worldStateRootHash;
protected Hash worldStateBlockHash;
protected boolean isFrozen;
protected DiffBasedWorldState(
final WORLDSTATE_STORAGE worldStateKeyValueStorage,
final BonsaiCachedWorldStorageManager 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.
*/
protected 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;
}
@Override
public boolean isPersisted() {
return isPersisted(worldStateKeyValueStorage);
}
private boolean isPersisted(final WorldStateKeyValueStorage worldStateKeyValueStorage) {
return !(worldStateKeyValueStorage instanceof BonsaiSnapshotWorldStateKeyValueStorage);
}
/**
* 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 WORLDSTATE_STORAGE getWorldStateStorage() {
return worldStateKeyValueStorage;
}
public BonsaiWorldStateUpdateAccumulator 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, (BonsaiWorldState) this);
}
};
stateUpdater
.getWorldStateTransaction()
.put(
TRIE_BRANCH_STORAGE,
BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY,
blockHeader.getHash().toArrayUnsafe());
worldStateBlockHash = blockHeader.getHash();
} else {
stateUpdater
.getWorldStateTransaction()
.remove(TRIE_BRANCH_STORAGE, BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY);
worldStateBlockHash = null;
}
stateUpdater
.getWorldStateTransaction()
.put(
TRIE_BRANCH_STORAGE,
BonsaiWorldStateKeyValueStorage.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(
Optional.of(
new BonsaiWorldStateKeyValueStorage.Updater(
noOpSegmentedTx, noOpTx, worldStateKeyValueStorage.getFlatDbStrategy())),
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.");
}
@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 BonsaiWorldStateLayerStorage worldStateLayerStorage =
(BonsaiWorldStateLayerStorage) worldStateKeyValueStorage;
if (!isPersisted(worldStateLayerStorage.getParentWorldStateStorage())) {
worldStateLayerStorage.getParentWorldStateStorage().close();
}
} catch (Exception e) {
// no op
}
}
@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();
}

@ -14,13 +14,13 @@
* *
*/ */
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.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey; import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; 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.WorldUpdater;
import org.hyperledger.besu.evm.worldstate.WorldView; import org.hyperledger.besu.evm.worldstate.WorldView;
@ -31,7 +31,7 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; 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); Optional<Bytes> getCode(Address address, final Hash codeHash);
@ -59,7 +59,7 @@ public interface BonsaiWorldView extends WorldView {
boolean isPersisted(); boolean isPersisted();
BonsaiWorldStateKeyValueStorage getWorldStateStorage(); DiffBasedWorldStateKeyValueStorage getWorldStateStorage();
WorldUpdater updater(); WorldUpdater updater();
} }

@ -14,7 +14,7 @@
* *
*/ */
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.AccountValue;
import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Address;
@ -23,9 +23,15 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
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.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.Account;
import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
@ -44,41 +50,39 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function; import java.util.function.Function;
import com.google.common.collect.ForwardingMap;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class BonsaiWorldStateUpdateAccumulator @SuppressWarnings("unchecked")
extends AbstractWorldUpdater<BonsaiWorldView, BonsaiAccount> public abstract class DiffBasedWorldStateUpdateAccumulator<ACCOUNT extends DiffBasedAccount>
implements BonsaiWorldView, TrieLogAccumulator { extends AbstractWorldUpdater<DiffBasedWorldView, ACCOUNT>
implements DiffBasedWorldView, TrieLogAccumulator {
private static final Logger LOG = private static final Logger LOG =
LoggerFactory.getLogger(BonsaiWorldStateUpdateAccumulator.class); LoggerFactory.getLogger(DiffBasedWorldStateUpdateAccumulator.class);
private final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader; private final Consumer<DiffBasedValue<ACCOUNT>> accountPreloader;
private final Consumer<StorageSlotKey> storagePreloader; private final Consumer<StorageSlotKey> storagePreloader;
private final AccountConsumingMap<BonsaiValue<BonsaiAccount>> accountsToUpdate; private final AccountConsumingMap<DiffBasedValue<ACCOUNT>> accountsToUpdate;
private final Map<Address, BonsaiValue<Bytes>> codeToUpdate = new ConcurrentHashMap<>(); private final Map<Address, DiffBasedValue<Bytes>> codeToUpdate = new ConcurrentHashMap<>();
private final Set<Address> storageToClear = Collections.synchronizedSet(new HashSet<>()); private final Set<Address> storageToClear = Collections.synchronizedSet(new HashSet<>());
private final EvmConfiguration evmConfiguration; private final EvmConfiguration evmConfiguration;
// storage sub mapped by _hashed_ key. This is because in self_destruct calls we need to // 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 // 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. // 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<>(); storageToUpdate = new ConcurrentHashMap<>();
private boolean isAccumulatorStateChanged; private boolean isAccumulatorStateChanged;
public BonsaiWorldStateUpdateAccumulator( public DiffBasedWorldStateUpdateAccumulator(
final BonsaiWorldView world, final DiffBasedWorldView world,
final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader, final Consumer<DiffBasedValue<ACCOUNT>> accountPreloader,
final Consumer<StorageSlotKey> storagePreloader, final Consumer<StorageSlotKey> storagePreloader,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration) {
super(world, evmConfiguration); super(world, evmConfiguration);
@ -89,15 +93,7 @@ public class BonsaiWorldStateUpdateAccumulator
this.evmConfiguration = evmConfiguration; this.evmConfiguration = evmConfiguration;
} }
public BonsaiWorldStateUpdateAccumulator copy() { protected void cloneFromUpdater(final DiffBasedWorldStateUpdateAccumulator<ACCOUNT> source) {
final BonsaiWorldStateUpdateAccumulator copy =
new BonsaiWorldStateUpdateAccumulator(
wrappedWorldView(), accountPreloader, storagePreloader, evmConfiguration);
copy.cloneFromUpdater(this);
return copy;
}
void cloneFromUpdater(final BonsaiWorldStateUpdateAccumulator source) {
accountsToUpdate.putAll(source.getAccountsToUpdate()); accountsToUpdate.putAll(source.getAccountsToUpdate());
codeToUpdate.putAll(source.codeToUpdate); codeToUpdate.putAll(source.codeToUpdate);
storageToClear.addAll(source.storageToClear); storageToClear.addAll(source.storageToClear);
@ -107,14 +103,25 @@ public class BonsaiWorldStateUpdateAccumulator
this.isAccumulatorStateChanged = true; this.isAccumulatorStateChanged = true;
} }
protected Consumer<DiffBasedValue<ACCOUNT>> getAccountPreloader() {
return accountPreloader;
}
protected Consumer<StorageSlotKey> getStoragePreloader() {
return storagePreloader;
}
protected EvmConfiguration getEvmConfiguration() {
return evmConfiguration;
}
@Override @Override
public Account get(final Address address) { public Account get(final Address address) {
return super.get(address); return super.get(address);
} }
@Override @Override
protected UpdateTrackingAccount<BonsaiAccount> track( protected UpdateTrackingAccount<ACCOUNT> track(final UpdateTrackingAccount<ACCOUNT> account) {
final UpdateTrackingAccount<BonsaiAccount> account) {
return super.track(account); return super.track(account);
} }
@ -125,10 +132,10 @@ public class BonsaiWorldStateUpdateAccumulator
@Override @Override
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) { public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address); DiffBasedValue<ACCOUNT> bonsaiValue = accountsToUpdate.get(address);
if (bonsaiValue == null) { if (bonsaiValue == null) {
bonsaiValue = new BonsaiValue<>(null, null); bonsaiValue = new DiffBasedValue<>(null, null);
accountsToUpdate.put(address, bonsaiValue); accountsToUpdate.put(address, bonsaiValue);
} else if (bonsaiValue.getUpdated() != null) { } else if (bonsaiValue.getUpdated() != null) {
if (bonsaiValue.getUpdated().isEmpty()) { if (bonsaiValue.getUpdated().isEmpty()) {
@ -138,8 +145,8 @@ public class BonsaiWorldStateUpdateAccumulator
} }
} }
final BonsaiAccount newAccount = final ACCOUNT newAccount =
new BonsaiAccount( createAccount(
this, this,
address, address,
hashAndSavePreImage(address), hashAndSavePreImage(address),
@ -153,12 +160,12 @@ public class BonsaiWorldStateUpdateAccumulator
} }
@Override @Override
public Map<Address, BonsaiValue<BonsaiAccount>> getAccountsToUpdate() { public Map<Address, DiffBasedValue<ACCOUNT>> getAccountsToUpdate() {
return accountsToUpdate; return accountsToUpdate;
} }
@Override @Override
public Map<Address, BonsaiValue<Bytes>> getCodeToUpdate() { public Map<Address, DiffBasedValue<Bytes>> getCodeToUpdate() {
return codeToUpdate; return codeToUpdate;
} }
@ -167,40 +174,41 @@ public class BonsaiWorldStateUpdateAccumulator
} }
@Override @Override
public Map<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>> public Map<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
getStorageToUpdate() { getStorageToUpdate() {
return storageToUpdate; return storageToUpdate;
} }
@Override @Override
protected BonsaiAccount getForMutation(final Address address) { protected ACCOUNT getForMutation(final Address address) {
return loadAccount(address, BonsaiValue::getUpdated); return loadAccount(address, DiffBasedValue::getUpdated);
} }
protected BonsaiAccount loadAccount( protected ACCOUNT loadAccount(
final Address address, final Address address, final Function<DiffBasedValue<ACCOUNT>, ACCOUNT> accountFunction) {
final Function<BonsaiValue<BonsaiAccount>, BonsaiAccount> bonsaiAccountFunction) {
try { try {
final BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address); final DiffBasedValue<ACCOUNT> bonsaiValue = accountsToUpdate.get(address);
if (bonsaiValue == null) { if (bonsaiValue == null) {
final Account account; final Account account;
if (wrappedWorldView() if (wrappedWorldView() instanceof DiffBasedWorldStateUpdateAccumulator) {
instanceof BonsaiWorldStateUpdateAccumulator bonsaiWorldStateUpdateAccumulator) { final DiffBasedWorldStateUpdateAccumulator<ACCOUNT> worldStateUpdateAccumulator =
account = bonsaiWorldStateUpdateAccumulator.loadAccount(address, bonsaiAccountFunction); (DiffBasedWorldStateUpdateAccumulator<ACCOUNT>) wrappedWorldView();
account = worldStateUpdateAccumulator.loadAccount(address, accountFunction);
} else { } else {
account = wrappedWorldView().get(address); account = wrappedWorldView().get(address);
} }
if (account instanceof BonsaiAccount bonsaiAccount) { if (account instanceof DiffBasedAccount diffBasedAccount) {
BonsaiAccount mutableAccount = new BonsaiAccount(bonsaiAccount, this, true); ACCOUNT mutableAccount = copyAccount((ACCOUNT) diffBasedAccount, this, true);
accountsToUpdate.put(address, new BonsaiValue<>(bonsaiAccount, mutableAccount)); accountsToUpdate.put(
address, new DiffBasedValue<>((ACCOUNT) diffBasedAccount, mutableAccount));
return mutableAccount; return mutableAccount;
} else { } else {
// add the empty read in accountsToUpdate // add the empty read in accountsToUpdate
accountsToUpdate.put(address, new BonsaiValue<>(null, null)); accountsToUpdate.put(address, new DiffBasedValue<>(null, null));
return null; return null;
} }
} else { } else {
return bonsaiAccountFunction.apply(bonsaiValue); return accountFunction.apply(bonsaiValue);
} }
} catch (MerkleTrieException e) { } catch (MerkleTrieException e) {
// need to throw to trigger the heal // need to throw to trigger the heal
@ -228,12 +236,12 @@ public class BonsaiWorldStateUpdateAccumulator
public void commit() { public void commit() {
this.isAccumulatorStateChanged = true; this.isAccumulatorStateChanged = true;
for (final Address deletedAddress : getDeletedAccounts()) { for (final Address deletedAddress : getDeletedAccounts()) {
final BonsaiValue<BonsaiAccount> accountValue = final DiffBasedValue<ACCOUNT> accountValue =
accountsToUpdate.computeIfAbsent( accountsToUpdate.computeIfAbsent(
deletedAddress, deletedAddress,
__ -> loadAccountFromParent(deletedAddress, new BonsaiValue<>(null, null, true))); __ -> loadAccountFromParent(deletedAddress, new DiffBasedValue<>(null, null, true)));
storageToClear.add(deletedAddress); storageToClear.add(deletedAddress);
final BonsaiValue<Bytes> codeValue = codeToUpdate.get(deletedAddress); final DiffBasedValue<Bytes> codeValue = codeToUpdate.get(deletedAddress);
if (codeValue != null) { if (codeValue != null) {
codeValue.setUpdated(null).setCleared(); codeValue.setUpdated(null).setCleared();
} else { } else {
@ -241,26 +249,27 @@ public class BonsaiWorldStateUpdateAccumulator
.getCode( .getCode(
deletedAddress, deletedAddress,
Optional.ofNullable(accountValue) Optional.ofNullable(accountValue)
.map(BonsaiValue::getPrior) .map(DiffBasedValue::getPrior)
.map(BonsaiAccount::getCodeHash) .map(DiffBasedAccount::getCodeHash)
.orElse(Hash.EMPTY)) .orElse(Hash.EMPTY))
.ifPresent( .ifPresent(
deletedCode -> 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 // mark all updated storage as to be cleared
final Map<StorageSlotKey, BonsaiValue<UInt256>> deletedStorageUpdates = final Map<StorageSlotKey, DiffBasedValue<UInt256>> deletedStorageUpdates =
storageToUpdate.computeIfAbsent( storageToUpdate.computeIfAbsent(
deletedAddress, deletedAddress,
k -> k ->
new StorageConsumingMap<>( new StorageConsumingMap<>(
deletedAddress, new ConcurrentHashMap<>(), storagePreloader)); deletedAddress, new ConcurrentHashMap<>(), storagePreloader));
final Iterator<Map.Entry<StorageSlotKey, BonsaiValue<UInt256>>> iter = final Iterator<Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>>> iter =
deletedStorageUpdates.entrySet().iterator(); deletedStorageUpdates.entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> updateEntry = iter.next(); final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> updateEntry = iter.next();
final BonsaiValue<UInt256> updatedSlot = updateEntry.getValue(); final DiffBasedValue<UInt256> updatedSlot = updateEntry.getValue();
if (updatedSlot.getPrior() == null || updatedSlot.getPrior().isZero()) { if (updatedSlot.getPrior() == null || updatedSlot.getPrior().isZero()) {
iter.remove(); iter.remove();
} else { } else {
@ -268,7 +277,7 @@ public class BonsaiWorldStateUpdateAccumulator
} }
} }
final BonsaiAccount originalValue = accountValue.getPrior(); final ACCOUNT originalValue = accountValue.getPrior();
if (originalValue != null) { if (originalValue != null) {
// Enumerate and delete addresses not updated // Enumerate and delete addresses not updated
wrappedWorldView() wrappedWorldView()
@ -279,7 +288,8 @@ public class BonsaiWorldStateUpdateAccumulator
new StorageSlotKey(Hash.wrap(keyHash), Optional.empty()); new StorageSlotKey(Hash.wrap(keyHash), Optional.empty());
if (!deletedStorageUpdates.containsKey(storageSlotKey)) { if (!deletedStorageUpdates.containsKey(storageSlotKey)) {
final UInt256 value = UInt256.fromBytes(RLP.decodeOne(entryValue)); final UInt256 value = UInt256.fromBytes(RLP.decodeOne(entryValue));
deletedStorageUpdates.put(storageSlotKey, new BonsaiValue<>(value, null, true)); deletedStorageUpdates.put(
storageSlotKey, new DiffBasedValue<>(value, null, true));
} }
}); });
} }
@ -293,11 +303,11 @@ public class BonsaiWorldStateUpdateAccumulator
.forEach( .forEach(
tracked -> { tracked -> {
final Address updatedAddress = tracked.getAddress(); final Address updatedAddress = tracked.getAddress();
final BonsaiAccount updatedAccount; final ACCOUNT updatedAccount;
final BonsaiValue<BonsaiAccount> updatedAccountValue = final DiffBasedValue<ACCOUNT> updatedAccountValue =
accountsToUpdate.get(updatedAddress); accountsToUpdate.get(updatedAddress);
final Map<StorageSlotKey, BonsaiValue<UInt256>> pendingStorageUpdates = final Map<StorageSlotKey, DiffBasedValue<UInt256>> pendingStorageUpdates =
storageToUpdate.computeIfAbsent( storageToUpdate.computeIfAbsent(
updatedAddress, updatedAddress,
k -> k ->
@ -310,12 +320,12 @@ public class BonsaiWorldStateUpdateAccumulator
} }
if (tracked.getWrappedAccount() == null) { if (tracked.getWrappedAccount() == null) {
updatedAccount = new BonsaiAccount(this, tracked); updatedAccount = createAccount(this, tracked);
tracked.setWrappedAccount(updatedAccount); tracked.setWrappedAccount(updatedAccount);
if (updatedAccountValue == null) { if (updatedAccountValue == null) {
accountsToUpdate.put(updatedAddress, new BonsaiValue<>(null, updatedAccount)); accountsToUpdate.put(updatedAddress, new DiffBasedValue<>(null, updatedAccount));
codeToUpdate.put( codeToUpdate.put(
updatedAddress, new BonsaiValue<>(null, updatedAccount.getCode())); updatedAddress, new DiffBasedValue<>(null, updatedAccount.getCode()));
} else { } else {
updatedAccountValue.setUpdated(updatedAccount); updatedAccountValue.setUpdated(updatedAccount);
} }
@ -333,17 +343,17 @@ public class BonsaiWorldStateUpdateAccumulator
} }
if (tracked.codeWasUpdated()) { if (tracked.codeWasUpdated()) {
final BonsaiValue<Bytes> pendingCode = final DiffBasedValue<Bytes> pendingCode =
codeToUpdate.computeIfAbsent( codeToUpdate.computeIfAbsent(
updatedAddress, updatedAddress,
addr -> addr ->
new BonsaiValue<>( new DiffBasedValue<>(
wrappedWorldView() wrappedWorldView()
.getCode( .getCode(
addr, addr,
Optional.ofNullable(updatedAccountValue) Optional.ofNullable(updatedAccountValue)
.map(BonsaiValue::getPrior) .map(DiffBasedValue::getPrior)
.map(BonsaiAccount::getCodeHash) .map(DiffBasedAccount::getCodeHash)
.orElse(Hash.EMPTY)) .orElse(Hash.EMPTY))
.orElse(null), .orElse(null),
null)); null));
@ -368,11 +378,11 @@ public class BonsaiWorldStateUpdateAccumulator
final StorageSlotKey slotKey = final StorageSlotKey slotKey =
new StorageSlotKey(slotHash, Optional.of(keyUInt)); new StorageSlotKey(slotHash, Optional.of(keyUInt));
final UInt256 value = storageUpdate.getValue(); final UInt256 value = storageUpdate.getValue();
final BonsaiValue<UInt256> pendingValue = pendingStorageUpdates.get(slotKey); final DiffBasedValue<UInt256> pendingValue = pendingStorageUpdates.get(slotKey);
if (pendingValue == null) { if (pendingValue == null) {
pendingStorageUpdates.put( pendingStorageUpdates.put(
slotKey, slotKey,
new BonsaiValue<>( new DiffBasedValue<>(
updatedAccount.getOriginalStorageValue(keyUInt), value)); updatedAccount.getOriginalStorageValue(keyUInt), value));
} else { } else {
pendingValue.setUpdated(value); pendingValue.setUpdated(value);
@ -393,7 +403,7 @@ public class BonsaiWorldStateUpdateAccumulator
@Override @Override
public Optional<Bytes> getCode(final Address address, final Hash codeHash) { 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) { if (localCode == null) {
final Optional<Bytes> code = wrappedWorldView().getCode(address, codeHash); final Optional<Bytes> code = wrappedWorldView().getCode(address, codeHash);
if (code.isEmpty() && !codeHash.equals(Hash.EMPTY)) { if (code.isEmpty() && !codeHash.equals(Hash.EMPTY)) {
@ -416,10 +426,10 @@ public class BonsaiWorldStateUpdateAccumulator
@Override @Override
public Optional<UInt256> getStorageValueByStorageSlotKey( public Optional<UInt256> getStorageValueByStorageSlotKey(
final Address address, final StorageSlotKey storageSlotKey) { final Address address, final StorageSlotKey storageSlotKey) {
final Map<StorageSlotKey, BonsaiValue<UInt256>> localAccountStorage = final Map<StorageSlotKey, DiffBasedValue<UInt256>> localAccountStorage =
storageToUpdate.get(address); storageToUpdate.get(address);
if (localAccountStorage != null) { if (localAccountStorage != null) {
final BonsaiValue<UInt256> value = localAccountStorage.get(storageSlotKey); final DiffBasedValue<UInt256> value = localAccountStorage.get(storageSlotKey);
if (value != null) { if (value != null) {
return Optional.ofNullable(value.getUpdated()); return Optional.ofNullable(value.getUpdated());
} }
@ -429,8 +439,8 @@ public class BonsaiWorldStateUpdateAccumulator
(wrappedWorldView() instanceof BonsaiWorldState bonsaiWorldState) (wrappedWorldView() instanceof BonsaiWorldState bonsaiWorldState)
? bonsaiWorldState.getStorageValueByStorageSlotKey( ? bonsaiWorldState.getStorageValueByStorageSlotKey(
() -> () ->
Optional.ofNullable(loadAccount(address, BonsaiValue::getPrior)) Optional.ofNullable(loadAccount(address, DiffBasedValue::getPrior))
.map(BonsaiAccount::getStorageRoot), .map(DiffBasedAccount::getStorageRoot),
address, address,
storageSlotKey) storageSlotKey)
: wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey); : wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey);
@ -439,7 +449,8 @@ public class BonsaiWorldStateUpdateAccumulator
address, address,
key -> key ->
new StorageConsumingMap<>(address, new ConcurrentHashMap<>(), storagePreloader)) 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; return valueUInt;
} catch (MerkleTrieException e) { } catch (MerkleTrieException e) {
@ -454,10 +465,10 @@ public class BonsaiWorldStateUpdateAccumulator
// TODO maybe log the read into the trie layer? // TODO maybe log the read into the trie layer?
StorageSlotKey storageSlotKey = StorageSlotKey storageSlotKey =
new StorageSlotKey(hashAndSavePreImage(storageKey), Optional.of(storageKey)); new StorageSlotKey(hashAndSavePreImage(storageKey), Optional.of(storageKey));
final Map<StorageSlotKey, BonsaiValue<UInt256>> localAccountStorage = final Map<StorageSlotKey, DiffBasedValue<UInt256>> localAccountStorage =
storageToUpdate.get(address); storageToUpdate.get(address);
if (localAccountStorage != null) { if (localAccountStorage != null) {
final BonsaiValue<UInt256> value = localAccountStorage.get(storageSlotKey); final DiffBasedValue<UInt256> value = localAccountStorage.get(storageSlotKey);
if (value != null) { if (value != null) {
if (value.isCleared()) { if (value.isCleared()) {
return UInt256.ZERO; return UInt256.ZERO;
@ -481,7 +492,7 @@ public class BonsaiWorldStateUpdateAccumulator
@Override @Override
public Map<Bytes32, Bytes> getAllAccountStorage(final Address address, final Hash rootHash) { public Map<Bytes32, Bytes> getAllAccountStorage(final Address address, final Hash rootHash) {
final Map<Bytes32, Bytes> results = wrappedWorldView().getAllAccountStorage(address, rootHash); final Map<Bytes32, Bytes> results = wrappedWorldView().getAllAccountStorage(address, rootHash);
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> bonsaiValueStorage = final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> bonsaiValueStorage =
storageToUpdate.get(address); storageToUpdate.get(address);
if (bonsaiValueStorage != null) { if (bonsaiValueStorage != null) {
// hash the key to match the implied storage interface of hashed slotKey // hash the key to match the implied storage interface of hashed slotKey
@ -497,7 +508,7 @@ public class BonsaiWorldStateUpdateAccumulator
} }
@Override @Override
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() { public DiffBasedWorldStateKeyValueStorage getWorldStateStorage() {
return wrappedWorldView().getWorldStateStorage(); return wrappedWorldView().getWorldStateStorage();
} }
@ -549,7 +560,7 @@ public class BonsaiWorldStateUpdateAccumulator
// non-change, a cached read. // non-change, a cached read.
return; return;
} }
BonsaiValue<BonsaiAccount> accountValue = accountsToUpdate.get(address); DiffBasedValue<ACCOUNT> accountValue = accountsToUpdate.get(address);
if (accountValue == null) { if (accountValue == null) {
accountValue = loadAccountFromParent(address, accountValue); accountValue = loadAccountFromParent(address, accountValue);
} }
@ -557,7 +568,7 @@ public class BonsaiWorldStateUpdateAccumulator
if (expectedValue == null && replacementValue != null) { if (expectedValue == null && replacementValue != null) {
accountsToUpdate.put( accountsToUpdate.put(
address, address,
new BonsaiValue<>(null, new BonsaiAccount(this, address, replacementValue, true))); new DiffBasedValue<>(null, createAccount(this, address, replacementValue, true)));
} else { } else {
throw new IllegalStateException( throw new IllegalStateException(
String.format( String.format(
@ -571,8 +582,7 @@ public class BonsaiWorldStateUpdateAccumulator
"Expected to create account, but the account exists. Address=%s", address)); "Expected to create account, but the account exists. Address=%s", address));
} }
} else { } else {
BonsaiAccount.assertCloseEnoughForDiffing( assertCloseEnoughForDiffing(accountValue.getUpdated(),
accountValue.getUpdated(),
expectedValue, expectedValue,
"Address=" + address + " Prior Value in Rolling Change"); "Address=" + address + " Prior Value in Rolling Change");
} }
@ -585,19 +595,18 @@ public class BonsaiWorldStateUpdateAccumulator
accountValue.setUpdated(null); accountValue.setUpdated(null);
} }
} else { } else {
accountValue.setUpdated( accountValue.setUpdated(createAccount(wrappedWorldView(), address, replacementValue, true));
new BonsaiAccount(wrappedWorldView(), address, replacementValue, true));
} }
} }
} }
private BonsaiValue<BonsaiAccount> loadAccountFromParent( private DiffBasedValue<ACCOUNT> loadAccountFromParent(
final Address address, final BonsaiValue<BonsaiAccount> defaultValue) { final Address address, final DiffBasedValue<ACCOUNT> defaultValue) {
try { try {
final Account parentAccount = wrappedWorldView().get(address); final Account parentAccount = wrappedWorldView().get(address);
if (parentAccount instanceof BonsaiAccount account) { if (parentAccount instanceof DiffBasedAccount account) {
final BonsaiValue<BonsaiAccount> loadedAccountValue = final DiffBasedValue<ACCOUNT> loadedAccountValue =
new BonsaiValue<>(new BonsaiAccount(account), account); new DiffBasedValue<>(copyAccount((ACCOUNT) account), ((ACCOUNT) account));
accountsToUpdate.put(address, loadedAccountValue); accountsToUpdate.put(address, loadedAccountValue);
return loadedAccountValue; return loadedAccountValue;
} else { } else {
@ -616,7 +625,7 @@ public class BonsaiWorldStateUpdateAccumulator
// non-change, a cached read. // non-change, a cached read.
return; return;
} }
BonsaiValue<Bytes> codeValue = codeToUpdate.get(address); DiffBasedValue<Bytes> codeValue = codeToUpdate.get(address);
if (codeValue == null) { if (codeValue == null) {
final Bytes storedCode = final Bytes storedCode =
wrappedWorldView() wrappedWorldView()
@ -624,14 +633,14 @@ public class BonsaiWorldStateUpdateAccumulator
address, Optional.ofNullable(expectedCode).map(Hash::hash).orElse(Hash.EMPTY)) address, Optional.ofNullable(expectedCode).map(Hash::hash).orElse(Hash.EMPTY))
.orElse(Bytes.EMPTY); .orElse(Bytes.EMPTY);
if (!storedCode.isEmpty()) { if (!storedCode.isEmpty()) {
codeValue = new BonsaiValue<>(storedCode, storedCode); codeValue = new DiffBasedValue<>(storedCode, storedCode);
codeToUpdate.put(address, codeValue); codeToUpdate.put(address, codeValue);
} }
} }
if (codeValue == null) { if (codeValue == null) {
if ((expectedCode == null || expectedCode.isEmpty()) && replacementCode != null) { if ((expectedCode == null || expectedCode.isEmpty()) && replacementCode != null) {
codeToUpdate.put(address, new BonsaiValue<>(null, replacementCode)); codeToUpdate.put(address, new DiffBasedValue<>(null, replacementCode));
} else { } else {
throw new IllegalStateException( throw new IllegalStateException(
String.format( String.format(
@ -659,10 +668,10 @@ public class BonsaiWorldStateUpdateAccumulator
} }
} }
private Map<StorageSlotKey, BonsaiValue<UInt256>> maybeCreateStorageMap( private Map<StorageSlotKey, DiffBasedValue<UInt256>> maybeCreateStorageMap(
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageMap, final Address address) { final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageMap, final Address address) {
if (storageMap == null) { if (storageMap == null) {
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> newMap = final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> newMap =
new StorageConsumingMap<>(address, new ConcurrentHashMap<>(), storagePreloader); new StorageConsumingMap<>(address, new ConcurrentHashMap<>(), storagePreloader);
storageToUpdate.put(address, newMap); storageToUpdate.put(address, newMap);
return newMap; return newMap;
@ -684,13 +693,13 @@ public class BonsaiWorldStateUpdateAccumulator
// corner case on deletes, non-change // corner case on deletes, non-change
return; return;
} }
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageMap = storageToUpdate.get(address); final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageMap = storageToUpdate.get(address);
BonsaiValue<UInt256> slotValue = storageMap == null ? null : storageMap.get(storageSlotKey); DiffBasedValue<UInt256> slotValue = storageMap == null ? null : storageMap.get(storageSlotKey);
if (slotValue == null) { if (slotValue == null) {
final Optional<UInt256> storageValue = final Optional<UInt256> storageValue =
wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey); wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey);
if (storageValue.isPresent()) { if (storageValue.isPresent()) {
slotValue = new BonsaiValue<>(storageValue.get(), storageValue.get()); slotValue = new DiffBasedValue<>(storageValue.get(), storageValue.get());
storageToUpdate storageToUpdate
.computeIfAbsent( .computeIfAbsent(
address, address,
@ -702,7 +711,7 @@ public class BonsaiWorldStateUpdateAccumulator
if (slotValue == null) { if (slotValue == null) {
if ((expectedValue == null || expectedValue.isZero()) && replacementValue != null) { if ((expectedValue == null || expectedValue.isZero()) && replacementValue != null) {
maybeCreateStorageMap(storageMap, address) maybeCreateStorageMap(storageMap, address)
.put(storageSlotKey, new BonsaiValue<>(null, replacementValue)); .put(storageSlotKey, new DiffBasedValue<>(null, replacementValue));
} else { } else {
throw new IllegalStateException( throw new IllegalStateException(
String.format( String.format(
@ -729,7 +738,7 @@ public class BonsaiWorldStateUpdateAccumulator
existingSlotValue == null ? "null" : existingSlotValue.toShortHexString())); existingSlotValue == null ? "null" : existingSlotValue.toShortHexString()));
} }
if (replacementValue == null && slotValue.getPrior() == null) { if (replacementValue == null && slotValue.getPrior() == null) {
final Map<StorageSlotKey, BonsaiValue<UInt256>> thisStorageUpdate = final Map<StorageSlotKey, DiffBasedValue<UInt256>> thisStorageUpdate =
maybeCreateStorageMap(storageMap, address); maybeCreateStorageMap(storageMap, address);
thisStorageUpdate.remove(storageSlotKey); thisStorageUpdate.remove(storageSlotKey);
if (thisStorageUpdate.isEmpty()) { if (thisStorageUpdate.isEmpty()) {
@ -767,69 +776,37 @@ public class BonsaiWorldStateUpdateAccumulator
deletedAccounts.clear(); deletedAccounts.clear();
} }
public static class AccountConsumingMap<T> extends ForwardingMap<Address, T> { protected Hash hashAndSavePreImage(final Bytes bytes) {
// by default do not save hash preImages
private final ConcurrentMap<Address, T> accounts; return Hash.hash(bytes);
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(@NotNull final Address address, @NotNull 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> { public abstract DiffBasedWorldStateUpdateAccumulator<ACCOUNT> copy();
private final Address address; protected abstract ACCOUNT copyAccount(final ACCOUNT account);
private final ConcurrentMap<K, T> storages; protected abstract ACCOUNT copyAccount(
private final Consumer<K> consumer; final ACCOUNT toCopy, final DiffBasedWorldView context, final boolean mutable);
public StorageConsumingMap( protected abstract ACCOUNT createAccount(
final Address address, final ConcurrentMap<K, T> storages, final Consumer<K> consumer) { final DiffBasedWorldView context,
this.address = address; final Address address,
this.storages = storages; final AccountValue stateTrieAccount,
this.consumer = consumer; final boolean mutable);
}
@Override
public T put(@NotNull final K slotKey, @NotNull final T value) {
consumer.process(address, slotKey);
return storages.put(slotKey, value);
}
public Consumer<K> getConsumer() { protected abstract ACCOUNT createAccount(
return consumer; final DiffBasedWorldView context,
} final Address address,
final Hash addressHash,
final long nonce,
final Wei balance,
final Hash storageRoot,
final Hash codeHash,
final boolean mutable);
@Override protected abstract ACCOUNT createAccount(
protected Map<K, T> delegate() { final DiffBasedWorldView context, final UpdateTrackingAccount<ACCOUNT> tracked);
return storages;
}
}
public interface Consumer<T> {
void process(final Address address, T value);
}
protected Hash hashAndSavePreImage(final Bytes bytes) { protected abstract void assertCloseEnoughForDiffing(final ACCOUNT source, final AccountValue account, final String context);
// by default do not save hash preImages
return Hash.hash(bytes);
}
} }

@ -0,0 +1,50 @@
/*
* Copyright ConsenSys AG.
*
* 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 com.google.common.collect.ForwardingMap;
import org.jetbrains.annotations.NotNull;
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(@NotNull final Address address, @NotNull 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,22 @@
/*
* Copyright ConsenSys AG.
*
* 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,54 @@
/*
* Copyright ConsenSys AG.
*
* 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 com.google.common.collect.ForwardingMap;
import org.jetbrains.annotations.NotNull;
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(@NotNull final K slotKey, @NotNull 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;
}
}

@ -18,7 +18,8 @@ package org.hyperledger.besu.ethereum.worldstate;
public enum DataStorageFormat { public enum DataStorageFormat {
FOREST(1), // Original format. Store all tries FOREST(1), // Original format. Store all tries
BONSAI(2); // New format. Store one trie, and trie logs to roll forward and backward. BONSAI(2), // New format. Store one trie, and trie logs to roll forward and backward.
VERKLE(3);
private final int databaseVersion; private final int databaseVersion;

@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.worldstate; package org.hyperledger.besu.ethereum.worldstate;
import org.hyperledger.besu.datatypes.Hash; 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.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import java.util.Optional; import java.util.Optional;

@ -25,10 +25,10 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKey
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
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.bonsai.trielog.TrieLogPruner; 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.ForestWorldStateArchive;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState; import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState;
@ -96,8 +96,8 @@ public class InMemoryKeyValueStorageProvider extends KeyValueStorageProvider {
final Blockchain blockchain, final EvmConfiguration evmConfiguration) { final Blockchain blockchain, final EvmConfiguration evmConfiguration) {
final InMemoryKeyValueStorageProvider inMemoryKeyValueStorageProvider = final InMemoryKeyValueStorageProvider inMemoryKeyValueStorageProvider =
new InMemoryKeyValueStorageProvider(); new InMemoryKeyValueStorageProvider();
final CachedMerkleTrieLoader cachedMerkleTrieLoader = final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader =
new CachedMerkleTrieLoader(new NoOpMetricsSystem()); new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
return new BonsaiWorldStateProvider( return new BonsaiWorldStateProvider(
(BonsaiWorldStateKeyValueStorage) (BonsaiWorldStateKeyValueStorage)
inMemoryKeyValueStorageProvider.createWorldStateStorage(DataStorageFormat.BONSAI), inMemoryKeyValueStorageProvider.createWorldStateStorage(DataStorageFormat.BONSAI),

@ -20,7 +20,7 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; 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.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; 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.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.storage.StorageProvider; 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.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;

@ -65,9 +65,10 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
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.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.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
@ -153,7 +154,7 @@ public abstract class AbstractIsolationTests {
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage, (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage,
blockchain, blockchain,
Optional.of(16L), Optional.of(16L),
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
null, null,
EvmConfiguration.DEFAULT, EvmConfiguration.DEFAULT,

@ -18,8 +18,8 @@ package org.hyperledger.besu.ethereum.trie.bonsai;
import static org.assertj.core.api.Assertions.assertThat; 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.BLOCKCHAIN;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE; 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.diffbased.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.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
@ -36,14 +36,15 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
@ -77,7 +78,7 @@ class BonsaiWorldStateProviderTest {
@Mock SegmentedKeyValueStorageTransaction segmentedKeyValueStorageTransaction; @Mock SegmentedKeyValueStorageTransaction segmentedKeyValueStorageTransaction;
BonsaiWorldStateProvider bonsaiWorldStateArchive; BonsaiWorldStateProvider bonsaiWorldStateArchive;
@Mock CachedWorldStorageManager cachedWorldStorageManager; @Mock BonsaiCachedWorldStorageManager cachedWorldStorageManager;
@Mock TrieLogManager trieLogManager; @Mock TrieLogManager trieLogManager;
@BeforeEach @BeforeEach
@ -108,7 +109,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager, trieLogManager,
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()), new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain, blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT);
assertThat(bonsaiWorldStateArchive.getMutable(chainHead, true)) assertThat(bonsaiWorldStateArchive.getMutable(chainHead, true))
@ -122,7 +123,7 @@ class BonsaiWorldStateProviderTest {
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()), new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain, blockchain,
Optional.of(512L), Optional.of(512L),
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
null, null,
EvmConfiguration.DEFAULT, EvmConfiguration.DEFAULT,
@ -143,7 +144,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager, trieLogManager,
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()), new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain, blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT);
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader(); final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
final BlockHeader chainHead = blockBuilder.number(511).buildHeader(); final BlockHeader chainHead = blockBuilder.number(511).buildHeader();
@ -175,7 +176,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager, trieLogManager,
worldStateKeyValueStorage, worldStateKeyValueStorage,
blockchain, blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT)); EvmConfiguration.DEFAULT));
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader(); final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
@ -201,7 +202,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager, trieLogManager,
worldStateKeyValueStorage, worldStateKeyValueStorage,
blockchain, blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT)); EvmConfiguration.DEFAULT));
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader(); final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
@ -238,7 +239,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager, trieLogManager,
worldStateKeyValueStorage, worldStateKeyValueStorage,
blockchain, blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT)); EvmConfiguration.DEFAULT));
// initial persisted state hash key // initial persisted state hash key
@ -278,7 +279,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager, trieLogManager,
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()), new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain, blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()), new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT)); EvmConfiguration.DEFAULT));
// initial persisted state hash key // initial persisted state hash key

@ -26,8 +26,8 @@ import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.TrieIterator; import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
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.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
@ -46,7 +46,7 @@ import org.mockito.Mockito;
class CachedMerkleTrieLoaderTest { class CachedMerkleTrieLoaderTest {
private CachedMerkleTrieLoader merkleTrieLoader; private BonsaiCachedMerkleTrieLoader merkleTrieLoader;
private final StorageProvider storageProvider = new InMemoryKeyValueStorageProvider(); private final StorageProvider storageProvider = new InMemoryKeyValueStorageProvider();
private final BonsaiWorldStateKeyValueStorage inMemoryWorldState = private final BonsaiWorldStateKeyValueStorage inMemoryWorldState =
Mockito.spy(new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem())); Mockito.spy(new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()));
@ -64,7 +64,7 @@ class CachedMerkleTrieLoaderTest {
TrieGenerator.generateTrie( TrieGenerator.generateTrie(
worldStateStorageCoordinator, worldStateStorageCoordinator,
accounts.stream().map(Address::addressHash).collect(Collectors.toList())); accounts.stream().map(Address::addressHash).collect(Collectors.toList()));
merkleTrieLoader = new CachedMerkleTrieLoader(new NoOpMetricsSystem()); merkleTrieLoader = new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
} }
@Test @Test

@ -29,11 +29,12 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
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.evm.account.MutableAccount; import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.log.LogsBloomFilter; import org.hyperledger.besu.evm.log.LogsBloomFilter;

@ -25,11 +25,12 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIden
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
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.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;

@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.trie.bonsai.storage;
import static org.assertj.core.api.Assertions.assertThat; 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.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.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.StorageEntriesCollector; import org.hyperledger.besu.ethereum.trie.StorageEntriesCollector;
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.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode; import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;

@ -24,6 +24,8 @@ import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
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.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog; import org.hyperledger.besu.plugin.services.trielogs.TrieLog;

@ -20,6 +20,7 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey; import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import java.util.Optional; import java.util.Optional;

@ -16,16 +16,17 @@
package org.hyperledger.besu.ethereum.trie.bonsai.trielog; package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner.noOpTrieLogPruner; import static org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner.noOpTrieLogPruner;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
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.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
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.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;

@ -26,7 +26,8 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader; 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.TrieLogPruner;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;

@ -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.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.storage.StorageProvider; 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.trie.forest.pruner.Pruner;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.metrics.BesuMetricCategory; 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.TrailingPeerRequirements;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException; import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader; 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.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.services.tasks.TaskCollection; 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.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.TrieNodeHealingRequest; 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.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.exception.StorageException;

@ -29,7 +29,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.StorageRangeDataR
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.AccountFlatDatabaseHealingRangeRequest; import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.AccountFlatDatabaseHealingRangeRequest;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.StorageFlatDatabaseHealingRangeRequest; 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.eth.sync.worldstate.WorldDownloadState;
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.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode; import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.context.SnapSyncStatePers
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.AccountRangeDataRequest; import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.AccountRangeDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest; import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader; 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.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.metrics.BesuMetricCategory; import org.hyperledger.besu.metrics.BesuMetricCategory;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.trie.NodeUpdater; 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.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.StackTrie;
import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider; import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.trie.CompactEncoding; import org.hyperledger.besu.ethereum.trie.CompactEncoding;
import org.hyperledger.besu.ethereum.trie.NodeUpdater; 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.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.trie.CompactEncoding;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector; import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator; 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.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector; import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator; 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.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; 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.fastsync.checkpoint.ImmutableCheckpoint;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -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.fastsync.worldstate.FastDownloaderFactory;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -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.fastsync.worldstate.NodeDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException; import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -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.manager.task.EthTask;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException; import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -22,7 +22,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Hash; 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.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector; import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator; 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.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.trie.patricia.StoredNodeFactory; import org.hyperledger.besu.ethereum.trie.patricia.StoredNodeFactory;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;

@ -38,7 +38,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.context.SnapSyncStatePers
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.BytecodeRequest; 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.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -29,7 +29,7 @@ import org.hyperledger.besu.ethereum.trie.CompactEncoding;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector; import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;

@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector; import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator; 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.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -22,7 +22,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.SnapWorldDownloadState;
import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; 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.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat; import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;

@ -16,11 +16,12 @@ package org.hyperledger.besu.ethereum.referencetests;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey; import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView; 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.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
@ -29,8 +30,8 @@ public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdate
private final BonsaiPreImageProxy preImageProxy; private final BonsaiPreImageProxy preImageProxy;
public BonsaiReferenceTestUpdateAccumulator( public BonsaiReferenceTestUpdateAccumulator(
final BonsaiWorldView world, final DiffBasedWorldView world,
final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader, final Consumer<DiffBasedValue<BonsaiAccount>> accountPreloader,
final Consumer<StorageSlotKey> storagePreloader, final Consumer<StorageSlotKey> storagePreloader,
final BonsaiPreImageProxy preImageProxy, final BonsaiPreImageProxy preImageProxy,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration) {

@ -18,15 +18,16 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
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.bonsai.trielog.TrieLogAddedEvent; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.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.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.ObservableMetricsSystem;
@ -51,8 +52,8 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
protected BonsaiReferenceTestWorldState( protected BonsaiReferenceTestWorldState(
final BonsaiReferenceTestWorldStateStorage worldStateKeyValueStorage, final BonsaiReferenceTestWorldStateStorage worldStateKeyValueStorage,
final CachedMerkleTrieLoader cachedMerkleTrieLoader, final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader,
final CachedWorldStorageManager cachedWorldStorageManager, final BonsaiCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager, final TrieLogManager trieLogManager,
final BonsaiPreImageProxy preImageProxy, final BonsaiPreImageProxy preImageProxy,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration) {
@ -113,7 +114,8 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
final Map<String, ReferenceTestWorldState.AccountMock> accounts, final Map<String, ReferenceTestWorldState.AccountMock> accounts,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration) {
final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem(); final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem();
final CachedMerkleTrieLoader cachedMerkleTrieLoader = new CachedMerkleTrieLoader(metricsSystem); final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader =
new BonsaiCachedMerkleTrieLoader(metricsSystem);
final TrieLogManager trieLogManager = new NoOpTrieLogManager(); final TrieLogManager trieLogManager = new NoOpTrieLogManager();
final BonsaiPreImageProxy preImageProxy = final BonsaiPreImageProxy preImageProxy =
new BonsaiPreImageProxy.BonsaiReferenceTestPreImageProxy(); new BonsaiPreImageProxy.BonsaiReferenceTestPreImageProxy();
@ -150,7 +152,7 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
return this.refTestStorage.streamAccounts(this, startKeyHash, limit); return this.refTestStorage.streamAccounts(this, startKeyHash, limit);
} }
static class NoOpCachedWorldStorageManager extends CachedWorldStorageManager { static class NoOpCachedWorldStorageManager extends BonsaiCachedWorldStorageManager {
public NoOpCachedWorldStorageManager() { public NoOpCachedWorldStorageManager() {
super( super(
@ -165,7 +167,7 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
public void addCachedLayer( public void addCachedLayer(
final BlockHeader blockHeader, final BlockHeader blockHeader,
final Hash worldStateRootHash, final Hash worldStateRootHash,
final BonsaiWorldState forWorldState) { final DiffBasedWorldState<?> forWorldState) {
// reference test world states are not cached // reference test world states are not cached
} }
@ -175,17 +177,17 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
} }
@Override @Override
public Optional<BonsaiWorldState> getWorldState(final Hash blockHash) { public Optional<DiffBasedWorldState<?>> getWorldState(final Hash blockHash) {
return Optional.empty(); return Optional.empty();
} }
@Override @Override
public Optional<BonsaiWorldState> getNearestWorldState(final BlockHeader blockHeader) { public Optional<DiffBasedWorldState<?>> getNearestWorldState(final BlockHeader blockHeader) {
return Optional.empty(); return Optional.empty();
} }
@Override @Override
public Optional<BonsaiWorldState> getHeadWorldState( public Optional<DiffBasedWorldState<?>> getHeadWorldState(
final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) { final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) {
return Optional.empty(); return Optional.empty();
} }
@ -205,10 +207,10 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
@SuppressWarnings({"UnsynchronizedOverridesSynchronized", "squid:S3551"}) @SuppressWarnings({"UnsynchronizedOverridesSynchronized", "squid:S3551"})
@Override @Override
public void saveTrieLog( public void saveTrieLog(
final BonsaiWorldStateUpdateAccumulator localUpdater, final DiffBasedWorldStateUpdateAccumulator<?> localUpdater,
final Hash forWorldStateRootHash, final Hash forWorldStateRootHash,
final BlockHeader forBlockHeader, final BlockHeader forBlockHeader,
final BonsaiWorldState forWorldState) { final DiffBasedWorldState<?> forWorldState) {
// notify trie log added observers, synchronously // notify trie log added observers, synchronously
TrieLog trieLog = trieLogFactory.create(localUpdater, forBlockHeader); TrieLog trieLog = trieLogFactory.create(localUpdater, forBlockHeader);
trieLogObservers.forEach(o -> o.onTrieLogAdded(new TrieLogAddedEvent(trieLog))); trieLogObservers.forEach(o -> o.onTrieLogAdded(new TrieLogAddedEvent(trieLog)));

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

Loading…
Cancel
Save