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

@ -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.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
import org.hyperledger.besu.ethereum.trie.forest.pruner.MarkSweepPruner;
import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner;
@ -611,10 +611,10 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
dataDirectory.toString(),
numberOfBlocksToCache);
final CachedMerkleTrieLoader cachedMerkleTrieLoader =
final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader =
besuComponent
.map(BesuComponent::getCachedMerkleTrieLoader)
.orElseGet(() -> new CachedMerkleTrieLoader(metricsSystem));
.orElseGet(() -> new BonsaiCachedMerkleTrieLoader(metricsSystem));
final WorldStateArchive worldStateArchive =
createWorldStateArchive(worldStateStorageCoordinator, blockchain, cachedMerkleTrieLoader);
@ -1065,7 +1065,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
WorldStateArchive createWorldStateArchive(
final WorldStateStorageCoordinator worldStateStorageCoordinator,
final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader) {
return switch (dataStorageConfiguration.getDataStorageFormat()) {
case BONSAI -> {
final GenesisConfigOptions genesisConfigOptions = configOptionsSupplier.get();
@ -1099,6 +1099,8 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
yield new ForestWorldStateArchive(
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.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
@ -174,7 +174,7 @@ public class BesuControllerBuilderTest {
.createWorldStateArchive(
any(WorldStateStorageCoordinator.class),
any(Blockchain.class),
any(CachedMerkleTrieLoader.class));
any(BonsaiCachedMerkleTrieLoader.class));
doReturn(mockWorldState).when(worldStateArchive).getMutable();
when(storageProvider.createWorldStateStorageCoordinator(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.Wei;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.AccountState;

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

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

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

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

@ -0,0 +1,60 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.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
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;

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

@ -12,7 +12,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
@ -24,9 +24,10 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FullFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.PartialFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FullFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.PartialFlatDbStrategy;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
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.SegmentedKeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
import org.hyperledger.besu.util.Subscribers;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import java.util.stream.Stream;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorage, AutoCloseable {
public class BonsaiWorldStateKeyValueStorage extends DiffBasedWorldStateKeyValueStorage
implements WorldStateKeyValueStorage {
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);
protected FlatDbMode flatDbMode;
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(
final StorageProvider provider, final ObservableMetricsSystem metricsSystem) {
this.composedWorldStateStorage =
super(
provider.getStorageBySegmentIdentifiers(
List.of(
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE));
this.trieLogStorage =
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE);
this.metricsSystem = metricsSystem;
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE)),
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE),
metricsSystem);
loadFlatDbStrategy();
}
@ -97,11 +75,9 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
final SegmentedKeyValueStorage composedWorldStateStorage,
final KeyValueStorage trieLogStorage,
final ObservableMetricsSystem metricsSystem) {
super(composedWorldStateStorage, trieLogStorage, metricsSystem);
this.flatDbMode = flatDbMode;
this.flatDbStrategy = flatDbStrategy;
this.composedWorldStateStorage = composedWorldStateStorage;
this.trieLogStorage = trieLogStorage;
this.metricsSystem = metricsSystem;
}
private void loadFlatDbStrategy() {
@ -131,6 +107,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return flatDbMode;
}
@Override
public FlatDbStrategy getFlatDbStrategy() {
if (flatDbStrategy == null) {
loadFlatDbStrategy();
@ -143,6 +120,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return DataStorageFormat.BONSAI;
}
@Override
public FlatDbMode getFlatDbMode() {
return flatDbMode;
}
@ -193,31 +171,6 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
.map(Bytes::wrap);
}
public Optional<byte[]> getTrieLog(final Hash blockHash) {
return trieLogStorage.get(blockHash.toArrayUnsafe());
}
public Stream<byte[]> streamTrieLogKeys(final 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(
final Hash accountHash, final StorageSlotKey storageSlotKey) {
return getStorageValueByStorageSlotKey(
@ -246,32 +199,11 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
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(
final Hash addressHash, final Bytes32 startKeyHash, final int limit) {
throw new RuntimeException("Bonsai Tries does not currently support enumerating storage");
}
public boolean isWorldStateAvailable(final Bytes32 rootHash, final Hash blockHash) {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY)
.map(Bytes32::wrap)
.map(hash -> hash.equals(rootHash) || trieLogStorage.containsKey(blockHash.toArrayUnsafe()))
.orElse(false);
}
public void upgradeToFullFlatDbMode() {
final SegmentedKeyValueStorageTransaction transaction =
composedWorldStateStorage.startTransaction();
@ -293,23 +225,10 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
@Override
public void clear() {
subscribers.forEach(BonsaiStorageSubscriber::onClearStorage);
getFlatDbStrategy().clearAll(composedWorldStateStorage);
composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE);
trieLogStorage.clear();
super.clear();
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
public Updater updater() {
return new Updater(
@ -318,16 +237,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
flatDbStrategy);
}
public boolean pruneTrieLog(final Hash blockHash) {
try {
return trieLogStorage.tryDelete(blockHash.toArrayUnsafe());
} catch (Exception e) {
LOG.error("Error pruning trie log for block hash {}", blockHash, e);
return false;
}
}
public static class Updater implements WorldStateKeyValueStorage.Updater {
public static class Updater implements DiffBasedWorldStateKeyValueStorage.Updater {
private final SegmentedKeyValueStorageTransaction composedWorldStateTransaction;
private final KeyValueStorageTransaction trieLogStorageTransaction;
@ -377,6 +287,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
return this;
}
@Override
public Updater saveWorldState(final Bytes blockHash, final Bytes32 nodeHash, final Bytes node) {
composedWorldStateTransaction.put(
TRIE_BRANCH_STORAGE, Bytes.EMPTY.toArrayUnsafe(), node.toArrayUnsafe());
@ -429,10 +340,12 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateTransaction, accountHash, slotHash);
}
@Override
public SegmentedKeyValueStorageTransaction getWorldStateTransaction() {
return composedWorldStateTransaction;
}
@Override
public KeyValueStorageTransaction getTrieLogStorageTransaction() {
return trieLogStorageTransaction;
}
@ -444,65 +357,10 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
composedWorldStateTransaction.commit();
}
@Override
public void rollback() {
composedWorldStateTransaction.rollback();
trieLogStorageTransaction.rollback();
}
}
@Override
public synchronized void close() throws Exception {
// when the storage clears, close
shouldClose.set(true);
tryClose();
}
public synchronized long subscribe(final BonsaiStorageSubscriber sub) {
if (isClosed.get()) {
throw new RuntimeException("Storage is marked to close or has already closed");
}
return subscribers.subscribe(sub);
}
public synchronized void unSubscribe(final long id) {
subscribers.unsubscribe(id);
try {
tryClose();
} catch (Exception e) {
LOG.atWarn()
.setMessage("exception while trying to close : {}")
.addArgument(e::getMessage)
.log();
}
}
protected synchronized void tryClose() throws Exception {
if (shouldClose.get() && subscribers.getSubscriberCount() < 1) {
doClose();
}
}
protected synchronized void doClose() throws Exception {
if (!isClosed.get()) {
// alert any subscribers we are closing:
subscribers.forEach(BonsaiStorageSubscriber::onCloseStorage);
// close all of the KeyValueStorages:
composedWorldStateStorage.close();
trieLogStorage.close();
// set storage closed
isClosed.set(true);
}
}
public interface BonsaiStorageSubscriber {
default void onClearStorage() {}
default void onClearFlatDatabaseStorage() {}
default void onClearTrieLog() {}
default void onCloseStorage() {}
}
}

@ -13,9 +13,10 @@
* 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.metrics.ObservableMetricsSystem;
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;
public class BonsaiWorldStateLayerStorage extends BonsaiSnapshotWorldStateKeyValueStorage
implements BonsaiStorageSubscriber {
implements DiffBasedLayeredWorldStateKeyValueStorage, StorageSubscriber {
public BonsaiWorldStateLayerStorage(final BonsaiWorldStateKeyValueStorage parent) {
this(
new LayeredKeyValueStorage(parent.composedWorldStateStorage),
parent.trieLogStorage,
new LayeredKeyValueStorage(parent.getComposedWorldStateStorage()),
parent.getTrieLogStorage(),
parent,
parent.metricsSystem);
parent.getMetricsSystem());
}
public BonsaiWorldStateLayerStorage(

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

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

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

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

@ -14,39 +14,33 @@
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView.encodeTrieValue;
import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView.encodeTrieValue;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.NodeLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator.StorageConsumingMap;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
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.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
@ -60,24 +54,10 @@ 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 class BonsaiWorldState
implements MutableWorldState, BonsaiWorldView, BonsaiStorageSubscriber {
public class BonsaiWorldState extends DiffBasedWorldState<BonsaiWorldStateKeyValueStorage> {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldState.class);
protected BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
protected final CachedMerkleTrieLoader cachedMerkleTrieLoader;
protected final CachedWorldStorageManager cachedWorldStorageManager;
protected final TrieLogManager trieLogManager;
private BonsaiWorldStateUpdateAccumulator accumulator;
protected Hash worldStateRootHash;
Hash worldStateBlockHash;
private boolean isFrozen;
protected final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader;
public BonsaiWorldState(
final BonsaiWorldStateProvider archive,
@ -93,90 +73,33 @@ public class BonsaiWorldState
protected BonsaiWorldState(
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final CachedWorldStorageManager cachedWorldStorageManager,
final BonsaiCachedMerkleTrieLoader cachedMerkleTrieLoader,
final BonsaiCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager,
final EvmConfiguration evmConfiguration) {
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.worldStateRootHash =
Hash.wrap(
Bytes32.wrap(
worldStateKeyValueStorage.getWorldStateRootHash().orElse(getEmptyTrieHash())));
this.worldStateBlockHash =
Hash.wrap(
Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
this.accumulator =
super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager);
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
this.setAccumulator(
new BonsaiWorldStateUpdateAccumulator(
this,
(addr, value) ->
cachedMerkleTrieLoader.preLoadAccount(
getWorldStateStorage(), worldStateRootHash, addr),
worldStateKeyValueStorage, worldStateRootHash, addr),
(addr, value) ->
cachedMerkleTrieLoader.preLoadStorageSlot(getWorldStateStorage(), addr, value),
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();
cachedMerkleTrieLoader.preLoadStorageSlot(worldStateKeyValueStorage, addr, value),
evmConfiguration));
}
@Override
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
return worldStateKeyValueStorage;
protected Hash calculateRootHash(
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 BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
@ -184,7 +107,7 @@ public class BonsaiWorldState
// This must be done before updating the accounts so
// that we can get the storage state hash
Stream<Map.Entry<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>>
Stream<Map.Entry<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>>
storageStream = worldStateUpdater.getStorageToUpdate().entrySet().stream();
if (maybeStateUpdater.isEmpty()) {
storageStream =
@ -203,7 +126,7 @@ public class BonsaiWorldState
createTrie(
(location, hash) ->
cachedMerkleTrieLoader.getAccountStateTrieNode(
worldStateKeyValueStorage, location, hash),
getWorldStateStorage(), location, hash),
worldStateRootHash);
// for manicured tries and composting, collect branches here (not implemented)
@ -228,10 +151,10 @@ public class BonsaiWorldState
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie) {
for (final Map.Entry<Address, BonsaiValue<BonsaiAccount>> accountUpdate :
for (final Map.Entry<Address, DiffBasedValue<BonsaiAccount>> accountUpdate :
worldStateUpdater.getAccountsToUpdate().entrySet()) {
final Bytes accountKey = accountUpdate.getKey();
final BonsaiValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue();
final DiffBasedValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue();
final BonsaiAccount updatedAccount = bonsaiValue.getUpdated();
try {
if (updatedAccount == null) {
@ -260,7 +183,7 @@ public class BonsaiWorldState
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
maybeStateUpdater.ifPresent(
bonsaiUpdater -> {
for (final Map.Entry<Address, BonsaiValue<Bytes>> codeUpdate :
for (final Map.Entry<Address, DiffBasedValue<Bytes>> codeUpdate :
worldStateUpdater.getCodeToUpdate().entrySet()) {
final Bytes updatedCode = codeUpdate.getValue().getUpdated();
final Hash accountHash = codeUpdate.getKey().addressHash();
@ -276,12 +199,12 @@ public class BonsaiWorldState
private void updateAccountStorageState(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>
final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
storageAccountUpdate) {
final Address updatedAddress = storageAccountUpdate.getKey();
final Hash updatedAddressHash = updatedAddress.addressHash();
if (worldStateUpdater.getAccountsToUpdate().containsKey(updatedAddress)) {
final BonsaiValue<BonsaiAccount> accountValue =
final DiffBasedValue<BonsaiAccount> accountValue =
worldStateUpdater.getAccountsToUpdate().get(updatedAddress);
final BonsaiAccount accountOriginal = accountValue.getPrior();
final Hash storageRoot =
@ -293,11 +216,11 @@ public class BonsaiWorldState
createTrie(
(location, key) ->
cachedMerkleTrieLoader.getAccountStorageTrieNode(
worldStateKeyValueStorage, updatedAddressHash, location, key),
getWorldStateStorage(), updatedAddressHash, location, key),
storageRoot);
// for manicured tries and composting, collect branches here (not implemented)
for (final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> storageUpdate :
for (final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> storageUpdate :
storageAccountUpdate.getValue().entrySet()) {
final Hash slotHash = storageUpdate.getKey().getSlotHash();
final UInt256 updatedStorage = storageUpdate.getValue().getUpdated();
@ -348,7 +271,7 @@ public class BonsaiWorldState
for (final Address address : worldStateUpdater.getStorageToClear()) {
// because we are clearing persisted values we need the account root as persisted
final BonsaiAccount oldAccount =
worldStateKeyValueStorage
getWorldStateStorage()
.getAccount(address.addressHash())
.map(
bytes -> BonsaiAccount.fromRLP(BonsaiWorldState.this, address, bytes, true))
@ -389,165 +312,27 @@ public class BonsaiWorldState
}
@Override
public void persist(final BlockHeader blockHeader) {
final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader);
LOG.atDebug()
.setMessage("Persist world state for block {}")
.addArgument(maybeBlockHeader)
.log();
final BonsaiWorldStateUpdateAccumulator localCopy = accumulator.copy();
boolean success = false;
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater =
worldStateKeyValueStorage.updater();
Runnable saveTrieLog = () -> {};
try {
final Hash newWorldStateRootHash =
calculateRootHash(isFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator);
// if we are persisted with a block header, and the prior state is the parent
// then persist the TrieLog for that transition.
// If specified but not a direct descendant simply store the new block hash.
if (blockHeader != null) {
verifyWorldStateRoot(newWorldStateRootHash, blockHeader);
saveTrieLog =
() -> {
trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this);
// not save a frozen state in the cache
if (!isFrozen) {
cachedWorldStorageManager.addCachedLayer(blockHeader, newWorldStateRootHash, this);
}
};
stateUpdater
.getWorldStateTransaction()
.put(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY, blockHeader.getHash().toArrayUnsafe());
worldStateBlockHash = blockHeader.getHash();
} else {
stateUpdater.getWorldStateTransaction().remove(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY);
worldStateBlockHash = null;
}
stateUpdater
.getWorldStateTransaction()
.put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, newWorldStateRootHash.toArrayUnsafe());
worldStateRootHash = newWorldStateRootHash;
success = true;
} finally {
if (success) {
stateUpdater.commit();
accumulator.reset();
saveTrieLog.run();
} else {
stateUpdater.rollback();
accumulator.reset();
}
}
}
protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) {
if (!calculatedStateRoot.equals(header.getStateRoot())) {
throw new RuntimeException(
"World State Root does not match expected value, header "
+ header.getStateRoot().toHexString()
+ " calculated "
+ calculatedStateRoot.toHexString());
}
}
@Override
public WorldUpdater updater() {
return accumulator;
}
@Override
public Hash rootHash() {
if (isFrozen && accumulator.isAccumulatorStateChanged()) {
worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy());
accumulator.resetAccumulatorStateChanged();
}
return Hash.wrap(worldStateRootHash);
}
static final KeyValueStorageTransaction noOpTx =
new KeyValueStorageTransaction() {
@Override
public void put(final byte[] key, final byte[] value) {
// no-op
}
@Override
public void remove(final byte[] key) {
// no-op
}
@Override
public void commit() throws StorageException {
// no-op
}
@Override
public void rollback() {
// no-op
}
};
static final SegmentedKeyValueStorageTransaction noOpSegmentedTx =
new SegmentedKeyValueStorageTransaction() {
@Override
public void put(
final SegmentIdentifier segmentIdentifier, final byte[] key, final byte[] value) {
// no-op
}
@Override
public void remove(final SegmentIdentifier segmentIdentifier, final byte[] key) {
// no-op
}
@Override
public void commit() throws StorageException {
// no-op
}
@Override
public void rollback() {
// no-op
}
};
@Override
public Hash frontierRootHash() {
return calculateRootHash(
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.");
public MutableWorldState freeze() {
this.isFrozen = true;
this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage());
return this;
}
@Override
public Account get(final Address address) {
return worldStateKeyValueStorage
return getWorldStateStorage()
.getAccount(address.addressHash())
.map(bytes -> BonsaiAccount.fromRLP(accumulator, address, bytes, true))
.orElse(null);
}
@Override
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
return worldStateKeyValueStorage.getCode(codeHash, address.addressHash());
}
protected Optional<Bytes> getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) {
return worldStateKeyValueStorage.getAccountStateTrieNode(location, nodeHash);
return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash);
}
protected void writeTrieNode(
@ -560,7 +345,7 @@ public class BonsaiWorldState
protected Optional<Bytes> getStorageTrieNode(
final Hash accountHash, final Bytes location, final Bytes32 nodeHash) {
return worldStateKeyValueStorage.getAccountStorageTrieNode(accountHash, location, nodeHash);
return getWorldStateStorage().getAccountStorageTrieNode(accountHash, location, nodeHash);
}
private void writeStorageTrieNode(
@ -581,7 +366,7 @@ public class BonsaiWorldState
@Override
public Optional<UInt256> getStorageValueByStorageSlotKey(
final Address address, final StorageSlotKey storageSlotKey) {
return worldStateKeyValueStorage
return getWorldStateStorage()
.getStorageValueByStorageSlotKey(address.addressHash(), storageSlotKey)
.map(UInt256::fromBytes);
}
@ -590,7 +375,7 @@ public class BonsaiWorldState
final Supplier<Optional<Hash>> storageRootSupplier,
final Address address,
final StorageSlotKey storageSlotKey) {
return worldStateKeyValueStorage
return getWorldStateStorage()
.getStorageValueByStorageSlotKey(storageRootSupplier, address.addressHash(), storageSlotKey)
.map(UInt256::fromBytes);
}
@ -608,50 +393,18 @@ public class BonsaiWorldState
return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE);
}
@Override
public MutableWorldState freeze() {
this.isFrozen = true;
this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(worldStateKeyValueStorage);
return this;
}
private StoredMerklePatriciaTrie<Bytes, Bytes> createTrie(
final NodeLoader nodeLoader, final Bytes32 rootHash) {
return new StoredMerklePatriciaTrie<>(
nodeLoader, rootHash, Function.identity(), Function.identity());
}
@Override
public void close() {
try {
if (!isPersisted()) {
this.worldStateKeyValueStorage.close();
if (isFrozen) {
closeFrozenStorage();
}
}
} catch (Exception e) {
// no op
}
}
private void closeFrozenStorage() {
try {
final BonsaiWorldStateLayerStorage worldStateLayerStorage =
(BonsaiWorldStateLayerStorage) worldStateKeyValueStorage;
if (!isPersisted(worldStateLayerStorage.getParentWorldStateStorage())) {
worldStateLayerStorage.getParentWorldStateStorage().close();
}
} catch (Exception e) {
// no op
}
}
protected Hash hashAndSavePreImage(final Bytes value) {
// by default do not save has preImages
return Hash.hash(value);
}
@Override
protected Hash getEmptyTrieHash() {
return Hash.EMPTY_TRIE_HASH;
}

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

@ -0,0 +1,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
*
*/
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent;

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

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

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

@ -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 {
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;

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

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

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

@ -18,8 +18,8 @@ package org.hyperledger.besu.ethereum.trie.bonsai;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.BLOCKCHAIN;
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
import static org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_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.anyList;
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.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
@ -77,7 +78,7 @@ class BonsaiWorldStateProviderTest {
@Mock SegmentedKeyValueStorageTransaction segmentedKeyValueStorageTransaction;
BonsaiWorldStateProvider bonsaiWorldStateArchive;
@Mock CachedWorldStorageManager cachedWorldStorageManager;
@Mock BonsaiCachedWorldStorageManager cachedWorldStorageManager;
@Mock TrieLogManager trieLogManager;
@BeforeEach
@ -108,7 +109,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT);
assertThat(bonsaiWorldStateArchive.getMutable(chainHead, true))
@ -122,7 +123,7 @@ class BonsaiWorldStateProviderTest {
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain,
Optional.of(512L),
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
new NoOpMetricsSystem(),
null,
EvmConfiguration.DEFAULT,
@ -143,7 +144,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT);
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
final BlockHeader chainHead = blockBuilder.number(511).buildHeader();
@ -175,7 +176,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
worldStateKeyValueStorage,
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
@ -201,7 +202,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
worldStateKeyValueStorage,
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
@ -238,7 +239,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
worldStateKeyValueStorage,
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
// initial persisted state hash key
@ -278,7 +279,7 @@ class BonsaiWorldStateProviderTest {
trieLogManager,
new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()),
blockchain,
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
EvmConfiguration.DEFAULT));
// 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.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
@ -46,7 +46,7 @@ import org.mockito.Mockito;
class CachedMerkleTrieLoaderTest {
private CachedMerkleTrieLoader merkleTrieLoader;
private BonsaiCachedMerkleTrieLoader merkleTrieLoader;
private final StorageProvider storageProvider = new InMemoryKeyValueStorageProvider();
private final BonsaiWorldStateKeyValueStorage inMemoryWorldState =
Mockito.spy(new BonsaiWorldStateKeyValueStorage(storageProvider, new NoOpMetricsSystem()));
@ -64,7 +64,7 @@ class CachedMerkleTrieLoaderTest {
TrieGenerator.generateTrie(
worldStateStorageCoordinator,
accounts.stream().map(Address::addressHash).collect(Collectors.toList()));
merkleTrieLoader = new CachedMerkleTrieLoader(new NoOpMetricsSystem());
merkleTrieLoader = new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
}
@Test

@ -29,11 +29,12 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.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.internal.EvmConfiguration;
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.rlp.BytesValueRLPInput;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.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.metrics.noop.NoOpMetricsSystem;
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.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.eq;
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.trie.MerkleTrie;
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.worldstate.FlatDbMode;
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.BlockHeaderTestFixture;
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.StateTrieAccountValue;
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.StorageSlotKey;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import java.util.Optional;

@ -16,16 +16,17 @@
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
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 org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.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.evm.internal.EvmConfiguration;
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.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
import java.util.Optional;
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.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
import org.hyperledger.besu.metrics.BesuMetricCategory;

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

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

@ -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.StorageFlatDatabaseHealingRangeRequest;
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.FlatDbMode;
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.SnapDataRequest;
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.WorldStateStorageCoordinator;
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.RLPInput;
import org.hyperledger.besu.ethereum.trie.NodeUpdater;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

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

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

@ -36,7 +36,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.ImmutableCheckpoint;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
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.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
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.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
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.sync.worldstate.StalledDownloadException;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -22,7 +22,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
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.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.trie.patricia.StoredNodeFactory;
import org.hyperledger.besu.ethereum.worldstate.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.SnapDataRequest;
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
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.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
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.RangeStorageEntriesCollector;
import org.hyperledger.besu.ethereum.trie.TrieIterator;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;

@ -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.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
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.StorageSlotKey;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.Consumer;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.apache.tuweni.bytes.Bytes;
@ -29,8 +30,8 @@ public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdate
private final BonsaiPreImageProxy preImageProxy;
public BonsaiReferenceTestUpdateAccumulator(
final BonsaiWorldView world,
final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader,
final DiffBasedWorldView world,
final Consumer<DiffBasedValue<BonsaiAccount>> accountPreloader,
final Consumer<StorageSlotKey> storagePreloader,
final BonsaiPreImageProxy preImageProxy,
final EvmConfiguration evmConfiguration) {

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

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

Loading…
Cancel
Save