mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 21:17:54 -05:00
storage format refactor for preparing verkle trie integration (#6721)
Splitting Bonsai code: This commit aims to divide Bonsai into two packages - Common Classes with a Prefix: The common part will include classes prefixed with "DiffBased." These classes are designed to provide a base for both Bonsai and any future storage format that might use this diff-based approach. - Bonsai's Specifics: Bonsai will retain its unique features in its own package. This means that while it shares the diff-based infrastructure with the common part, it also has its own specific functionalities that are not shared with other storage format. - Extension to Verkle: this modification add the possibility of adding "Verkle" as a new storage format based on the diff-based architecture. Like Bonsai, Verkle would use the common diff-based classes but also have its own specific features. --------- Signed-off-by: Karim TAAM <karim.t2am@gmail.com> Signed-off-by: Karim Taam <karim.t2am@gmail.com>
This commit is contained in:
@@ -27,9 +27,9 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -25,8 +25,8 @@ import org.hyperledger.besu.controller.BesuController;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ package org.hyperledger.besu.components;
|
||||
import org.hyperledger.besu.cli.BesuCommand;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCache;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoaderModule;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoaderModule;
|
||||
import org.hyperledger.besu.metrics.MetricsSystemModule;
|
||||
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
|
||||
import org.hyperledger.besu.services.BesuPluginContextImpl;
|
||||
@@ -37,7 +37,7 @@ import org.slf4j.Logger;
|
||||
modules = {
|
||||
BesuCommandModule.class,
|
||||
MetricsSystemModule.class,
|
||||
CachedMerkleTrieLoaderModule.class,
|
||||
BonsaiCachedMerkleTrieLoaderModule.class,
|
||||
BesuPluginContextModule.class,
|
||||
BlobCacheModule.class
|
||||
})
|
||||
@@ -55,7 +55,7 @@ public interface BesuComponent {
|
||||
*
|
||||
* @return CachedMerkleTrieLoader
|
||||
*/
|
||||
CachedMerkleTrieLoader getCachedMerkleTrieLoader();
|
||||
BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader();
|
||||
|
||||
/**
|
||||
* a metrics system that is observable by a Prometheus or OTEL metrics collection subsystem
|
||||
|
||||
@@ -81,11 +81,11 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
|
||||
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogPruner;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.pruner.MarkSweepPruner;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner;
|
||||
@@ -576,13 +576,14 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
dataDirectory.toString(),
|
||||
numberOfBlocksToCache);
|
||||
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader =
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
|
||||
besuComponent
|
||||
.map(BesuComponent::getCachedMerkleTrieLoader)
|
||||
.orElseGet(() -> new CachedMerkleTrieLoader(metricsSystem));
|
||||
.orElseGet(() -> new BonsaiCachedMerkleTrieLoader(metricsSystem));
|
||||
|
||||
final WorldStateArchive worldStateArchive =
|
||||
createWorldStateArchive(worldStateStorageCoordinator, blockchain, cachedMerkleTrieLoader);
|
||||
createWorldStateArchive(
|
||||
worldStateStorageCoordinator, blockchain, bonsaiCachedMerkleTrieLoader);
|
||||
|
||||
if (blockchain.getChainHeadBlockNumber() < 1) {
|
||||
genesisState.writeStateTo(worldStateArchive.getMutable());
|
||||
@@ -1048,7 +1049,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
WorldStateArchive createWorldStateArchive(
|
||||
final WorldStateStorageCoordinator worldStateStorageCoordinator,
|
||||
final Blockchain blockchain,
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader) {
|
||||
return switch (dataStorageConfiguration.getDataStorageFormat()) {
|
||||
case BONSAI -> {
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage =
|
||||
@@ -1057,7 +1058,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
worldStateKeyValueStorage,
|
||||
blockchain,
|
||||
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
|
||||
cachedMerkleTrieLoader,
|
||||
bonsaiCachedMerkleTrieLoader,
|
||||
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
|
||||
evmConfiguration);
|
||||
}
|
||||
@@ -1067,6 +1068,8 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
yield new ForestWorldStateArchive(
|
||||
worldStateStorageCoordinator, preimageStorage, evmConfiguration);
|
||||
}
|
||||
default -> throw new IllegalStateException(
|
||||
"Unexpected value: " + dataStorageConfiguration.getDataStorageFormat());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
|
||||
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
|
||||
|
||||
@@ -43,9 +43,9 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.pruner.PrunerConfiguration;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
@@ -189,7 +189,7 @@ public class BesuControllerBuilderTest {
|
||||
.createWorldStateArchive(
|
||||
any(WorldStateStorageCoordinator.class),
|
||||
any(Blockchain.class),
|
||||
any(CachedMerkleTrieLoader.class));
|
||||
any(BonsaiCachedMerkleTrieLoader.class));
|
||||
doReturn(mockWorldState).when(worldStateArchive).getMutable();
|
||||
when(storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration))
|
||||
.thenReturn(new WorldStateStorageCoordinator(bonsaiWorldStateStorage));
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.account.AccountState;
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ import org.hyperledger.besu.ethereum.core.Withdrawal;
|
||||
import org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater;
|
||||
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
|
||||
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
|
||||
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.hyperledger.besu.ethereum.chain.VariablesStorage;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
|
||||
@@ -19,11 +19,11 @@ package org.hyperledger.besu.ethereum.trie.common;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.NoOpCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.NoOpTrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.NoOpBonsaiCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
@@ -59,8 +59,8 @@ public class GenesisWorldStateProvider {
|
||||
* @return a mutable world state for the Genesis block
|
||||
*/
|
||||
private static MutableWorldState createGenesisBonsaiWorldState() {
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader =
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem());
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
|
||||
final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage =
|
||||
new BonsaiWorldStateKeyValueStorage(
|
||||
new KeyValueStorageProvider(
|
||||
@@ -71,8 +71,8 @@ public class GenesisWorldStateProvider {
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
|
||||
return new BonsaiWorldState(
|
||||
bonsaiWorldStateKeyValueStorage,
|
||||
cachedMerkleTrieLoader,
|
||||
new NoOpCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage),
|
||||
bonsaiCachedMerkleTrieLoader,
|
||||
new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage),
|
||||
new NoOpTrieLogManager(),
|
||||
EvmConfiguration.DEFAULT);
|
||||
}
|
||||
|
||||
@@ -14,48 +14,34 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import org.hyperledger.besu.datatypes.AccountValue;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPException;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
|
||||
import org.hyperledger.besu.evm.ModificationNotAllowedException;
|
||||
import org.hyperledger.besu.evm.account.AccountStorageEntry;
|
||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
|
||||
public class BonsaiAccount implements MutableAccount, AccountValue {
|
||||
private final BonsaiWorldView context;
|
||||
private boolean immutable;
|
||||
|
||||
private final Address address;
|
||||
private final Hash addressHash;
|
||||
private Hash codeHash;
|
||||
private long nonce;
|
||||
private Wei balance;
|
||||
public class BonsaiAccount extends DiffBasedAccount {
|
||||
private Hash storageRoot;
|
||||
private Bytes code;
|
||||
|
||||
private final Map<UInt256, UInt256> updatedStorage = new HashMap<>();
|
||||
|
||||
public BonsaiAccount(
|
||||
final BonsaiWorldView context,
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final Hash addressHash,
|
||||
final long nonce,
|
||||
@@ -63,31 +49,24 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
|
||||
final Hash storageRoot,
|
||||
final Hash codeHash,
|
||||
final boolean mutable) {
|
||||
this.context = context;
|
||||
this.address = address;
|
||||
this.addressHash = addressHash;
|
||||
this.nonce = nonce;
|
||||
this.balance = balance;
|
||||
super(context, address, addressHash, nonce, balance, codeHash, mutable);
|
||||
this.storageRoot = storageRoot;
|
||||
this.codeHash = codeHash;
|
||||
|
||||
this.immutable = !mutable;
|
||||
}
|
||||
|
||||
public BonsaiAccount(
|
||||
final BonsaiWorldView context,
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final AccountValue stateTrieAccount,
|
||||
final boolean mutable) {
|
||||
this(
|
||||
super(
|
||||
context,
|
||||
address,
|
||||
address.addressHash(),
|
||||
stateTrieAccount.getNonce(),
|
||||
stateTrieAccount.getBalance(),
|
||||
stateTrieAccount.getStorageRoot(),
|
||||
stateTrieAccount.getCodeHash(),
|
||||
mutable);
|
||||
this.storageRoot = stateTrieAccount.getStorageRoot();
|
||||
}
|
||||
|
||||
public BonsaiAccount(final BonsaiAccount toCopy) {
|
||||
@@ -95,37 +74,35 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
|
||||
}
|
||||
|
||||
public BonsaiAccount(
|
||||
final BonsaiAccount toCopy, final BonsaiWorldView context, final boolean mutable) {
|
||||
this.context = context;
|
||||
this.address = toCopy.address;
|
||||
this.addressHash = toCopy.addressHash;
|
||||
this.nonce = toCopy.nonce;
|
||||
this.balance = toCopy.balance;
|
||||
final BonsaiAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
|
||||
super(
|
||||
context,
|
||||
toCopy.address,
|
||||
toCopy.addressHash,
|
||||
toCopy.nonce,
|
||||
toCopy.balance,
|
||||
toCopy.codeHash,
|
||||
mutable);
|
||||
this.storageRoot = toCopy.storageRoot;
|
||||
this.codeHash = toCopy.codeHash;
|
||||
this.code = toCopy.code;
|
||||
updatedStorage.putAll(toCopy.updatedStorage);
|
||||
|
||||
this.immutable = !mutable;
|
||||
}
|
||||
|
||||
public BonsaiAccount(
|
||||
final BonsaiWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) {
|
||||
this.context = context;
|
||||
this.address = tracked.getAddress();
|
||||
this.addressHash = tracked.getAddressHash();
|
||||
this.nonce = tracked.getNonce();
|
||||
this.balance = tracked.getBalance();
|
||||
final DiffBasedWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) {
|
||||
super(
|
||||
context,
|
||||
tracked.getAddress(),
|
||||
tracked.getAddressHash(),
|
||||
tracked.getNonce(),
|
||||
tracked.getBalance(),
|
||||
tracked.getCodeHash(),
|
||||
true);
|
||||
this.storageRoot = Hash.EMPTY_TRIE_HASH;
|
||||
this.codeHash = tracked.getCodeHash();
|
||||
this.code = tracked.getCode();
|
||||
updatedStorage.putAll(tracked.getUpdatedStorage());
|
||||
|
||||
this.immutable = false;
|
||||
}
|
||||
|
||||
public static BonsaiAccount fromRLP(
|
||||
final BonsaiWorldView context,
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final Bytes encoded,
|
||||
final boolean mutable)
|
||||
@@ -144,88 +121,11 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
|
||||
context, address, address.addressHash(), nonce, balance, storageRoot, codeHash, mutable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash getAddressHash() {
|
||||
return addressHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNonce(final long value) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
nonce = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wei getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBalance(final Wei value) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
balance = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bytes getCode() {
|
||||
if (code == null) {
|
||||
code = context.getCode(address, codeHash).orElse(Bytes.EMPTY);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCode(final Bytes code) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
this.code = code;
|
||||
if (code == null || code.isEmpty()) {
|
||||
this.codeHash = Hash.EMPTY;
|
||||
} else {
|
||||
this.codeHash = Hash.hash(code);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash getCodeHash() {
|
||||
return codeHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt256 getStorageValue(final UInt256 key) {
|
||||
return context.getStorageValue(address, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt256 getOriginalStorageValue(final UInt256 key) {
|
||||
return context.getPriorStorageValue(address, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
|
||||
final Bytes32 startKeyHash, final int limit) {
|
||||
return context.getWorldStateStorage().storageEntriesFrom(this.addressHash, startKeyHash, limit);
|
||||
}
|
||||
|
||||
public Bytes serializeAccount() {
|
||||
final BytesValueRLPOutput out = new BytesValueRLPOutput();
|
||||
writeTo(out);
|
||||
return out.encoded();
|
||||
return ((BonsaiWorldStateKeyValueStorage) context.getWorldStateStorage())
|
||||
.storageEntriesFrom(this.addressHash, startKeyHash, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -240,24 +140,6 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
|
||||
out.endList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageValue(final UInt256 key, final UInt256 value) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
updatedStorage.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearStorage() {
|
||||
updatedStorage.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<UInt256, UInt256> getUpdatedStorage() {
|
||||
return updatedStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash getStorageRoot() {
|
||||
return storageRoot;
|
||||
@@ -270,11 +152,6 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
|
||||
this.storageRoot = storageRoot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void becomeImmutable() {
|
||||
immutable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccountState{"
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.plugin.BesuContext;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateProvider.class);
|
||||
private final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader;
|
||||
|
||||
public BonsaiWorldStateProvider(
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final Blockchain blockchain,
|
||||
final Optional<Long> maxLayersToLoad,
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
|
||||
final BesuContext pluginContext,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
super(worldStateKeyValueStorage, blockchain, maxLayersToLoad, pluginContext);
|
||||
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
|
||||
provideCachedWorldStorageManager(
|
||||
new BonsaiCachedWorldStorageManager(this, worldStateKeyValueStorage));
|
||||
loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BonsaiWorldStateProvider(
|
||||
final BonsaiCachedWorldStorageManager bonsaiCachedWorldStorageManager,
|
||||
final TrieLogManager trieLogManager,
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final Blockchain blockchain,
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
super(worldStateKeyValueStorage, blockchain, trieLogManager);
|
||||
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
|
||||
provideCachedWorldStorageManager(bonsaiCachedWorldStorageManager);
|
||||
loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration));
|
||||
}
|
||||
|
||||
public BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader() {
|
||||
return bonsaiCachedMerkleTrieLoader;
|
||||
}
|
||||
|
||||
private BonsaiWorldStateKeyValueStorage getWorldStateKeyValueStorage() {
|
||||
return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage;
|
||||
}
|
||||
/**
|
||||
* Prepares the state healing process for a given address and location. It prepares the state
|
||||
* healing, including retrieving data from storage, identifying invalid slots or nodes, removing
|
||||
* account and slot from the state trie, and committing the changes. Finally, it downgrades the
|
||||
* world state storage to partial flat database mode.
|
||||
*/
|
||||
public void prepareStateHealing(final Address address, final Bytes location) {
|
||||
final Set<Bytes> keysToDelete = new HashSet<>();
|
||||
final BonsaiWorldStateKeyValueStorage.Updater updater =
|
||||
getWorldStateKeyValueStorage().updater();
|
||||
final Hash accountHash = address.addressHash();
|
||||
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
|
||||
new StoredMerklePatriciaTrie<>(
|
||||
(l, h) -> {
|
||||
final Optional<Bytes> node =
|
||||
getWorldStateKeyValueStorage().getAccountStateTrieNode(l, h);
|
||||
if (node.isPresent()) {
|
||||
keysToDelete.add(l);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
persistedState.getWorldStateRootHash(),
|
||||
Function.identity(),
|
||||
Function.identity());
|
||||
try {
|
||||
accountTrie
|
||||
.get(accountHash)
|
||||
.map(RLP::input)
|
||||
.map(StateTrieAccountValue::readFrom)
|
||||
.ifPresent(
|
||||
account -> {
|
||||
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
|
||||
new StoredMerklePatriciaTrie<>(
|
||||
(l, h) -> {
|
||||
Optional<Bytes> node =
|
||||
getWorldStateKeyValueStorage()
|
||||
.getAccountStorageTrieNode(accountHash, l, h);
|
||||
if (node.isPresent()) {
|
||||
keysToDelete.add(Bytes.concatenate(accountHash, l));
|
||||
}
|
||||
return node;
|
||||
},
|
||||
account.getStorageRoot(),
|
||||
Function.identity(),
|
||||
Function.identity());
|
||||
try {
|
||||
storageTrie.getPath(location);
|
||||
} catch (Exception eA) {
|
||||
LOG.warn("Invalid slot found for account {} at location {}", address, location);
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
} catch (Exception eA) {
|
||||
LOG.warn("Invalid node for account {} at location {}", address, location);
|
||||
// ignore
|
||||
}
|
||||
keysToDelete.forEach(updater::removeAccountStateTrieNode);
|
||||
updater.commit();
|
||||
|
||||
getWorldStateKeyValueStorage().downgradeToPartialFlatDbMode();
|
||||
}
|
||||
}
|
||||
@@ -13,14 +13,15 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.metrics.BesuMetricCategory;
|
||||
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
|
||||
@@ -37,8 +38,7 @@ import io.prometheus.client.guava.cache.CacheMetricsCollector;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
|
||||
public class CachedMerkleTrieLoader
|
||||
implements BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
|
||||
public class BonsaiCachedMerkleTrieLoader implements StorageSubscriber {
|
||||
|
||||
private static final int ACCOUNT_CACHE_SIZE = 100_000;
|
||||
private static final int STORAGE_CACHE_SIZE = 200_000;
|
||||
@@ -47,7 +47,7 @@ public class CachedMerkleTrieLoader
|
||||
private final Cache<Bytes, Bytes> storageNodes =
|
||||
CacheBuilder.newBuilder().recordStats().maximumSize(STORAGE_CACHE_SIZE).build();
|
||||
|
||||
public CachedMerkleTrieLoader(final ObservableMetricsSystem metricsSystem) {
|
||||
public BonsaiCachedMerkleTrieLoader(final ObservableMetricsSystem metricsSystem) {
|
||||
|
||||
CacheMetricsCollector cacheMetrics = new CacheMetricsCollector();
|
||||
cacheMetrics.addCache("accountsNodes", accountNodes);
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
|
||||
|
||||
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
|
||||
|
||||
@@ -21,11 +21,11 @@ import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class CachedMerkleTrieLoaderModule {
|
||||
public class BonsaiCachedMerkleTrieLoaderModule {
|
||||
|
||||
@Provides
|
||||
CachedMerkleTrieLoader provideCachedMerkleTrieLoaderModule(
|
||||
BonsaiCachedMerkleTrieLoader provideCachedMerkleTrieLoaderModule(
|
||||
final ObservableMetricsSystem metricsSystem) {
|
||||
return new CachedMerkleTrieLoader(metricsSystem);
|
||||
return new BonsaiCachedMerkleTrieLoader(metricsSystem);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
|
||||
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
|
||||
public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager {
|
||||
|
||||
public BonsaiCachedWorldStorageManager(
|
||||
final BonsaiWorldStateProvider archive,
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
|
||||
super(archive, worldStateKeyValueStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiffBasedWorldState createWorldState(
|
||||
final DiffBasedWorldStateProvider archive,
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
return new BonsaiWorldState(
|
||||
(BonsaiWorldStateProvider) archive,
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiffBasedWorldStateKeyValueStorage createLayeredKeyValueStorage(
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
|
||||
return new BonsaiWorldStateLayerStorage(
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiffBasedWorldStateKeyValueStorage createSnapshotKeyValueStorage(
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
|
||||
return new BonsaiSnapshotWorldStateKeyValueStorage(
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage);
|
||||
}
|
||||
}
|
||||
@@ -12,19 +12,19 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NoOpCachedWorldStorageManager extends CachedWorldStorageManager {
|
||||
public class NoOpBonsaiCachedWorldStorageManager extends BonsaiCachedWorldStorageManager {
|
||||
|
||||
public NoOpCachedWorldStorageManager(
|
||||
public NoOpBonsaiCachedWorldStorageManager(
|
||||
final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage) {
|
||||
super(null, bonsaiWorldStateKeyValueStorage);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public class NoOpCachedWorldStorageManager extends CachedWorldStorageManager {
|
||||
public synchronized void addCachedLayer(
|
||||
final BlockHeader blockHeader,
|
||||
final Hash worldStateRootHash,
|
||||
final BonsaiWorldState forWorldState) {
|
||||
final DiffBasedWorldState forWorldState) {
|
||||
// no cache
|
||||
}
|
||||
|
||||
@@ -43,17 +43,17 @@ public class NoOpCachedWorldStorageManager extends CachedWorldStorageManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BonsaiWorldState> getWorldState(final Hash blockHash) {
|
||||
public Optional<DiffBasedWorldState> getWorldState(final Hash blockHash) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BonsaiWorldState> getNearestWorldState(final BlockHeader blockHeader) {
|
||||
public Optional<DiffBasedWorldState> getNearestWorldState(final BlockHeader blockHeader) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BonsaiWorldState> getHeadWorldState(
|
||||
public Optional<DiffBasedWorldState> getHeadWorldState(
|
||||
final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) {
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
@@ -13,11 +13,12 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedSnapshotWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.exception.StorageException;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.SnappableKeyValueStorage;
|
||||
@@ -32,7 +33,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKeyValueStorage
|
||||
implements BonsaiStorageSubscriber {
|
||||
implements DiffBasedSnapshotWorldStateKeyValueStorage, StorageSubscriber {
|
||||
|
||||
protected final BonsaiWorldStateKeyValueStorage parentWorldStateStorage;
|
||||
private static final Logger LOG =
|
||||
@@ -53,9 +54,9 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
|
||||
final BonsaiWorldStateKeyValueStorage worldStateStorageKeyValueStorage) {
|
||||
this(
|
||||
worldStateStorageKeyValueStorage,
|
||||
((SnappableKeyValueStorage) worldStateStorageKeyValueStorage.composedWorldStateStorage)
|
||||
((SnappableKeyValueStorage) worldStateStorageKeyValueStorage.getComposedWorldStateStorage())
|
||||
.takeSnapshot(),
|
||||
worldStateStorageKeyValueStorage.trieLogStorage);
|
||||
worldStateStorageKeyValueStorage.getTrieLogStorage());
|
||||
}
|
||||
|
||||
private boolean isClosedGet() {
|
||||
@@ -207,7 +208,7 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
|
||||
protected synchronized void doClose() throws Exception {
|
||||
if (!isClosedGet()) {
|
||||
// alert any subscribers we are closing:
|
||||
subscribers.forEach(BonsaiStorageSubscriber::onCloseStorage);
|
||||
subscribers.forEach(StorageSubscriber::onCloseStorage);
|
||||
|
||||
// close all of the SnappedKeyValueStorages:
|
||||
composedWorldStateStorage.close();
|
||||
@@ -220,6 +221,7 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BonsaiWorldStateKeyValueStorage getParentWorldStateStorage() {
|
||||
return parentWorldStateStorage;
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
|
||||
@@ -24,8 +24,9 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.flat.FlatDbStrategyProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategyProvider;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
@@ -37,52 +38,28 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorage, AutoCloseable {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateKeyValueStorage.class);
|
||||
|
||||
// 0x776f726c64526f6f74
|
||||
public static final byte[] WORLD_ROOT_HASH_KEY = "worldRoot".getBytes(StandardCharsets.UTF_8);
|
||||
// 0x776f726c64426c6f636b48617368
|
||||
public static final byte[] WORLD_BLOCK_HASH_KEY =
|
||||
"worldBlockHash".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
public class BonsaiWorldStateKeyValueStorage extends DiffBasedWorldStateKeyValueStorage
|
||||
implements WorldStateKeyValueStorage {
|
||||
protected final FlatDbStrategyProvider flatDbStrategyProvider;
|
||||
|
||||
protected final SegmentedKeyValueStorage composedWorldStateStorage;
|
||||
protected final KeyValueStorage trieLogStorage;
|
||||
|
||||
private final AtomicBoolean shouldClose = new AtomicBoolean(false);
|
||||
|
||||
protected final AtomicBoolean isClosed = new AtomicBoolean(false);
|
||||
|
||||
protected final Subscribers<BonsaiStorageSubscriber> subscribers = Subscribers.create();
|
||||
|
||||
public BonsaiWorldStateKeyValueStorage(
|
||||
final StorageProvider provider,
|
||||
final MetricsSystem metricsSystem,
|
||||
final DataStorageConfiguration dataStorageConfiguration) {
|
||||
this.composedWorldStateStorage =
|
||||
super(
|
||||
provider.getStorageBySegmentIdentifiers(
|
||||
List.of(
|
||||
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE));
|
||||
this.trieLogStorage =
|
||||
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE);
|
||||
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE)),
|
||||
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE));
|
||||
this.flatDbStrategyProvider =
|
||||
new FlatDbStrategyProvider(metricsSystem, dataStorageConfiguration);
|
||||
flatDbStrategyProvider.loadFlatDbStrategy(composedWorldStateStorage);
|
||||
@@ -92,9 +69,8 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
final FlatDbStrategyProvider flatDbStrategyProvider,
|
||||
final SegmentedKeyValueStorage composedWorldStateStorage,
|
||||
final KeyValueStorage trieLogStorage) {
|
||||
super(composedWorldStateStorage, trieLogStorage);
|
||||
this.flatDbStrategyProvider = flatDbStrategyProvider;
|
||||
this.composedWorldStateStorage = composedWorldStateStorage;
|
||||
this.trieLogStorage = trieLogStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,6 +78,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
return DataStorageFormat.BONSAI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlatDbMode getFlatDbMode() {
|
||||
return flatDbStrategyProvider.getFlatDbMode();
|
||||
}
|
||||
@@ -155,31 +132,6 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
.map(Bytes::wrap);
|
||||
}
|
||||
|
||||
public Optional<byte[]> getTrieLog(final Hash blockHash) {
|
||||
return trieLogStorage.get(blockHash.toArrayUnsafe());
|
||||
}
|
||||
|
||||
public Stream<byte[]> streamTrieLogKeys(final long limit) {
|
||||
return trieLogStorage.streamKeys().limit(limit);
|
||||
}
|
||||
|
||||
public Optional<Bytes> getStateTrieNode(final Bytes location) {
|
||||
return composedWorldStateStorage
|
||||
.get(TRIE_BRANCH_STORAGE, location.toArrayUnsafe())
|
||||
.map(Bytes::wrap);
|
||||
}
|
||||
|
||||
public Optional<Bytes> getWorldStateRootHash() {
|
||||
return composedWorldStateStorage.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY).map(Bytes::wrap);
|
||||
}
|
||||
|
||||
public Optional<Hash> getWorldStateBlockHash() {
|
||||
return composedWorldStateStorage
|
||||
.get(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY)
|
||||
.map(Bytes32::wrap)
|
||||
.map(Hash::wrap);
|
||||
}
|
||||
|
||||
public Optional<Bytes> getStorageValueByStorageSlotKey(
|
||||
final Hash accountHash, final StorageSlotKey storageSlotKey) {
|
||||
return getStorageValueByStorageSlotKey(
|
||||
@@ -209,34 +161,11 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
composedWorldStateStorage);
|
||||
}
|
||||
|
||||
public Map<Bytes32, Bytes> streamFlatAccounts(
|
||||
final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
|
||||
return flatDbStrategyProvider
|
||||
.getFlatDbStrategy(composedWorldStateStorage)
|
||||
.streamAccountFlatDatabase(composedWorldStateStorage, startKeyHash, endKeyHash, max);
|
||||
}
|
||||
|
||||
public Map<Bytes32, Bytes> streamFlatStorages(
|
||||
final Hash accountHash, final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
|
||||
return flatDbStrategyProvider
|
||||
.getFlatDbStrategy(composedWorldStateStorage)
|
||||
.streamStorageFlatDatabase(
|
||||
composedWorldStateStorage, accountHash, startKeyHash, endKeyHash, max);
|
||||
}
|
||||
|
||||
public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
|
||||
final Hash addressHash, final Bytes32 startKeyHash, final int limit) {
|
||||
throw new RuntimeException("Bonsai Tries does not currently support enumerating storage");
|
||||
}
|
||||
|
||||
public boolean isWorldStateAvailable(final Bytes32 rootHash, final Hash blockHash) {
|
||||
return composedWorldStateStorage
|
||||
.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY)
|
||||
.map(Bytes32::wrap)
|
||||
.map(hash -> hash.equals(rootHash) || trieLogStorage.containsKey(blockHash.toArrayUnsafe()))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
public void upgradeToFullFlatDbMode() {
|
||||
flatDbStrategyProvider.upgradeToFullFlatDbMode(composedWorldStateStorage);
|
||||
}
|
||||
@@ -247,26 +176,14 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
subscribers.forEach(BonsaiStorageSubscriber::onClearStorage);
|
||||
flatDbStrategyProvider
|
||||
.getFlatDbStrategy(composedWorldStateStorage)
|
||||
.clearAll(composedWorldStateStorage);
|
||||
composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE);
|
||||
trieLogStorage.clear();
|
||||
super.clear();
|
||||
flatDbStrategyProvider.loadFlatDbStrategy(
|
||||
composedWorldStateStorage); // force reload of flat db reader strategy
|
||||
}
|
||||
|
||||
public void clearTrieLog() {
|
||||
subscribers.forEach(BonsaiStorageSubscriber::onClearTrieLog);
|
||||
trieLogStorage.clear();
|
||||
}
|
||||
|
||||
public void clearFlatDatabase() {
|
||||
subscribers.forEach(BonsaiStorageSubscriber::onClearFlatDatabaseStorage);
|
||||
flatDbStrategyProvider
|
||||
.getFlatDbStrategy(composedWorldStateStorage)
|
||||
.resetOnResync(composedWorldStateStorage);
|
||||
@Override
|
||||
public FlatDbStrategy getFlatDbStrategy() {
|
||||
return flatDbStrategyProvider.getFlatDbStrategy(composedWorldStateStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -277,20 +194,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
flatDbStrategyProvider.getFlatDbStrategy(composedWorldStateStorage));
|
||||
}
|
||||
|
||||
public boolean pruneTrieLog(final Hash blockHash) {
|
||||
try {
|
||||
return trieLogStorage.tryDelete(blockHash.toArrayUnsafe());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error pruning trie log for block hash {}", blockHash, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public FlatDbStrategy getFlatDbStrategy() {
|
||||
return flatDbStrategyProvider.getFlatDbStrategy(composedWorldStateStorage);
|
||||
}
|
||||
|
||||
public static class Updater implements WorldStateKeyValueStorage.Updater {
|
||||
public static class Updater implements DiffBasedWorldStateKeyValueStorage.Updater {
|
||||
|
||||
private final SegmentedKeyValueStorageTransaction composedWorldStateTransaction;
|
||||
private final KeyValueStorageTransaction trieLogStorageTransaction;
|
||||
@@ -340,6 +244,7 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Updater saveWorldState(final Bytes blockHash, final Bytes32 nodeHash, final Bytes node) {
|
||||
composedWorldStateTransaction.put(
|
||||
TRIE_BRANCH_STORAGE, Bytes.EMPTY.toArrayUnsafe(), node.toArrayUnsafe());
|
||||
@@ -392,10 +297,12 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
composedWorldStateTransaction, accountHash, slotHash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SegmentedKeyValueStorageTransaction getWorldStateTransaction() {
|
||||
return composedWorldStateTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyValueStorageTransaction getTrieLogStorageTransaction() {
|
||||
return trieLogStorageTransaction;
|
||||
}
|
||||
@@ -407,65 +314,10 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateKeyValueStorag
|
||||
composedWorldStateTransaction.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
composedWorldStateTransaction.rollback();
|
||||
trieLogStorageTransaction.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws Exception {
|
||||
// when the storage clears, close
|
||||
shouldClose.set(true);
|
||||
tryClose();
|
||||
}
|
||||
|
||||
public synchronized long subscribe(final BonsaiStorageSubscriber sub) {
|
||||
if (isClosed.get()) {
|
||||
throw new RuntimeException("Storage is marked to close or has already closed");
|
||||
}
|
||||
return subscribers.subscribe(sub);
|
||||
}
|
||||
|
||||
public synchronized void unSubscribe(final long id) {
|
||||
subscribers.unsubscribe(id);
|
||||
try {
|
||||
tryClose();
|
||||
} catch (Exception e) {
|
||||
LOG.atWarn()
|
||||
.setMessage("exception while trying to close : {}")
|
||||
.addArgument(e::getMessage)
|
||||
.log();
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void tryClose() throws Exception {
|
||||
if (shouldClose.get() && subscribers.getSubscriberCount() < 1) {
|
||||
doClose();
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void doClose() throws Exception {
|
||||
if (!isClosed.get()) {
|
||||
// alert any subscribers we are closing:
|
||||
subscribers.forEach(BonsaiStorageSubscriber::onCloseStorage);
|
||||
|
||||
// close all of the KeyValueStorages:
|
||||
composedWorldStateStorage.close();
|
||||
trieLogStorage.close();
|
||||
|
||||
// set storage closed
|
||||
isClosed.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
public interface BonsaiStorageSubscriber {
|
||||
default void onClearStorage() {}
|
||||
|
||||
default void onClearFlatDatabaseStorage() {}
|
||||
|
||||
default void onClearTrieLog() {}
|
||||
|
||||
default void onCloseStorage() {}
|
||||
}
|
||||
}
|
||||
@@ -13,21 +13,22 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
|
||||
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.SnappedKeyValueStorage;
|
||||
import org.hyperledger.besu.services.kvstore.LayeredKeyValueStorage;
|
||||
|
||||
public class BonsaiWorldStateLayerStorage extends BonsaiSnapshotWorldStateKeyValueStorage
|
||||
implements BonsaiStorageSubscriber {
|
||||
implements DiffBasedLayeredWorldStateKeyValueStorage, StorageSubscriber {
|
||||
|
||||
public BonsaiWorldStateLayerStorage(final BonsaiWorldStateKeyValueStorage parent) {
|
||||
this(
|
||||
new LayeredKeyValueStorage(parent.composedWorldStateStorage),
|
||||
parent.trieLogStorage,
|
||||
new LayeredKeyValueStorage(parent.getComposedWorldStateStorage()),
|
||||
parent.getTrieLogStorage(),
|
||||
parent);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
|
||||
@@ -21,6 +21,8 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIden
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.trie.NodeLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.CodeStorageStrategy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
|
||||
import org.hyperledger.besu.metrics.BesuMetricCategory;
|
||||
import org.hyperledger.besu.plugin.services.MetricsSystem;
|
||||
import org.hyperledger.besu.plugin.services.metrics.Counter;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
|
||||
@@ -21,6 +21,8 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIden
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.trie.NodeLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.CodeStorageStrategy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredNodeFactory;
|
||||
import org.hyperledger.besu.metrics.BesuMetricCategory;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
|
||||
|
||||
import org.hyperledger.besu.datatypes.AccountValue;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
@@ -23,7 +23,8 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
import org.hyperledger.besu.plugin.data.BlockHeader;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
@@ -150,7 +151,7 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
|
||||
final TrieLogLayer newLayer = new TrieLogLayer();
|
||||
|
||||
input.enterList();
|
||||
newLayer.blockHash = Hash.wrap(input.readBytes32());
|
||||
newLayer.setBlockHash(Hash.wrap(input.readBytes32()));
|
||||
|
||||
while (!input.isEndOfCurrentList()) {
|
||||
input.enterList();
|
||||
@@ -164,7 +165,9 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
|
||||
final StateTrieAccountValue newValue = nullOrValue(input, StateTrieAccountValue::readFrom);
|
||||
final boolean isCleared = getOptionalIsCleared(input);
|
||||
input.leaveList();
|
||||
newLayer.accounts.put(address, new BonsaiValue<>(oldValue, newValue, isCleared));
|
||||
newLayer
|
||||
.getAccountChanges()
|
||||
.put(address, new DiffBasedValue<>(oldValue, newValue, isCleared));
|
||||
}
|
||||
|
||||
if (input.nextIsNull()) {
|
||||
@@ -175,13 +178,13 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
|
||||
final Bytes newCode = nullOrValue(input, RLPInput::readBytes);
|
||||
final boolean isCleared = getOptionalIsCleared(input);
|
||||
input.leaveList();
|
||||
newLayer.code.put(address, new BonsaiValue<>(oldCode, newCode, isCleared));
|
||||
newLayer.getCodeChanges().put(address, new DiffBasedValue<>(oldCode, newCode, isCleared));
|
||||
}
|
||||
|
||||
if (input.nextIsNull()) {
|
||||
input.skipNext();
|
||||
} else {
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageChanges = new TreeMap<>();
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageChanges = new TreeMap<>();
|
||||
input.enterList();
|
||||
while (!input.isEndOfCurrentList()) {
|
||||
input.enterList();
|
||||
@@ -190,11 +193,11 @@ public class TrieLogFactoryImpl implements TrieLogFactory {
|
||||
final UInt256 oldValue = nullOrValue(input, RLPInput::readUInt256Scalar);
|
||||
final UInt256 newValue = nullOrValue(input, RLPInput::readUInt256Scalar);
|
||||
final boolean isCleared = getOptionalIsCleared(input);
|
||||
storageChanges.put(storageSlotKey, new BonsaiValue<>(oldValue, newValue, isCleared));
|
||||
storageChanges.put(storageSlotKey, new DiffBasedValue<>(oldValue, newValue, isCleared));
|
||||
input.leaveList();
|
||||
}
|
||||
input.leaveList();
|
||||
newLayer.storage.put(address, storageChanges);
|
||||
newLayer.getStorageChanges().put(address, storageChanges);
|
||||
}
|
||||
|
||||
// TODO add trie nodes
|
||||
@@ -14,39 +14,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
|
||||
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView.encodeTrieValue;
|
||||
import static org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView.encodeTrieValue;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.ethereum.trie.NodeLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator.StorageConsumingMap;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
import org.hyperledger.besu.plugin.services.exception.StorageException;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
|
||||
|
||||
@@ -63,24 +57,10 @@ import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.rlp.RLP;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BonsaiWorldState
|
||||
implements MutableWorldState, BonsaiWorldView, BonsaiStorageSubscriber {
|
||||
public class BonsaiWorldState extends DiffBasedWorldState {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldState.class);
|
||||
|
||||
protected BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
|
||||
|
||||
protected final CachedMerkleTrieLoader cachedMerkleTrieLoader;
|
||||
protected final CachedWorldStorageManager cachedWorldStorageManager;
|
||||
protected final TrieLogManager trieLogManager;
|
||||
private BonsaiWorldStateUpdateAccumulator accumulator;
|
||||
|
||||
protected Hash worldStateRootHash;
|
||||
Hash worldStateBlockHash;
|
||||
private boolean isFrozen;
|
||||
protected final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader;
|
||||
|
||||
public BonsaiWorldState(
|
||||
final BonsaiWorldStateProvider archive,
|
||||
@@ -96,90 +76,39 @@ public class BonsaiWorldState
|
||||
|
||||
public BonsaiWorldState(
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
|
||||
final CachedWorldStorageManager cachedWorldStorageManager,
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
|
||||
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
|
||||
final TrieLogManager trieLogManager,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
|
||||
this.worldStateRootHash =
|
||||
Hash.wrap(
|
||||
Bytes32.wrap(
|
||||
worldStateKeyValueStorage.getWorldStateRootHash().orElse(getEmptyTrieHash())));
|
||||
this.worldStateBlockHash =
|
||||
Hash.wrap(
|
||||
Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
|
||||
this.accumulator =
|
||||
super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager);
|
||||
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
|
||||
this.setAccumulator(
|
||||
new BonsaiWorldStateUpdateAccumulator(
|
||||
this,
|
||||
(addr, value) ->
|
||||
cachedMerkleTrieLoader.preLoadAccount(
|
||||
getWorldStateStorage(), worldStateRootHash, addr),
|
||||
bonsaiCachedMerkleTrieLoader.preLoadAccount(
|
||||
worldStateKeyValueStorage, worldStateRootHash, addr),
|
||||
(addr, value) ->
|
||||
cachedMerkleTrieLoader.preLoadStorageSlot(getWorldStateStorage(), addr, value),
|
||||
evmConfiguration);
|
||||
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
|
||||
this.cachedWorldStorageManager = cachedWorldStorageManager;
|
||||
this.trieLogManager = trieLogManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the accumulator solves the chicken-egg problem of needing a worldstate reference
|
||||
* (this) when construction the Accumulator.
|
||||
*
|
||||
* @param accumulator accumulator to use.
|
||||
*/
|
||||
public void setAccumulator(final BonsaiWorldStateUpdateAccumulator accumulator) {
|
||||
this.accumulator = accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the world state block hash of this world state
|
||||
*
|
||||
* @return the world state block hash.
|
||||
*/
|
||||
public Hash getWorldStateBlockHash() {
|
||||
return worldStateBlockHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the world state root hash of this world state
|
||||
*
|
||||
* @return the world state root hash.
|
||||
*/
|
||||
public Hash getWorldStateRootHash() {
|
||||
return worldStateRootHash;
|
||||
}
|
||||
|
||||
@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();
|
||||
bonsaiCachedMerkleTrieLoader.preLoadStorageSlot(
|
||||
getWorldStateStorage(), addr, value),
|
||||
evmConfiguration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
|
||||
return worldStateKeyValueStorage;
|
||||
return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage;
|
||||
}
|
||||
|
||||
private Hash calculateRootHash(
|
||||
@Override
|
||||
protected Hash calculateRootHash(
|
||||
final Optional<DiffBasedWorldStateKeyValueStorage.Updater> maybeStateUpdater,
|
||||
final DiffBasedWorldStateUpdateAccumulator<?> worldStateUpdater) {
|
||||
return internalCalculateRootHash(
|
||||
maybeStateUpdater.map(BonsaiWorldStateKeyValueStorage.Updater.class::cast),
|
||||
(BonsaiWorldStateUpdateAccumulator) worldStateUpdater);
|
||||
}
|
||||
|
||||
private Hash internalCalculateRootHash(
|
||||
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
|
||||
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
|
||||
|
||||
@@ -187,7 +116,7 @@ public class BonsaiWorldState
|
||||
|
||||
// This must be done before updating the accounts so
|
||||
// that we can get the storage state hash
|
||||
Stream<Map.Entry<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>>
|
||||
Stream<Map.Entry<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>>
|
||||
storageStream = worldStateUpdater.getStorageToUpdate().entrySet().stream();
|
||||
if (maybeStateUpdater.isEmpty()) {
|
||||
storageStream =
|
||||
@@ -205,8 +134,8 @@ public class BonsaiWorldState
|
||||
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
|
||||
createTrie(
|
||||
(location, hash) ->
|
||||
cachedMerkleTrieLoader.getAccountStateTrieNode(
|
||||
worldStateKeyValueStorage, location, hash),
|
||||
bonsaiCachedMerkleTrieLoader.getAccountStateTrieNode(
|
||||
getWorldStateStorage(), location, hash),
|
||||
worldStateRootHash);
|
||||
|
||||
// for manicured tries and composting, collect branches here (not implemented)
|
||||
@@ -231,10 +160,10 @@ public class BonsaiWorldState
|
||||
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
|
||||
final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
|
||||
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie) {
|
||||
for (final Map.Entry<Address, BonsaiValue<BonsaiAccount>> accountUpdate :
|
||||
for (final Map.Entry<Address, DiffBasedValue<BonsaiAccount>> accountUpdate :
|
||||
worldStateUpdater.getAccountsToUpdate().entrySet()) {
|
||||
final Bytes accountKey = accountUpdate.getKey();
|
||||
final BonsaiValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue();
|
||||
final DiffBasedValue<BonsaiAccount> bonsaiValue = accountUpdate.getValue();
|
||||
final BonsaiAccount updatedAccount = bonsaiValue.getUpdated();
|
||||
try {
|
||||
if (updatedAccount == null) {
|
||||
@@ -264,7 +193,7 @@ public class BonsaiWorldState
|
||||
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
|
||||
maybeStateUpdater.ifPresent(
|
||||
bonsaiUpdater -> {
|
||||
for (final Map.Entry<Address, BonsaiValue<Bytes>> codeUpdate :
|
||||
for (final Map.Entry<Address, DiffBasedValue<Bytes>> codeUpdate :
|
||||
worldStateUpdater.getCodeToUpdate().entrySet()) {
|
||||
final Bytes updatedCode = codeUpdate.getValue().getUpdated();
|
||||
final Hash accountHash = codeUpdate.getKey().addressHash();
|
||||
@@ -294,12 +223,12 @@ public class BonsaiWorldState
|
||||
private void updateAccountStorageState(
|
||||
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
|
||||
final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
|
||||
final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>
|
||||
final Map.Entry<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
|
||||
storageAccountUpdate) {
|
||||
final Address updatedAddress = storageAccountUpdate.getKey();
|
||||
final Hash updatedAddressHash = updatedAddress.addressHash();
|
||||
if (worldStateUpdater.getAccountsToUpdate().containsKey(updatedAddress)) {
|
||||
final BonsaiValue<BonsaiAccount> accountValue =
|
||||
final DiffBasedValue<BonsaiAccount> accountValue =
|
||||
worldStateUpdater.getAccountsToUpdate().get(updatedAddress);
|
||||
final BonsaiAccount accountOriginal = accountValue.getPrior();
|
||||
final Hash storageRoot =
|
||||
@@ -310,12 +239,12 @@ public class BonsaiWorldState
|
||||
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
|
||||
createTrie(
|
||||
(location, key) ->
|
||||
cachedMerkleTrieLoader.getAccountStorageTrieNode(
|
||||
worldStateKeyValueStorage, updatedAddressHash, location, key),
|
||||
bonsaiCachedMerkleTrieLoader.getAccountStorageTrieNode(
|
||||
getWorldStateStorage(), updatedAddressHash, location, key),
|
||||
storageRoot);
|
||||
|
||||
// for manicured tries and composting, collect branches here (not implemented)
|
||||
for (final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> storageUpdate :
|
||||
for (final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> storageUpdate :
|
||||
storageAccountUpdate.getValue().entrySet()) {
|
||||
final Hash slotHash = storageUpdate.getKey().getSlotHash();
|
||||
final UInt256 updatedStorage = storageUpdate.getValue().getUpdated();
|
||||
@@ -360,11 +289,10 @@ public class BonsaiWorldState
|
||||
private void clearStorage(
|
||||
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
|
||||
final BonsaiWorldStateUpdateAccumulator worldStateUpdater) {
|
||||
|
||||
for (final Address address : worldStateUpdater.getStorageToClear()) {
|
||||
// because we are clearing persisted values we need the account root as persisted
|
||||
final BonsaiAccount oldAccount =
|
||||
worldStateKeyValueStorage
|
||||
getWorldStateStorage()
|
||||
.getAccount(address.addressHash())
|
||||
.map(bytes -> BonsaiAccount.fromRLP(BonsaiWorldState.this, address, bytes, true))
|
||||
.orElse(null);
|
||||
@@ -379,7 +307,7 @@ public class BonsaiWorldState
|
||||
(location, key) -> getStorageTrieNode(addressHash, location, key),
|
||||
oldAccount.getStorageRoot());
|
||||
try {
|
||||
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> storageToDelete =
|
||||
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> storageToDelete =
|
||||
worldStateUpdater.getStorageToUpdate().get(address);
|
||||
Map<Bytes32, Bytes> entriesToDelete = storageTrie.entriesFrom(Bytes32.ZERO, 256);
|
||||
while (!entriesToDelete.isEmpty()) {
|
||||
@@ -394,7 +322,7 @@ public class BonsaiWorldState
|
||||
address.addressHash(), storageSlotKey.getSlotHash()));
|
||||
storageToDelete
|
||||
.computeIfAbsent(
|
||||
storageSlotKey, key -> new BonsaiValue<>(slotValue, null, true))
|
||||
storageSlotKey, key -> new DiffBasedValue<>(slotValue, null, true))
|
||||
.setPrior(slotValue);
|
||||
});
|
||||
entriesToDelete.keySet().forEach(storageTrie::remove);
|
||||
@@ -412,138 +340,6 @@ public class BonsaiWorldState
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persist(final BlockHeader blockHeader) {
|
||||
final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader);
|
||||
LOG.atDebug()
|
||||
.setMessage("Persist world state for block {}")
|
||||
.addArgument(maybeBlockHeader)
|
||||
.log();
|
||||
|
||||
final BonsaiWorldStateUpdateAccumulator localCopy = accumulator.copy();
|
||||
|
||||
boolean success = false;
|
||||
|
||||
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater =
|
||||
worldStateKeyValueStorage.updater();
|
||||
Runnable saveTrieLog = () -> {};
|
||||
|
||||
try {
|
||||
final Hash newWorldStateRootHash =
|
||||
calculateRootHash(isFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator);
|
||||
// if we are persisted with a block header, and the prior state is the parent
|
||||
// then persist the TrieLog for that transition.
|
||||
// If specified but not a direct descendant simply store the new block hash.
|
||||
if (blockHeader != null) {
|
||||
verifyWorldStateRoot(newWorldStateRootHash, blockHeader);
|
||||
saveTrieLog =
|
||||
() -> {
|
||||
trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this);
|
||||
// not save a frozen state in the cache
|
||||
if (!isFrozen) {
|
||||
cachedWorldStorageManager.addCachedLayer(blockHeader, newWorldStateRootHash, this);
|
||||
}
|
||||
};
|
||||
|
||||
stateUpdater
|
||||
.getWorldStateTransaction()
|
||||
.put(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY, blockHeader.getHash().toArrayUnsafe());
|
||||
worldStateBlockHash = blockHeader.getHash();
|
||||
} else {
|
||||
stateUpdater.getWorldStateTransaction().remove(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY);
|
||||
worldStateBlockHash = null;
|
||||
}
|
||||
|
||||
stateUpdater
|
||||
.getWorldStateTransaction()
|
||||
.put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, newWorldStateRootHash.toArrayUnsafe());
|
||||
worldStateRootHash = newWorldStateRootHash;
|
||||
success = true;
|
||||
} finally {
|
||||
if (success) {
|
||||
stateUpdater.commit();
|
||||
accumulator.reset();
|
||||
saveTrieLog.run();
|
||||
} else {
|
||||
stateUpdater.rollback();
|
||||
accumulator.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) {
|
||||
if (!calculatedStateRoot.equals(header.getStateRoot())) {
|
||||
throw new RuntimeException(
|
||||
"World State Root does not match expected value, header "
|
||||
+ header.getStateRoot().toHexString()
|
||||
+ " calculated "
|
||||
+ calculatedStateRoot.toHexString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldUpdater updater() {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash rootHash() {
|
||||
if (isFrozen && accumulator.isAccumulatorStateChanged()) {
|
||||
worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy());
|
||||
accumulator.resetAccumulatorStateChanged();
|
||||
}
|
||||
return Hash.wrap(worldStateRootHash);
|
||||
}
|
||||
|
||||
static final KeyValueStorageTransaction noOpTx =
|
||||
new KeyValueStorageTransaction() {
|
||||
|
||||
@Override
|
||||
public void put(final byte[] key, final byte[] value) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final byte[] key) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() throws StorageException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
// no-op
|
||||
}
|
||||
};
|
||||
|
||||
static final SegmentedKeyValueStorageTransaction noOpSegmentedTx =
|
||||
new SegmentedKeyValueStorageTransaction() {
|
||||
|
||||
@Override
|
||||
public void put(
|
||||
final SegmentIdentifier segmentIdentifier, final byte[] key, final byte[] value) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final SegmentIdentifier segmentIdentifier, final byte[] key) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() throws StorageException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
// no-op
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Hash frontierRootHash() {
|
||||
return calculateRootHash(
|
||||
@@ -553,25 +349,28 @@ public class BonsaiWorldState
|
||||
accumulator.copy());
|
||||
}
|
||||
|
||||
public Hash blockHash() {
|
||||
return worldStateBlockHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<StreamableAccount> streamAccounts(final Bytes32 startKeyHash, final int limit) {
|
||||
throw new RuntimeException("Bonsai Tries do not provide account streaming.");
|
||||
public MutableWorldState freeze() {
|
||||
this.isFrozen = true;
|
||||
this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account get(final Address address) {
|
||||
return worldStateKeyValueStorage
|
||||
return getWorldStateStorage()
|
||||
.getAccount(address.addressHash())
|
||||
.map(bytes -> BonsaiAccount.fromRLP(accumulator, address, bytes, true))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
|
||||
return getWorldStateStorage().getCode(codeHash, address.addressHash());
|
||||
}
|
||||
|
||||
protected Optional<Bytes> getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) {
|
||||
return worldStateKeyValueStorage.getAccountStateTrieNode(location, nodeHash);
|
||||
return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash);
|
||||
}
|
||||
|
||||
private void writeTrieNode(
|
||||
@@ -584,7 +383,7 @@ public class BonsaiWorldState
|
||||
|
||||
protected Optional<Bytes> getStorageTrieNode(
|
||||
final Hash accountHash, final Bytes location, final Bytes32 nodeHash) {
|
||||
return worldStateKeyValueStorage.getAccountStorageTrieNode(accountHash, location, nodeHash);
|
||||
return getWorldStateStorage().getAccountStorageTrieNode(accountHash, location, nodeHash);
|
||||
}
|
||||
|
||||
private void writeStorageTrieNode(
|
||||
@@ -605,7 +404,7 @@ public class BonsaiWorldState
|
||||
@Override
|
||||
public Optional<UInt256> getStorageValueByStorageSlotKey(
|
||||
final Address address, final StorageSlotKey storageSlotKey) {
|
||||
return worldStateKeyValueStorage
|
||||
return getWorldStateStorage()
|
||||
.getStorageValueByStorageSlotKey(address.addressHash(), storageSlotKey)
|
||||
.map(UInt256::fromBytes);
|
||||
}
|
||||
@@ -614,7 +413,7 @@ public class BonsaiWorldState
|
||||
final Supplier<Optional<Hash>> storageRootSupplier,
|
||||
final Address address,
|
||||
final StorageSlotKey storageSlotKey) {
|
||||
return worldStateKeyValueStorage
|
||||
return getWorldStateStorage()
|
||||
.getStorageValueByStorageSlotKey(storageRootSupplier, address.addressHash(), storageSlotKey)
|
||||
.map(UInt256::fromBytes);
|
||||
}
|
||||
@@ -632,50 +431,18 @@ public class BonsaiWorldState
|
||||
return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableWorldState freeze() {
|
||||
this.isFrozen = true;
|
||||
this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(worldStateKeyValueStorage);
|
||||
return this;
|
||||
}
|
||||
|
||||
private StoredMerklePatriciaTrie<Bytes, Bytes> createTrie(
|
||||
final NodeLoader nodeLoader, final Bytes32 rootHash) {
|
||||
return new StoredMerklePatriciaTrie<>(
|
||||
nodeLoader, rootHash, Function.identity(), Function.identity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
if (!isPersisted()) {
|
||||
this.worldStateKeyValueStorage.close();
|
||||
if (isFrozen) {
|
||||
closeFrozenStorage();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no op
|
||||
}
|
||||
}
|
||||
|
||||
private void closeFrozenStorage() {
|
||||
try {
|
||||
final BonsaiWorldStateLayerStorage worldStateLayerStorage =
|
||||
(BonsaiWorldStateLayerStorage) worldStateKeyValueStorage;
|
||||
if (!isPersisted(worldStateLayerStorage.getParentWorldStateStorage())) {
|
||||
worldStateLayerStorage.getParentWorldStateStorage().close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no op
|
||||
}
|
||||
}
|
||||
|
||||
protected Hash hashAndSavePreImage(final Bytes value) {
|
||||
// by default do not save has preImages
|
||||
return Hash.hash(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Hash getEmptyTrieHash() {
|
||||
return Hash.EMPTY_TRIE_HASH;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview;
|
||||
|
||||
import org.hyperledger.besu.datatypes.AccountValue;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.Consumer;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
|
||||
|
||||
public class BonsaiWorldStateUpdateAccumulator
|
||||
extends DiffBasedWorldStateUpdateAccumulator<BonsaiAccount> {
|
||||
public BonsaiWorldStateUpdateAccumulator(
|
||||
final DiffBasedWorldView world,
|
||||
final Consumer<DiffBasedValue<BonsaiAccount>> accountPreloader,
|
||||
final Consumer<StorageSlotKey> storagePreloader,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
super(world, accountPreloader, storagePreloader, evmConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiffBasedWorldStateUpdateAccumulator<BonsaiAccount> copy() {
|
||||
final BonsaiWorldStateUpdateAccumulator copy =
|
||||
new BonsaiWorldStateUpdateAccumulator(
|
||||
wrappedWorldView(),
|
||||
getAccountPreloader(),
|
||||
getStoragePreloader(),
|
||||
getEvmConfiguration());
|
||||
copy.cloneFromUpdater(this);
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BonsaiAccount copyAccount(final BonsaiAccount account) {
|
||||
return new BonsaiAccount(account);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BonsaiAccount copyAccount(
|
||||
final BonsaiAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
|
||||
return new BonsaiAccount(toCopy, context, mutable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BonsaiAccount createAccount(
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final AccountValue stateTrieAccount,
|
||||
final boolean mutable) {
|
||||
return new BonsaiAccount(context, address, stateTrieAccount, mutable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BonsaiAccount createAccount(
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final Hash addressHash,
|
||||
final long nonce,
|
||||
final Wei balance,
|
||||
final Hash storageRoot,
|
||||
final Hash codeHash,
|
||||
final boolean mutable) {
|
||||
return new BonsaiAccount(
|
||||
context, address, addressHash, nonce, balance, storageRoot, codeHash, mutable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BonsaiAccount createAccount(
|
||||
final DiffBasedWorldView context, final UpdateTrackingAccount<BonsaiAccount> tracked) {
|
||||
return new BonsaiAccount(context, tracked);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertCloseEnoughForDiffing(
|
||||
final BonsaiAccount source, final AccountValue account, final String context) {
|
||||
BonsaiAccount.assertCloseEnoughForDiffing(source, account, context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common;
|
||||
|
||||
import org.hyperledger.besu.datatypes.AccountValue;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
|
||||
import org.hyperledger.besu.evm.ModificationNotAllowedException;
|
||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
|
||||
public abstract class DiffBasedAccount implements MutableAccount, AccountValue {
|
||||
protected final DiffBasedWorldView context;
|
||||
protected boolean immutable;
|
||||
protected final Address address;
|
||||
protected final Hash addressHash;
|
||||
protected Hash codeHash;
|
||||
protected long nonce;
|
||||
protected Wei balance;
|
||||
protected Bytes code;
|
||||
|
||||
protected final Map<UInt256, UInt256> updatedStorage = new HashMap<>();
|
||||
|
||||
public DiffBasedAccount(
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final Hash addressHash,
|
||||
final long nonce,
|
||||
final Wei balance,
|
||||
final Hash codeHash,
|
||||
final boolean mutable) {
|
||||
this.context = context;
|
||||
this.address = address;
|
||||
this.addressHash = addressHash;
|
||||
this.nonce = nonce;
|
||||
this.balance = balance;
|
||||
this.codeHash = codeHash;
|
||||
|
||||
this.immutable = !mutable;
|
||||
}
|
||||
|
||||
public DiffBasedAccount(
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final AccountValue stateTrieAccount,
|
||||
final boolean mutable) {
|
||||
this(
|
||||
context,
|
||||
address,
|
||||
address.addressHash(),
|
||||
stateTrieAccount.getNonce(),
|
||||
stateTrieAccount.getBalance(),
|
||||
stateTrieAccount.getCodeHash(),
|
||||
mutable);
|
||||
}
|
||||
|
||||
public DiffBasedAccount(
|
||||
final DiffBasedAccount toCopy, final DiffBasedWorldView context, final boolean mutable) {
|
||||
this.context = context;
|
||||
this.address = toCopy.address;
|
||||
this.addressHash = toCopy.addressHash;
|
||||
this.nonce = toCopy.nonce;
|
||||
this.balance = toCopy.balance;
|
||||
this.codeHash = toCopy.codeHash;
|
||||
this.code = toCopy.code;
|
||||
updatedStorage.putAll(toCopy.updatedStorage);
|
||||
|
||||
this.immutable = !mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash getAddressHash() {
|
||||
return addressHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNonce(final long value) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
nonce = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wei getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBalance(final Wei value) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
balance = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bytes getCode() {
|
||||
if (code == null) {
|
||||
code = context.getCode(address, codeHash).orElse(Bytes.EMPTY);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCode(final Bytes code) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
this.code = code;
|
||||
if (code == null || code.isEmpty()) {
|
||||
this.codeHash = Hash.EMPTY;
|
||||
} else {
|
||||
this.codeHash = Hash.hash(code);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash getCodeHash() {
|
||||
return codeHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt256 getStorageValue(final UInt256 key) {
|
||||
return context.getStorageValue(address, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt256 getOriginalStorageValue(final UInt256 key) {
|
||||
return context.getPriorStorageValue(address, key);
|
||||
}
|
||||
|
||||
public Bytes serializeAccount() {
|
||||
final BytesValueRLPOutput out = new BytesValueRLPOutput();
|
||||
writeTo(out);
|
||||
return out.encoded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageValue(final UInt256 key, final UInt256 value) {
|
||||
if (immutable) {
|
||||
throw new ModificationNotAllowedException();
|
||||
}
|
||||
updatedStorage.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearStorage() {
|
||||
updatedStorage.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<UInt256, UInt256> getUpdatedStorage() {
|
||||
return updatedStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void becomeImmutable() {
|
||||
immutable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccountState{"
|
||||
+ "address="
|
||||
+ address
|
||||
+ ", nonce="
|
||||
+ nonce
|
||||
+ ", balance="
|
||||
+ balance
|
||||
+ ", codeHash="
|
||||
+ codeHash
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
@@ -11,38 +11,37 @@
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common;
|
||||
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
|
||||
public class DiffBasedValue<T> implements TrieLog.LogTuple<T> {
|
||||
private T prior;
|
||||
private T updated;
|
||||
private boolean lastStepCleared;
|
||||
|
||||
private boolean clearedAtLeastOnce;
|
||||
|
||||
public BonsaiValue(final T prior, final T updated) {
|
||||
public DiffBasedValue(final T prior, final T updated) {
|
||||
this.prior = prior;
|
||||
this.updated = updated;
|
||||
this.lastStepCleared = false;
|
||||
this.clearedAtLeastOnce = false;
|
||||
}
|
||||
|
||||
public BonsaiValue(final T prior, final T updated, final boolean lastStepCleared) {
|
||||
public DiffBasedValue(final T prior, final T updated, final boolean lastStepCleared) {
|
||||
this.prior = prior;
|
||||
this.updated = updated;
|
||||
this.lastStepCleared = lastStepCleared;
|
||||
this.clearedAtLeastOnce = lastStepCleared;
|
||||
}
|
||||
|
||||
public BonsaiValue(
|
||||
public DiffBasedValue(
|
||||
final T prior,
|
||||
final T updated,
|
||||
final boolean lastStepCleared,
|
||||
@@ -63,12 +62,12 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
|
||||
return updated;
|
||||
}
|
||||
|
||||
public BonsaiValue<T> setPrior(final T prior) {
|
||||
public DiffBasedValue<T> setPrior(final T prior) {
|
||||
this.prior = prior;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BonsaiValue<T> setUpdated(final T updated) {
|
||||
public DiffBasedValue<T> setUpdated(final T updated) {
|
||||
this.lastStepCleared = updated == null;
|
||||
if (lastStepCleared) {
|
||||
this.clearedAtLeastOnce = true;
|
||||
@@ -94,7 +93,7 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BonsaiValue{"
|
||||
return "DiffBasedValue{"
|
||||
+ "prior="
|
||||
+ prior
|
||||
+ ", updated="
|
||||
@@ -112,7 +111,7 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
BonsaiValue<?> that = (BonsaiValue<?>) o;
|
||||
DiffBasedValue<?> that = (DiffBasedValue<?>) o;
|
||||
return new EqualsBuilder()
|
||||
.append(lastStepCleared, that.lastStepCleared)
|
||||
.append(prior, that.prior)
|
||||
@@ -129,7 +128,7 @@ public class BonsaiValue<T> implements TrieLog.LogTuple<T> {
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
public BonsaiValue<T> copy() {
|
||||
return new BonsaiValue<T>(prior, updated, lastStepCleared, clearedAtLeastOnce);
|
||||
public DiffBasedValue<T> copy() {
|
||||
return new DiffBasedValue<T>(prior, updated, lastStepCleared, clearedAtLeastOnce);
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager.RETAINED_LAYERS;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
@@ -25,91 +23,75 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.proof.WorldStateProof;
|
||||
import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldState;
|
||||
import org.hyperledger.besu.plugin.BesuContext;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateProvider.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DiffBasedWorldStateProvider.class);
|
||||
|
||||
private final Blockchain blockchain;
|
||||
protected final Blockchain blockchain;
|
||||
|
||||
private final CachedWorldStorageManager cachedWorldStorageManager;
|
||||
private final TrieLogManager trieLogManager;
|
||||
private final BonsaiWorldState persistedState;
|
||||
private final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
|
||||
private final CachedMerkleTrieLoader cachedMerkleTrieLoader;
|
||||
protected final TrieLogManager trieLogManager;
|
||||
protected DiffBasedCachedWorldStorageManager cachedWorldStorageManager;
|
||||
protected DiffBasedWorldState persistedState;
|
||||
|
||||
public BonsaiWorldStateProvider(
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
protected final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage;
|
||||
|
||||
public DiffBasedWorldStateProvider(
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final Blockchain blockchain,
|
||||
final Optional<Long> maxLayersToLoad,
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
|
||||
final BesuContext pluginContext,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final BesuContext pluginContext) {
|
||||
|
||||
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
|
||||
this.cachedWorldStorageManager = new CachedWorldStorageManager(this, worldStateKeyValueStorage);
|
||||
|
||||
// TODO: de-dup constructors
|
||||
this.trieLogManager =
|
||||
new TrieLogManager(
|
||||
blockchain,
|
||||
worldStateKeyValueStorage,
|
||||
maxLayersToLoad.orElse(RETAINED_LAYERS),
|
||||
maxLayersToLoad.orElse(DiffBasedCachedWorldStorageManager.RETAINED_LAYERS),
|
||||
pluginContext);
|
||||
this.blockchain = blockchain;
|
||||
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
|
||||
this.persistedState = new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration);
|
||||
blockchain
|
||||
.getBlockHeader(persistedState.getWorldStateBlockHash())
|
||||
.ifPresent(
|
||||
blockHeader ->
|
||||
this.cachedWorldStorageManager.addCachedLayer(
|
||||
blockHeader, persistedState.getWorldStateRootHash(), persistedState));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BonsaiWorldStateProvider(
|
||||
final CachedWorldStorageManager cachedWorldStorageManager,
|
||||
final TrieLogManager trieLogManager,
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
public DiffBasedWorldStateProvider(
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final Blockchain blockchain,
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
this.cachedWorldStorageManager = cachedWorldStorageManager;
|
||||
final TrieLogManager trieLogManager) {
|
||||
|
||||
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
|
||||
// TODO: de-dup constructors
|
||||
this.trieLogManager = trieLogManager;
|
||||
this.blockchain = blockchain;
|
||||
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
|
||||
this.persistedState = new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration);
|
||||
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
|
||||
}
|
||||
|
||||
protected void provideCachedWorldStorageManager(
|
||||
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager) {
|
||||
this.cachedWorldStorageManager = cachedWorldStorageManager;
|
||||
}
|
||||
|
||||
protected void loadPersistedState(final DiffBasedWorldState persistedState) {
|
||||
this.persistedState = persistedState;
|
||||
blockchain
|
||||
.getBlockHeader(persistedState.getWorldStateBlockHash())
|
||||
.ifPresent(
|
||||
@@ -158,9 +140,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
.getWorldState(blockHeader.getHash())
|
||||
.or(() -> cachedWorldStorageManager.getNearestWorldState(blockHeader))
|
||||
.or(() -> cachedWorldStorageManager.getHeadWorldState(blockchain::getBlockHeader))
|
||||
.flatMap(
|
||||
bonsaiWorldState ->
|
||||
rollMutableStateToBlockHash(bonsaiWorldState, blockHeader.getHash()))
|
||||
.flatMap(worldState -> rollMutableStateToBlockHash(worldState, blockHeader.getHash()))
|
||||
.map(MutableWorldState::freeze);
|
||||
}
|
||||
}
|
||||
@@ -172,7 +152,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
}
|
||||
|
||||
Optional<MutableWorldState> rollMutableStateToBlockHash(
|
||||
final BonsaiWorldState mutableState, final Hash blockHash) {
|
||||
final DiffBasedWorldState mutableState, final Hash blockHash) {
|
||||
if (blockHash.equals(mutableState.blockHash())) {
|
||||
return Optional.of(mutableState);
|
||||
} else {
|
||||
@@ -221,19 +201,19 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
}
|
||||
|
||||
// attempt the state rolling
|
||||
final BonsaiWorldStateUpdateAccumulator bonsaiUpdater =
|
||||
(BonsaiWorldStateUpdateAccumulator) mutableState.updater();
|
||||
final DiffBasedWorldStateUpdateAccumulator<?> diffBasedUpdater =
|
||||
(DiffBasedWorldStateUpdateAccumulator<?>) mutableState.updater();
|
||||
try {
|
||||
for (final TrieLog rollBack : rollBacks) {
|
||||
LOG.debug("Attempting Rollback of {}", rollBack.getBlockHash());
|
||||
bonsaiUpdater.rollBack(rollBack);
|
||||
diffBasedUpdater.rollBack(rollBack);
|
||||
}
|
||||
for (int i = rollForwards.size() - 1; i >= 0; i--) {
|
||||
final var forward = rollForwards.get(i);
|
||||
LOG.debug("Attempting Rollforward of {}", rollForwards.get(i).getBlockHash());
|
||||
bonsaiUpdater.rollForward(forward);
|
||||
diffBasedUpdater.rollForward(forward);
|
||||
}
|
||||
bonsaiUpdater.commit();
|
||||
diffBasedUpdater.commit();
|
||||
|
||||
mutableState.persist(blockchain.getBlockHeader(blockHash).get());
|
||||
|
||||
@@ -247,7 +227,7 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
throw re;
|
||||
} catch (final Exception e) {
|
||||
// if we fail we must clean up the updater
|
||||
bonsaiUpdater.reset();
|
||||
diffBasedUpdater.reset();
|
||||
LOG.debug(
|
||||
"State rolling failed on "
|
||||
+ mutableState.getWorldStateStorage().getClass().getSimpleName()
|
||||
@@ -269,80 +249,16 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
}
|
||||
}
|
||||
|
||||
public CachedMerkleTrieLoader getCachedMerkleTrieLoader() {
|
||||
return cachedMerkleTrieLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableWorldState getMutable() {
|
||||
return persistedState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the state healing process for a given address and location. It prepares the state
|
||||
* healing, including retrieving data from storage, identifying invalid slots or nodes, removing
|
||||
* account and slot from the state trie, and committing the changes. Finally, it downgrades the
|
||||
* world state storage to partial flat database mode.
|
||||
*/
|
||||
public void prepareStateHealing(final Address address, final Bytes location) {
|
||||
final Set<Bytes> keysToDelete = new HashSet<>();
|
||||
final BonsaiWorldStateKeyValueStorage.Updater updater = worldStateKeyValueStorage.updater();
|
||||
final Hash accountHash = address.addressHash();
|
||||
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
|
||||
new StoredMerklePatriciaTrie<>(
|
||||
(l, h) -> {
|
||||
final Optional<Bytes> node = worldStateKeyValueStorage.getAccountStateTrieNode(l, h);
|
||||
if (node.isPresent()) {
|
||||
keysToDelete.add(l);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
persistedState.getWorldStateRootHash(),
|
||||
Function.identity(),
|
||||
Function.identity());
|
||||
try {
|
||||
accountTrie
|
||||
.get(accountHash)
|
||||
.map(RLP::input)
|
||||
.map(StateTrieAccountValue::readFrom)
|
||||
.ifPresent(
|
||||
account -> {
|
||||
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
|
||||
new StoredMerklePatriciaTrie<>(
|
||||
(l, h) -> {
|
||||
Optional<Bytes> node =
|
||||
worldStateKeyValueStorage.getAccountStorageTrieNode(
|
||||
accountHash, l, h);
|
||||
if (node.isPresent()) {
|
||||
keysToDelete.add(Bytes.concatenate(accountHash, l));
|
||||
}
|
||||
return node;
|
||||
},
|
||||
account.getStorageRoot(),
|
||||
Function.identity(),
|
||||
Function.identity());
|
||||
try {
|
||||
storageTrie.getPath(location);
|
||||
} catch (Exception eA) {
|
||||
LOG.warn("Invalid slot found for account {} at location {}", address, location);
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
} catch (Exception eA) {
|
||||
LOG.warn("Invalid node for account {} at location {}", address, location);
|
||||
// ignore
|
||||
}
|
||||
keysToDelete.forEach(bytes -> updater.removeAccountStateTrieNode(bytes));
|
||||
updater.commit();
|
||||
|
||||
worldStateKeyValueStorage.downgradeToPartialFlatDbMode();
|
||||
}
|
||||
|
||||
public TrieLogManager getTrieLogManager() {
|
||||
return trieLogManager;
|
||||
}
|
||||
|
||||
public CachedWorldStorageManager getCachedWorldStorageManager() {
|
||||
public DiffBasedCachedWorldStorageManager getCachedWorldStorageManager() {
|
||||
return cachedWorldStorageManager;
|
||||
}
|
||||
|
||||
@@ -360,7 +276,8 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
|
||||
final Address accountAddress,
|
||||
final List<UInt256> accountStorageKeys,
|
||||
final Function<Optional<WorldStateProof>, ? extends Optional<U>> mapper) {
|
||||
try (BonsaiWorldState ws = (BonsaiWorldState) getMutable(blockHeader, false).orElse(null)) {
|
||||
try (DiffBasedWorldState ws =
|
||||
(DiffBasedWorldState) getMutable(blockHeader, false).orElse(null)) {
|
||||
if (ws != null) {
|
||||
final WorldStateProofProvider worldStateProofProvider =
|
||||
new WorldStateProofProvider(
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common;
|
||||
|
||||
public interface StorageSubscriber {
|
||||
default void onClearStorage() {}
|
||||
|
||||
default void onClearFlatDatabaseStorage() {}
|
||||
|
||||
default void onClearTrieLog() {}
|
||||
|
||||
default void onCloseStorage() {}
|
||||
}
|
||||
@@ -12,15 +12,15 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.cache;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -35,20 +35,20 @@ import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CachedWorldStorageManager
|
||||
implements BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
|
||||
public abstract class DiffBasedCachedWorldStorageManager implements StorageSubscriber {
|
||||
public static final long RETAINED_LAYERS = 512; // at least 256 + typical rollbacks
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CachedWorldStorageManager.class);
|
||||
private final BonsaiWorldStateProvider archive;
|
||||
private static final Logger LOG =
|
||||
LoggerFactory.getLogger(DiffBasedCachedWorldStorageManager.class);
|
||||
private final DiffBasedWorldStateProvider archive;
|
||||
private final EvmConfiguration evmConfiguration;
|
||||
|
||||
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
|
||||
private final Map<Bytes32, CachedBonsaiWorldView> cachedWorldStatesByHash;
|
||||
private final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
|
||||
private final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash;
|
||||
|
||||
private CachedWorldStorageManager(
|
||||
final BonsaiWorldStateProvider archive,
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final Map<Bytes32, CachedBonsaiWorldView> cachedWorldStatesByHash,
|
||||
private DiffBasedCachedWorldStorageManager(
|
||||
final DiffBasedWorldStateProvider archive,
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
worldStateKeyValueStorage.subscribe(this);
|
||||
this.rootWorldStateStorage = worldStateKeyValueStorage;
|
||||
@@ -57,32 +57,32 @@ public class CachedWorldStorageManager
|
||||
this.evmConfiguration = evmConfiguration;
|
||||
}
|
||||
|
||||
public CachedWorldStorageManager(
|
||||
final BonsaiWorldStateProvider archive,
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage) {
|
||||
public DiffBasedCachedWorldStorageManager(
|
||||
final DiffBasedWorldStateProvider archive,
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) {
|
||||
this(archive, worldStateKeyValueStorage, new ConcurrentHashMap<>(), EvmConfiguration.DEFAULT);
|
||||
}
|
||||
|
||||
public synchronized void addCachedLayer(
|
||||
final BlockHeader blockHeader,
|
||||
final Hash worldStateRootHash,
|
||||
final BonsaiWorldState forWorldState) {
|
||||
final Optional<CachedBonsaiWorldView> cachedBonsaiWorldView =
|
||||
final DiffBasedWorldState forWorldState) {
|
||||
final Optional<DiffBasedCachedWorldView> cachedDiffBasedWorldView =
|
||||
Optional.ofNullable(this.cachedWorldStatesByHash.get(blockHeader.getBlockHash()));
|
||||
if (cachedBonsaiWorldView.isPresent()) {
|
||||
if (cachedDiffBasedWorldView.isPresent()) {
|
||||
// only replace if it is a layered storage
|
||||
if (forWorldState.isPersisted()
|
||||
&& cachedBonsaiWorldView.get().getWorldStateStorage()
|
||||
instanceof BonsaiWorldStateLayerStorage) {
|
||||
&& cachedDiffBasedWorldView.get().getWorldStateStorage()
|
||||
instanceof DiffBasedLayeredWorldStateKeyValueStorage) {
|
||||
LOG.atDebug()
|
||||
.setMessage("updating layered world state for block {}, state root hash {}")
|
||||
.addArgument(blockHeader::toLogString)
|
||||
.addArgument(worldStateRootHash::toShortHexString)
|
||||
.log();
|
||||
cachedBonsaiWorldView
|
||||
cachedDiffBasedWorldView
|
||||
.get()
|
||||
.updateWorldStateStorage(
|
||||
new BonsaiSnapshotWorldStateKeyValueStorage(forWorldState.getWorldStateStorage()));
|
||||
createSnapshotKeyValueStorage(forWorldState.getWorldStateStorage()));
|
||||
}
|
||||
} else {
|
||||
LOG.atDebug()
|
||||
@@ -93,16 +93,16 @@ public class CachedWorldStorageManager
|
||||
if (forWorldState.isPersisted()) {
|
||||
cachedWorldStatesByHash.put(
|
||||
blockHeader.getHash(),
|
||||
new CachedBonsaiWorldView(
|
||||
blockHeader,
|
||||
new BonsaiSnapshotWorldStateKeyValueStorage(forWorldState.getWorldStateStorage())));
|
||||
new DiffBasedCachedWorldView(
|
||||
blockHeader, createSnapshotKeyValueStorage(forWorldState.getWorldStateStorage())));
|
||||
} else {
|
||||
// otherwise, add the layer to the cache
|
||||
cachedWorldStatesByHash.put(
|
||||
blockHeader.getHash(),
|
||||
new CachedBonsaiWorldView(
|
||||
new DiffBasedCachedWorldView(
|
||||
blockHeader,
|
||||
((BonsaiWorldStateLayerStorage) forWorldState.getWorldStateStorage()).clone()));
|
||||
((DiffBasedLayeredWorldStateKeyValueStorage) forWorldState.getWorldStateStorage())
|
||||
.clone()));
|
||||
}
|
||||
}
|
||||
scrubCachedLayers(blockHeader.getNumber());
|
||||
@@ -122,15 +122,15 @@ public class CachedWorldStorageManager
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<BonsaiWorldState> getWorldState(final Hash blockHash) {
|
||||
public Optional<DiffBasedWorldState> getWorldState(final Hash blockHash) {
|
||||
if (cachedWorldStatesByHash.containsKey(blockHash)) {
|
||||
// return a new worldstate using worldstate storage and an isolated copy of the updater
|
||||
return Optional.ofNullable(cachedWorldStatesByHash.get(blockHash))
|
||||
.map(
|
||||
cached ->
|
||||
new BonsaiWorldState(
|
||||
createWorldState(
|
||||
archive,
|
||||
new BonsaiWorldStateLayerStorage(cached.getWorldStateStorage()),
|
||||
createLayeredKeyValueStorage(cached.getWorldStateStorage()),
|
||||
evmConfiguration));
|
||||
}
|
||||
LOG.atDebug()
|
||||
@@ -141,7 +141,7 @@ public class CachedWorldStorageManager
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Optional<BonsaiWorldState> getNearestWorldState(final BlockHeader blockHeader) {
|
||||
public Optional<DiffBasedWorldState> getNearestWorldState(final BlockHeader blockHeader) {
|
||||
LOG.atDebug()
|
||||
.setMessage("getting nearest worldstate for {}")
|
||||
.addArgument(blockHeader.toLogString())
|
||||
@@ -149,7 +149,7 @@ public class CachedWorldStorageManager
|
||||
|
||||
return Optional.ofNullable(
|
||||
cachedWorldStatesByHash.get(blockHeader.getParentHash())) // search parent block
|
||||
.map(CachedBonsaiWorldView::getWorldStateStorage)
|
||||
.map(DiffBasedCachedWorldView::getWorldStateStorage)
|
||||
.or(
|
||||
() -> {
|
||||
// or else search the nearest state in the cache
|
||||
@@ -158,22 +158,22 @@ public class CachedWorldStorageManager
|
||||
.addArgument(blockHeader.toLogString())
|
||||
.log();
|
||||
|
||||
final List<CachedBonsaiWorldView> cachedBonsaiWorldViews =
|
||||
final List<DiffBasedCachedWorldView> cachedDiffBasedWorldViews =
|
||||
new ArrayList<>(cachedWorldStatesByHash.values());
|
||||
return cachedBonsaiWorldViews.stream()
|
||||
return cachedDiffBasedWorldViews.stream()
|
||||
.sorted(
|
||||
Comparator.comparingLong(
|
||||
view -> Math.abs(blockHeader.getNumber() - view.getBlockNumber())))
|
||||
.map(CachedBonsaiWorldView::getWorldStateStorage)
|
||||
.map(DiffBasedCachedWorldView::getWorldStateStorage)
|
||||
.findFirst();
|
||||
})
|
||||
.map(
|
||||
storage ->
|
||||
new BonsaiWorldState( // wrap the state in a layered worldstate
|
||||
archive, new BonsaiWorldStateLayerStorage(storage), evmConfiguration));
|
||||
createWorldState( // wrap the state in a layered worldstate
|
||||
archive, createLayeredKeyValueStorage(storage), evmConfiguration));
|
||||
}
|
||||
|
||||
public Optional<BonsaiWorldState> getHeadWorldState(
|
||||
public Optional<DiffBasedWorldState> getHeadWorldState(
|
||||
final Function<Hash, Optional<BlockHeader>> hashBlockHeaderFunction) {
|
||||
|
||||
LOG.atDebug().setMessage("getting head worldstate").log();
|
||||
@@ -187,7 +187,7 @@ public class CachedWorldStorageManager
|
||||
addCachedLayer(
|
||||
blockHeader,
|
||||
blockHeader.getStateRoot(),
|
||||
new BonsaiWorldState(archive, rootWorldStateStorage, evmConfiguration));
|
||||
createWorldState(archive, rootWorldStateStorage, evmConfiguration));
|
||||
return getWorldState(blockHeader.getHash());
|
||||
});
|
||||
}
|
||||
@@ -219,4 +219,15 @@ public class CachedWorldStorageManager
|
||||
public void onCloseStorage() {
|
||||
this.cachedWorldStatesByHash.clear();
|
||||
}
|
||||
|
||||
public abstract DiffBasedWorldState createWorldState(
|
||||
final DiffBasedWorldStateProvider archive,
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final EvmConfiguration evmConfiguration);
|
||||
|
||||
public abstract DiffBasedWorldStateKeyValueStorage createLayeredKeyValueStorage(
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage);
|
||||
|
||||
public abstract DiffBasedWorldStateKeyValueStorage createSnapshotKeyValueStorage(
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage);
|
||||
}
|
||||
@@ -13,30 +13,30 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.cache;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.cache;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CachedBonsaiWorldView
|
||||
implements BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber {
|
||||
private BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage;
|
||||
public class DiffBasedCachedWorldView implements StorageSubscriber {
|
||||
private DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage;
|
||||
private final BlockHeader blockHeader;
|
||||
private long worldViewSubscriberId;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CachedBonsaiWorldView.class);
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DiffBasedCachedWorldView.class);
|
||||
|
||||
public CachedBonsaiWorldView(
|
||||
final BlockHeader blockHeader, final BonsaiWorldStateKeyValueStorage worldView) {
|
||||
public DiffBasedCachedWorldView(
|
||||
final BlockHeader blockHeader, final DiffBasedWorldStateKeyValueStorage worldView) {
|
||||
this.blockHeader = blockHeader;
|
||||
this.worldStateKeyValueStorage = worldView;
|
||||
this.worldViewSubscriberId = worldStateKeyValueStorage.subscribe(this);
|
||||
}
|
||||
|
||||
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
|
||||
public DiffBasedWorldStateKeyValueStorage getWorldStateStorage() {
|
||||
return worldStateKeyValueStorage;
|
||||
}
|
||||
|
||||
@@ -58,10 +58,10 @@ public class CachedBonsaiWorldView
|
||||
}
|
||||
|
||||
public synchronized void updateWorldStateStorage(
|
||||
final BonsaiWorldStateKeyValueStorage newWorldStateStorage) {
|
||||
final DiffBasedWorldStateKeyValueStorage newWorldStateStorage) {
|
||||
long newSubscriberId = newWorldStateStorage.subscribe(this);
|
||||
this.worldStateKeyValueStorage.unSubscribe(this.worldViewSubscriberId);
|
||||
BonsaiWorldStateKeyValueStorage oldWorldStateStorage = this.worldStateKeyValueStorage;
|
||||
final DiffBasedWorldStateKeyValueStorage oldWorldStateStorage = this.worldStateKeyValueStorage;
|
||||
this.worldStateKeyValueStorage = newWorldStateStorage;
|
||||
this.worldViewSubscriberId = newSubscriberId;
|
||||
try {
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage;
|
||||
|
||||
public interface DiffBasedLayeredWorldStateKeyValueStorage
|
||||
extends DiffBasedSnapshotWorldStateKeyValueStorage {
|
||||
|
||||
DiffBasedWorldStateKeyValueStorage clone();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage;
|
||||
|
||||
public interface DiffBasedSnapshotWorldStateKeyValueStorage {
|
||||
|
||||
DiffBasedWorldStateKeyValueStorage getParentWorldStateStorage();
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat.FlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
|
||||
import org.hyperledger.besu.util.Subscribers;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class DiffBasedWorldStateKeyValueStorage
|
||||
implements WorldStateKeyValueStorage, AutoCloseable {
|
||||
private static final Logger LOG =
|
||||
LoggerFactory.getLogger(DiffBasedWorldStateKeyValueStorage.class);
|
||||
|
||||
// 0x776f726c64526f6f74
|
||||
public static final byte[] WORLD_ROOT_HASH_KEY = "worldRoot".getBytes(StandardCharsets.UTF_8);
|
||||
// 0x776f726c64426c6f636b48617368
|
||||
public static final byte[] WORLD_BLOCK_HASH_KEY =
|
||||
"worldBlockHash".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
private final AtomicBoolean shouldClose = new AtomicBoolean(false);
|
||||
|
||||
protected final AtomicBoolean isClosed = new AtomicBoolean(false);
|
||||
|
||||
protected final Subscribers<StorageSubscriber> subscribers = Subscribers.create();
|
||||
protected final SegmentedKeyValueStorage composedWorldStateStorage;
|
||||
protected final KeyValueStorage trieLogStorage;
|
||||
|
||||
public DiffBasedWorldStateKeyValueStorage(final StorageProvider provider) {
|
||||
this.composedWorldStateStorage =
|
||||
provider.getStorageBySegmentIdentifiers(
|
||||
List.of(
|
||||
ACCOUNT_INFO_STATE, CODE_STORAGE, ACCOUNT_STORAGE_STORAGE, TRIE_BRANCH_STORAGE));
|
||||
this.trieLogStorage =
|
||||
provider.getStorageBySegmentIdentifier(KeyValueSegmentIdentifier.TRIE_LOG_STORAGE);
|
||||
}
|
||||
|
||||
public DiffBasedWorldStateKeyValueStorage(
|
||||
final SegmentedKeyValueStorage composedWorldStateStorage,
|
||||
final KeyValueStorage trieLogStorage) {
|
||||
this.composedWorldStateStorage = composedWorldStateStorage;
|
||||
this.trieLogStorage = trieLogStorage;
|
||||
}
|
||||
|
||||
public abstract FlatDbMode getFlatDbMode();
|
||||
|
||||
public abstract FlatDbStrategy getFlatDbStrategy();
|
||||
|
||||
@Override
|
||||
public abstract DataStorageFormat getDataStorageFormat();
|
||||
|
||||
public SegmentedKeyValueStorage getComposedWorldStateStorage() {
|
||||
return composedWorldStateStorage;
|
||||
}
|
||||
|
||||
public KeyValueStorage getTrieLogStorage() {
|
||||
return trieLogStorage;
|
||||
}
|
||||
|
||||
public Optional<byte[]> getTrieLog(final Hash blockHash) {
|
||||
return trieLogStorage.get(blockHash.toArrayUnsafe());
|
||||
}
|
||||
|
||||
public Stream<byte[]> streamTrieLogKeys(final long limit) {
|
||||
return trieLogStorage.streamKeys().limit(limit);
|
||||
}
|
||||
|
||||
public Optional<Bytes> getStateTrieNode(final Bytes location) {
|
||||
return composedWorldStateStorage
|
||||
.get(TRIE_BRANCH_STORAGE, location.toArrayUnsafe())
|
||||
.map(Bytes::wrap);
|
||||
}
|
||||
|
||||
public Optional<Bytes> getWorldStateRootHash() {
|
||||
return composedWorldStateStorage.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY).map(Bytes::wrap);
|
||||
}
|
||||
|
||||
public Optional<Hash> getWorldStateBlockHash() {
|
||||
return composedWorldStateStorage
|
||||
.get(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY)
|
||||
.map(Bytes32::wrap)
|
||||
.map(Hash::wrap);
|
||||
}
|
||||
|
||||
public Map<Bytes32, Bytes> streamFlatAccounts(
|
||||
final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
|
||||
return getFlatDbStrategy()
|
||||
.streamAccountFlatDatabase(composedWorldStateStorage, startKeyHash, endKeyHash, max);
|
||||
}
|
||||
|
||||
public Map<Bytes32, Bytes> streamFlatStorages(
|
||||
final Hash accountHash, final Bytes startKeyHash, final Bytes32 endKeyHash, final long max) {
|
||||
return getFlatDbStrategy()
|
||||
.streamStorageFlatDatabase(
|
||||
composedWorldStateStorage, accountHash, startKeyHash, endKeyHash, max);
|
||||
}
|
||||
|
||||
public boolean isWorldStateAvailable(final Bytes32 rootHash, final Hash blockHash) {
|
||||
return composedWorldStateStorage
|
||||
.get(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY)
|
||||
.map(Bytes32::wrap)
|
||||
.map(hash -> hash.equals(rootHash) || trieLogStorage.containsKey(blockHash.toArrayUnsafe()))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
subscribers.forEach(StorageSubscriber::onClearStorage);
|
||||
getFlatDbStrategy().clearAll(composedWorldStateStorage);
|
||||
composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE);
|
||||
trieLogStorage.clear();
|
||||
}
|
||||
|
||||
public void clearTrieLog() {
|
||||
subscribers.forEach(StorageSubscriber::onClearTrieLog);
|
||||
trieLogStorage.clear();
|
||||
}
|
||||
|
||||
public void clearFlatDatabase() {
|
||||
subscribers.forEach(StorageSubscriber::onClearFlatDatabaseStorage);
|
||||
getFlatDbStrategy().resetOnResync(composedWorldStateStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Updater updater();
|
||||
|
||||
public boolean pruneTrieLog(final Hash blockHash) {
|
||||
try {
|
||||
return trieLogStorage.tryDelete(blockHash.toArrayUnsafe());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error pruning trie log for block hash {}", blockHash, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws Exception {
|
||||
// when the storage clears, close
|
||||
shouldClose.set(true);
|
||||
tryClose();
|
||||
}
|
||||
|
||||
public synchronized long subscribe(final StorageSubscriber sub) {
|
||||
if (isClosed.get()) {
|
||||
throw new RuntimeException("Storage is marked to close or has already closed");
|
||||
}
|
||||
return subscribers.subscribe(sub);
|
||||
}
|
||||
|
||||
public synchronized void unSubscribe(final long id) {
|
||||
subscribers.unsubscribe(id);
|
||||
try {
|
||||
tryClose();
|
||||
} catch (Exception e) {
|
||||
LOG.atWarn()
|
||||
.setMessage("exception while trying to close : {}")
|
||||
.addArgument(e::getMessage)
|
||||
.log();
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void tryClose() throws Exception {
|
||||
if (shouldClose.get() && subscribers.getSubscriberCount() < 1) {
|
||||
doClose();
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void doClose() throws Exception {
|
||||
if (!isClosed.get()) {
|
||||
// alert any subscribers we are closing:
|
||||
subscribers.forEach(StorageSubscriber::onCloseStorage);
|
||||
|
||||
// close all of the KeyValueStorages:
|
||||
composedWorldStateStorage.close();
|
||||
trieLogStorage.close();
|
||||
|
||||
// set storage closed
|
||||
isClosed.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Updater extends WorldStateKeyValueStorage.Updater {
|
||||
|
||||
DiffBasedWorldStateKeyValueStorage.Updater saveWorldState(
|
||||
final Bytes blockHash, final Bytes32 nodeHash, final Bytes node);
|
||||
|
||||
SegmentedKeyValueStorageTransaction getWorldStateTransaction();
|
||||
|
||||
KeyValueStorageTransaction getTrieLogStorageTransaction();
|
||||
|
||||
@Override
|
||||
void commit();
|
||||
|
||||
void rollback();
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorage;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_STORAGE_STORAGE;
|
||||
@@ -13,11 +13,13 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.CODE_STORAGE;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
|
||||
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FullFlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.PartialFlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.plugin.services.MetricsSystem;
|
||||
@@ -12,12 +12,12 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -30,10 +30,10 @@ public class NoOpTrieLogManager extends TrieLogManager {
|
||||
|
||||
@Override
|
||||
public synchronized void saveTrieLog(
|
||||
final BonsaiWorldStateUpdateAccumulator localUpdater,
|
||||
final DiffBasedWorldStateUpdateAccumulator<?> localUpdater,
|
||||
final Hash forWorldStateRootHash,
|
||||
final BlockHeader forBlockHeader,
|
||||
final BonsaiWorldState forWorldState) {
|
||||
final DiffBasedWorldState forWorldState) {
|
||||
// notify trie log added observers, synchronously
|
||||
TrieLog trieLog = trieLogFactory.create(localUpdater, forBlockHeader);
|
||||
trieLogObservers.forEach(o -> o.onTrieLogAdded(new TrieLogAddedEvent(trieLog)));
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
|
||||
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent;
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.hyperledger.besu.datatypes.AccountValue;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -49,21 +49,21 @@ public class TrieLogLayer implements TrieLog {
|
||||
protected Hash blockHash;
|
||||
protected Optional<Long> blockNumber = Optional.empty();
|
||||
|
||||
Map<Address, BonsaiValue<AccountValue>> getAccounts() {
|
||||
Map<Address, DiffBasedValue<AccountValue>> getAccounts() {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
Map<Address, BonsaiValue<Bytes>> getCode() {
|
||||
Map<Address, DiffBasedValue<Bytes>> getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> getStorage() {
|
||||
Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
protected final Map<Address, BonsaiValue<AccountValue>> accounts;
|
||||
protected final Map<Address, BonsaiValue<Bytes>> code;
|
||||
protected final Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> storage;
|
||||
protected final Map<Address, DiffBasedValue<AccountValue>> accounts;
|
||||
protected final Map<Address, DiffBasedValue<Bytes>> code;
|
||||
protected final Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> storage;
|
||||
protected boolean frozen = false;
|
||||
|
||||
public TrieLogLayer() {
|
||||
@@ -104,14 +104,14 @@ public class TrieLogLayer implements TrieLog {
|
||||
public TrieLogLayer addAccountChange(
|
||||
final Address address, final AccountValue oldValue, final AccountValue newValue) {
|
||||
checkState(!frozen, "Layer is Frozen");
|
||||
accounts.put(address, new BonsaiValue<>(oldValue, newValue));
|
||||
accounts.put(address, new DiffBasedValue<>(oldValue, newValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TrieLogLayer addCodeChange(
|
||||
final Address address, final Bytes oldValue, final Bytes newValue, final Hash blockHash) {
|
||||
checkState(!frozen, "Layer is Frozen");
|
||||
code.put(address, new BonsaiValue<>(oldValue, newValue, newValue == null));
|
||||
code.put(address, new DiffBasedValue<>(oldValue, newValue, newValue == null));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -123,22 +123,22 @@ public class TrieLogLayer implements TrieLog {
|
||||
checkState(!frozen, "Layer is Frozen");
|
||||
storage
|
||||
.computeIfAbsent(address, a -> new TreeMap<>())
|
||||
.put(slot, new BonsaiValue<>(oldValue, newValue));
|
||||
.put(slot, new DiffBasedValue<>(oldValue, newValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Address, BonsaiValue<AccountValue>> getAccountChanges() {
|
||||
public Map<Address, DiffBasedValue<AccountValue>> getAccountChanges() {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Address, BonsaiValue<Bytes>> getCodeChanges() {
|
||||
public Map<Address, DiffBasedValue<Bytes>> getCodeChanges() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> getStorageChanges() {
|
||||
public Map<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> getStorageChanges() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
@@ -147,18 +147,18 @@ public class TrieLogLayer implements TrieLog {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<StorageSlotKey, BonsaiValue<UInt256>> getStorageChanges(final Address address) {
|
||||
public Map<StorageSlotKey, DiffBasedValue<UInt256>> getStorageChanges(final Address address) {
|
||||
return storage.getOrDefault(address, Map.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Bytes> getPriorCode(final Address address) {
|
||||
return Optional.ofNullable(code.get(address)).map(BonsaiValue::getPrior);
|
||||
return Optional.ofNullable(code.get(address)).map(DiffBasedValue::getPrior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Bytes> getCode(final Address address) {
|
||||
return Optional.ofNullable(code.get(address)).map(BonsaiValue::getUpdated);
|
||||
return Optional.ofNullable(code.get(address)).map(DiffBasedValue::getUpdated);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,7 +166,7 @@ public class TrieLogLayer implements TrieLog {
|
||||
final Address address, final StorageSlotKey storageSlotKey) {
|
||||
return Optional.ofNullable(storage.get(address))
|
||||
.map(i -> i.get(storageSlotKey))
|
||||
.map(BonsaiValue::getPrior);
|
||||
.map(DiffBasedValue::getPrior);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -174,24 +174,24 @@ public class TrieLogLayer implements TrieLog {
|
||||
final Address address, final StorageSlotKey storageSlotKey) {
|
||||
return Optional.ofNullable(storage.get(address))
|
||||
.map(i -> i.get(storageSlotKey))
|
||||
.map(BonsaiValue::getUpdated);
|
||||
.map(DiffBasedValue::getUpdated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AccountValue> getPriorAccount(final Address address) {
|
||||
return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getPrior);
|
||||
return Optional.ofNullable(accounts.get(address)).map(DiffBasedValue::getPrior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AccountValue> getAccount(final Address address) {
|
||||
return Optional.ofNullable(accounts.get(address)).map(BonsaiValue::getUpdated);
|
||||
return Optional.ofNullable(accounts.get(address)).map(DiffBasedValue::getUpdated);
|
||||
}
|
||||
|
||||
public String dump() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("TrieLog{" + "blockHash=").append(blockHash).append(frozen).append('}');
|
||||
sb.append("accounts\n");
|
||||
for (final Map.Entry<Address, BonsaiValue<AccountValue>> account : accounts.entrySet()) {
|
||||
for (final Map.Entry<Address, DiffBasedValue<AccountValue>> account : accounts.entrySet()) {
|
||||
sb.append(" : ").append(account.getKey()).append("\n");
|
||||
if (Objects.equals(account.getValue().getPrior(), account.getValue().getUpdated())) {
|
||||
sb.append(" = ").append(account.getValue().getUpdated()).append("\n");
|
||||
@@ -201,7 +201,7 @@ public class TrieLogLayer implements TrieLog {
|
||||
}
|
||||
}
|
||||
sb.append("code").append("\n");
|
||||
for (final Map.Entry<Address, BonsaiValue<Bytes>> code : code.entrySet()) {
|
||||
for (final Map.Entry<Address, DiffBasedValue<Bytes>> code : code.entrySet()) {
|
||||
sb.append(" : ").append(code.getKey()).append("\n");
|
||||
if (Objects.equals(code.getValue().getPrior(), code.getValue().getUpdated())) {
|
||||
sb.append(" = ").append(code.getValue().getPrior()).append("\n");
|
||||
@@ -211,10 +211,10 @@ public class TrieLogLayer implements TrieLog {
|
||||
}
|
||||
}
|
||||
sb.append("Storage").append("\n");
|
||||
for (final Map.Entry<Address, Map<StorageSlotKey, BonsaiValue<UInt256>>> storage :
|
||||
for (final Map.Entry<Address, Map<StorageSlotKey, DiffBasedValue<UInt256>>> storage :
|
||||
storage.entrySet()) {
|
||||
sb.append(" : ").append(storage.getKey()).append("\n");
|
||||
for (final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> slot :
|
||||
for (final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> slot :
|
||||
storage.getValue().entrySet()) {
|
||||
final UInt256 originalValue = slot.getValue().getPrior();
|
||||
final UInt256 updatedValue = slot.getValue().getUpdated();
|
||||
@@ -13,14 +13,15 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.plugin.BesuContext;
|
||||
import org.hyperledger.besu.plugin.services.TrieLogService;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
@@ -41,7 +42,7 @@ public class TrieLogManager {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TrieLogManager.class);
|
||||
public static final long LOG_RANGE_LIMIT = 1000; // restrict trielog range queries to 1k logs
|
||||
protected final Blockchain blockchain;
|
||||
protected final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
|
||||
protected final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
|
||||
|
||||
protected final long maxLayersToLoad;
|
||||
protected final Subscribers<TrieLogEvent.TrieLogObserver> trieLogObservers = Subscribers.create();
|
||||
@@ -50,7 +51,7 @@ public class TrieLogManager {
|
||||
|
||||
public TrieLogManager(
|
||||
final Blockchain blockchain,
|
||||
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final long maxLayersToLoad,
|
||||
final BesuContext pluginContext) {
|
||||
this.blockchain = blockchain;
|
||||
@@ -60,15 +61,15 @@ public class TrieLogManager {
|
||||
}
|
||||
|
||||
public synchronized void saveTrieLog(
|
||||
final BonsaiWorldStateUpdateAccumulator localUpdater,
|
||||
final DiffBasedWorldStateUpdateAccumulator<?> localUpdater,
|
||||
final Hash forWorldStateRootHash,
|
||||
final BlockHeader forBlockHeader,
|
||||
final BonsaiWorldState forWorldState) {
|
||||
final DiffBasedWorldState forWorldState) {
|
||||
// do not overwrite a trielog layer that already exists in the database.
|
||||
// if it's only in memory we need to save it
|
||||
// for example, in case of reorg we don't replace a trielog layer
|
||||
if (rootWorldStateStorage.getTrieLog(forBlockHeader.getHash()).isEmpty()) {
|
||||
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater =
|
||||
final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater =
|
||||
forWorldState.getWorldStateStorage().updater();
|
||||
boolean success = false;
|
||||
try {
|
||||
@@ -90,7 +91,7 @@ public class TrieLogManager {
|
||||
}
|
||||
|
||||
private TrieLog prepareTrieLog(
|
||||
final BlockHeader blockHeader, final BonsaiWorldStateUpdateAccumulator localUpdater) {
|
||||
final BlockHeader blockHeader, final DiffBasedWorldStateUpdateAccumulator<?> localUpdater) {
|
||||
LOG.atDebug()
|
||||
.setMessage("Adding layered world state for {}")
|
||||
.addArgument(blockHeader::toLogString)
|
||||
@@ -104,7 +105,7 @@ public class TrieLogManager {
|
||||
final BlockHeader blockHeader,
|
||||
final Hash worldStateRootHash,
|
||||
final TrieLog trieLog,
|
||||
final BonsaiWorldStateKeyValueStorage.Updater stateUpdater) {
|
||||
final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater) {
|
||||
LOG.atDebug()
|
||||
.setMessage("Persisting trie log for block hash {} and world state root {}")
|
||||
.addArgument(blockHeader::toLogString)
|
||||
@@ -13,13 +13,13 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLogEvent;
|
||||
|
||||
import java.util.Comparator;
|
||||
@@ -41,7 +41,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
|
||||
|
||||
private final int pruningLimit;
|
||||
private final int loadingLimit;
|
||||
private final BonsaiWorldStateKeyValueStorage rootWorldStateStorage;
|
||||
private final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage;
|
||||
private final Blockchain blockchain;
|
||||
private final Consumer<Runnable> executeAsync;
|
||||
private final long numBlocksToRetain;
|
||||
@@ -51,7 +51,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
|
||||
TreeMultimap.create(Comparator.reverseOrder(), Comparator.naturalOrder());
|
||||
|
||||
public TrieLogPruner(
|
||||
final BonsaiWorldStateKeyValueStorage rootWorldStateStorage,
|
||||
final DiffBasedWorldStateKeyValueStorage rootWorldStateStorage,
|
||||
final Blockchain blockchain,
|
||||
final Consumer<Runnable> executeAsync,
|
||||
final long numBlocksToRetain,
|
||||
@@ -100,7 +100,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
|
||||
}
|
||||
}
|
||||
|
||||
void addToPruneQueue(final long blockNumber, final Hash blockHash) {
|
||||
public void addToPruneQueue(final long blockNumber, final Hash blockHash) {
|
||||
LOG.atTrace()
|
||||
.setMessage("adding trie log to queue for later pruning blockNumber {}; blockHash {}")
|
||||
.addArgument(blockNumber)
|
||||
@@ -109,7 +109,7 @@ public class TrieLogPruner implements TrieLogEvent.TrieLogObserver {
|
||||
trieLogBlocksAndForksByDescendingBlockNumber.put(blockNumber, blockHash);
|
||||
}
|
||||
|
||||
int pruneFromQueue() {
|
||||
public int pruneFromQueue() {
|
||||
final long retainAboveThisBlock = blockchain.getChainHeadBlockNumber() - numBlocksToRetain;
|
||||
final Optional<Hash> finalized = blockchain.getFinalized();
|
||||
if (requireFinalizedBlock && finalized.isEmpty()) {
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
|
||||
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedSnapshotWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
import org.hyperledger.besu.plugin.services.exception.StorageException;
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
|
||||
import org.hyperledger.besu.plugin.services.storage.SegmentedKeyValueStorageTransaction;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class DiffBasedWorldState
|
||||
implements MutableWorldState, DiffBasedWorldView, StorageSubscriber {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DiffBasedWorldState.class);
|
||||
|
||||
protected DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage;
|
||||
protected final DiffBasedCachedWorldStorageManager cachedWorldStorageManager;
|
||||
protected final TrieLogManager trieLogManager;
|
||||
protected DiffBasedWorldStateUpdateAccumulator<?> accumulator;
|
||||
|
||||
protected Hash worldStateRootHash;
|
||||
protected Hash worldStateBlockHash;
|
||||
protected boolean isFrozen;
|
||||
|
||||
protected DiffBasedWorldState(
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
|
||||
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
|
||||
final TrieLogManager trieLogManager) {
|
||||
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
|
||||
this.worldStateRootHash =
|
||||
Hash.wrap(
|
||||
Bytes32.wrap(
|
||||
worldStateKeyValueStorage.getWorldStateRootHash().orElse(getEmptyTrieHash())));
|
||||
this.worldStateBlockHash =
|
||||
Hash.wrap(
|
||||
Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
|
||||
this.cachedWorldStorageManager = cachedWorldStorageManager;
|
||||
this.trieLogManager = trieLogManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Having a protected method to override the accumulator solves the chicken-egg problem of needing
|
||||
* a worldstate reference (this) when construction the Accumulator.
|
||||
*
|
||||
* @param accumulator accumulator to use.
|
||||
*/
|
||||
public void setAccumulator(final DiffBasedWorldStateUpdateAccumulator<?> accumulator) {
|
||||
this.accumulator = accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the world state block hash of this world state
|
||||
*
|
||||
* @return the world state block hash.
|
||||
*/
|
||||
public Hash getWorldStateBlockHash() {
|
||||
return worldStateBlockHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the world state root hash of this world state
|
||||
*
|
||||
* @return the world state root hash.
|
||||
*/
|
||||
public Hash getWorldStateRootHash() {
|
||||
return worldStateRootHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersisted() {
|
||||
return isPersisted(worldStateKeyValueStorage);
|
||||
}
|
||||
|
||||
private boolean isPersisted(final WorldStateKeyValueStorage worldStateKeyValueStorage) {
|
||||
return !(worldStateKeyValueStorage instanceof DiffBasedSnapshotWorldStateKeyValueStorage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the worldState to this block header
|
||||
*
|
||||
* @param blockHeader block to use
|
||||
*/
|
||||
public void resetWorldStateTo(final BlockHeader blockHeader) {
|
||||
worldStateBlockHash = blockHeader.getBlockHash();
|
||||
worldStateRootHash = blockHeader.getStateRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiffBasedWorldStateKeyValueStorage getWorldStateStorage() {
|
||||
return worldStateKeyValueStorage;
|
||||
}
|
||||
|
||||
public DiffBasedWorldStateUpdateAccumulator<?> getAccumulator() {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persist(final BlockHeader blockHeader) {
|
||||
final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader);
|
||||
LOG.atDebug()
|
||||
.setMessage("Persist world state for block {}")
|
||||
.addArgument(maybeBlockHeader)
|
||||
.log();
|
||||
|
||||
final DiffBasedWorldStateUpdateAccumulator<?> localCopy = accumulator.copy();
|
||||
|
||||
boolean success = false;
|
||||
|
||||
final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater =
|
||||
worldStateKeyValueStorage.updater();
|
||||
Runnable saveTrieLog = () -> {};
|
||||
|
||||
try {
|
||||
final Hash newWorldStateRootHash =
|
||||
calculateRootHash(isFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator);
|
||||
// if we are persisted with a block header, and the prior state is the parent
|
||||
// then persist the TrieLog for that transition.
|
||||
// If specified but not a direct descendant simply store the new block hash.
|
||||
if (blockHeader != null) {
|
||||
verifyWorldStateRoot(newWorldStateRootHash, blockHeader);
|
||||
saveTrieLog =
|
||||
() -> {
|
||||
trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this);
|
||||
// not save a frozen state in the cache
|
||||
if (!isFrozen) {
|
||||
cachedWorldStorageManager.addCachedLayer(blockHeader, newWorldStateRootHash, this);
|
||||
}
|
||||
};
|
||||
|
||||
stateUpdater
|
||||
.getWorldStateTransaction()
|
||||
.put(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY, blockHeader.getHash().toArrayUnsafe());
|
||||
worldStateBlockHash = blockHeader.getHash();
|
||||
} else {
|
||||
stateUpdater.getWorldStateTransaction().remove(TRIE_BRANCH_STORAGE, WORLD_BLOCK_HASH_KEY);
|
||||
worldStateBlockHash = null;
|
||||
}
|
||||
|
||||
stateUpdater
|
||||
.getWorldStateTransaction()
|
||||
.put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, newWorldStateRootHash.toArrayUnsafe());
|
||||
worldStateRootHash = newWorldStateRootHash;
|
||||
success = true;
|
||||
} finally {
|
||||
if (success) {
|
||||
stateUpdater.commit();
|
||||
accumulator.reset();
|
||||
saveTrieLog.run();
|
||||
} else {
|
||||
stateUpdater.rollback();
|
||||
accumulator.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) {
|
||||
if (!calculatedStateRoot.equals(header.getStateRoot())) {
|
||||
throw new RuntimeException(
|
||||
"World State Root does not match expected value, header "
|
||||
+ header.getStateRoot().toHexString()
|
||||
+ " calculated "
|
||||
+ calculatedStateRoot.toHexString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldUpdater updater() {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hash rootHash() {
|
||||
if (isFrozen && accumulator.isAccumulatorStateChanged()) {
|
||||
worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy());
|
||||
accumulator.resetAccumulatorStateChanged();
|
||||
}
|
||||
return Hash.wrap(worldStateRootHash);
|
||||
}
|
||||
|
||||
protected static final KeyValueStorageTransaction noOpTx =
|
||||
new KeyValueStorageTransaction() {
|
||||
|
||||
@Override
|
||||
public void put(final byte[] key, final byte[] value) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final byte[] key) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() throws StorageException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
// no-op
|
||||
}
|
||||
};
|
||||
|
||||
protected static final SegmentedKeyValueStorageTransaction noOpSegmentedTx =
|
||||
new SegmentedKeyValueStorageTransaction() {
|
||||
|
||||
@Override
|
||||
public void put(
|
||||
final SegmentIdentifier segmentIdentifier, final byte[] key, final byte[] value) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final SegmentIdentifier segmentIdentifier, final byte[] key) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() throws StorageException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
// no-op
|
||||
}
|
||||
};
|
||||
|
||||
public Hash blockHash() {
|
||||
return worldStateBlockHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<StreamableAccount> streamAccounts(final Bytes32 startKeyHash, final int limit) {
|
||||
throw new RuntimeException("storage format do not provide account streaming.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInt256 getPriorStorageValue(final Address address, final UInt256 storageKey) {
|
||||
return getStorageValue(address, storageKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
if (!isPersisted()) {
|
||||
this.worldStateKeyValueStorage.close();
|
||||
if (isFrozen) {
|
||||
closeFrozenStorage();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no op
|
||||
}
|
||||
}
|
||||
|
||||
private void closeFrozenStorage() {
|
||||
try {
|
||||
final DiffBasedLayeredWorldStateKeyValueStorage worldStateLayerStorage =
|
||||
(DiffBasedLayeredWorldStateKeyValueStorage) worldStateKeyValueStorage;
|
||||
if (!isPersisted(worldStateLayerStorage.getParentWorldStateStorage())) {
|
||||
worldStateLayerStorage.getParentWorldStateStorage().close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// no op
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Hash frontierRootHash();
|
||||
|
||||
@Override
|
||||
public abstract MutableWorldState freeze();
|
||||
|
||||
@Override
|
||||
public abstract Account get(final Address address);
|
||||
|
||||
@Override
|
||||
public abstract UInt256 getStorageValue(final Address address, final UInt256 storageKey);
|
||||
|
||||
@Override
|
||||
public abstract Optional<UInt256> getStorageValueByStorageSlotKey(
|
||||
final Address address, final StorageSlotKey storageSlotKey);
|
||||
|
||||
@Override
|
||||
public abstract Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash);
|
||||
|
||||
protected abstract Hash calculateRootHash(
|
||||
final Optional<DiffBasedWorldStateKeyValueStorage.Updater> maybeStateUpdater,
|
||||
final DiffBasedWorldStateUpdateAccumulator<?> worldStateUpdater);
|
||||
|
||||
protected abstract Hash getEmptyTrieHash();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
@@ -11,16 +11,15 @@
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldView;
|
||||
|
||||
@@ -31,7 +30,7 @@ import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
|
||||
public interface BonsaiWorldView extends WorldView {
|
||||
public interface DiffBasedWorldView extends WorldView {
|
||||
|
||||
Optional<Bytes> getCode(Address address, final Hash codeHash);
|
||||
|
||||
@@ -59,7 +58,7 @@ public interface BonsaiWorldView extends WorldView {
|
||||
|
||||
boolean isPersisted();
|
||||
|
||||
BonsaiWorldStateKeyValueStorage getWorldStateStorage();
|
||||
DiffBasedWorldStateKeyValueStorage getWorldStateStorage();
|
||||
|
||||
WorldUpdater updater();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
@@ -11,10 +11,9 @@
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator;
|
||||
|
||||
import org.hyperledger.besu.datatypes.AccountValue;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
@@ -23,9 +22,14 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.AccountConsumingMap;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.Consumer;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
@@ -44,42 +48,40 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.collect.ForwardingMap;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class BonsaiWorldStateUpdateAccumulator
|
||||
extends AbstractWorldUpdater<BonsaiWorldView, BonsaiAccount>
|
||||
implements BonsaiWorldView, TrieLogAccumulator {
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract class DiffBasedWorldStateUpdateAccumulator<ACCOUNT extends DiffBasedAccount>
|
||||
extends AbstractWorldUpdater<DiffBasedWorldView, ACCOUNT>
|
||||
implements DiffBasedWorldView, TrieLogAccumulator {
|
||||
private static final Logger LOG =
|
||||
LoggerFactory.getLogger(BonsaiWorldStateUpdateAccumulator.class);
|
||||
protected final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader;
|
||||
LoggerFactory.getLogger(DiffBasedWorldStateUpdateAccumulator.class);
|
||||
protected final Consumer<DiffBasedValue<ACCOUNT>> accountPreloader;
|
||||
protected final Consumer<StorageSlotKey> storagePreloader;
|
||||
|
||||
private final AccountConsumingMap<BonsaiValue<BonsaiAccount>> accountsToUpdate;
|
||||
private final Map<Address, BonsaiValue<Bytes>> codeToUpdate = new ConcurrentHashMap<>();
|
||||
private final AccountConsumingMap<DiffBasedValue<ACCOUNT>> accountsToUpdate;
|
||||
private final Map<Address, DiffBasedValue<Bytes>> codeToUpdate = new ConcurrentHashMap<>();
|
||||
private final Set<Address> storageToClear = Collections.synchronizedSet(new HashSet<>());
|
||||
protected final EvmConfiguration evmConfiguration;
|
||||
|
||||
// storage sub mapped by _hashed_ key. This is because in self_destruct calls we need to
|
||||
// enumerate the old storage and delete it. Those are trie stored by hashed key by spec and the
|
||||
// alternative was to keep a giant pre-image cache of the entire trie.
|
||||
private final Map<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>
|
||||
private final Map<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
|
||||
storageToUpdate = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<UInt256, Hash> storageKeyHashLookup = new ConcurrentHashMap<>();
|
||||
protected boolean isAccumulatorStateChanged;
|
||||
|
||||
public BonsaiWorldStateUpdateAccumulator(
|
||||
final BonsaiWorldView world,
|
||||
final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader,
|
||||
public DiffBasedWorldStateUpdateAccumulator(
|
||||
final DiffBasedWorldView world,
|
||||
final Consumer<DiffBasedValue<ACCOUNT>> accountPreloader,
|
||||
final Consumer<StorageSlotKey> storagePreloader,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
super(world, evmConfiguration);
|
||||
@@ -90,15 +92,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
this.evmConfiguration = evmConfiguration;
|
||||
}
|
||||
|
||||
public BonsaiWorldStateUpdateAccumulator copy() {
|
||||
final BonsaiWorldStateUpdateAccumulator copy =
|
||||
new BonsaiWorldStateUpdateAccumulator(
|
||||
wrappedWorldView(), accountPreloader, storagePreloader, evmConfiguration);
|
||||
copy.cloneFromUpdater(this);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void cloneFromUpdater(final BonsaiWorldStateUpdateAccumulator source) {
|
||||
protected void cloneFromUpdater(final DiffBasedWorldStateUpdateAccumulator<ACCOUNT> source) {
|
||||
accountsToUpdate.putAll(source.getAccountsToUpdate());
|
||||
codeToUpdate.putAll(source.codeToUpdate);
|
||||
storageToClear.addAll(source.storageToClear);
|
||||
@@ -108,14 +102,25 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
this.isAccumulatorStateChanged = true;
|
||||
}
|
||||
|
||||
protected Consumer<DiffBasedValue<ACCOUNT>> getAccountPreloader() {
|
||||
return accountPreloader;
|
||||
}
|
||||
|
||||
protected Consumer<StorageSlotKey> getStoragePreloader() {
|
||||
return storagePreloader;
|
||||
}
|
||||
|
||||
protected EvmConfiguration getEvmConfiguration() {
|
||||
return evmConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account get(final Address address) {
|
||||
return super.get(address);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UpdateTrackingAccount<BonsaiAccount> track(
|
||||
final UpdateTrackingAccount<BonsaiAccount> account) {
|
||||
protected UpdateTrackingAccount<ACCOUNT> track(final UpdateTrackingAccount<ACCOUNT> account) {
|
||||
return super.track(account);
|
||||
}
|
||||
|
||||
@@ -126,21 +131,21 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
|
||||
@Override
|
||||
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
|
||||
BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address);
|
||||
DiffBasedValue<ACCOUNT> diffBasedValue = accountsToUpdate.get(address);
|
||||
|
||||
if (bonsaiValue == null) {
|
||||
bonsaiValue = new BonsaiValue<>(null, null);
|
||||
accountsToUpdate.put(address, bonsaiValue);
|
||||
} else if (bonsaiValue.getUpdated() != null) {
|
||||
if (bonsaiValue.getUpdated().isEmpty()) {
|
||||
return track(new UpdateTrackingAccount<>(bonsaiValue.getUpdated()));
|
||||
if (diffBasedValue == null) {
|
||||
diffBasedValue = new DiffBasedValue<>(null, null);
|
||||
accountsToUpdate.put(address, diffBasedValue);
|
||||
} else if (diffBasedValue.getUpdated() != null) {
|
||||
if (diffBasedValue.getUpdated().isEmpty()) {
|
||||
return track(new UpdateTrackingAccount<>(diffBasedValue.getUpdated()));
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot create an account when one already exists");
|
||||
}
|
||||
}
|
||||
|
||||
final BonsaiAccount newAccount =
|
||||
new BonsaiAccount(
|
||||
final ACCOUNT newAccount =
|
||||
createAccount(
|
||||
this,
|
||||
address,
|
||||
hashAndSaveAccountPreImage(address),
|
||||
@@ -149,17 +154,17 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
Hash.EMPTY_TRIE_HASH,
|
||||
Hash.EMPTY,
|
||||
true);
|
||||
bonsaiValue.setUpdated(newAccount);
|
||||
diffBasedValue.setUpdated(newAccount);
|
||||
return track(new UpdateTrackingAccount<>(newAccount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Address, BonsaiValue<BonsaiAccount>> getAccountsToUpdate() {
|
||||
public Map<Address, DiffBasedValue<ACCOUNT>> getAccountsToUpdate() {
|
||||
return accountsToUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Address, BonsaiValue<Bytes>> getCodeToUpdate() {
|
||||
public Map<Address, DiffBasedValue<Bytes>> getCodeToUpdate() {
|
||||
return codeToUpdate;
|
||||
}
|
||||
|
||||
@@ -168,40 +173,41 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Address, StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>>
|
||||
public Map<Address, StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>>>
|
||||
getStorageToUpdate() {
|
||||
return storageToUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BonsaiAccount getForMutation(final Address address) {
|
||||
return loadAccount(address, BonsaiValue::getUpdated);
|
||||
protected ACCOUNT getForMutation(final Address address) {
|
||||
return loadAccount(address, DiffBasedValue::getUpdated);
|
||||
}
|
||||
|
||||
protected BonsaiAccount loadAccount(
|
||||
final Address address,
|
||||
final Function<BonsaiValue<BonsaiAccount>, BonsaiAccount> bonsaiAccountFunction) {
|
||||
protected ACCOUNT loadAccount(
|
||||
final Address address, final Function<DiffBasedValue<ACCOUNT>, ACCOUNT> accountFunction) {
|
||||
try {
|
||||
final BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address);
|
||||
if (bonsaiValue == null) {
|
||||
final DiffBasedValue<ACCOUNT> diffBasedValue = accountsToUpdate.get(address);
|
||||
if (diffBasedValue == null) {
|
||||
final Account account;
|
||||
if (wrappedWorldView()
|
||||
instanceof BonsaiWorldStateUpdateAccumulator bonsaiWorldStateUpdateAccumulator) {
|
||||
account = bonsaiWorldStateUpdateAccumulator.loadAccount(address, bonsaiAccountFunction);
|
||||
if (wrappedWorldView() instanceof DiffBasedWorldStateUpdateAccumulator) {
|
||||
final DiffBasedWorldStateUpdateAccumulator<ACCOUNT> worldStateUpdateAccumulator =
|
||||
(DiffBasedWorldStateUpdateAccumulator<ACCOUNT>) wrappedWorldView();
|
||||
account = worldStateUpdateAccumulator.loadAccount(address, accountFunction);
|
||||
} else {
|
||||
account = wrappedWorldView().get(address);
|
||||
}
|
||||
if (account instanceof BonsaiAccount bonsaiAccount) {
|
||||
BonsaiAccount mutableAccount = new BonsaiAccount(bonsaiAccount, this, true);
|
||||
accountsToUpdate.put(address, new BonsaiValue<>(bonsaiAccount, mutableAccount));
|
||||
if (account instanceof DiffBasedAccount diffBasedAccount) {
|
||||
ACCOUNT mutableAccount = copyAccount((ACCOUNT) diffBasedAccount, this, true);
|
||||
accountsToUpdate.put(
|
||||
address, new DiffBasedValue<>((ACCOUNT) diffBasedAccount, mutableAccount));
|
||||
return mutableAccount;
|
||||
} else {
|
||||
// add the empty read in accountsToUpdate
|
||||
accountsToUpdate.put(address, new BonsaiValue<>(null, null));
|
||||
accountsToUpdate.put(address, new DiffBasedValue<>(null, null));
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return bonsaiAccountFunction.apply(bonsaiValue);
|
||||
return accountFunction.apply(diffBasedValue);
|
||||
}
|
||||
} catch (MerkleTrieException e) {
|
||||
// need to throw to trigger the heal
|
||||
@@ -229,12 +235,12 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
public void commit() {
|
||||
this.isAccumulatorStateChanged = true;
|
||||
for (final Address deletedAddress : getDeletedAccounts()) {
|
||||
final BonsaiValue<BonsaiAccount> accountValue =
|
||||
final DiffBasedValue<ACCOUNT> accountValue =
|
||||
accountsToUpdate.computeIfAbsent(
|
||||
deletedAddress,
|
||||
__ -> loadAccountFromParent(deletedAddress, new BonsaiValue<>(null, null, true)));
|
||||
__ -> loadAccountFromParent(deletedAddress, new DiffBasedValue<>(null, null, true)));
|
||||
storageToClear.add(deletedAddress);
|
||||
final BonsaiValue<Bytes> codeValue = codeToUpdate.get(deletedAddress);
|
||||
final DiffBasedValue<Bytes> codeValue = codeToUpdate.get(deletedAddress);
|
||||
if (codeValue != null) {
|
||||
codeValue.setUpdated(null).setCleared();
|
||||
} else {
|
||||
@@ -242,26 +248,27 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
.getCode(
|
||||
deletedAddress,
|
||||
Optional.ofNullable(accountValue)
|
||||
.map(BonsaiValue::getPrior)
|
||||
.map(BonsaiAccount::getCodeHash)
|
||||
.map(DiffBasedValue::getPrior)
|
||||
.map(DiffBasedAccount::getCodeHash)
|
||||
.orElse(Hash.EMPTY))
|
||||
.ifPresent(
|
||||
deletedCode ->
|
||||
codeToUpdate.put(deletedAddress, new BonsaiValue<>(deletedCode, null, true)));
|
||||
codeToUpdate.put(
|
||||
deletedAddress, new DiffBasedValue<>(deletedCode, null, true)));
|
||||
}
|
||||
|
||||
// mark all updated storage as to be cleared
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> deletedStorageUpdates =
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> deletedStorageUpdates =
|
||||
storageToUpdate.computeIfAbsent(
|
||||
deletedAddress,
|
||||
k ->
|
||||
new StorageConsumingMap<>(
|
||||
deletedAddress, new ConcurrentHashMap<>(), storagePreloader));
|
||||
final Iterator<Map.Entry<StorageSlotKey, BonsaiValue<UInt256>>> iter =
|
||||
final Iterator<Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>>> iter =
|
||||
deletedStorageUpdates.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
final Map.Entry<StorageSlotKey, BonsaiValue<UInt256>> updateEntry = iter.next();
|
||||
final BonsaiValue<UInt256> updatedSlot = updateEntry.getValue();
|
||||
final Map.Entry<StorageSlotKey, DiffBasedValue<UInt256>> updateEntry = iter.next();
|
||||
final DiffBasedValue<UInt256> updatedSlot = updateEntry.getValue();
|
||||
if (updatedSlot.getPrior() == null || updatedSlot.getPrior().isZero()) {
|
||||
iter.remove();
|
||||
} else {
|
||||
@@ -269,7 +276,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
}
|
||||
}
|
||||
|
||||
final BonsaiAccount originalValue = accountValue.getPrior();
|
||||
final ACCOUNT originalValue = accountValue.getPrior();
|
||||
if (originalValue != null) {
|
||||
// Enumerate and delete addresses not updated
|
||||
wrappedWorldView()
|
||||
@@ -280,7 +287,8 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
new StorageSlotKey(Hash.wrap(keyHash), Optional.empty());
|
||||
if (!deletedStorageUpdates.containsKey(storageSlotKey)) {
|
||||
final UInt256 value = UInt256.fromBytes(RLP.decodeOne(entryValue));
|
||||
deletedStorageUpdates.put(storageSlotKey, new BonsaiValue<>(value, null, true));
|
||||
deletedStorageUpdates.put(
|
||||
storageSlotKey, new DiffBasedValue<>(value, null, true));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -294,11 +302,11 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
.forEach(
|
||||
tracked -> {
|
||||
final Address updatedAddress = tracked.getAddress();
|
||||
final BonsaiAccount updatedAccount;
|
||||
final BonsaiValue<BonsaiAccount> updatedAccountValue =
|
||||
final ACCOUNT updatedAccount;
|
||||
final DiffBasedValue<ACCOUNT> updatedAccountValue =
|
||||
accountsToUpdate.get(updatedAddress);
|
||||
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> pendingStorageUpdates =
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> pendingStorageUpdates =
|
||||
storageToUpdate.computeIfAbsent(
|
||||
updatedAddress,
|
||||
k ->
|
||||
@@ -311,12 +319,12 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
}
|
||||
|
||||
if (tracked.getWrappedAccount() == null) {
|
||||
updatedAccount = new BonsaiAccount(this, tracked);
|
||||
updatedAccount = createAccount(this, tracked);
|
||||
tracked.setWrappedAccount(updatedAccount);
|
||||
if (updatedAccountValue == null) {
|
||||
accountsToUpdate.put(updatedAddress, new BonsaiValue<>(null, updatedAccount));
|
||||
accountsToUpdate.put(updatedAddress, new DiffBasedValue<>(null, updatedAccount));
|
||||
codeToUpdate.put(
|
||||
updatedAddress, new BonsaiValue<>(null, updatedAccount.getCode()));
|
||||
updatedAddress, new DiffBasedValue<>(null, updatedAccount.getCode()));
|
||||
} else {
|
||||
updatedAccountValue.setUpdated(updatedAccount);
|
||||
}
|
||||
@@ -334,17 +342,17 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
}
|
||||
|
||||
if (tracked.codeWasUpdated()) {
|
||||
final BonsaiValue<Bytes> pendingCode =
|
||||
final DiffBasedValue<Bytes> pendingCode =
|
||||
codeToUpdate.computeIfAbsent(
|
||||
updatedAddress,
|
||||
addr ->
|
||||
new BonsaiValue<>(
|
||||
new DiffBasedValue<>(
|
||||
wrappedWorldView()
|
||||
.getCode(
|
||||
addr,
|
||||
Optional.ofNullable(updatedAccountValue)
|
||||
.map(BonsaiValue::getPrior)
|
||||
.map(BonsaiAccount::getCodeHash)
|
||||
.map(DiffBasedValue::getPrior)
|
||||
.map(DiffBasedAccount::getCodeHash)
|
||||
.orElse(Hash.EMPTY))
|
||||
.orElse(null),
|
||||
null));
|
||||
@@ -368,12 +376,11 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
final StorageSlotKey slotKey =
|
||||
new StorageSlotKey(hashAndSaveSlotPreImage(keyUInt), Optional.of(keyUInt));
|
||||
final UInt256 value = storageUpdate.getValue();
|
||||
final BonsaiValue<UInt256> pendingValue = pendingStorageUpdates.get(slotKey);
|
||||
|
||||
final DiffBasedValue<UInt256> pendingValue = pendingStorageUpdates.get(slotKey);
|
||||
if (pendingValue == null) {
|
||||
pendingStorageUpdates.put(
|
||||
slotKey,
|
||||
new BonsaiValue<>(
|
||||
new DiffBasedValue<>(
|
||||
updatedAccount.getOriginalStorageValue(keyUInt), value));
|
||||
} else {
|
||||
pendingValue.setUpdated(value);
|
||||
@@ -394,7 +401,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
|
||||
@Override
|
||||
public Optional<Bytes> getCode(final Address address, final Hash codeHash) {
|
||||
final BonsaiValue<Bytes> localCode = codeToUpdate.get(address);
|
||||
final DiffBasedValue<Bytes> localCode = codeToUpdate.get(address);
|
||||
if (localCode == null) {
|
||||
final Optional<Bytes> code = wrappedWorldView().getCode(address, codeHash);
|
||||
if (code.isEmpty() && !codeHash.equals(Hash.EMPTY)) {
|
||||
@@ -417,31 +424,26 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
@Override
|
||||
public Optional<UInt256> getStorageValueByStorageSlotKey(
|
||||
final Address address, final StorageSlotKey storageSlotKey) {
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> localAccountStorage =
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> localAccountStorage =
|
||||
storageToUpdate.get(address);
|
||||
if (localAccountStorage != null) {
|
||||
final BonsaiValue<UInt256> value = localAccountStorage.get(storageSlotKey);
|
||||
final DiffBasedValue<UInt256> value = localAccountStorage.get(storageSlotKey);
|
||||
if (value != null) {
|
||||
return Optional.ofNullable(value.getUpdated());
|
||||
}
|
||||
}
|
||||
try {
|
||||
final Optional<UInt256> valueUInt =
|
||||
(wrappedWorldView() instanceof BonsaiWorldState bonsaiWorldState)
|
||||
? bonsaiWorldState.getStorageValueByStorageSlotKey(
|
||||
() ->
|
||||
Optional.ofNullable(loadAccount(address, BonsaiValue::getPrior))
|
||||
.map(BonsaiAccount::getStorageRoot),
|
||||
address,
|
||||
storageSlotKey)
|
||||
(wrappedWorldView() instanceof DiffBasedWorldState worldState)
|
||||
? worldState.getStorageValueByStorageSlotKey(address, storageSlotKey)
|
||||
: wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey);
|
||||
storageToUpdate
|
||||
.computeIfAbsent(
|
||||
address,
|
||||
key ->
|
||||
new StorageConsumingMap<>(address, new ConcurrentHashMap<>(), storagePreloader))
|
||||
.put(storageSlotKey, new BonsaiValue<>(valueUInt.orElse(null), valueUInt.orElse(null)));
|
||||
|
||||
.put(
|
||||
storageSlotKey, new DiffBasedValue<>(valueUInt.orElse(null), valueUInt.orElse(null)));
|
||||
return valueUInt;
|
||||
} catch (MerkleTrieException e) {
|
||||
// need to throw to trigger the heal
|
||||
@@ -455,10 +457,10 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
// TODO maybe log the read into the trie layer?
|
||||
StorageSlotKey storageSlotKey =
|
||||
new StorageSlotKey(hashAndSaveSlotPreImage(storageKey), Optional.of(storageKey));
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> localAccountStorage =
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> localAccountStorage =
|
||||
storageToUpdate.get(address);
|
||||
if (localAccountStorage != null) {
|
||||
final BonsaiValue<UInt256> value = localAccountStorage.get(storageSlotKey);
|
||||
final DiffBasedValue<UInt256> value = localAccountStorage.get(storageSlotKey);
|
||||
if (value != null) {
|
||||
if (value.isLastStepCleared()) {
|
||||
return UInt256.ZERO;
|
||||
@@ -482,11 +484,11 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
@Override
|
||||
public Map<Bytes32, Bytes> getAllAccountStorage(final Address address, final Hash rootHash) {
|
||||
final Map<Bytes32, Bytes> results = wrappedWorldView().getAllAccountStorage(address, rootHash);
|
||||
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> bonsaiValueStorage =
|
||||
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> diffBasedValueStorage =
|
||||
storageToUpdate.get(address);
|
||||
if (bonsaiValueStorage != null) {
|
||||
if (diffBasedValueStorage != null) {
|
||||
// hash the key to match the implied storage interface of hashed slotKey
|
||||
bonsaiValueStorage.forEach(
|
||||
diffBasedValueStorage.forEach(
|
||||
(key, value) -> results.put(key.getSlotHash(), value.getUpdated()));
|
||||
}
|
||||
return results;
|
||||
@@ -498,7 +500,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
}
|
||||
|
||||
@Override
|
||||
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
|
||||
public DiffBasedWorldStateKeyValueStorage getWorldStateStorage() {
|
||||
return wrappedWorldView().getWorldStateStorage();
|
||||
}
|
||||
|
||||
@@ -550,7 +552,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
// non-change, a cached read.
|
||||
return;
|
||||
}
|
||||
BonsaiValue<BonsaiAccount> accountValue = accountsToUpdate.get(address);
|
||||
DiffBasedValue<ACCOUNT> accountValue = accountsToUpdate.get(address);
|
||||
if (accountValue == null) {
|
||||
accountValue = loadAccountFromParent(address, accountValue);
|
||||
}
|
||||
@@ -558,7 +560,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
if (expectedValue == null && replacementValue != null) {
|
||||
accountsToUpdate.put(
|
||||
address,
|
||||
new BonsaiValue<>(null, new BonsaiAccount(this, address, replacementValue, true)));
|
||||
new DiffBasedValue<>(null, createAccount(this, address, replacementValue, true)));
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
@@ -572,7 +574,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
"Expected to create account, but the account exists. Address=%s", address));
|
||||
}
|
||||
} else {
|
||||
BonsaiAccount.assertCloseEnoughForDiffing(
|
||||
assertCloseEnoughForDiffing(
|
||||
accountValue.getUpdated(),
|
||||
expectedValue,
|
||||
"Address=" + address + " Prior Value in Rolling Change");
|
||||
@@ -586,19 +588,18 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
accountValue.setUpdated(null);
|
||||
}
|
||||
} else {
|
||||
accountValue.setUpdated(
|
||||
new BonsaiAccount(wrappedWorldView(), address, replacementValue, true));
|
||||
accountValue.setUpdated(createAccount(wrappedWorldView(), address, replacementValue, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BonsaiValue<BonsaiAccount> loadAccountFromParent(
|
||||
final Address address, final BonsaiValue<BonsaiAccount> defaultValue) {
|
||||
private DiffBasedValue<ACCOUNT> loadAccountFromParent(
|
||||
final Address address, final DiffBasedValue<ACCOUNT> defaultValue) {
|
||||
try {
|
||||
final Account parentAccount = wrappedWorldView().get(address);
|
||||
if (parentAccount instanceof BonsaiAccount account) {
|
||||
final BonsaiValue<BonsaiAccount> loadedAccountValue =
|
||||
new BonsaiValue<>(new BonsaiAccount(account), account);
|
||||
if (parentAccount instanceof DiffBasedAccount account) {
|
||||
final DiffBasedValue<ACCOUNT> loadedAccountValue =
|
||||
new DiffBasedValue<>(copyAccount((ACCOUNT) account), ((ACCOUNT) account));
|
||||
accountsToUpdate.put(address, loadedAccountValue);
|
||||
return loadedAccountValue;
|
||||
} else {
|
||||
@@ -617,7 +618,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
// non-change, a cached read.
|
||||
return;
|
||||
}
|
||||
BonsaiValue<Bytes> codeValue = codeToUpdate.get(address);
|
||||
DiffBasedValue<Bytes> codeValue = codeToUpdate.get(address);
|
||||
if (codeValue == null) {
|
||||
final Bytes storedCode =
|
||||
wrappedWorldView()
|
||||
@@ -625,14 +626,14 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
address, Optional.ofNullable(expectedCode).map(Hash::hash).orElse(Hash.EMPTY))
|
||||
.orElse(Bytes.EMPTY);
|
||||
if (!storedCode.isEmpty()) {
|
||||
codeValue = new BonsaiValue<>(storedCode, storedCode);
|
||||
codeValue = new DiffBasedValue<>(storedCode, storedCode);
|
||||
codeToUpdate.put(address, codeValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (codeValue == null) {
|
||||
if ((expectedCode == null || expectedCode.isEmpty()) && replacementCode != null) {
|
||||
codeToUpdate.put(address, new BonsaiValue<>(null, replacementCode));
|
||||
codeToUpdate.put(address, new DiffBasedValue<>(null, replacementCode));
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
@@ -660,10 +661,10 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
}
|
||||
}
|
||||
|
||||
private Map<StorageSlotKey, BonsaiValue<UInt256>> maybeCreateStorageMap(
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageMap, final Address address) {
|
||||
private Map<StorageSlotKey, DiffBasedValue<UInt256>> maybeCreateStorageMap(
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageMap, final Address address) {
|
||||
if (storageMap == null) {
|
||||
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> newMap =
|
||||
final StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> newMap =
|
||||
new StorageConsumingMap<>(address, new ConcurrentHashMap<>(), storagePreloader);
|
||||
storageToUpdate.put(address, newMap);
|
||||
return newMap;
|
||||
@@ -685,13 +686,13 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
// corner case on deletes, non-change
|
||||
return;
|
||||
}
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> storageMap = storageToUpdate.get(address);
|
||||
BonsaiValue<UInt256> slotValue = storageMap == null ? null : storageMap.get(storageSlotKey);
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> storageMap = storageToUpdate.get(address);
|
||||
DiffBasedValue<UInt256> slotValue = storageMap == null ? null : storageMap.get(storageSlotKey);
|
||||
if (slotValue == null) {
|
||||
final Optional<UInt256> storageValue =
|
||||
wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey);
|
||||
if (storageValue.isPresent()) {
|
||||
slotValue = new BonsaiValue<>(storageValue.get(), storageValue.get());
|
||||
slotValue = new DiffBasedValue<>(storageValue.get(), storageValue.get());
|
||||
storageToUpdate
|
||||
.computeIfAbsent(
|
||||
address,
|
||||
@@ -703,7 +704,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
if (slotValue == null) {
|
||||
if ((expectedValue == null || expectedValue.isZero()) && replacementValue != null) {
|
||||
maybeCreateStorageMap(storageMap, address)
|
||||
.put(storageSlotKey, new BonsaiValue<>(null, replacementValue));
|
||||
.put(storageSlotKey, new DiffBasedValue<>(null, replacementValue));
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
@@ -730,7 +731,7 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
existingSlotValue == null ? "null" : existingSlotValue.toShortHexString()));
|
||||
}
|
||||
if (replacementValue == null && slotValue.getPrior() == null) {
|
||||
final Map<StorageSlotKey, BonsaiValue<UInt256>> thisStorageUpdate =
|
||||
final Map<StorageSlotKey, DiffBasedValue<UInt256>> thisStorageUpdate =
|
||||
maybeCreateStorageMap(storageMap, address);
|
||||
thisStorageUpdate.remove(storageSlotKey);
|
||||
if (thisStorageUpdate.isEmpty()) {
|
||||
@@ -769,67 +770,6 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
storageKeyHashLookup.clear();
|
||||
}
|
||||
|
||||
public static class AccountConsumingMap<T> extends ForwardingMap<Address, T> {
|
||||
|
||||
private final ConcurrentMap<Address, T> accounts;
|
||||
private final Consumer<T> consumer;
|
||||
|
||||
public AccountConsumingMap(
|
||||
final ConcurrentMap<Address, T> accounts, final Consumer<T> consumer) {
|
||||
this.accounts = accounts;
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T put(@Nonnull final Address address, @Nonnull final T value) {
|
||||
consumer.process(address, value);
|
||||
return accounts.put(address, value);
|
||||
}
|
||||
|
||||
public Consumer<T> getConsumer() {
|
||||
return consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Address, T> delegate() {
|
||||
return accounts;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StorageConsumingMap<K, T> extends ForwardingMap<K, T> {
|
||||
|
||||
private final Address address;
|
||||
|
||||
private final ConcurrentMap<K, T> storages;
|
||||
private final Consumer<K> consumer;
|
||||
|
||||
public StorageConsumingMap(
|
||||
final Address address, final ConcurrentMap<K, T> storages, final Consumer<K> consumer) {
|
||||
this.address = address;
|
||||
this.storages = storages;
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T put(@Nonnull final K slotKey, @Nonnull final T value) {
|
||||
consumer.process(address, slotKey);
|
||||
return storages.put(slotKey, value);
|
||||
}
|
||||
|
||||
public Consumer<K> getConsumer() {
|
||||
return consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<K, T> delegate() {
|
||||
return storages;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Consumer<T> {
|
||||
void process(final Address address, T value);
|
||||
}
|
||||
|
||||
protected Hash hashAndSaveAccountPreImage(final Address address) {
|
||||
// no need to save account preimage by default
|
||||
return Hash.hash(address);
|
||||
@@ -843,4 +783,33 @@ public class BonsaiWorldStateUpdateAccumulator
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public abstract DiffBasedWorldStateUpdateAccumulator<ACCOUNT> copy();
|
||||
|
||||
protected abstract ACCOUNT copyAccount(final ACCOUNT account);
|
||||
|
||||
protected abstract ACCOUNT copyAccount(
|
||||
final ACCOUNT toCopy, final DiffBasedWorldView context, final boolean mutable);
|
||||
|
||||
protected abstract ACCOUNT createAccount(
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final AccountValue stateTrieAccount,
|
||||
final boolean mutable);
|
||||
|
||||
protected abstract ACCOUNT createAccount(
|
||||
final DiffBasedWorldView context,
|
||||
final Address address,
|
||||
final Hash addressHash,
|
||||
final long nonce,
|
||||
final Wei balance,
|
||||
final Hash storageRoot,
|
||||
final Hash codeHash,
|
||||
final boolean mutable);
|
||||
|
||||
protected abstract ACCOUNT createAccount(
|
||||
final DiffBasedWorldView context, final UpdateTrackingAccount<ACCOUNT> tracked);
|
||||
|
||||
protected abstract void assertCloseEnoughForDiffing(
|
||||
final ACCOUNT source, final AccountValue account, final String context);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.collect.ForwardingMap;
|
||||
|
||||
public class AccountConsumingMap<T> extends ForwardingMap<Address, T> {
|
||||
|
||||
private final ConcurrentMap<Address, T> accounts;
|
||||
private final Consumer<T> consumer;
|
||||
|
||||
public AccountConsumingMap(final ConcurrentMap<Address, T> accounts, final Consumer<T> consumer) {
|
||||
this.accounts = accounts;
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T put(@Nonnull final Address address, @Nonnull final T value) {
|
||||
consumer.process(address, value);
|
||||
return accounts.put(address, value);
|
||||
}
|
||||
|
||||
public Consumer<T> getConsumer() {
|
||||
return consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Address, T> delegate() {
|
||||
return accounts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
|
||||
public interface Consumer<T> {
|
||||
void process(final Address address, T value);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright Hyperledger Besu Contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.google.common.collect.ForwardingMap;
|
||||
|
||||
public class StorageConsumingMap<K, T> extends ForwardingMap<K, T> {
|
||||
|
||||
private final Address address;
|
||||
|
||||
private final ConcurrentMap<K, T> storages;
|
||||
private final Consumer<K> consumer;
|
||||
|
||||
public StorageConsumingMap(
|
||||
final Address address, final ConcurrentMap<K, T> storages, final Consumer<K> consumer) {
|
||||
this.address = address;
|
||||
this.storages = storages;
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T put(@Nonnull final K slotKey, @Nonnull final T value) {
|
||||
consumer.process(address, slotKey);
|
||||
return storages.put(slotKey, value);
|
||||
}
|
||||
|
||||
public Consumer<K> getConsumer() {
|
||||
return consumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<K, T> delegate() {
|
||||
return storages;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
package org.hyperledger.besu.ethereum.worldstate;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKey
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.ForestWorldStateArchive;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState;
|
||||
@@ -95,15 +95,15 @@ public class InMemoryKeyValueStorageProvider extends KeyValueStorageProvider {
|
||||
final Blockchain blockchain, final EvmConfiguration evmConfiguration) {
|
||||
final InMemoryKeyValueStorageProvider inMemoryKeyValueStorageProvider =
|
||||
new InMemoryKeyValueStorageProvider();
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader =
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem());
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
|
||||
return new BonsaiWorldStateProvider(
|
||||
(BonsaiWorldStateKeyValueStorage)
|
||||
inMemoryKeyValueStorageProvider.createWorldStateStorage(
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
|
||||
blockchain,
|
||||
Optional.empty(),
|
||||
cachedMerkleTrieLoader,
|
||||
bonsaiCachedMerkleTrieLoader,
|
||||
null,
|
||||
evmConfiguration);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
|
||||
@@ -41,9 +41,9 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -66,8 +66,8 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
@@ -159,7 +159,7 @@ public abstract class AbstractIsolationTests {
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage,
|
||||
blockchain,
|
||||
Optional.of(16L),
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
null,
|
||||
EvmConfiguration.DEFAULT);
|
||||
var ws = archive.getMutable();
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.TrieIterator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
@@ -45,9 +45,9 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
class CachedMerkleTrieLoaderTest {
|
||||
class BonsaiCachedMerkleTrieLoaderTest {
|
||||
|
||||
private CachedMerkleTrieLoader merkleTrieLoader;
|
||||
private BonsaiCachedMerkleTrieLoader merkleTrieLoader;
|
||||
private final StorageProvider storageProvider = new InMemoryKeyValueStorageProvider();
|
||||
private final BonsaiWorldStateKeyValueStorage inMemoryWorldState =
|
||||
Mockito.spy(
|
||||
@@ -69,7 +69,7 @@ class CachedMerkleTrieLoaderTest {
|
||||
TrieGenerator.generateTrie(
|
||||
worldStateStorageCoordinator,
|
||||
accounts.stream().map(Address::addressHash).collect(Collectors.toList()));
|
||||
merkleTrieLoader = new CachedMerkleTrieLoader(new NoOpMetricsSystem());
|
||||
merkleTrieLoader = new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.BLOCKCHAIN;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
|
||||
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_BLOCK_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -36,13 +36,13 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
|
||||
@@ -77,7 +77,7 @@ class BonsaiWorldStateProviderTest {
|
||||
@Mock SegmentedKeyValueStorageTransaction segmentedKeyValueStorageTransaction;
|
||||
BonsaiWorldStateProvider bonsaiWorldStateArchive;
|
||||
|
||||
@Mock CachedWorldStorageManager cachedWorldStorageManager;
|
||||
@Mock BonsaiCachedWorldStorageManager cachedWorldStorageManager;
|
||||
@Mock TrieLogManager trieLogManager;
|
||||
|
||||
@BeforeEach
|
||||
@@ -111,7 +111,7 @@ class BonsaiWorldStateProviderTest {
|
||||
new NoOpMetricsSystem(),
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
|
||||
blockchain,
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
EvmConfiguration.DEFAULT);
|
||||
|
||||
assertThat(bonsaiWorldStateArchive.getMutable(chainHead, true))
|
||||
@@ -128,7 +128,7 @@ class BonsaiWorldStateProviderTest {
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
|
||||
blockchain,
|
||||
Optional.of(512L),
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
null,
|
||||
EvmConfiguration.DEFAULT);
|
||||
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
|
||||
@@ -150,7 +150,7 @@ class BonsaiWorldStateProviderTest {
|
||||
new NoOpMetricsSystem(),
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
|
||||
blockchain,
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
EvmConfiguration.DEFAULT);
|
||||
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
|
||||
final BlockHeader chainHead = blockBuilder.number(511).buildHeader();
|
||||
@@ -185,7 +185,7 @@ class BonsaiWorldStateProviderTest {
|
||||
trieLogManager,
|
||||
worldStateKeyValueStorage,
|
||||
blockchain,
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
EvmConfiguration.DEFAULT));
|
||||
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
|
||||
|
||||
@@ -214,7 +214,7 @@ class BonsaiWorldStateProviderTest {
|
||||
trieLogManager,
|
||||
worldStateKeyValueStorage,
|
||||
blockchain,
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
EvmConfiguration.DEFAULT));
|
||||
|
||||
final BlockHeader blockHeader = blockBuilder.number(0).buildHeader();
|
||||
@@ -254,7 +254,7 @@ class BonsaiWorldStateProviderTest {
|
||||
trieLogManager,
|
||||
worldStateKeyValueStorage,
|
||||
blockchain,
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
EvmConfiguration.DEFAULT));
|
||||
|
||||
// initial persisted state hash key
|
||||
@@ -297,7 +297,7 @@ class BonsaiWorldStateProviderTest {
|
||||
new NoOpMetricsSystem(),
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
|
||||
blockchain,
|
||||
new CachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
new BonsaiCachedMerkleTrieLoader(new NoOpMetricsSystem()),
|
||||
EvmConfiguration.DEFAULT));
|
||||
|
||||
// initial persisted state hash key
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -29,11 +29,11 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.ACCOUNT_INFO_STATE;
|
||||
@@ -25,11 +25,11 @@ import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIden
|
||||
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
|
||||
@@ -12,11 +12,11 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier.TRIE_BRANCH_STORAGE;
|
||||
import static org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage.WORLD_ROOT_HASH_KEY;
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
|
||||
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -22,9 +22,10 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -26,7 +26,10 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogPruner;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.worldview;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
@@ -23,8 +23,8 @@ import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -69,8 +69,8 @@ class BonsaiWorldStateTest {
|
||||
@MethodSource("priorAndUpdatedEmptyAndNullBytes")
|
||||
void codeUpdateDoesNothingWhenMarkedAsDeletedButAlreadyDeleted(
|
||||
final Bytes prior, final Bytes updated) {
|
||||
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
|
||||
Map.of(Address.ZERO, new BonsaiValue<>(prior, updated));
|
||||
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
|
||||
Map.of(Address.ZERO, new DiffBasedValue<>(prior, updated));
|
||||
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
|
||||
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
|
||||
|
||||
@@ -79,8 +79,8 @@ class BonsaiWorldStateTest {
|
||||
|
||||
@Test
|
||||
void codeUpdateDoesNothingWhenAddingSameAsExistingValue() {
|
||||
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
|
||||
Map.of(Address.ZERO, new BonsaiValue<>(CODE, CODE));
|
||||
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
|
||||
Map.of(Address.ZERO, new DiffBasedValue<>(CODE, CODE));
|
||||
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
|
||||
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
|
||||
|
||||
@@ -90,8 +90,8 @@ class BonsaiWorldStateTest {
|
||||
@ParameterizedTest
|
||||
@MethodSource("emptyAndNullBytes")
|
||||
void removesCodeWhenMarkedAsDeleted(final Bytes updated) {
|
||||
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
|
||||
Map.of(Address.ZERO, new BonsaiValue<>(CODE, updated));
|
||||
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
|
||||
Map.of(Address.ZERO, new DiffBasedValue<>(CODE, updated));
|
||||
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
|
||||
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
|
||||
|
||||
@@ -101,8 +101,8 @@ class BonsaiWorldStateTest {
|
||||
@ParameterizedTest
|
||||
@MethodSource("codeValueAndEmptyAndNullBytes")
|
||||
void addsCodeForNewCodeValue(final Bytes prior) {
|
||||
final Map<Address, BonsaiValue<Bytes>> codeToUpdate =
|
||||
Map.of(ACCOUNT, new BonsaiValue<>(prior, CODE));
|
||||
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate =
|
||||
Map.of(ACCOUNT, new DiffBasedValue<>(prior, CODE));
|
||||
|
||||
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
|
||||
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
|
||||
@@ -112,10 +112,10 @@ class BonsaiWorldStateTest {
|
||||
|
||||
@Test
|
||||
void updateCodeForMultipleValues() {
|
||||
final Map<Address, BonsaiValue<Bytes>> codeToUpdate = new HashMap<>();
|
||||
codeToUpdate.put(Address.fromHexString("0x1"), new BonsaiValue<>(null, CODE));
|
||||
codeToUpdate.put(Address.fromHexString("0x2"), new BonsaiValue<>(CODE, null));
|
||||
codeToUpdate.put(Address.fromHexString("0x3"), new BonsaiValue<>(Bytes.of(9), CODE));
|
||||
final Map<Address, DiffBasedValue<Bytes>> codeToUpdate = new HashMap<>();
|
||||
codeToUpdate.put(Address.fromHexString("0x1"), new DiffBasedValue<>(null, CODE));
|
||||
codeToUpdate.put(Address.fromHexString("0x2"), new DiffBasedValue<>(CODE, null));
|
||||
codeToUpdate.put(Address.fromHexString("0x3"), new DiffBasedValue<>(Bytes.of(9), CODE));
|
||||
|
||||
when(bonsaiWorldStateUpdateAccumulator.getCodeToUpdate()).thenReturn(codeToUpdate);
|
||||
worldState.updateCode(Optional.of(bonsaiUpdater), bonsaiWorldStateUpdateAccumulator);
|
||||
@@ -13,13 +13,15 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.storage.flat;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.storage.flat;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.FullFlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.flat.PartialFlatDbStrategy;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
|
||||
@@ -13,7 +13,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.bonsai.trielog;
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.trielog;
|
||||
|
||||
import org.hyperledger.besu.datatypes.AccountValue;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
@@ -66,6 +66,7 @@ public class ForestKeyValueStorageWorldStateStorageTest {
|
||||
storage.updater().putCode(MerkleTrie.EMPTY_TRIE_NODE).putCode(Bytes.EMPTY).commit();
|
||||
|
||||
assertThat(storage.getCode(Hash.EMPTY_TRIE_HASH)).contains(MerkleTrie.EMPTY_TRIE_NODE);
|
||||
|
||||
assertThat(storage.getCode(Hash.EMPTY)).contains(Bytes.EMPTY);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.eth.sync.state.PendingBlocksManager;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.pruner.Pruner;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
import org.hyperledger.besu.metrics.BesuMetricCategory;
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.TrailingPeerRequirements;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
|
||||
import org.hyperledger.besu.services.tasks.TaskCollection;
|
||||
|
||||
@@ -20,7 +20,7 @@ import static org.hyperledger.besu.ethereum.eth.sync.StorageExceptionManager.get
|
||||
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.TrieNodeHealingRequest;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
import org.hyperledger.besu.plugin.services.exception.StorageException;
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.AccountFlatD
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.heal.StorageFlatDatabaseHealingRangeRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldDownloadState;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.AccountRangeDataR
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
import org.hyperledger.besu.metrics.BesuMetricCategory;
|
||||
import org.hyperledger.besu.plugin.services.MetricsSystem;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput;
|
||||
import org.hyperledger.besu.ethereum.trie.NodeUpdater;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.proof.WorldStateProofProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.CompactEncoding;
|
||||
import org.hyperledger.besu.ethereum.trie.NodeUpdater;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
|
||||
import org.hyperledger.besu.ethereum.trie.TrieIterator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
|
||||
import org.hyperledger.besu.ethereum.trie.TrieIterator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.ImmutableCheckpoint;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.fastsync.worldstate.FastDownloaderFactory;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.worldstate.FastWorldState
|
||||
import org.hyperledger.besu.ethereum.eth.sync.fastsync.worldstate.NodeDataRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.task.EthTask;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
|
||||
@@ -22,7 +22,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
|
||||
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
|
||||
import org.hyperledger.besu.ethereum.trie.TrieIterator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredNodeFactory;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.AccountRangeDataR
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.BytecodeRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.StorageRangeDataRequest;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.BytecodeRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.snapsync.request.SnapDataRequest;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.worldstate.WorldStateDownloadProcess;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
|
||||
import org.hyperledger.besu.ethereum.trie.TrieIterator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
@@ -51,6 +51,7 @@ public class TaskGenerator {
|
||||
new InMemoryKeyValueStorageProvider(),
|
||||
new NoOpMetricsSystem(),
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
|
||||
|
||||
final WorldStateStorageCoordinator worldStateStorageCoordinator =
|
||||
new WorldStateStorageCoordinator(worldStateKeyValueStorage);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
|
||||
import org.hyperledger.besu.ethereum.trie.TrieIterator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateKeyValueStorage;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeManager;
|
||||
import org.hyperledger.besu.ethereum.trie.RangeStorageEntriesCollector;
|
||||
import org.hyperledger.besu.ethereum.trie.TrieIterator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
@@ -89,7 +89,6 @@ class StorageFlatDatabaseHealingRangeRequestTest {
|
||||
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG);
|
||||
worldStateStorageCoordinator = new WorldStateStorageCoordinator(worldStateKeyValueStorage);
|
||||
proofProvider = new WorldStateProofProvider(worldStateStorageCoordinator);
|
||||
|
||||
trie =
|
||||
TrieGenerator.generateTrie(
|
||||
worldStateStorageCoordinator,
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.hyperledger.besu.ethereum.core.TrieGenerator;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.MerkleTrie;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
|
||||
|
||||
@@ -17,11 +17,13 @@ package org.hyperledger.besu.ethereum.referencetests;
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.datatypes.StorageSlotKey;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiValue;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedValue;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.Consumer;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -32,8 +34,8 @@ public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdate
|
||||
private final BonsaiPreImageProxy preImageProxy;
|
||||
|
||||
public BonsaiReferenceTestUpdateAccumulator(
|
||||
final BonsaiWorldView world,
|
||||
final Consumer<BonsaiValue<BonsaiAccount>> accountPreloader,
|
||||
final DiffBasedWorldView world,
|
||||
final Consumer<DiffBasedValue<BonsaiAccount>> accountPreloader,
|
||||
final Consumer<StorageSlotKey> storagePreloader,
|
||||
final BonsaiPreImageProxy preImageProxy,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
@@ -65,7 +67,7 @@ public class BonsaiReferenceTestUpdateAccumulator extends BonsaiWorldStateUpdate
|
||||
getStorageToUpdate()
|
||||
.forEach(
|
||||
(k, v) -> {
|
||||
StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>> newMap =
|
||||
StorageConsumingMap<StorageSlotKey, DiffBasedValue<UInt256>> newMap =
|
||||
new StorageConsumingMap<>(k, new ConcurrentHashMap<>(), v.getConsumer());
|
||||
v.forEach((key, value) -> newMap.put(key, value.copy()));
|
||||
copy.getStorageToUpdate().put(k, newMap);
|
||||
|
||||
@@ -18,16 +18,18 @@ import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.CachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.cache.NoOpCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogAddedEvent;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.NoOpBonsaiCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
|
||||
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
|
||||
import org.hyperledger.besu.evm.internal.EvmConfiguration;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
|
||||
@@ -54,14 +56,14 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
|
||||
|
||||
protected BonsaiReferenceTestWorldState(
|
||||
final BonsaiReferenceTestWorldStateStorage worldStateKeyValueStorage,
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
|
||||
final CachedWorldStorageManager cachedWorldStorageManager,
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
|
||||
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
|
||||
final TrieLogManager trieLogManager,
|
||||
final BonsaiPreImageProxy preImageProxy,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
super(
|
||||
worldStateKeyValueStorage,
|
||||
cachedMerkleTrieLoader,
|
||||
bonsaiCachedMerkleTrieLoader,
|
||||
cachedWorldStorageManager,
|
||||
trieLogManager,
|
||||
evmConfiguration);
|
||||
@@ -72,21 +74,21 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
|
||||
new BonsaiReferenceTestUpdateAccumulator(
|
||||
this,
|
||||
(addr, value) ->
|
||||
cachedMerkleTrieLoader.preLoadAccount(
|
||||
bonsaiCachedMerkleTrieLoader.preLoadAccount(
|
||||
getWorldStateStorage(), worldStateRootHash, addr),
|
||||
(addr, value) ->
|
||||
cachedMerkleTrieLoader.preLoadStorageSlot(getWorldStateStorage(), addr, value),
|
||||
bonsaiCachedMerkleTrieLoader.preLoadStorageSlot(
|
||||
getWorldStateStorage(), addr, value),
|
||||
preImageProxy,
|
||||
evmConfiguration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceTestWorldState copy() {
|
||||
var layerCopy =
|
||||
new BonsaiReferenceTestWorldStateStorage(worldStateKeyValueStorage, preImageProxy);
|
||||
var layerCopy = new BonsaiReferenceTestWorldStateStorage(getWorldStateStorage(), preImageProxy);
|
||||
return new BonsaiReferenceTestWorldState(
|
||||
layerCopy,
|
||||
cachedMerkleTrieLoader,
|
||||
bonsaiCachedMerkleTrieLoader,
|
||||
cachedWorldStorageManager,
|
||||
trieLogManager,
|
||||
preImageProxy,
|
||||
@@ -187,8 +189,9 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
|
||||
private BonsaiWorldState createBonsaiWorldState(final boolean isFrozen) {
|
||||
BonsaiWorldState bonsaiWorldState =
|
||||
new BonsaiWorldState(
|
||||
new BonsaiWorldStateLayerStorage(worldStateKeyValueStorage),
|
||||
cachedMerkleTrieLoader,
|
||||
new BonsaiWorldStateLayerStorage(
|
||||
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage),
|
||||
bonsaiCachedMerkleTrieLoader,
|
||||
cachedWorldStorageManager,
|
||||
trieLogManager,
|
||||
evmConfiguration);
|
||||
@@ -209,8 +212,11 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
|
||||
final Map<String, ReferenceTestWorldState.AccountMock> accounts,
|
||||
final EvmConfiguration evmConfiguration) {
|
||||
final ObservableMetricsSystem metricsSystem = new NoOpMetricsSystem();
|
||||
final CachedMerkleTrieLoader cachedMerkleTrieLoader = new CachedMerkleTrieLoader(metricsSystem);
|
||||
|
||||
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader =
|
||||
new BonsaiCachedMerkleTrieLoader(metricsSystem);
|
||||
final TrieLogManager trieLogManager = new ReferenceTestsInMemoryTrieLogManager();
|
||||
|
||||
final BonsaiPreImageProxy preImageProxy =
|
||||
new BonsaiPreImageProxy.BonsaiReferenceTestPreImageProxy();
|
||||
|
||||
@@ -223,13 +229,13 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
|
||||
final BonsaiReferenceTestWorldStateStorage worldStateKeyValueStorage =
|
||||
new BonsaiReferenceTestWorldStateStorage(bonsaiWorldStateKeyValueStorage, preImageProxy);
|
||||
|
||||
final NoOpCachedWorldStorageManager noOpCachedWorldStorageManager =
|
||||
new NoOpCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage);
|
||||
final NoOpBonsaiCachedWorldStorageManager noOpCachedWorldStorageManager =
|
||||
new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage);
|
||||
|
||||
final BonsaiReferenceTestWorldState worldState =
|
||||
new BonsaiReferenceTestWorldState(
|
||||
worldStateKeyValueStorage,
|
||||
cachedMerkleTrieLoader,
|
||||
bonsaiCachedMerkleTrieLoader,
|
||||
noOpCachedWorldStorageManager,
|
||||
trieLogManager,
|
||||
preImageProxy,
|
||||
@@ -260,10 +266,10 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
|
||||
|
||||
@Override
|
||||
public synchronized void saveTrieLog(
|
||||
final BonsaiWorldStateUpdateAccumulator localUpdater,
|
||||
final DiffBasedWorldStateUpdateAccumulator<?> localUpdater,
|
||||
final Hash forWorldStateRootHash,
|
||||
final BlockHeader forBlockHeader,
|
||||
final BonsaiWorldState forWorldState) {
|
||||
final DiffBasedWorldState forWorldState) {
|
||||
// notify trie log added observers, synchronously
|
||||
TrieLog trieLog = trieLogFactory.create(localUpdater, forBlockHeader);
|
||||
trieLogCache.put(forBlockHeader.getHash(), trieLogFactory.serialize(trieLog));
|
||||
|
||||
@@ -16,11 +16,11 @@ package org.hyperledger.besu.ethereum.referencetests;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiPreImageProxy;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldView;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiPreImageProxy;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateLayerStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldView;
|
||||
import org.hyperledger.besu.evm.account.AccountStorageEntry;
|
||||
import org.hyperledger.besu.evm.worldstate.WorldState;
|
||||
|
||||
@@ -64,7 +64,7 @@ public class BonsaiReferenceTestWorldStateStorage extends BonsaiWorldStateLayerS
|
||||
}
|
||||
|
||||
public Stream<WorldState.StreamableAccount> streamAccounts(
|
||||
final BonsaiWorldView context, final Bytes32 startKeyHash, final int limit) {
|
||||
final DiffBasedWorldView context, final Bytes32 startKeyHash, final int limit) {
|
||||
return streamFlatAccounts(startKeyHash, UInt256.MAX_VALUE, limit)
|
||||
.entrySet()
|
||||
// map back to addresses using preImage provider:
|
||||
|
||||
@@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx4g \
|
||||
--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED \
|
||||
--add-opens jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
|
||||
# Could be moved to sonar properties after https://sonarsource.atlassian.net/browse/SONARGRADL-134
|
||||
systemProp.sonar.gradle.skipCompile=true
|
||||
systemProp.sonar.gradle.skipCompile=true
|
||||
Reference in New Issue
Block a user