Feature/fleet mode rebase (#6641)

* fleet mode squash commit rebase

Signed-off-by: garyschulte <garyschulte@gmail.com>
pull/7134/head
garyschulte 6 months ago committed by GitHub
parent 8df6bcaddd
commit ebb883075f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 9
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java
  2. 4
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java
  3. 10
      besu/src/main/java/org/hyperledger/besu/Runner.java
  4. 48
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  5. 9
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/JsonRpcHttpOptions.java
  6. 41
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java
  7. 20
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  8. 48
      besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java
  9. 5
      besu/src/main/java/org/hyperledger/besu/services/BesuEventsImpl.java
  10. 19
      besu/src/main/java/org/hyperledger/besu/services/BesuPluginContextImpl.java
  11. 49
      besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java
  12. 44
      besu/src/main/java/org/hyperledger/besu/services/P2PServiceImpl.java
  13. 82
      besu/src/main/java/org/hyperledger/besu/services/RlpConverterServiceImpl.java
  14. 166
      besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java
  15. 43
      besu/src/main/java/org/hyperledger/besu/services/TransactionPoolServiceImpl.java
  16. 4
      besu/src/test/java/org/hyperledger/besu/PrivacyTest.java
  17. 4
      besu/src/test/java/org/hyperledger/besu/RunnerTest.java
  18. 3
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  19. 3
      besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java
  20. 54
      besu/src/test/java/org/hyperledger/besu/services/RlpConverterServiceImplTest.java
  21. 3
      consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingMiningCoordinatorTest.java
  22. 4
      datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobGas.java
  23. 13
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/ChainPrunerConfiguration.java
  24. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java
  25. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/MutableBlockchain.java
  26. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java
  27. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java
  28. 26
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java
  29. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java
  30. 3
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java
  31. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java
  32. 72
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java
  33. 17
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java
  34. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/StorageSubscriber.java
  35. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java
  36. 5
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedWorldStateKeyValueStorage.java
  37. 40
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java
  38. 52
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java
  39. 79
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java
  40. 4
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java
  41. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java
  42. 10
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java
  43. 19
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java
  44. 4
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java
  45. 4
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java
  46. 4
      ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java
  47. 14
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java
  48. 1
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PipelineChainDownloader.java
  49. 2
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java
  50. 1
      ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/PeerDiscoveryController.java
  51. 20
      ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/RecursivePeerRefreshState.java
  52. 7
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java
  53. 123
      ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/NoOpMerkleTrie.java
  54. 2
      plugin-api/build.gradle
  55. 3
      plugin-api/src/main/java/org/hyperledger/besu/plugin/BesuPlugin.java
  56. 15
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuConfiguration.java
  57. 8
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuEvents.java
  58. 34
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BlockchainService.java
  59. 3
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TrieLogService.java
  60. 27
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/p2p/P2PService.java
  61. 74
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rlp/RlpConverterService.java
  62. 62
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/SynchronizationService.java
  63. 26
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java
  64. 26
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/transactionpool/TransactionPoolService.java
  65. 27
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/trielogs/TrieLogProvider.java

@ -180,11 +180,10 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.from(node.getMiningParameters()) .from(node.getMiningParameters())
.transactionSelectionService(transactionSelectionServiceImpl) .transactionSelectionService(transactionSelectionServiceImpl)
.build(); .build();
commonPluginConfiguration.init( commonPluginConfiguration
dataDir, .init(dataDir, dataDir.resolve(DATABASE_PATH), node.getDataStorageConfiguration())
dataDir.resolve(DATABASE_PATH), .withMiningParameters(miningParameters);
node.getDataStorageConfiguration(),
miningParameters);
final BesuPluginContextImpl besuPluginContext = final BesuPluginContextImpl besuPluginContext =
besuPluginContextMap.computeIfAbsent( besuPluginContextMap.computeIfAbsent(
node, node,

@ -274,7 +274,9 @@ public class PrivacyNode implements AutoCloseable {
private PrivacyStorageProvider createKeyValueStorageProvider( private PrivacyStorageProvider createKeyValueStorageProvider(
final Path dataLocation, final Path dbLocation) { final Path dataLocation, final Path dbLocation) {
final var besuConfiguration = new BesuConfigurationImpl(); final var besuConfiguration = new BesuConfigurationImpl();
besuConfiguration.init(dataLocation, dbLocation, null, besuConfig.getMiningParameters()); besuConfiguration
.init(dataLocation, dbLocation, null)
.withMiningParameters(besuConfig.getMiningParameters());
return new PrivacyKeyValueStorageProviderBuilder() return new PrivacyKeyValueStorageProviderBuilder()
.withStorageFactory( .withStorageFactory(
new RocksDBKeyValuePrivacyStorageFactory( new RocksDBKeyValuePrivacyStorageFactory(

@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolEvictionService; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolEvictionService;
import org.hyperledger.besu.ethereum.p2p.network.NetworkRunner; import org.hyperledger.besu.ethereum.p2p.network.NetworkRunner;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.stratum.StratumServer; import org.hyperledger.besu.ethereum.stratum.StratumServer;
import org.hyperledger.besu.ethstats.EthStatsService; import org.hyperledger.besu.ethstats.EthStatsService;
import org.hyperledger.besu.metrics.MetricsService; import org.hyperledger.besu.metrics.MetricsService;
@ -422,6 +423,15 @@ public class Runner implements AutoCloseable {
return networkRunner.getNetwork().getLocalEnode(); return networkRunner.getNetwork().getLocalEnode();
} }
/**
* get P2PNetwork service.
*
* @return p2p network service.
*/
public P2PNetwork getP2PNetwork() {
return networkRunner.getNetwork();
}
@FunctionalInterface @FunctionalInterface
private interface SynchronousShutdown { private interface SynchronousShutdown {
/** /**

@ -172,21 +172,29 @@ import org.hyperledger.besu.plugin.services.TransactionSimulationService;
import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.metrics.MetricCategory; import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry; import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
import org.hyperledger.besu.plugin.services.p2p.P2PService;
import org.hyperledger.besu.plugin.services.rlp.RlpConverterService;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule; import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory; import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.plugin.services.sync.SynchronizationService;
import org.hyperledger.besu.plugin.services.transactionpool.TransactionPoolService;
import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuEventsImpl; import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.BlockchainServiceImpl; import org.hyperledger.besu.services.BlockchainServiceImpl;
import org.hyperledger.besu.services.P2PServiceImpl;
import org.hyperledger.besu.services.PermissioningServiceImpl; import org.hyperledger.besu.services.PermissioningServiceImpl;
import org.hyperledger.besu.services.PicoCLIOptionsImpl; import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.PrivacyPluginServiceImpl; import org.hyperledger.besu.services.PrivacyPluginServiceImpl;
import org.hyperledger.besu.services.RlpConverterServiceImpl;
import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.RpcEndpointServiceImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.SynchronizationServiceImpl;
import org.hyperledger.besu.services.TraceServiceImpl; import org.hyperledger.besu.services.TraceServiceImpl;
import org.hyperledger.besu.services.TransactionPoolServiceImpl;
import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl; import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl;
import org.hyperledger.besu.services.TransactionSelectionServiceImpl; import org.hyperledger.besu.services.TransactionSelectionServiceImpl;
import org.hyperledger.besu.services.TransactionSimulationServiceImpl; import org.hyperledger.besu.services.TransactionSimulationServiceImpl;
@ -1161,12 +1169,15 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final var runner = buildRunner(); final var runner = buildRunner();
runner.startExternalServices(); runner.startExternalServices();
startPlugins(); startPlugins(runner);
validatePluginOptions(); validatePluginOptions();
setReleaseMetrics(); setReleaseMetrics();
preSynchronization(); preSynchronization();
runner.startEthereumMainLoop(); runner.startEthereumMainLoop();
besuPluginContext.afterExternalServicesMainLoop();
runner.awaitStop(); runner.awaitStop();
} catch (final Exception e) { } catch (final Exception e) {
@ -1327,7 +1338,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
pidPath); pidPath);
} }
private void startPlugins() { private void startPlugins(final Runner runner) {
blockchainServiceImpl.init( blockchainServiceImpl.init(
besuController.getProtocolContext(), besuController.getProtocolSchedule()); besuController.getProtocolContext(), besuController.getProtocolSchedule());
transactionSimulationServiceImpl.init( transactionSimulationServiceImpl.init(
@ -1348,6 +1359,26 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuController.getProtocolContext().getBadBlockManager())); besuController.getProtocolContext().getBadBlockManager()));
besuPluginContext.addService(MetricsSystem.class, getMetricsSystem()); besuPluginContext.addService(MetricsSystem.class, getMetricsSystem());
besuPluginContext.addService(BlockchainService.class, blockchainServiceImpl);
besuPluginContext.addService(
SynchronizationService.class,
new SynchronizationServiceImpl(
besuController.getProtocolContext(),
besuController.getProtocolSchedule(),
besuController.getSyncState(),
besuController.getProtocolContext().getWorldStateArchive()));
besuPluginContext.addService(P2PService.class, new P2PServiceImpl(runner.getP2PNetwork()));
besuPluginContext.addService(
TransactionPoolService.class,
new TransactionPoolServiceImpl(besuController.getTransactionPool()));
besuPluginContext.addService(
RlpConverterService.class,
new RlpConverterServiceImpl(besuController.getProtocolSchedule()));
besuPluginContext.addService( besuPluginContext.addService(
TraceService.class, TraceService.class,
new TraceServiceImpl( new TraceServiceImpl(
@ -1653,11 +1684,11 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private void validateChainDataPruningParams() { private void validateChainDataPruningParams() {
if (unstableChainPruningOptions.getChainDataPruningEnabled() if (unstableChainPruningOptions.getChainDataPruningEnabled()
&& unstableChainPruningOptions.getChainDataPruningBlocksRetained() && unstableChainPruningOptions.getChainDataPruningBlocksRetained()
< ChainPruningOptions.DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED) { < unstableChainPruningOptions.getChainDataPruningBlocksRetainedLimit()) {
throw new ParameterException( throw new ParameterException(
this.commandLine, this.commandLine,
"--Xchain-pruning-blocks-retained must be >= " "--Xchain-pruning-blocks-retained must be >= "
+ ChainPruningOptions.DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED); + unstableChainPruningOptions.getChainDataPruningBlocksRetainedLimit());
} }
} }
@ -1843,11 +1874,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
* @return instance of BesuControllerBuilder * @return instance of BesuControllerBuilder
*/ */
public BesuControllerBuilder getControllerBuilder() { public BesuControllerBuilder getControllerBuilder() {
pluginCommonConfiguration.init( pluginCommonConfiguration
dataDir(), .init(dataDir(), dataDir().resolve(DATABASE_PATH), getDataStorageConfiguration())
dataDir().resolve(DATABASE_PATH), .withMiningParameters(getMiningParameters())
getDataStorageConfiguration(), .withJsonRpcHttpOptions(jsonRpcHttpOptions);
miningParametersSupplier.get());
final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName);
return controllerBuilderFactory return controllerBuilderFactory
.fromEthNetworkConfig(updateNetworkConfig(network), getDefaultSyncModeIfNotSet()) .fromEthNetworkConfig(updateNetworkConfig(network), getDefaultSyncModeIfNotSet())

@ -475,6 +475,15 @@ public class JsonRpcHttpOptions {
return rpcHttpApis; return rpcHttpApis;
} }
/**
* Returns the host for RPC over HTTP.
*
* @return The port number
*/
public String getRpcHttpHost() {
return rpcHttpHost;
}
/** /**
* Returns the port for RPC over HTTP. * Returns the port for RPC over HTTP.
* *

@ -28,10 +28,17 @@ public class ChainPruningOptions implements CLIOptions<ChainPrunerConfiguration>
private static final String CHAIN_PRUNING_ENABLED_FLAG = "--Xchain-pruning-enabled"; private static final String CHAIN_PRUNING_ENABLED_FLAG = "--Xchain-pruning-enabled";
private static final String CHAIN_PRUNING_BLOCKS_RETAINED_FLAG = private static final String CHAIN_PRUNING_BLOCKS_RETAINED_FLAG =
"--Xchain-pruning-blocks-retained"; "--Xchain-pruning-blocks-retained";
private static final String CHAIN_PRUNING_BLOCKS_RETAINED_LIMIT_FLAG =
"--Xchain-pruning-blocks-retained-limit";
private static final String CHAIN_PRUNING_FREQUENCY_FLAG = "--Xchain-pruning-frequency"; private static final String CHAIN_PRUNING_FREQUENCY_FLAG = "--Xchain-pruning-frequency";
/** The constant DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED. */ /**
public static final long DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED = 7200; * The "CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED_LIMIT" field sets the minimum limit for the
* "CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED" value. For most networks, the default value of this
* limit is the safest. Reducing this value requires careful consideration and understanding of
* the potential implications. Lowering this limit may have unintended side effects.
*/
public static final long CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED_LIMIT = 7200;
/** The constant DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY. */ /** The constant DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY. */
public static final int DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY = 256; public static final int DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY = 256;
@ -47,11 +54,21 @@ public class ChainPruningOptions implements CLIOptions<ChainPrunerConfiguration>
hidden = true, hidden = true,
names = {CHAIN_PRUNING_BLOCKS_RETAINED_FLAG}, names = {CHAIN_PRUNING_BLOCKS_RETAINED_FLAG},
description = description =
"The number of recent blocks for which to keep the chain data. Must be >= " "The number of recent blocks for which to keep the chain data. Should be >= "
+ DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED + CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED_LIMIT
+ " (default: ${DEFAULT-VALUE})")
private final Long chainDataPruningBlocksRetained = CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED_LIMIT;
@CommandLine.Option(
hidden = true,
names = {CHAIN_PRUNING_BLOCKS_RETAINED_LIMIT_FLAG},
description =
"Allows setting the limit below which no more blocks can be pruned. This prevents setting a value lower than this for "
+ CHAIN_PRUNING_BLOCKS_RETAINED_FLAG
+ ". This flag should be used with caution as reducing the limit may have unintended side effects."
+ " (default: ${DEFAULT-VALUE})") + " (default: ${DEFAULT-VALUE})")
private final Long chainDataPruningBlocksRetained = private final Long chainDataPruningBlocksRetainedLimit =
DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED; CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED_LIMIT;
@CommandLine.Option( @CommandLine.Option(
hidden = true, hidden = true,
@ -91,11 +108,21 @@ public class ChainPruningOptions implements CLIOptions<ChainPrunerConfiguration>
return chainDataPruningBlocksRetained; return chainDataPruningBlocksRetained;
} }
/**
* Get the configured number of retained blocks for chain pruning.
*
* @return the number of retained blocks
*/
public Long getChainDataPruningBlocksRetainedLimit() {
return chainDataPruningBlocksRetainedLimit;
}
@Override @Override
public ChainPrunerConfiguration toDomainObject() { public ChainPrunerConfiguration toDomainObject() {
return new ChainPrunerConfiguration( return new ChainPrunerConfiguration(
chainDataPruningEnabled, chainDataPruningEnabled,
chainDataPruningBlocksRetained, chainDataPruningBlocksRetained,
chainDataPruningBlocksRetainedLimit,
chainDataPruningBlocksFrequency.getValue()); chainDataPruningBlocksFrequency.getValue());
} }
@ -106,6 +133,8 @@ public class ChainPruningOptions implements CLIOptions<ChainPrunerConfiguration>
chainDataPruningEnabled.toString(), chainDataPruningEnabled.toString(),
CHAIN_PRUNING_BLOCKS_RETAINED_FLAG, CHAIN_PRUNING_BLOCKS_RETAINED_FLAG,
chainDataPruningBlocksRetained.toString(), chainDataPruningBlocksRetained.toString(),
CHAIN_PRUNING_BLOCKS_RETAINED_LIMIT_FLAG,
chainDataPruningBlocksRetainedLimit.toString(),
CHAIN_PRUNING_FREQUENCY_FLAG, CHAIN_PRUNING_FREQUENCY_FLAG,
chainDataPruningBlocksFrequency.toString()); chainDataPruningBlocksFrequency.toString());
} }

@ -610,16 +610,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
blockchain, worldStateArchive, protocolSchedule, this::createConsensusContext); blockchain, worldStateArchive, protocolSchedule, this::createConsensusContext);
validateContext(protocolContext); validateContext(protocolContext);
if (chainPrunerConfiguration.getChainPruningEnabled()) {
final ChainDataPruner chainDataPruner = createChainPruner(blockchainStorage);
blockchain.observeBlockAdded(chainDataPruner);
LOG.info(
"Chain data pruning enabled with recent blocks retained to be: "
+ chainPrunerConfiguration.getChainPruningBlocksRetained()
+ " and frequency to be: "
+ chainPrunerConfiguration.getChainPruningBlocksFrequency());
}
protocolSchedule.setPublicWorldStateArchiveForPrivacyBlockProcessor( protocolSchedule.setPublicWorldStateArchiveForPrivacyBlockProcessor(
protocolContext.getWorldStateArchive()); protocolContext.getWorldStateArchive());
@ -668,6 +658,16 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
final boolean fullSyncDisabled = !SyncMode.isFullSync(syncConfig.getSyncMode()); final boolean fullSyncDisabled = !SyncMode.isFullSync(syncConfig.getSyncMode());
final SyncState syncState = new SyncState(blockchain, ethPeers, fullSyncDisabled, checkpoint); final SyncState syncState = new SyncState(blockchain, ethPeers, fullSyncDisabled, checkpoint);
if (chainPrunerConfiguration.getChainPruningEnabled()) {
final ChainDataPruner chainDataPruner = createChainPruner(blockchainStorage);
blockchain.observeBlockAdded(chainDataPruner);
LOG.info(
"Chain data pruning enabled with recent blocks retained to be: "
+ chainPrunerConfiguration.getChainPruningBlocksRetained()
+ " and frequency to be: "
+ chainPrunerConfiguration.getChainPruningBlocksFrequency());
}
final TransactionPool transactionPool = final TransactionPool transactionPool =
TransactionPoolFactory.createTransactionPool( TransactionPoolFactory.createTransactionPool(
protocolSchedule, protocolSchedule,

@ -14,6 +14,7 @@
*/ */
package org.hyperledger.besu.services; package org.hyperledger.besu.services;
import org.hyperledger.besu.cli.options.stable.JsonRpcHttpOptions;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
@ -21,13 +22,18 @@ import org.hyperledger.besu.plugin.services.BesuConfiguration;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Optional;
/** A concrete implementation of BesuConfiguration which is used in Besu plugin framework. */ /** A concrete implementation of BesuConfiguration which is used in Besu plugin framework. */
public class BesuConfigurationImpl implements BesuConfiguration { public class BesuConfigurationImpl implements BesuConfiguration {
private Path storagePath; private Path storagePath;
private Path dataPath; private Path dataPath;
private DataStorageConfiguration dataStorageConfiguration; private DataStorageConfiguration dataStorageConfiguration;
private MiningParameters miningParameters;
// defaults
private MiningParameters miningParameters = MiningParameters.newDefault();
private Optional<String> rpcHttpHost = Optional.of("http://localhost");
private Optional<Integer> rpcHttpPort = Optional.of(8545);
/** Default Constructor. */ /** Default Constructor. */
public BesuConfigurationImpl() {} public BesuConfigurationImpl() {}
@ -38,17 +44,49 @@ public class BesuConfigurationImpl implements BesuConfiguration {
* @param dataPath The Path representing data folder * @param dataPath The Path representing data folder
* @param storagePath The path representing storage folder * @param storagePath The path representing storage folder
* @param dataStorageConfiguration The data storage configuration * @param dataStorageConfiguration The data storage configuration
* @param miningParameters The mining parameters * @return BesuConfigurationImpl instance
*/ */
public void init( public BesuConfigurationImpl init(
final Path dataPath, final Path dataPath,
final Path storagePath, final Path storagePath,
final DataStorageConfiguration dataStorageConfiguration, final DataStorageConfiguration dataStorageConfiguration) {
final MiningParameters miningParameters) {
this.dataPath = dataPath; this.dataPath = dataPath;
this.storagePath = storagePath; this.storagePath = storagePath;
this.dataStorageConfiguration = dataStorageConfiguration; this.dataStorageConfiguration = dataStorageConfiguration;
return this;
}
/**
* Set the mining parameters
*
* @param miningParameters configured mining parameters
* @return BesuConfigurationImpl instance
*/
public BesuConfigurationImpl withMiningParameters(final MiningParameters miningParameters) {
this.miningParameters = miningParameters; this.miningParameters = miningParameters;
return this;
}
/**
* Set the RPC http options
*
* @param rpcHttpOptions configured rpc http options
* @return BesuConfigurationImpl instance
*/
public BesuConfigurationImpl withJsonRpcHttpOptions(final JsonRpcHttpOptions rpcHttpOptions) {
this.rpcHttpHost = Optional.ofNullable(rpcHttpOptions.getRpcHttpHost());
this.rpcHttpPort = Optional.ofNullable(rpcHttpOptions.getRpcHttpPort());
return this;
}
@Override
public Optional<String> getRpcHttpHost() {
return rpcHttpHost;
}
@Override
public Optional<Integer> getRpcHttpPort() {
return rpcHttpPort;
} }
@Override @Override

@ -114,6 +114,11 @@ public class BesuEventsImpl implements BesuEvents {
blockchain.removeObserver(listenerIdentifier); blockchain.removeObserver(listenerIdentifier);
} }
@Override
public long addInitialSyncCompletionListener(final InitialSyncCompletionListener listener) {
return syncState.subscribeCompletionReached(listener);
}
@Override @Override
public long addTransactionAddedListener(final TransactionAddedListener listener) { public long addTransactionAddedListener(final TransactionAddedListener listener) {
return transactionPool.subscribePendingTransactions(listener::onTransactionAdded); return transactionPool.subscribePendingTransactions(listener::onTransactionAdded);

@ -262,6 +262,25 @@ public class BesuPluginContextImpl implements BesuContext, PluginVersionsProvide
state = Lifecycle.BEFORE_MAIN_LOOP_FINISHED; state = Lifecycle.BEFORE_MAIN_LOOP_FINISHED;
} }
/** Execute all plugin setup code after external services. */
public void afterExternalServicesMainLoop() {
checkState(
state == Lifecycle.BEFORE_MAIN_LOOP_FINISHED,
"BesuContext should be in state %s but it was in %s",
Lifecycle.BEFORE_MAIN_LOOP_FINISHED,
state);
final Iterator<BesuPlugin> pluginsIterator = registeredPlugins.iterator();
while (pluginsIterator.hasNext()) {
final BesuPlugin plugin = pluginsIterator.next();
try {
plugin.afterExternalServicePostMainLoop();
} finally {
pluginsIterator.remove();
}
}
}
/** Stop plugins. */ /** Stop plugins. */
public void stopPlugins() { public void stopPlugins() {
checkState( checkState(

@ -17,17 +17,22 @@ package org.hyperledger.besu.services;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.plugin.Unstable; import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockContext; import org.hyperledger.besu.plugin.data.BlockContext;
import org.hyperledger.besu.plugin.data.BlockHeader; import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.data.TransactionReceipt;
import org.hyperledger.besu.plugin.services.BlockchainService; import org.hyperledger.besu.plugin.services.BlockchainService;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors;
/** The Blockchain service implementation. */ /** The Blockchain service implementation. */
@Unstable @Unstable
@ -35,9 +40,7 @@ public class BlockchainServiceImpl implements BlockchainService {
private ProtocolContext protocolContext; private ProtocolContext protocolContext;
private ProtocolSchedule protocolSchedule; private ProtocolSchedule protocolSchedule;
private MutableBlockchain blockchain;
/** Create a new instance */
public BlockchainServiceImpl() {}
/** /**
* Instantiates a new Blockchain service. * Instantiates a new Blockchain service.
@ -48,6 +51,7 @@ public class BlockchainServiceImpl implements BlockchainService {
public void init(final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule) { public void init(final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule) {
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule; this.protocolSchedule = protocolSchedule;
this.blockchain = protocolContext.getBlockchain();
} }
/** /**
@ -91,6 +95,43 @@ public class BlockchainServiceImpl implements BlockchainService {
feeMarket.targetGasUsed(chainHeadHeader))); feeMarket.targetGasUsed(chainHeadHeader)));
} }
@Override
public Optional<List<TransactionReceipt>> getReceiptsByBlockHash(final Hash blockHash) {
return blockchain
.getTxReceipts(blockHash)
.map(
list -> list.stream().map(TransactionReceipt.class::cast).collect(Collectors.toList()));
}
@Override
public void storeBlock(
final BlockHeader blockHeader,
final BlockBody blockBody,
final List<TransactionReceipt> receipts) {
final org.hyperledger.besu.ethereum.core.BlockHeader coreHeader =
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader;
final org.hyperledger.besu.ethereum.core.BlockBody coreBody =
(org.hyperledger.besu.ethereum.core.BlockBody) blockBody;
final List<org.hyperledger.besu.ethereum.core.TransactionReceipt> coreReceipts =
receipts.stream()
.map(org.hyperledger.besu.ethereum.core.TransactionReceipt.class::cast)
.toList();
blockchain.unsafeImportBlock(
new Block(coreHeader, coreBody),
coreReceipts,
Optional.ofNullable(blockchain.calculateTotalDifficulty(coreHeader)));
}
@Override
public Optional<Hash> getSafeBlock() {
return blockchain.getSafeBlock();
}
@Override
public Optional<Hash> getFinalizedBlock() {
return blockchain.getFinalized();
}
private static BlockContext blockContext( private static BlockContext blockContext(
final Supplier<BlockHeader> blockHeaderSupplier, final Supplier<BlockHeader> blockHeaderSupplier,
final Supplier<BlockBody> blockBodySupplier) { final Supplier<BlockBody> blockBodySupplier) {

@ -0,0 +1,44 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.services;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.plugin.services.p2p.P2PService;
/** Service to enable and disable P2P discovery. */
public class P2PServiceImpl implements P2PService {
private final P2PNetwork p2PNetwork;
/**
* Creates a new P2PServiceImpl.
*
* @param p2PNetwork the P2P network to enable and disable.
*/
public P2PServiceImpl(final P2PNetwork p2PNetwork) {
this.p2PNetwork = p2PNetwork;
}
/** Enables P2P discovery. */
@Override
public void enableDiscovery() {
p2PNetwork.start();
}
@Override
public void disableDiscovery() {
p2PNetwork.stop();
}
}

@ -0,0 +1,82 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.services;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.data.TransactionReceipt;
import org.hyperledger.besu.plugin.services.rlp.RlpConverterService;
import org.apache.tuweni.bytes.Bytes;
/** RLP Serialiaztion/Deserialization service. */
public class RlpConverterServiceImpl implements RlpConverterService {
private final BlockHeaderFunctions blockHeaderFunctions;
/**
* Constructor for RlpConverterServiceImpl.
*
* @param protocolSchedule the protocol schedule.
*/
public RlpConverterServiceImpl(final ProtocolSchedule protocolSchedule) {
this.blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
}
@Override
public BlockHeader buildHeaderFromRlp(final Bytes rlp) {
return org.hyperledger.besu.ethereum.core.BlockHeader.readFrom(
RLP.input(rlp), blockHeaderFunctions);
}
@Override
public BlockBody buildBodyFromRlp(final Bytes rlp) {
return org.hyperledger.besu.ethereum.core.BlockBody.readWrappedBodyFrom(
RLP.input(rlp), blockHeaderFunctions);
}
@Override
public TransactionReceipt buildReceiptFromRlp(final Bytes rlp) {
return org.hyperledger.besu.ethereum.core.TransactionReceipt.readFrom(RLP.input(rlp));
}
@Override
public Bytes buildRlpFromHeader(final BlockHeader blockHeader) {
return RLP.encode(
org.hyperledger.besu.ethereum.core.BlockHeader.convertPluginBlockHeader(
blockHeader, blockHeaderFunctions)
::writeTo);
}
@Override
public Bytes buildRlpFromBody(final BlockBody blockBody) {
return RLP.encode(
rlpOutput ->
((org.hyperledger.besu.ethereum.core.BlockBody) blockBody)
.writeWrappedBodyTo(rlpOutput));
}
@Override
public Bytes buildRlpFromReceipt(final TransactionReceipt receipt) {
return RLP.encode(
rlpOutput ->
((org.hyperledger.besu.ethereum.core.TransactionReceipt) receipt)
.writeToForNetwork(rlpOutput));
}
}

@ -0,0 +1,166 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.services;
import org.hyperledger.besu.consensus.merge.MergeContext;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.services.sync.SynchronizationService;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Synchronization service. */
public class SynchronizationServiceImpl implements SynchronizationService {
private static final Logger LOG = LoggerFactory.getLogger(SynchronizationServiceImpl.class);
private final ProtocolContext protocolContext;
private final ProtocolSchedule protocolSchedule;
private final SyncState syncState;
private final Optional<DiffBasedWorldStateProvider> worldStateArchive;
/**
* Constructor for SynchronizationServiceImpl.
*
* @param protocolContext protocol context
* @param protocolSchedule protocol schedule
* @param syncState sync state
* @param worldStateArchive world state archive
*/
public SynchronizationServiceImpl(
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final SyncState syncState,
final WorldStateArchive worldStateArchive) {
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
this.syncState = syncState;
this.worldStateArchive =
Optional.ofNullable(worldStateArchive)
.filter(z -> z instanceof DiffBasedWorldStateProvider)
.map(DiffBasedWorldStateProvider.class::cast);
}
@Override
public void fireNewUnverifiedForkchoiceEvent(
final Hash head, final Hash safeBlock, final Hash finalizedBlock) {
final MergeContext mergeContext = protocolContext.getConsensusContext(MergeContext.class);
if (mergeContext != null) {
mergeContext.fireNewUnverifiedForkchoiceEvent(head, safeBlock, finalizedBlock);
protocolContext.getBlockchain().setFinalized(finalizedBlock);
protocolContext.getBlockchain().setSafeBlock(safeBlock);
} else {
LOG.atWarn()
.setMessage(
"The merge context is unavailable, hence the fork choice event cannot be triggered")
.log();
}
}
@Override
public boolean setHead(final BlockHeader blockHeader, final BlockBody blockBody) {
final BlockImporter blockImporter =
protocolSchedule
.getByBlockHeader((org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader)
.getBlockImporter();
return blockImporter
.importBlock(
protocolContext,
new Block(
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader,
(org.hyperledger.besu.ethereum.core.BlockBody) blockBody),
HeaderValidationMode.SKIP_DETACHED)
.isImported();
}
@Override
public boolean setHeadUnsafe(final BlockHeader blockHeader, final BlockBody blockBody) {
final org.hyperledger.besu.ethereum.core.BlockHeader coreHeader =
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader;
final MutableBlockchain blockchain = protocolContext.getBlockchain();
if (worldStateArchive.flatMap(archive -> archive.getMutable(coreHeader, true)).isPresent()) {
if (coreHeader.getParentHash().equals(blockchain.getChainHeadHash())) {
LOG.atDebug()
.setMessage(
"Forwarding chain head to the block {} saved from a previous newPayload invocation")
.addArgument(coreHeader::toLogString)
.log();
return blockchain.forwardToBlock(coreHeader);
} else {
LOG.atDebug()
.setMessage("New head {} is a chain reorg, rewind chain head to it")
.addArgument(coreHeader::toLogString)
.log();
return blockchain.rewindToBlock(coreHeader.getBlockHash());
}
} else {
LOG.atWarn()
.setMessage("The world state is unavailable, setting of head cannot be performed.")
.log();
}
return false;
}
@Override
public boolean isInitialSyncPhaseDone() {
return syncState.isInitialSyncPhaseDone();
}
@Override
public void disableWorldStateTrie() {
// TODO maybe find a best way in the future to delete and disable trie
worldStateArchive.ifPresent(
archive -> {
archive.getDefaultWorldStateConfig().setTrieDisabled(true);
final DiffBasedWorldStateKeyValueStorage worldStateStorage =
archive.getWorldStateKeyValueStorage();
final Optional<Hash> worldStateBlockHash = worldStateStorage.getWorldStateBlockHash();
final Optional<Bytes> worldStateRootHash = worldStateStorage.getWorldStateRootHash();
if (worldStateRootHash.isPresent() && worldStateBlockHash.isPresent()) {
worldStateStorage.clearTrie();
// keep root and block hash in the trie branch
final DiffBasedWorldStateKeyValueStorage.Updater updater = worldStateStorage.updater();
updater.saveWorldState(
worldStateBlockHash.get(), Bytes32.wrap(worldStateRootHash.get()), Bytes.EMPTY);
updater.commit();
// currently only bonsai needs an explicit upgrade to full flat db
if (worldStateStorage instanceof BonsaiWorldStateKeyValueStorage bonsaiStorage) {
bonsaiStorage.upgradeToFullFlatDbMode();
}
}
});
}
}

@ -0,0 +1,43 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.services;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.plugin.services.transactionpool.TransactionPoolService;
/** Service to enable and disable the transaction pool. */
public class TransactionPoolServiceImpl implements TransactionPoolService {
private final TransactionPool transactionPool;
/**
* Creates a new TransactionPoolServiceImpl.
*
* @param transactionPool the transaction pool to control
*/
public TransactionPoolServiceImpl(final TransactionPool transactionPool) {
this.transactionPool = transactionPool;
}
@Override
public void disableTransactionPool() {
transactionPool.setDisabled();
}
@Override
public void enableTransactionPool() {
transactionPool.setEnabled();
}
}

@ -137,7 +137,9 @@ public class PrivacyTest {
final DataStorageConfiguration dataStorageConfiguration, final DataStorageConfiguration dataStorageConfiguration,
final MiningParameters miningParameters) { final MiningParameters miningParameters) {
final var besuConfiguration = new BesuConfigurationImpl(); final var besuConfiguration = new BesuConfigurationImpl();
besuConfiguration.init(dataDir, dbDir, dataStorageConfiguration, miningParameters); besuConfiguration
.init(dataDir, dbDir, dataStorageConfiguration)
.withMiningParameters(miningParameters);
return new PrivacyKeyValueStorageProviderBuilder() return new PrivacyKeyValueStorageProviderBuilder()
.withStorageFactory( .withStorageFactory(
new RocksDBKeyValuePrivacyStorageFactory( new RocksDBKeyValuePrivacyStorageFactory(

@ -391,7 +391,9 @@ public final class RunnerTest {
final DataStorageConfiguration dataStorageConfiguration, final DataStorageConfiguration dataStorageConfiguration,
final MiningParameters miningParameters) { final MiningParameters miningParameters) {
final var besuConfiguration = new BesuConfigurationImpl(); final var besuConfiguration = new BesuConfigurationImpl();
besuConfiguration.init(dataDir, dbDir, dataStorageConfiguration, miningParameters); besuConfiguration
.init(dataDir, dbDir, dataStorageConfiguration)
.withMiningParameters(miningParameters);
return new KeyValueStorageProviderBuilder() return new KeyValueStorageProviderBuilder()
.withStorageFactory( .withStorageFactory(
new RocksDBKeyValueStorageFactory( new RocksDBKeyValueStorageFactory(

@ -127,6 +127,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Captor; import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -214,7 +215,7 @@ public abstract class CommandTestAbstract {
@Mock protected TransactionSelectionServiceImpl txSelectionService; @Mock protected TransactionSelectionServiceImpl txSelectionService;
@Mock protected SecurityModuleServiceImpl securityModuleService; @Mock protected SecurityModuleServiceImpl securityModuleService;
@Mock protected SecurityModule securityModule; @Mock protected SecurityModule securityModule;
@Mock protected BesuConfigurationImpl commonPluginConfiguration; @Spy protected BesuConfigurationImpl commonPluginConfiguration = new BesuConfigurationImpl();
@Mock protected KeyValueStorageFactory rocksDBStorageFactory; @Mock protected KeyValueStorageFactory rocksDBStorageFactory;
@Mock protected PrivacyKeyValueStorageFactory rocksDBSPrivacyStorageFactory; @Mock protected PrivacyKeyValueStorageFactory rocksDBSPrivacyStorageFactory;
@Mock protected PicoCLIOptions cliOptions; @Mock protected PicoCLIOptions cliOptions;

@ -30,7 +30,6 @@ import org.hyperledger.besu.consensus.common.bft.blockcreation.BftMiningCoordina
import org.hyperledger.besu.ethereum.ConsensusContext; import org.hyperledger.besu.ethereum.ConsensusContext;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.NoopMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.MiningParameters;
@ -68,7 +67,7 @@ public class ConsensusScheduleBesuControllerBuilderTest {
private @Mock ProtocolSchedule protocolSchedule1; private @Mock ProtocolSchedule protocolSchedule1;
private @Mock ProtocolSchedule protocolSchedule2; private @Mock ProtocolSchedule protocolSchedule2;
private @Mock ProtocolSchedule protocolSchedule3; private @Mock ProtocolSchedule protocolSchedule3;
private @Mock NoopMiningCoordinator miningCoordinator1; private @Mock MiningCoordinator miningCoordinator1;
private @Mock BftMiningCoordinator miningCoordinator2; private @Mock BftMiningCoordinator miningCoordinator2;
@Test @Test

@ -0,0 +1,54 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.services;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.Test;
public class RlpConverterServiceImplTest {
@Test
public void testBuildRlpFromHeader() {
// Arrange
RlpConverterServiceImpl rlpConverterServiceImpl =
new RlpConverterServiceImpl(ProtocolScheduleFixture.MAINNET);
// header with cancun fields
BlockHeader header =
new BlockHeaderTestFixture()
.timestamp(1710338135 + 1)
.baseFeePerGas(Wei.of(1000))
.requestsRoot(Hash.ZERO)
.withdrawalsRoot(Hash.ZERO)
.blobGasUsed(500L)
.excessBlobGas(BlobGas.of(500L))
.buildHeader();
Bytes rlpBytes = rlpConverterServiceImpl.buildRlpFromHeader(header);
BlockHeader deserialized = rlpConverterServiceImpl.buildHeaderFromRlp(rlpBytes);
// Assert
assertThat(header).isEqualTo(deserialized);
assertThat(header.getBlobGasUsed()).isEqualTo(deserialized.getBlobGasUsed());
assertThat(header.getExcessBlobGas()).isEqualTo(deserialized.getExcessBlobGas());
}
}

@ -30,7 +30,6 @@ import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreatorFa
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftMiningCoordinator; import org.hyperledger.besu.consensus.common.bft.blockcreation.BftMiningCoordinator;
import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler; import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.blockcreation.NoopMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.BlockAddedEvent; import org.hyperledger.besu.ethereum.chain.BlockAddedEvent;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
@ -122,7 +121,7 @@ public class MigratingMiningCoordinatorTest {
@Test @Test
public void onBlockAddedShouldNotDelegateWhenDelegateIsNoop() { public void onBlockAddedShouldNotDelegateWhenDelegateIsNoop() {
NoopMiningCoordinator mockNoopCoordinator = mock(NoopMiningCoordinator.class); MiningCoordinator mockNoopCoordinator = mock(MiningCoordinator.class);
coordinatorSchedule = createCoordinatorSchedule(mockNoopCoordinator, coordinator2); coordinatorSchedule = createCoordinatorSchedule(mockNoopCoordinator, coordinator2);
when(blockHeader.getNumber()).thenReturn(GENESIS_BLOCK_NUMBER); when(blockHeader.getNumber()).thenReturn(GENESIS_BLOCK_NUMBER);

@ -16,6 +16,7 @@ package org.hyperledger.besu.datatypes;
import java.math.BigInteger; import java.math.BigInteger;
import com.fasterxml.jackson.annotation.JsonValue;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.BaseUInt64Value; import org.apache.tuweni.units.bigints.BaseUInt64Value;
import org.apache.tuweni.units.bigints.UInt64; import org.apache.tuweni.units.bigints.UInt64;
@ -123,6 +124,7 @@ public final class BlobGas extends BaseUInt64Value<BlobGas> implements Quantity
return toBigInteger(); return toBigInteger();
} }
@JsonValue
@Override @Override
public String toHexString() { public String toHexString() {
return super.toHexString(); return super.toHexString();
@ -140,6 +142,6 @@ public final class BlobGas extends BaseUInt64Value<BlobGas> implements Quantity
* @return the blob gas * @return the blob gas
*/ */
public static BlobGas fromQuantity(final Quantity quantity) { public static BlobGas fromQuantity(final Quantity quantity) {
return BlobGas.wrap((Bytes) quantity); return BlobGas.of(quantity.getAsBigInteger());
} }
} }

@ -16,15 +16,20 @@ package org.hyperledger.besu.ethereum.chain;
public class ChainPrunerConfiguration { public class ChainPrunerConfiguration {
public static final ChainPrunerConfiguration DEFAULT = public static final ChainPrunerConfiguration DEFAULT =
new ChainPrunerConfiguration(false, 7200, 256); new ChainPrunerConfiguration(false, 7200, 7200, 256);
private final boolean enabled; private final boolean enabled;
private final long blocksRetained; private final long blocksRetained;
private final long blocksFrequency; private final long blocksFrequency;
private final long blocksRetainedLimit;
public ChainPrunerConfiguration( public ChainPrunerConfiguration(
final boolean enabled, final long blocksRetained, final long blocksFrequency) { final boolean enabled,
final long blocksRetained,
final long blocksRetainedLimit,
final long blocksFrequency) {
this.enabled = enabled; this.enabled = enabled;
this.blocksRetained = blocksRetained; this.blocksRetained = blocksRetained;
this.blocksRetainedLimit = blocksRetainedLimit;
this.blocksFrequency = blocksFrequency; this.blocksFrequency = blocksFrequency;
} }
@ -32,6 +37,10 @@ public class ChainPrunerConfiguration {
return blocksRetained; return blocksRetained;
} }
public long getBlocksRetainedLimit() {
return blocksRetainedLimit;
}
public boolean getChainPruningEnabled() { public boolean getChainPruningEnabled() {
return enabled; return enabled;
} }

@ -469,7 +469,8 @@ public class DefaultBlockchain implements MutableBlockchain {
updater.commit(); updater.commit();
} }
private Difficulty calculateTotalDifficulty(final BlockHeader blockHeader) { @Override
public Difficulty calculateTotalDifficulty(final BlockHeader blockHeader) {
if (blockHeader.getNumber() == BlockHeader.GENESIS_BLOCK_NUMBER) { if (blockHeader.getNumber() == BlockHeader.GENESIS_BLOCK_NUMBER) {
return blockHeader.getDifficulty(); return blockHeader.getDifficulty();
} }

@ -56,6 +56,8 @@ public interface MutableBlockchain extends Blockchain {
void unsafeSetChainHead(final BlockHeader blockHeader, final Difficulty totalDifficulty); void unsafeSetChainHead(final BlockHeader blockHeader, final Difficulty totalDifficulty);
Difficulty calculateTotalDifficulty(final BlockHeader blockHeader);
/** /**
* Rolls back the canonical chainhead to the specified block number. * Rolls back the canonical chainhead to the specified block number.
* *

@ -309,7 +309,7 @@ public class BlockHeader extends SealableBlockHeader
.map(h -> Hash.fromHexString(h.toHexString())) .map(h -> Hash.fromHexString(h.toHexString()))
.orElse(null), .orElse(null),
pluginBlockHeader.getBlobGasUsed().map(Long::longValue).orElse(null), pluginBlockHeader.getBlobGasUsed().map(Long::longValue).orElse(null),
pluginBlockHeader.getExcessBlobGas().map(BlobGas::fromQuantity).orElse(null), pluginBlockHeader.getExcessBlobGas().map(BlobGas.class::cast).orElse(null),
pluginBlockHeader.getParentBeaconBlockRoot().orElse(null), pluginBlockHeader.getParentBeaconBlockRoot().orElse(null),
pluginBlockHeader pluginBlockHeader
.getRequestsRoot() .getRequestsRoot()

@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.NoOpBonsaiCache
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; 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.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState; import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
@ -72,7 +73,8 @@ public class GenesisWorldStateProvider {
bonsaiCachedMerkleTrieLoader, bonsaiCachedMerkleTrieLoader,
new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage), new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage),
new NoOpTrieLogManager(), new NoOpTrieLogManager(),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
} }
/** /**

@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldSt
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; 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.DiffBasedWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
@ -54,8 +55,11 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
super(worldStateKeyValueStorage, blockchain, maxLayersToLoad, pluginContext); super(worldStateKeyValueStorage, blockchain, maxLayersToLoad, pluginContext);
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
provideCachedWorldStorageManager( provideCachedWorldStorageManager(
new BonsaiCachedWorldStorageManager(this, worldStateKeyValueStorage)); new BonsaiCachedWorldStorageManager(
loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration)); this, worldStateKeyValueStorage, this::cloneBonsaiWorldStateConfig));
loadPersistedState(
new BonsaiWorldState(
this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig));
} }
@VisibleForTesting @VisibleForTesting
@ -69,14 +73,16 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
super(worldStateKeyValueStorage, blockchain, trieLogManager); super(worldStateKeyValueStorage, blockchain, trieLogManager);
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
provideCachedWorldStorageManager(bonsaiCachedWorldStorageManager); provideCachedWorldStorageManager(bonsaiCachedWorldStorageManager);
loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration)); loadPersistedState(
new BonsaiWorldState(
this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig));
} }
public BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader() { public BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader() {
return bonsaiCachedMerkleTrieLoader; return bonsaiCachedMerkleTrieLoader;
} }
private BonsaiWorldStateKeyValueStorage getWorldStateKeyValueStorage() { private BonsaiWorldStateKeyValueStorage getBonsaiWorldStateKeyValueStorage() {
return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage; return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage;
} }
@ -89,13 +95,13 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
public void prepareStateHealing(final Address address, final Bytes location) { public void prepareStateHealing(final Address address, final Bytes location) {
final Set<Bytes> keysToDelete = new HashSet<>(); final Set<Bytes> keysToDelete = new HashSet<>();
final BonsaiWorldStateKeyValueStorage.Updater updater = final BonsaiWorldStateKeyValueStorage.Updater updater =
getWorldStateKeyValueStorage().updater(); getBonsaiWorldStateKeyValueStorage().updater();
final Hash accountHash = address.addressHash(); final Hash accountHash = address.addressHash();
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie = final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
new StoredMerklePatriciaTrie<>( new StoredMerklePatriciaTrie<>(
(l, h) -> { (l, h) -> {
final Optional<Bytes> node = final Optional<Bytes> node =
getWorldStateKeyValueStorage().getAccountStateTrieNode(l, h); getBonsaiWorldStateKeyValueStorage().getAccountStateTrieNode(l, h);
if (node.isPresent()) { if (node.isPresent()) {
keysToDelete.add(l); keysToDelete.add(l);
} }
@ -115,7 +121,7 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
new StoredMerklePatriciaTrie<>( new StoredMerklePatriciaTrie<>(
(l, h) -> { (l, h) -> {
Optional<Bytes> node = Optional<Bytes> node =
getWorldStateKeyValueStorage() getBonsaiWorldStateKeyValueStorage()
.getAccountStorageTrieNode(accountHash, l, h); .getAccountStorageTrieNode(accountHash, l, h);
if (node.isPresent()) { if (node.isPresent()) {
keysToDelete.add(Bytes.concatenate(accountHash, l)); keysToDelete.add(Bytes.concatenate(accountHash, l));
@ -139,6 +145,10 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
keysToDelete.forEach(updater::removeAccountStateTrieNode); keysToDelete.forEach(updater::removeAccountStateTrieNode);
updater.commit(); updater.commit();
getWorldStateKeyValueStorage().downgradeToPartialFlatDbMode(); getBonsaiWorldStateKeyValueStorage().downgradeToPartialFlatDbMode();
}
private DiffBasedWorldStateConfig cloneBonsaiWorldStateConfig() {
return new DiffBasedWorldStateConfig(defaultWorldStateConfig);
} }
} }

@ -23,14 +23,18 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStatePr
import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager; 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.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.function.Supplier;
public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager { public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager {
public BonsaiCachedWorldStorageManager( public BonsaiCachedWorldStorageManager(
final BonsaiWorldStateProvider archive, final BonsaiWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) { final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
super(archive, worldStateKeyValueStorage); final Supplier<DiffBasedWorldStateConfig> defaultBonsaiWorldStateConfigSupplier) {
super(archive, worldStateKeyValueStorage, defaultBonsaiWorldStateConfigSupplier);
} }
@Override @Override
@ -41,7 +45,8 @@ public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorage
return new BonsaiWorldState( return new BonsaiWorldState(
(BonsaiWorldStateProvider) archive, (BonsaiWorldStateProvider) archive,
(BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage, (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage,
evmConfiguration); evmConfiguration,
defaultBonsaiWorldStateConfigSupplier.get());
} }
@Override @Override

@ -18,6 +18,7 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
@ -26,7 +27,7 @@ public class NoOpBonsaiCachedWorldStorageManager extends BonsaiCachedWorldStorag
public NoOpBonsaiCachedWorldStorageManager( public NoOpBonsaiCachedWorldStorageManager(
final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage) { final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage) {
super(null, bonsaiWorldStateKeyValueStorage); super(null, bonsaiWorldStateKeyValueStorage, DiffBasedWorldStateConfig::new);
} }
@Override @Override

@ -203,6 +203,15 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
} }
} }
@Override
public void onClearTrie() {
try {
doClose();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override @Override
protected synchronized void doClose() throws Exception { protected synchronized void doClose() throws Exception {
if (!isClosedGet()) { if (!isClosedGet()) {

@ -23,6 +23,7 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrie;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.trie.NoOpMerkleTrie;
import org.hyperledger.besu.ethereum.trie.NodeLoader; import org.hyperledger.besu.ethereum.trie.NodeLoader;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount; 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.BonsaiWorldStateProvider;
@ -34,6 +35,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCached
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; 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.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; 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.diffbased.common.worldview.accumulator.preload.StorageConsumingMap;
import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie;
@ -63,13 +65,15 @@ public class BonsaiWorldState extends DiffBasedWorldState {
public BonsaiWorldState( public BonsaiWorldState(
final BonsaiWorldStateProvider archive, final BonsaiWorldStateProvider archive,
final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration,
final DiffBasedWorldStateConfig diffBasedWorldStateConfig) {
this( this(
worldStateKeyValueStorage, worldStateKeyValueStorage,
archive.getCachedMerkleTrieLoader(), archive.getCachedMerkleTrieLoader(),
archive.getCachedWorldStorageManager(), archive.getCachedWorldStorageManager(),
archive.getTrieLogManager(), archive.getTrieLogManager(),
evmConfiguration); evmConfiguration,
diffBasedWorldStateConfig);
} }
public BonsaiWorldState( public BonsaiWorldState(
@ -77,21 +81,32 @@ public class BonsaiWorldState extends DiffBasedWorldState {
final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader, final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader,
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager, final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager, final TrieLogManager trieLogManager,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration,
super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager); final DiffBasedWorldStateConfig diffBasedWorldStateConfig) {
super(
worldStateKeyValueStorage,
cachedWorldStorageManager,
trieLogManager,
diffBasedWorldStateConfig);
this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader;
this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.setAccumulator( this.setAccumulator(
new BonsaiWorldStateUpdateAccumulator( new BonsaiWorldStateUpdateAccumulator(
this, this,
(addr, value) -> (addr, value) ->
bonsaiCachedMerkleTrieLoader.preLoadAccount( bonsaiCachedMerkleTrieLoader.preLoadAccount(
worldStateKeyValueStorage, worldStateRootHash, addr), getWorldStateStorage(), worldStateRootHash, addr),
(addr, value) -> (addr, value) ->
bonsaiCachedMerkleTrieLoader.preLoadStorageSlot( this.bonsaiCachedMerkleTrieLoader.preLoadStorageSlot(
getWorldStateStorage(), addr, value), getWorldStateStorage(), addr, value),
evmConfiguration)); evmConfiguration));
} }
@Override
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
return getWorldStateStorage().getCode(codeHash, address.addressHash());
}
@Override @Override
public BonsaiWorldStateKeyValueStorage getWorldStateStorage() { public BonsaiWorldStateKeyValueStorage getWorldStateStorage() {
return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage; return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage;
@ -129,7 +144,7 @@ public class BonsaiWorldState extends DiffBasedWorldState {
updateCode(maybeStateUpdater, worldStateUpdater); updateCode(maybeStateUpdater, worldStateUpdater);
// next walk the account trie // next walk the account trie
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie = final MerkleTrie<Bytes, Bytes> accountTrie =
createTrie( createTrie(
(location, hash) -> (location, hash) ->
bonsaiCachedMerkleTrieLoader.getAccountStateTrieNode( bonsaiCachedMerkleTrieLoader.getAccountStateTrieNode(
@ -157,7 +172,7 @@ public class BonsaiWorldState extends DiffBasedWorldState {
private void updateTheAccounts( private void updateTheAccounts(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater, final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater, final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie) { final MerkleTrie<Bytes, Bytes> accountTrie) {
for (final Map.Entry<Address, DiffBasedValue<BonsaiAccount>> accountUpdate : for (final Map.Entry<Address, DiffBasedValue<BonsaiAccount>> accountUpdate :
worldStateUpdater.getAccountsToUpdate().entrySet()) { worldStateUpdater.getAccountsToUpdate().entrySet()) {
final Bytes accountKey = accountUpdate.getKey(); final Bytes accountKey = accountUpdate.getKey();
@ -234,7 +249,7 @@ public class BonsaiWorldState extends DiffBasedWorldState {
|| worldStateUpdater.getStorageToClear().contains(updatedAddress)) || worldStateUpdater.getStorageToClear().contains(updatedAddress))
? Hash.EMPTY_TRIE_HASH ? Hash.EMPTY_TRIE_HASH
: accountOriginal.getStorageRoot(); : accountOriginal.getStorageRoot();
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie = final MerkleTrie<Bytes, Bytes> storageTrie =
createTrie( createTrie(
(location, key) -> (location, key) ->
bonsaiCachedMerkleTrieLoader.getAccountStorageTrieNode( bonsaiCachedMerkleTrieLoader.getAccountStorageTrieNode(
@ -277,8 +292,11 @@ public class BonsaiWorldState extends DiffBasedWorldState {
(location, key, value) -> (location, key, value) ->
writeStorageTrieNode( writeStorageTrieNode(
bonsaiUpdater, updatedAddressHash, location, key, value))); bonsaiUpdater, updatedAddressHash, location, key, value)));
final Hash newStorageRoot = Hash.wrap(storageTrie.getRootHash()); // only use storage root of the trie when trie is enabled
accountUpdated.setStorageRoot(newStorageRoot); if (!worldStateConfig.isTrieDisabled()) {
final Hash newStorageRoot = Hash.wrap(storageTrie.getRootHash());
accountUpdated.setStorageRoot(newStorageRoot);
}
} }
} }
// for manicured tries and composting, trim and compost here // for manicured tries and composting, trim and compost here
@ -347,13 +365,6 @@ public class BonsaiWorldState extends DiffBasedWorldState {
accumulator.copy()); accumulator.copy());
} }
@Override
public MutableWorldState freeze() {
this.isFrozen = true;
this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage());
return this;
}
@Override @Override
public Account get(final Address address) { public Account get(final Address address) {
return getWorldStateStorage() return getWorldStateStorage()
@ -362,11 +373,6 @@ public class BonsaiWorldState extends DiffBasedWorldState {
.orElse(null); .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) { protected Optional<Bytes> getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) {
return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash); return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash);
} }
@ -423,16 +429,26 @@ public class BonsaiWorldState extends DiffBasedWorldState {
@Override @Override
public Map<Bytes32, Bytes> getAllAccountStorage(final Address address, final Hash rootHash) { public Map<Bytes32, Bytes> getAllAccountStorage(final Address address, final Hash rootHash) {
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie = final MerkleTrie<Bytes, Bytes> storageTrie =
createTrie( createTrie(
(location, key) -> getStorageTrieNode(address.addressHash(), location, key), rootHash); (location, key) -> getStorageTrieNode(address.addressHash(), location, key), rootHash);
return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE); return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE);
} }
private StoredMerklePatriciaTrie<Bytes, Bytes> createTrie( @Override
final NodeLoader nodeLoader, final Bytes32 rootHash) { public MutableWorldState freeze() {
return new StoredMerklePatriciaTrie<>( this.worldStateConfig.setFrozen(true);
nodeLoader, rootHash, Function.identity(), Function.identity()); this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage());
return this;
}
private MerkleTrie<Bytes, Bytes> createTrie(final NodeLoader nodeLoader, final Bytes32 rootHash) {
if (worldStateConfig.isTrieDisabled()) {
return new NoOpMerkleTrie<>();
} else {
return new StoredMerklePatriciaTrie<>(
nodeLoader, rootHash, Function.identity(), Function.identity());
}
} }
protected Hash hashAndSavePreImage(final Bytes value) { protected Hash hashAndSavePreImage(final Bytes value) {

@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCached
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; 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.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
@ -54,6 +55,7 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
protected DiffBasedWorldState persistedState; protected DiffBasedWorldState persistedState;
protected final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage; protected final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage;
protected final DiffBasedWorldStateConfig defaultWorldStateConfig;
public DiffBasedWorldStateProvider( public DiffBasedWorldStateProvider(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
@ -70,6 +72,7 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
maxLayersToLoad.orElse(DiffBasedCachedWorldStorageManager.RETAINED_LAYERS), maxLayersToLoad.orElse(DiffBasedCachedWorldStorageManager.RETAINED_LAYERS),
pluginContext); pluginContext);
this.blockchain = blockchain; this.blockchain = blockchain;
this.defaultWorldStateConfig = new DiffBasedWorldStateConfig();
} }
public DiffBasedWorldStateProvider( public DiffBasedWorldStateProvider(
@ -81,6 +84,7 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
// TODO: de-dup constructors // TODO: de-dup constructors
this.trieLogManager = trieLogManager; this.trieLogManager = trieLogManager;
this.blockchain = blockchain; this.blockchain = blockchain;
this.defaultWorldStateConfig = new DiffBasedWorldStateConfig();
} }
protected void provideCachedWorldStorageManager( protected void provideCachedWorldStorageManager(
@ -252,6 +256,19 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
return persistedState; return persistedState;
} }
public DiffBasedWorldStateConfig getDefaultWorldStateConfig() {
return defaultWorldStateConfig;
}
public void disableTrie() {
defaultWorldStateConfig.setTrieDisabled(true);
worldStateKeyValueStorage.clearTrie();
}
public DiffBasedWorldStateKeyValueStorage getWorldStateKeyValueStorage() {
return worldStateKeyValueStorage;
}
public TrieLogManager getTrieLogManager() { public TrieLogManager getTrieLogManager() {
return trieLogManager; return trieLogManager;
} }

@ -21,5 +21,7 @@ public interface StorageSubscriber {
default void onClearTrieLog() {} default void onClearTrieLog() {}
default void onClearTrie() {}
default void onCloseStorage() {} default void onCloseStorage() {}
} }

@ -23,6 +23,7 @@ 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.DiffBasedLayeredWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; 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.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.ArrayList; import java.util.ArrayList;
@ -33,6 +34,7 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
@ -46,6 +48,7 @@ public abstract class DiffBasedCachedWorldStorageManager implements StorageSubsc
LoggerFactory.getLogger(DiffBasedCachedWorldStorageManager.class); LoggerFactory.getLogger(DiffBasedCachedWorldStorageManager.class);
private final DiffBasedWorldStateProvider archive; private final DiffBasedWorldStateProvider archive;
private final EvmConfiguration evmConfiguration; private final EvmConfiguration evmConfiguration;
protected final Supplier<DiffBasedWorldStateConfig> defaultBonsaiWorldStateConfigSupplier;
private final Cache<Hash, BlockHeader> stateRootToBlockHeaderCache = private final Cache<Hash, BlockHeader> stateRootToBlockHeaderCache =
Caffeine.newBuilder() Caffeine.newBuilder()
.maximumSize(RETAINED_LAYERS) .maximumSize(RETAINED_LAYERS)
@ -59,18 +62,26 @@ public abstract class DiffBasedCachedWorldStorageManager implements StorageSubsc
final DiffBasedWorldStateProvider archive, final DiffBasedWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash, final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash,
final EvmConfiguration evmConfiguration) { final EvmConfiguration evmConfiguration,
final Supplier<DiffBasedWorldStateConfig> defaultBonsaiWorldStateConfigSupplier) {
worldStateKeyValueStorage.subscribe(this); worldStateKeyValueStorage.subscribe(this);
this.rootWorldStateStorage = worldStateKeyValueStorage; this.rootWorldStateStorage = worldStateKeyValueStorage;
this.cachedWorldStatesByHash = cachedWorldStatesByHash; this.cachedWorldStatesByHash = cachedWorldStatesByHash;
this.archive = archive; this.archive = archive;
this.evmConfiguration = evmConfiguration; this.evmConfiguration = evmConfiguration;
this.defaultBonsaiWorldStateConfigSupplier = defaultBonsaiWorldStateConfigSupplier;
} }
public DiffBasedCachedWorldStorageManager( public DiffBasedCachedWorldStorageManager(
final DiffBasedWorldStateProvider archive, final DiffBasedWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) { final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
this(archive, worldStateKeyValueStorage, new ConcurrentHashMap<>(), EvmConfiguration.DEFAULT); final Supplier<DiffBasedWorldStateConfig> defaultBonsaiWorldStateConfigSupplier) {
this(
archive,
worldStateKeyValueStorage,
new ConcurrentHashMap<>(),
EvmConfiguration.DEFAULT,
defaultBonsaiWorldStateConfigSupplier);
} }
public synchronized void addCachedLayer( public synchronized void addCachedLayer(
@ -263,6 +274,11 @@ public abstract class DiffBasedCachedWorldStorageManager implements StorageSubsc
this.cachedWorldStatesByHash.clear(); this.cachedWorldStatesByHash.clear();
} }
@Override
public void onClearTrie() {
this.cachedWorldStatesByHash.clear();
}
@Override @Override
public void onCloseStorage() { public void onCloseStorage() {
this.cachedWorldStatesByHash.clear(); this.cachedWorldStatesByHash.clear();

@ -174,6 +174,11 @@ public abstract class DiffBasedWorldStateKeyValueStorage
trieLogStorage.clear(); trieLogStorage.clear();
} }
public void clearTrie() {
subscribers.forEach(StorageSubscriber::onClearTrie);
composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE);
}
public void clearFlatDatabase() { public void clearFlatDatabase() {
subscribers.forEach(StorageSubscriber::onClearFlatDatabaseStorage); subscribers.forEach(StorageSubscriber::onClearFlatDatabaseStorage);
getFlatDbStrategy().resetOnResync(composedWorldStateStorage); getFlatDbStrategy().resetOnResync(composedWorldStateStorage);

@ -34,6 +34,7 @@ import java.util.Optional;
import java.util.stream.LongStream; import java.util.stream.LongStream;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -147,15 +148,46 @@ public class TrieLogManager {
trieLogService.getObservers().forEach(trieLogObservers::subscribe); trieLogService.getObservers().forEach(trieLogObservers::subscribe);
// return the TrieLogFactory implementation from the TrieLogService // return the TrieLogFactory implementation from the TrieLogService
return trieLogService.getTrieLogFactory(); if (trieLogService.getTrieLogFactory().isPresent()) {
} else { return trieLogService.getTrieLogFactory().get();
// Otherwise default to TrieLogFactoryImpl }
return new TrieLogFactoryImpl();
} }
// Otherwise default to TrieLogFactoryImpl
return new TrieLogFactoryImpl();
} }
private TrieLogProvider getTrieLogProvider() { private TrieLogProvider getTrieLogProvider() {
return new TrieLogProvider() { return new TrieLogProvider() {
@Override
public Optional<Bytes> getRawTrieLogLayer(final Hash blockHash) {
return rootWorldStateStorage.getTrieLog(blockHash).map(Bytes::wrap);
}
@Override
public Optional<Bytes> getRawTrieLogLayer(final long blockNumber) {
return TrieLogManager.this
.blockchain
.getBlockHeader(blockNumber)
.map(BlockHeader::getHash)
.flatMap(this::getRawTrieLogLayer);
}
@Override
public void saveRawTrieLogLayer(
final Hash blockHash, final long blockNumber, final Bytes trieLog) {
final DiffBasedWorldStateKeyValueStorage.Updater updater = rootWorldStateStorage.updater();
updater
.getTrieLogStorageTransaction()
.put(blockHash.toArrayUnsafe(), trieLog.toArrayUnsafe());
updater.commit();
// TODO maybe find a way to have a clean and complete trielog for observers
trieLogObservers.forEach(
o ->
o.onTrieLogAdded(
new TrieLogAddedEvent(
new TrieLogLayer().setBlockHash(blockHash).setBlockNumber(blockNumber))));
}
@Override @Override
public Optional<TrieLog> getTrieLogLayer(final Hash blockHash) { public Optional<TrieLog> getTrieLogLayer(final Hash blockHash) {
return TrieLogManager.this.getTrieLogLayer(blockHash); return TrieLogManager.this.getTrieLogLayer(blockHash);

@ -60,12 +60,13 @@ public abstract class DiffBasedWorldState
protected Hash worldStateRootHash; protected Hash worldStateRootHash;
protected Hash worldStateBlockHash; protected Hash worldStateBlockHash;
protected boolean isFrozen; protected DiffBasedWorldStateConfig worldStateConfig;
protected DiffBasedWorldState( protected DiffBasedWorldState(
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final DiffBasedCachedWorldStorageManager cachedWorldStorageManager, final DiffBasedCachedWorldStorageManager cachedWorldStorageManager,
final TrieLogManager trieLogManager) { final TrieLogManager trieLogManager,
final DiffBasedWorldStateConfig diffBasedWorldStateConfig) {
this.worldStateKeyValueStorage = worldStateKeyValueStorage; this.worldStateKeyValueStorage = worldStateKeyValueStorage;
this.worldStateRootHash = this.worldStateRootHash =
Hash.wrap( Hash.wrap(
@ -76,11 +77,12 @@ public abstract class DiffBasedWorldState
Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO))); Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
this.cachedWorldStorageManager = cachedWorldStorageManager; this.cachedWorldStorageManager = cachedWorldStorageManager;
this.trieLogManager = trieLogManager; this.trieLogManager = trieLogManager;
this.worldStateConfig = diffBasedWorldStateConfig;
} }
/** /**
* Having a protected method to override the accumulator solves the chicken-egg problem of needing * Having a protected method to override the accumulator solves the chicken-egg problem of needing
* a worldstate reference (this) when construction the Accumulator. * a worldstate reference (this) when constructing the Accumulator.
* *
* @param accumulator accumulator to use. * @param accumulator accumulator to use.
*/ */
@ -134,6 +136,15 @@ public abstract class DiffBasedWorldState
return accumulator; return accumulator;
} }
protected Hash unsafeRootHashUpdate(
final BlockHeader blockHeader,
final DiffBasedWorldStateKeyValueStorage.Updater stateUpdater) {
// calling calculateRootHash in order to update the state
calculateRootHash(
worldStateConfig.isFrozen() ? Optional.empty() : Optional.of(stateUpdater), accumulator);
return blockHeader.getStateRoot();
}
@Override @Override
public void persist(final BlockHeader blockHeader) { public void persist(final BlockHeader blockHeader) {
final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader); final Optional<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader);
@ -151,19 +162,32 @@ public abstract class DiffBasedWorldState
Runnable saveTrieLog = () -> {}; Runnable saveTrieLog = () -> {};
try { try {
final Hash newWorldStateRootHash = final Hash calculatedRootHash;
calculateRootHash(isFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator);
if (blockHeader == null || !worldStateConfig.isTrieDisabled()) {
calculatedRootHash =
calculateRootHash(
worldStateConfig.isFrozen() ? Optional.empty() : Optional.of(stateUpdater),
accumulator);
} else {
// if the trie is disabled, we cannot calculate the state root, so we directly use the root
// of the block. It's important to understand that in all networks,
// the state root must be validated independently and the block should not be trusted
// implicitly. This mode
// can be used in cases where Besu would just be a follower of another trusted client.
calculatedRootHash = unsafeRootHashUpdate(blockHeader, stateUpdater);
}
// if we are persisted with a block header, and the prior state is the parent // if we are persisted with a block header, and the prior state is the parent
// then persist the TrieLog for that transition. // then persist the TrieLog for that transition.
// If specified but not a direct descendant simply store the new block hash. // If specified but not a direct descendant simply store the new block hash.
if (blockHeader != null) { if (blockHeader != null) {
verifyWorldStateRoot(newWorldStateRootHash, blockHeader); verifyWorldStateRoot(calculatedRootHash, blockHeader);
saveTrieLog = saveTrieLog =
() -> { () -> {
trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this); trieLogManager.saveTrieLog(localCopy, calculatedRootHash, blockHeader, this);
// not save a frozen state in the cache // not save a frozen state in the cache
if (!isFrozen) { if (!worldStateConfig.isFrozen()) {
cachedWorldStorageManager.addCachedLayer(blockHeader, newWorldStateRootHash, this); cachedWorldStorageManager.addCachedLayer(blockHeader, calculatedRootHash, this);
} }
}; };
@ -178,8 +202,8 @@ public abstract class DiffBasedWorldState
stateUpdater stateUpdater
.getWorldStateTransaction() .getWorldStateTransaction()
.put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, newWorldStateRootHash.toArrayUnsafe()); .put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, calculatedRootHash.toArrayUnsafe());
worldStateRootHash = newWorldStateRootHash; worldStateRootHash = calculatedRootHash;
success = true; success = true;
} finally { } finally {
if (success) { if (success) {
@ -194,7 +218,7 @@ public abstract class DiffBasedWorldState
} }
protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) { protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) {
if (!calculatedStateRoot.equals(header.getStateRoot())) { if (!worldStateConfig.isTrieDisabled() && !calculatedStateRoot.equals(header.getStateRoot())) {
throw new RuntimeException( throw new RuntimeException(
"World State Root does not match expected value, header " "World State Root does not match expected value, header "
+ header.getStateRoot().toHexString() + header.getStateRoot().toHexString()
@ -210,7 +234,7 @@ public abstract class DiffBasedWorldState
@Override @Override
public Hash rootHash() { public Hash rootHash() {
if (isFrozen && accumulator.isAccumulatorStateChanged()) { if (worldStateConfig.isFrozen() && accumulator.isAccumulatorStateChanged()) {
worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy()); worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy());
accumulator.resetAccumulatorStateChanged(); accumulator.resetAccumulatorStateChanged();
} }
@ -285,7 +309,7 @@ public abstract class DiffBasedWorldState
try { try {
if (!isPersisted()) { if (!isPersisted()) {
this.worldStateKeyValueStorage.close(); this.worldStateKeyValueStorage.close();
if (isFrozen) { if (worldStateConfig.isFrozen()) {
closeFrozenStorage(); closeFrozenStorage();
} }
} }

@ -0,0 +1,79 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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;
public class DiffBasedWorldStateConfig {
private boolean isFrozen;
private boolean isTrieDisabled;
public DiffBasedWorldStateConfig() {
this(false, false);
}
public DiffBasedWorldStateConfig(final boolean isTrieDisabled) {
this(false, isTrieDisabled);
}
public DiffBasedWorldStateConfig(final DiffBasedWorldStateConfig config) {
this(config.isFrozen(), config.isTrieDisabled());
}
public DiffBasedWorldStateConfig(final boolean isFrozen, final boolean isTrieDisabled) {
this.isFrozen = isFrozen;
this.isTrieDisabled = isTrieDisabled;
}
/**
* Checks if the world state is frozen. When the world state is frozen, it cannot mutate.
*
* @return true if the world state is frozen, false otherwise.
*/
public boolean isFrozen() {
return isFrozen;
}
/**
* Sets the frozen status of the world state. When the world state is frozen, it cannot mutate.
*
* @param frozen the new frozen status to set.
*/
public void setFrozen(final boolean frozen) {
isFrozen = frozen;
}
/**
* Checks if the trie is disabled for the world state. When the trie is disabled, the world state
* will only work with the flat database and not the trie. In this mode, it's impossible to verify
* the state root.
*
* @return true if the trie is disabled, false otherwise.
*/
public boolean isTrieDisabled() {
return isTrieDisabled;
}
/**
* Sets the disabled status of the trie for the world state. When the trie is disabled, the world
* state will only work with the flat database and not the trie. In this mode, it's impossible to
* verify the state root.
*
* @param trieDisabled the new disabled status to set for the trie.
*/
public void setTrieDisabled(final boolean trieDisabled) {
isTrieDisabled = trieDisabled;
}
}

@ -46,6 +46,7 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider; 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.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
@ -100,7 +101,8 @@ class BlockImportExceptionHandlingTest {
(BonsaiWorldStateProvider) worldStateArchive, (BonsaiWorldStateProvider) worldStateArchive,
(BonsaiWorldStateKeyValueStorage) (BonsaiWorldStateKeyValueStorage)
worldStateStorageCoordinator.worldStateKeyValueStorage(), worldStateStorageCoordinator.worldStateKeyValueStorage(),
EvmConfiguration.DEFAULT)); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig()));
private final BadBlockManager badBlockManager = new BadBlockManager(); private final BadBlockManager badBlockManager = new BadBlockManager();

@ -48,6 +48,7 @@ public class ChainDataPrunerTest {
new ChainDataPrunerStorage(new InMemoryKeyValueStorage()), new ChainDataPrunerStorage(new InMemoryKeyValueStorage()),
512, 512,
0, 0,
// completed
new BlockingExecutor()); new BlockingExecutor());
Block genesisBlock = gen.genesisBlock(); Block genesisBlock = gen.genesisBlock();
final MutableBlockchain blockchain = final MutableBlockchain blockchain =
@ -87,6 +88,7 @@ public class ChainDataPrunerTest {
new ChainDataPrunerStorage(new InMemoryKeyValueStorage()), new ChainDataPrunerStorage(new InMemoryKeyValueStorage()),
512, 512,
0, 0,
// completed
new BlockingExecutor()); new BlockingExecutor());
Block genesisBlock = gen.genesisBlock(); Block genesisBlock = gen.genesisBlock();
final MutableBlockchain blockchain = final MutableBlockchain blockchain =

@ -199,6 +199,16 @@ public abstract class AbstractIsolationTests {
.withCommonConfiguration( .withCommonConfiguration(
new BesuConfiguration() { new BesuConfiguration() {
@Override
public Optional<String> getRpcHttpHost() {
return Optional.empty();
}
@Override
public Optional<Integer> getRpcHttpPort() {
return Optional.empty();
}
@Override @Override
public Path getStoragePath() { public Path getStoragePath() {
return tempData.resolve("database"); return tempData.resolve("database");

@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactor
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; 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.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
@ -162,7 +163,8 @@ class LogRollingTests {
archive, archive,
new BonsaiWorldStateKeyValueStorage( new BonsaiWorldStateKeyValueStorage(
provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final WorldUpdater updater = worldState.updater(); final WorldUpdater updater = worldState.updater();
final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L));
@ -178,7 +180,8 @@ class LogRollingTests {
secondProvider, secondProvider,
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final BonsaiWorldStateUpdateAccumulator secondUpdater = final BonsaiWorldStateUpdateAccumulator secondUpdater =
(BonsaiWorldStateUpdateAccumulator) secondWorldState.updater(); (BonsaiWorldStateUpdateAccumulator) secondWorldState.updater();
@ -210,7 +213,8 @@ class LogRollingTests {
archive, archive,
new BonsaiWorldStateKeyValueStorage( new BonsaiWorldStateKeyValueStorage(
provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final WorldUpdater updater = worldState.updater(); final WorldUpdater updater = worldState.updater();
final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L));
@ -234,7 +238,8 @@ class LogRollingTests {
secondProvider, secondProvider,
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final BonsaiWorldStateUpdateAccumulator secondUpdater = final BonsaiWorldStateUpdateAccumulator secondUpdater =
(BonsaiWorldStateUpdateAccumulator) secondWorldState.updater(); (BonsaiWorldStateUpdateAccumulator) secondWorldState.updater();
@ -267,7 +272,8 @@ class LogRollingTests {
archive, archive,
new BonsaiWorldStateKeyValueStorage( new BonsaiWorldStateKeyValueStorage(
provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final WorldUpdater updater = worldState.updater(); final WorldUpdater updater = worldState.updater();
final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L));
@ -298,7 +304,8 @@ class LogRollingTests {
secondProvider, secondProvider,
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final WorldUpdater secondUpdater = secondWorldState.updater(); final WorldUpdater secondUpdater = secondWorldState.updater();
final MutableAccount secondMutableAccount = final MutableAccount secondMutableAccount =

@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactor
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; 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.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
@ -57,7 +58,8 @@ public class RollingImport {
archive, archive,
new BonsaiWorldStateKeyValueStorage( new BonsaiWorldStateKeyValueStorage(
provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final SegmentedInMemoryKeyValueStorage worldStateKeyValueStorage = final SegmentedInMemoryKeyValueStorage worldStateKeyValueStorage =
(SegmentedInMemoryKeyValueStorage) (SegmentedInMemoryKeyValueStorage)
provider.getStorageBySegmentIdentifiers( provider.getStorageBySegmentIdentifiers(

@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.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.ethereum.trie.diffbased.common.DiffBasedValue;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
import java.util.HashMap; import java.util.HashMap;
@ -61,7 +62,8 @@ class BonsaiWorldStateTest {
new BonsaiWorldState( new BonsaiWorldState(
InMemoryKeyValueStorageProvider.createBonsaiInMemoryWorldStateArchive(blockchain), InMemoryKeyValueStorageProvider.createBonsaiInMemoryWorldStateArchive(blockchain),
bonsaiWorldStateKeyValueStorage, bonsaiWorldStateKeyValueStorage,
EvmConfiguration.DEFAULT); EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
} }
@ParameterizedTest @ParameterizedTest

@ -24,7 +24,6 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthContext;
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager;
@ -165,8 +164,7 @@ public class WorldStateDownloaderBenchmark {
private StorageProvider createKeyValueStorageProvider(final Path dataDir, final Path dbDir) { private StorageProvider createKeyValueStorageProvider(final Path dataDir, final Path dbDir) {
final var besuConfiguration = new BesuConfigurationImpl(); final var besuConfiguration = new BesuConfigurationImpl();
besuConfiguration.init( besuConfiguration.init(dataDir, dbDir, DataStorageConfiguration.DEFAULT_CONFIG);
dataDir, dbDir, DataStorageConfiguration.DEFAULT_CONFIG, MiningParameters.newDefault());
return new KeyValueStorageProviderBuilder() return new KeyValueStorageProviderBuilder()
.withStorageFactory( .withStorageFactory(
new RocksDBKeyValueStorageFactory( new RocksDBKeyValueStorageFactory(

@ -28,6 +28,7 @@ import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.time.Duration; import java.time.Duration;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -36,6 +37,8 @@ public abstract class AbstractSyncTargetManager {
private static final Logger LOG = LoggerFactory.getLogger(AbstractSyncTargetManager.class); private static final Logger LOG = LoggerFactory.getLogger(AbstractSyncTargetManager.class);
private final AtomicBoolean cancelled = new AtomicBoolean(false);
private final SynchronizerConfiguration config; private final SynchronizerConfiguration config;
private final ProtocolSchedule protocolSchedule; private final ProtocolSchedule protocolSchedule;
private final ProtocolContext protocolContext; private final ProtocolContext protocolContext;
@ -56,6 +59,9 @@ public abstract class AbstractSyncTargetManager {
} }
public CompletableFuture<SyncTarget> findSyncTarget() { public CompletableFuture<SyncTarget> findSyncTarget() {
if (isCancelled()) {
return completedFuture(null);
}
return selectBestAvailableSyncTarget() return selectBestAvailableSyncTarget()
.thenCompose( .thenCompose(
maybeBestPeer -> { maybeBestPeer -> {
@ -99,6 +105,10 @@ public abstract class AbstractSyncTargetManager {
}); });
} }
public synchronized void cancel() {
cancelled.set(true);
}
protected Optional<SyncTarget> finalizeSelectedSyncTarget(final SyncTarget syncTarget) { protected Optional<SyncTarget> finalizeSelectedSyncTarget(final SyncTarget syncTarget) {
return Optional.of(syncTarget); return Optional.of(syncTarget);
} }
@ -115,5 +125,9 @@ public abstract class AbstractSyncTargetManager {
.timeout(WaitForPeerTask.create(ethContext, metricsSystem), Duration.ofSeconds(5)); .timeout(WaitForPeerTask.create(ethContext, metricsSystem), Duration.ofSeconds(5));
} }
private boolean isCancelled() {
return cancelled.get();
}
public abstract boolean shouldContinueDownloading(); public abstract boolean shouldContinueDownloading();
} }

@ -85,6 +85,7 @@ public class PipelineChainDownloader implements ChainDownloader {
@Override @Override
public synchronized void cancel() { public synchronized void cancel() {
cancelled.set(true); cancelled.set(true);
syncTargetManager.cancel();
if (currentDownloadPipeline != null) { if (currentDownloadPipeline != null) {
currentDownloadPipeline.abort(); currentDownloadPipeline.abort();
} }

@ -87,7 +87,7 @@ public class EvmToolCommandOptionsModule {
@Singleton @Singleton
BesuConfiguration provideBesuConfiguration() { BesuConfiguration provideBesuConfiguration() {
final var besuConfiguration = new BesuConfigurationImpl(); final var besuConfiguration = new BesuConfigurationImpl();
besuConfiguration.init(dataPath, dataPath.resolve(BesuController.DATABASE_PATH), null, null); besuConfiguration.init(dataPath, dataPath.resolve(BesuController.DATABASE_PATH), null);
return besuConfiguration; return besuConfiguration;
} }

@ -260,6 +260,7 @@ public class PeerDiscoveryController {
l.clear(); l.clear();
}); });
inflightInteractions.clear(); inflightInteractions.clear();
recursivePeerRefreshState.cancel();
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }

@ -105,6 +105,10 @@ public class RecursivePeerRefreshState {
} }
private void bondingInitiateRound() { private void bondingInitiateRound() {
if (!iterativeSearchInProgress) {
// cancelled so we can ignore
return;
}
currentRoundTimeout.ifPresent(RoundTimeout::cancelTimeout); currentRoundTimeout.ifPresent(RoundTimeout::cancelTimeout);
final List<MetadataPeer> candidates = bondingRoundCandidates(); final List<MetadataPeer> candidates = bondingRoundCandidates();
if (candidates.isEmpty()) { if (candidates.isEmpty()) {
@ -137,6 +141,10 @@ public class RecursivePeerRefreshState {
} }
private void bondingCancelOutstandingRequests() { private void bondingCancelOutstandingRequests() {
if (!iterativeSearchInProgress) {
// cancelled so we can ignore
return;
}
LOG.debug("Bonding round timed out"); LOG.debug("Bonding round timed out");
for (final Map.Entry<Bytes, MetadataPeer> entry : oneTrueMap.entrySet()) { for (final Map.Entry<Bytes, MetadataPeer> entry : oneTrueMap.entrySet()) {
final MetadataPeer metadataPeer = entry.getValue(); final MetadataPeer metadataPeer = entry.getValue();
@ -149,6 +157,10 @@ public class RecursivePeerRefreshState {
} }
private void neighboursInitiateRound() { private void neighboursInitiateRound() {
if (!iterativeSearchInProgress) {
// cancelled so we can ignore
return;
}
currentRoundTimeout.ifPresent(RoundTimeout::cancelTimeout); currentRoundTimeout.ifPresent(RoundTimeout::cancelTimeout);
final List<MetadataPeer> candidates = neighboursRoundCandidates(); final List<MetadataPeer> candidates = neighboursRoundCandidates();
if (candidates.isEmpty() || reachedMaximumNumberOfRounds()) { if (candidates.isEmpty() || reachedMaximumNumberOfRounds()) {
@ -172,6 +184,10 @@ public class RecursivePeerRefreshState {
} }
private void neighboursCancelOutstandingRequests() { private void neighboursCancelOutstandingRequests() {
if (!iterativeSearchInProgress) {
// cancelled so we can ignore
return;
}
LOG.debug("Neighbours round timed out"); LOG.debug("Neighbours round timed out");
for (final Map.Entry<Bytes, MetadataPeer> entry : oneTrueMap.entrySet()) { for (final Map.Entry<Bytes, MetadataPeer> entry : oneTrueMap.entrySet()) {
final MetadataPeer metadataPeer = entry.getValue(); final MetadataPeer metadataPeer = entry.getValue();
@ -218,6 +234,10 @@ public class RecursivePeerRefreshState {
} }
void onBondingComplete(final DiscoveryPeer peer) { void onBondingComplete(final DiscoveryPeer peer) {
if (!iterativeSearchInProgress) {
// cancelled so we can ignore
return;
}
final MetadataPeer iterationParticipant = oneTrueMap.get(peer.getId()); final MetadataPeer iterationParticipant = oneTrueMap.get(peer.getId());
if (iterationParticipant == null) { if (iterationParticipant == null) {
return; return;

@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCached
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent;
import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig;
import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration;
@ -66,7 +67,8 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
bonsaiCachedMerkleTrieLoader, bonsaiCachedMerkleTrieLoader,
cachedWorldStorageManager, cachedWorldStorageManager,
trieLogManager, trieLogManager,
evmConfiguration); evmConfiguration,
new DiffBasedWorldStateConfig());
this.refTestStorage = worldStateKeyValueStorage; this.refTestStorage = worldStateKeyValueStorage;
this.preImageProxy = preImageProxy; this.preImageProxy = preImageProxy;
this.evmConfiguration = evmConfiguration; this.evmConfiguration = evmConfiguration;
@ -194,7 +196,8 @@ public class BonsaiReferenceTestWorldState extends BonsaiWorldState
bonsaiCachedMerkleTrieLoader, bonsaiCachedMerkleTrieLoader,
cachedWorldStorageManager, cachedWorldStorageManager,
trieLogManager, trieLogManager,
evmConfiguration); evmConfiguration,
new DiffBasedWorldStateConfig());
if (isFrozen) { if (isFrozen) {
bonsaiWorldState.freeze(); // freeze state bonsaiWorldState.freeze(); // freeze state
} }

@ -0,0 +1,123 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
/**
* A noop {@link MerkleTrie}.
*
* @param <V> The type of values of this trie.
*/
public class NoOpMerkleTrie<K extends Bytes, V> implements MerkleTrie<K, V> {
public NoOpMerkleTrie() {}
@Override
public Optional<V> get(final K key) {
return Optional.empty();
}
@Override
public Optional<V> getPath(final K path) {
return Optional.empty();
}
@Override
public Proof<V> getValueWithProof(final K key) {
return new Proof<>(Optional.empty(), new ArrayList<>());
}
@Override
public void put(final K key, final V value) {
// noop
}
@Override
public void putPath(final K path, final V value) {
// noop
}
@Override
public void put(final K key, final PathNodeVisitor<V> putVisitor) {
// noop
}
@Override
public void remove(final K key) {
// noop
}
@Override
public void removePath(final K path, final PathNodeVisitor<V> removeVisitor) {
// noop
}
@Override
public Bytes32 getRootHash() {
return EMPTY_TRIE_NODE_HASH;
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + getRootHash() + "]";
}
@Override
public void commit(final NodeUpdater nodeUpdater) {
// Nothing to do here
}
@Override
public void commit(final NodeUpdater nodeUpdater, final CommitVisitor<V> commitVisitor) {
// Nothing to do here
}
@Override
public Map<Bytes32, V> entriesFrom(final Bytes32 startKeyHash, final int limit) {
return new HashMap<>();
}
@Override
public Map<Bytes32, V> entriesFrom(final Function<Node<V>, Map<Bytes32, V>> handler) {
return new HashMap<>();
}
@Override
public void visitAll(final Consumer<Node<V>> nodeConsumer) {
// noop
}
@Override
public CompletableFuture<Void> visitAll(
final Consumer<Node<V>> nodeConsumer, final ExecutorService executorService) {
return CompletableFuture.completedFuture(null);
}
@Override
public void visitLeafs(final TrieIterator.LeafHandler<V> handler) {
// nopop
}
}

@ -70,7 +70,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) { tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought" description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files files = sourceSets.main.allJava.files
knownHash = 'xU0LMvStiFihBKBxkfNHB7oIg0PUHWkPuv2yt1GVC94=' knownHash = 'wMhttXj2aWFgpN9msxHz/FwQVovpYRxNysnZEpwZYxg='
} }
check.dependsOn('checkAPIChanges') check.dependsOn('checkAPIChanges')

@ -63,6 +63,9 @@ public interface BesuPlugin {
*/ */
void start(); void start();
/** Hook to execute plugin setup code after external services */
default void afterExternalServicePostMainLoop() {}
/** /**
* Called when the plugin is being reloaded. This method will be called through a dedicated JSON * Called when the plugin is being reloaded. This method will be called through a dedicated JSON
* RPC endpoint. If not overridden this method does nothing for convenience. The plugin should * RPC endpoint. If not overridden this method does nothing for convenience. The plugin should

@ -20,10 +20,25 @@ import org.hyperledger.besu.plugin.services.storage.DataStorageConfiguration;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Optional;
/** Generally useful configuration provided by Besu. */ /** Generally useful configuration provided by Besu. */
public interface BesuConfiguration extends BesuService { public interface BesuConfiguration extends BesuService {
/**
* Get the configured RPC http host.
*
* @return the configured RPC http host.
*/
Optional<String> getRpcHttpHost();
/**
* Get the configured RPC http port.
*
* @return the configured RPC http port.
*/
Optional<Integer> getRpcHttpPort();
/** /**
* Location of the working directory of the storage in the file system running the client. * Location of the working directory of the storage in the file system running the client.
* *

@ -93,6 +93,14 @@ public interface BesuEvents extends BesuService {
*/ */
void removeBlockReorgListener(long listenerIdentifier); void removeBlockReorgListener(long listenerIdentifier);
/**
* Add an initial sync completion listener.
*
* @param listener to subscribe to initial sync completion events
* @return id of listener subscription
*/
long addInitialSyncCompletionListener(final InitialSyncCompletionListener listener);
/** /**
* Add a listener watching new transactions added to the node. * Add a listener watching new transactions added to the node.
* *

@ -17,9 +17,12 @@ package org.hyperledger.besu.plugin.services;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.plugin.Unstable; import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockContext; import org.hyperledger.besu.plugin.data.BlockContext;
import org.hyperledger.besu.plugin.data.BlockHeader; import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.data.TransactionReceipt;
import java.util.List;
import java.util.Optional; import java.util.Optional;
/** A service that plugins can use to query blocks by number */ /** A service that plugins can use to query blocks by number */
@ -40,6 +43,23 @@ public interface BlockchainService extends BesuService {
*/ */
Hash getChainHeadHash(); Hash getChainHeadHash();
/**
* Get the receipts for a block by block hash
*
* @param blockHash the block hash
* @return the transaction receipts
*/
Optional<List<TransactionReceipt>> getReceiptsByBlockHash(Hash blockHash);
/**
* Store a block
*
* @param blockHeader the block header
* @param blockBody the block body
* @param receipts the transaction receipts
*/
void storeBlock(BlockHeader blockHeader, BlockBody blockBody, List<TransactionReceipt> receipts);
/** /**
* Get the block header of the chain head * Get the block header of the chain head
* *
@ -53,4 +73,18 @@ public interface BlockchainService extends BesuService {
* @return base fee of the next block or empty if the fee market does not support base fee * @return base fee of the next block or empty if the fee market does not support base fee
*/ */
Optional<Wei> getNextBlockBaseFee(); Optional<Wei> getNextBlockBaseFee();
/**
* Get the block hash of the safe block
*
* @return the block hash of the safe block
*/
Optional<Hash> getSafeBlock();
/**
* Get the block hash of the finalized block
*
* @return the block hash of the finalized block
*/
Optional<Hash> getFinalizedBlock();
} }

@ -19,6 +19,7 @@ import org.hyperledger.besu.plugin.services.trielogs.TrieLogFactory;
import org.hyperledger.besu.plugin.services.trielogs.TrieLogProvider; import org.hyperledger.besu.plugin.services.trielogs.TrieLogProvider;
import java.util.List; import java.util.List;
import java.util.Optional;
/** /**
* A service interface for registering observers for trie log events. * A service interface for registering observers for trie log events.
@ -39,7 +40,7 @@ public interface TrieLogService extends BesuService {
* *
* @return the TrieLogFactory implementation * @return the TrieLogFactory implementation
*/ */
TrieLogFactory getTrieLogFactory(); Optional<TrieLogFactory> getTrieLogFactory();
/** /**
* Configure a TrieLogProvider implementation to use for retrieving stored TrieLogs. * Configure a TrieLogProvider implementation to use for retrieving stored TrieLogs.

@ -0,0 +1,27 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.plugin.services.p2p;
import org.hyperledger.besu.plugin.services.BesuService;
/** Service to enable and disable P2P service. */
public interface P2PService extends BesuService {
/** Enables P2P discovery. */
void enableDiscovery();
/** Disables P2P discovery. */
void disableDiscovery();
}

@ -0,0 +1,74 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.plugin.services.rlp;
import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.data.TransactionReceipt;
import org.hyperledger.besu.plugin.services.BesuService;
import org.apache.tuweni.bytes.Bytes;
/** RLP Serialiaztion/Deserialization service. */
public interface RlpConverterService extends BesuService {
/**
* Builds a block header from RLP.
*
* @param rlp the RLP to build the block header from.
* @return the block header.
*/
BlockHeader buildHeaderFromRlp(final Bytes rlp);
/**
* Builds a block body from RLP.
*
* @param rlp the RLP to build the block body from.
* @return the block body.
*/
BlockBody buildBodyFromRlp(final Bytes rlp);
/**
* Builds a transaction receipt from RLP.
*
* @param rlp the RLP to build the transaction receipt from.
* @return the transaction receipt.
*/
TransactionReceipt buildReceiptFromRlp(final Bytes rlp);
/**
* RLP encodes a block header.
*
* @param blockHeader the block header to build RLP from.
* @return the RLP.
*/
Bytes buildRlpFromHeader(final BlockHeader blockHeader);
/**
* RLP encodes a block body.
*
* @param blockBody the block body to build RLP from.
* @return the RLP.
*/
Bytes buildRlpFromBody(final BlockBody blockBody);
/**
* RLP encodes a transaction receipt.
*
* @param receipt the transaction receipt to build RLP from.
* @return the RLP.
*/
Bytes buildRlpFromReceipt(final TransactionReceipt receipt);
}

@ -0,0 +1,62 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.plugin.services.sync;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.services.BesuService;
/** Synchronization service wraps the sync state and sync event lifecycle. */
public interface SynchronizationService extends BesuService {
/**
* Enables P2P discovery.
*
* @param head the head of the chain.
* @param safeBlock the safe block.
* @param finalizedBlock the finalized block.
*/
void fireNewUnverifiedForkchoiceEvent(Hash head, Hash safeBlock, Hash finalizedBlock);
/**
* Set the head of the chain.
*
* @param blockHeader the block header
* @param blockBody the block body
* @return true if the head was set, false otherwise.
*/
boolean setHead(final BlockHeader blockHeader, final BlockBody blockBody);
/**
* Adds the block header and body to the head of the chain directly, without using a block
* importer or validation.
*
* @param blockHeader the block header
* @param blockBody the block body
* @return true if the head was set, false otherwise.
*/
boolean setHeadUnsafe(BlockHeader blockHeader, BlockBody blockBody);
/**
* Returns whether the initial chain and worldstate sync is complete.
*
* @return true if the initial sync phase is done, false otherwise.
*/
boolean isInitialSyncPhaseDone();
/** Disables the worldstate trie for update. */
void disableWorldStateTrie();
}

@ -0,0 +1,26 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.plugin.services.sync;
/** interface for worldstate configuration * */
public interface WorldStateConfiguration {
/**
* Returns whether the trie is disabled.
*
* @return true if the trie is disabled, false otherwise.
*/
boolean isTrieDisabled();
}

@ -0,0 +1,26 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.plugin.services.transactionpool;
import org.hyperledger.besu.plugin.services.BesuService;
/** Service to enable and disable the transaction pool. */
public interface TransactionPoolService extends BesuService {
/** Enables the transaction pool. */
void disableTransactionPool();
/** Disables the transaction pool. */
void enableTransactionPool();
}

@ -19,8 +19,19 @@ import org.hyperledger.besu.datatypes.Hash;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
/** Trielog provider interface for a given block hash. */ /** Trielog provider interface for a given block hash. */
public interface TrieLogProvider { public interface TrieLogProvider {
/**
* Saves the TrieLog layer for the given block hash.
*
* @param blockHash the block hash
* @param blockNumber the block number
* @param trieLog the associated TrieLog layer
*/
void saveRawTrieLogLayer(final Hash blockHash, final long blockNumber, final Bytes trieLog);
/** /**
* Returns the TrieLog layer for the given block hash. * Returns the TrieLog layer for the given block hash.
* *
@ -30,6 +41,14 @@ public interface TrieLogProvider {
*/ */
<T extends TrieLog.LogTuple<?>> Optional<TrieLog> getTrieLogLayer(final Hash blockHash); <T extends TrieLog.LogTuple<?>> Optional<TrieLog> getTrieLogLayer(final Hash blockHash);
/**
* Get the raw TrieLog layer for the given block hash.
*
* @param blockHash the block hash
* @return the raw TrieLog layer bytes for the given block hash
*/
Optional<Bytes> getRawTrieLogLayer(final Hash blockHash);
/** /**
* Returns the TrieLog layer for the given block number. * Returns the TrieLog layer for the given block number.
* *
@ -39,6 +58,14 @@ public interface TrieLogProvider {
*/ */
<T extends TrieLog.LogTuple<?>> Optional<TrieLog> getTrieLogLayer(final long blockNumber); <T extends TrieLog.LogTuple<?>> Optional<TrieLog> getTrieLogLayer(final long blockNumber);
/**
* Get the raw TrieLog layer for the given block number.
*
* @param blockNumber the block number
* @return the raw TrieLog layer bytes for the given block number
*/
Optional<Bytes> getRawTrieLogLayer(final long blockNumber);
/** /**
* Returns the TrieLog layers for the given block number range. * Returns the TrieLog layers for the given block number range.
* *

Loading…
Cancel
Save