Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import org.hyperledger.besu.cli.options.unstable.PrivacyPluginOptions;
import org.hyperledger.besu.cli.options.unstable.RPCOptions;
import org.hyperledger.besu.cli.options.unstable.SynchronizerOptions;
import org.hyperledger.besu.cli.options.unstable.TrieLogPruningOptions;
import org.hyperledger.besu.cli.presynctasks.PreSynchronizationTaskRunner;
import org.hyperledger.besu.cli.presynctasks.PrivateDatabaseMigrationPreSyncTask;
import org.hyperledger.besu.cli.subcommands.PasswordSubCommand;
Expand Down Expand Up @@ -294,6 +295,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final EvmOptions unstableEvmOptions = EvmOptions.create();
private final IpcOptions unstableIpcOptions = IpcOptions.create();
private final ChainPruningOptions unstableChainPruningOptions = ChainPruningOptions.create();
private final TrieLogPruningOptions unstableTrieLogPruningOptions =
TrieLogPruningOptions.create();

// stable CLI options
private final DataStorageOptions dataStorageOptions = DataStorageOptions.create();
Expand Down Expand Up @@ -1530,6 +1533,7 @@ private void handleUnstableOptions() {
.put("EVM Options", unstableEvmOptions)
.put("IPC Options", unstableIpcOptions)
.put("Chain Data Pruning Options", unstableChainPruningOptions)
.put("Trie Log Pruning Options", unstableTrieLogPruningOptions)
.build();

UnstableOptionsSubCommand.createUnstableOptions(commandLine, unstableOptions);
Expand Down Expand Up @@ -2165,6 +2169,7 @@ public BesuControllerBuilder getControllerBuilder() {
.maxRemotelyInitiatedPeers(maxRemoteInitiatedPeers)
.randomPeerPriority(p2PDiscoveryOptionGroup.randomPeerPriority)
.chainPruningConfiguration(unstableChainPruningOptions.toDomainObject())
.trieLogPrunerConfiguration(unstableTrieLogPruningOptions.toDomainObject())
.cacheLastBlocks(numberOfblocksToCache);
}

Expand Down Expand Up @@ -3432,6 +3437,10 @@ private String generateConfigurationOverview() {
builder.setHighSpecEnabled();
}

if (unstableTrieLogPruningOptions.getTrieLogPruningEnabled()) {
builder.setTrieLogPruningEnabled();
}

builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation());

builder.setPluginContext(besuComponent.getBesuPluginContext());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class ConfigurationOverviewBuilder {
private Collection<String> engineApis;
private String engineJwtFilePath;
private boolean isHighSpec = false;
private boolean isTrieLogPruning = false;
private TransactionPoolConfiguration.Implementation txPoolImplementation;
private Map<String, String> environment;
private BesuPluginContextImpl besuPluginContext;
Expand Down Expand Up @@ -169,6 +170,16 @@ public ConfigurationOverviewBuilder setHighSpecEnabled() {
return this;
}

/**
* Sets high spec enabled.
*
* @return the builder
*/
public ConfigurationOverviewBuilder setTrieLogPruningEnabled() {
isTrieLogPruning = true;
return this;
}

/**
* Sets the txpool implementation in use.
*
Expand Down Expand Up @@ -258,6 +269,10 @@ public String build() {

lines.add("Using " + txPoolImplementation + " transaction pool implementation");

if (isTrieLogPruning) {
lines.add("Trie log pruning enabled");
}

lines.add("");
lines.add("Host:");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.cli.options.unstable;

import org.hyperledger.besu.cli.options.CLIOptions;
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogPrunerConfiguration;

import java.util.Arrays;
import java.util.List;

import picocli.CommandLine;

/** The trie log pruning CLI options. */
public class TrieLogPruningOptions implements CLIOptions<TrieLogPrunerConfiguration> {

private static final String TRIE_LOG_PRUNING_ENABLED_FLAG = "--Xtrie-log-pruning-enabled";

@CommandLine.Option(
hidden = true,
names = {TRIE_LOG_PRUNING_ENABLED_FLAG},
description = "Enable trie log pruning (default: ${DEFAULT-VALUE})")
private final Boolean trieLogPruningEnabled = Boolean.FALSE;

/**
* Create trie log pruning options.
*
* @return the trie log pruning options
*/
public static TrieLogPruningOptions create() {
return new TrieLogPruningOptions();
}

/**
* Gets trie log pruning enabled.
*
* @return the trie log pruning enabled
*/
public Boolean getTrieLogPruningEnabled() {
return trieLogPruningEnabled;
}

@Override
public TrieLogPrunerConfiguration toDomainObject() {
return new TrieLogPrunerConfiguration(trieLogPruningEnabled);
}

@Override
public List<String> getCLIOptions() {
return Arrays.asList(TRIE_LOG_PRUNING_ENABLED_FLAG, trieLogPruningEnabled.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import org.hyperledger.besu.ethereum.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogPrunerConfiguration;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.BlockchainStorage;
import org.hyperledger.besu.ethereum.chain.ChainDataPruner;
Expand Down Expand Up @@ -179,6 +181,9 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
private int maxRemotelyInitiatedPeers;
/** The Chain pruner configuration. */
protected ChainPrunerConfiguration chainPrunerConfiguration = ChainPrunerConfiguration.DEFAULT;
/** The Trie log pruner configuration. */
protected TrieLogPrunerConfiguration trieLogPrunerConfiguration =
TrieLogPrunerConfiguration.DEFAULT;

private NetworkingConfiguration networkingConfiguration;
private Boolean randomPeerPriority;
Expand Down Expand Up @@ -508,7 +513,19 @@ public BesuControllerBuilder chainPruningConfiguration(
}

/**
* Chain pruning configuration besu controller builder.
* Trie log pruning configuration besu controller builder.
*
* @param trieLogPrunerConfiguration the trie log pruner configuration
* @return the besu controller builder
*/
public BesuControllerBuilder trieLogPrunerConfiguration(
final TrieLogPrunerConfiguration trieLogPrunerConfiguration) {
this.trieLogPrunerConfiguration = trieLogPrunerConfiguration;
return this;
}

/**
* Cache last blocks configuration besu controller builder.
*
* @param numberOfBlocksToCache the number of blocks to cache
* @return the besu controller builder
Expand Down Expand Up @@ -613,8 +630,15 @@ public BesuController build() {
.map(BesuComponent::getCachedMerkleTrieLoader)
.orElseGet(() -> new CachedMerkleTrieLoader(metricsSystem));

final TrieLogPruner trieLogPruner =
trieLogPrunerConfiguration.getTrieLogPruningEnabled()
? new TrieLogPruner((BonsaiWorldStateKeyValueStorage) worldStateStorage, blockchain)
: TrieLogPruner.noOpTrieLogPruner();
trieLogPruner.initialise();

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

if (blockchain.getChainHeadBlockNumber() < 1) {
genesisState.writeStateTo(worldStateArchive.getMutable());
Expand Down Expand Up @@ -1070,7 +1094,8 @@ private Optional<SnapProtocolManager> createSnapProtocolManager(
WorldStateArchive createWorldStateArchive(
final WorldStateStorage worldStateStorage,
final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader) {
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final TrieLogPruner trieLogPruner) {
switch (dataStorageConfiguration.getDataStorageFormat()) {
case BONSAI:
return new BonsaiWorldStateProvider(
Expand All @@ -1079,7 +1104,8 @@ WorldStateArchive createWorldStateArchive(
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
cachedMerkleTrieLoader,
metricsSystem,
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null));
besuComponent.map(BesuComponent::getBesuPluginContext).orElse(null),
trieLogPruner);

case FOREST:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ public void initMocks() throws Exception {
when(mockControllerBuilder.randomPeerPriority(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.chainPruningConfiguration(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.trieLogPrunerConfiguration(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.lowerBoundPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxRemotelyInitiatedPeers(anyInt()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.MiningParameters;
Expand Down Expand Up @@ -165,7 +166,10 @@ public void shouldDisablePruningIfBonsaiIsEnabled() {
doReturn(worldStateArchive)
.when(besuControllerBuilder)
.createWorldStateArchive(
any(WorldStateStorage.class), any(Blockchain.class), any(CachedMerkleTrieLoader.class));
any(WorldStateStorage.class),
any(Blockchain.class),
any(CachedMerkleTrieLoader.class),
any(TrieLogPruner.class));
doReturn(mockWorldState).when(worldStateArchive).getMutable();

when(storageProvider.createWorldStateStorage(DataStorageFormat.BONSAI))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.hyperledger.besu.ethereum.bonsai.cache.CachedWorldStorageManager;
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.bonsai.trielog.TrieLogPruner;
import org.hyperledger.besu.ethereum.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.chain.Blockchain;
Expand All @@ -32,10 +33,8 @@
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.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.worldstate.WorldState;
Expand Down Expand Up @@ -68,36 +67,25 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
private final BonsaiWorldStateKeyValueStorage worldStateStorage;
private final CachedMerkleTrieLoader cachedMerkleTrieLoader;

public BonsaiWorldStateProvider(
final StorageProvider provider,
final Blockchain blockchain,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final ObservableMetricsSystem metricsSystem,
final BesuContext pluginContext) {
this(
(BonsaiWorldStateKeyValueStorage)
provider.createWorldStateStorage(DataStorageFormat.BONSAI),
blockchain,
Optional.empty(),
cachedMerkleTrieLoader,
metricsSystem,
pluginContext);
}

public BonsaiWorldStateProvider(
final BonsaiWorldStateKeyValueStorage worldStateStorage,
final Blockchain blockchain,
final Optional<Long> maxLayersToLoad,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final ObservableMetricsSystem metricsSystem,
final BesuContext pluginContext) {
final BesuContext pluginContext,
final TrieLogPruner trieLogPruner) {

this.cachedWorldStorageManager =
new CachedWorldStorageManager(this, worldStateStorage, metricsSystem);
// TODO: de-dup constructors
this.trieLogManager =
new TrieLogManager(
blockchain, worldStateStorage, maxLayersToLoad.orElse(RETAINED_LAYERS), pluginContext);
blockchain,
worldStateStorage,
maxLayersToLoad.orElse(RETAINED_LAYERS),
pluginContext,
trieLogPruner);
this.blockchain = blockchain;
this.worldStateStorage = worldStateStorage;
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
Expand Down Expand Up @@ -203,6 +204,10 @@ public Optional<byte[]> getTrieLog(final Hash blockHash) {
return trieLogStorage.get(blockHash.toArrayUnsafe());
}

public Stream<byte[]> streamTrieLogs(final int limit) {
return trieLogStorage.streamKeys().limit(limit);
}

public Optional<Bytes> getStateTrieNode(final Bytes location) {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, location.toArrayUnsafe())
Expand Down Expand Up @@ -335,6 +340,10 @@ public long prune(final Predicate<byte[]> inUseCheck) {
throw new RuntimeException("Bonsai Tries do not work with pruning.");
}

public boolean pruneTrieLog(final byte[] blockHashBytes) {
return trieLogStorage.tryDelete(blockHashBytes);
}

@Override
public long addNodeAddedListener(final NodesAddedListener listener) {
throw new RuntimeException("addNodeAddedListener not available");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,19 @@ public class TrieLogManager {
protected final Subscribers<TrieLogEvent.TrieLogObserver> trieLogObservers = Subscribers.create();

protected final TrieLogFactory trieLogFactory;
private final TrieLogPruner trieLogPruner;

public TrieLogManager(
final Blockchain blockchain,
final BonsaiWorldStateKeyValueStorage worldStateStorage,
final long maxLayersToLoad,
final BesuContext pluginContext) {
final BesuContext pluginContext,
final TrieLogPruner trieLogPruner) {
this.blockchain = blockchain;
this.rootWorldStateStorage = worldStateStorage;
this.maxLayersToLoad = maxLayersToLoad;
this.trieLogFactory = setupTrieLogFactory(pluginContext);
this.trieLogPruner = trieLogPruner;
}

public synchronized void saveTrieLog(
Expand All @@ -82,6 +85,9 @@ public synchronized void saveTrieLog(
} finally {
if (success) {
stateUpdater.commit();
trieLogPruner.cacheForLaterPruning(
forBlockHeader.getNumber(), forBlockHeader.getBlockHash().toArrayUnsafe());
trieLogPruner.pruneFromCache();
} else {
stateUpdater.rollback();
}
Expand Down
Loading