From ebb883075fe832be6e55e1822731a6e5f8a6f930 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Wed, 22 May 2024 10:02:34 -0700 Subject: [PATCH 01/42] Feature/fleet mode rebase (#6641) * fleet mode squash commit rebase Signed-off-by: garyschulte --- .../dsl/node/ThreadBesuNodeRunner.java | 9 +- .../acceptance/dsl/privacy/PrivacyNode.java | 4 +- .../java/org/hyperledger/besu/Runner.java | 10 ++ .../org/hyperledger/besu/cli/BesuCommand.java | 48 ++++- .../options/stable/JsonRpcHttpOptions.java | 9 + .../options/unstable/ChainPruningOptions.java | 41 ++++- .../controller/BesuControllerBuilder.java | 20 +-- .../besu/services/BesuConfigurationImpl.java | 48 ++++- .../besu/services/BesuEventsImpl.java | 5 + .../besu/services/BesuPluginContextImpl.java | 19 ++ .../besu/services/BlockchainServiceImpl.java | 49 +++++- .../besu/services/P2PServiceImpl.java | 44 +++++ .../services/RlpConverterServiceImpl.java | 82 +++++++++ .../services/SynchronizationServiceImpl.java | 166 ++++++++++++++++++ .../services/TransactionPoolServiceImpl.java | 43 +++++ .../org/hyperledger/besu/PrivacyTest.java | 4 +- .../java/org/hyperledger/besu/RunnerTest.java | 4 +- .../besu/cli/CommandTestAbstract.java | 3 +- ...nsusScheduleBesuControllerBuilderTest.java | 3 +- .../services/RlpConverterServiceImplTest.java | 54 ++++++ .../MigratingMiningCoordinatorTest.java | 3 +- .../hyperledger/besu/datatypes/BlobGas.java | 4 +- .../chain/ChainPrunerConfiguration.java | 13 +- .../ethereum/chain/DefaultBlockchain.java | 3 +- .../ethereum/chain/MutableBlockchain.java | 2 + .../besu/ethereum/core/BlockHeader.java | 2 +- .../common/GenesisWorldStateProvider.java | 4 +- .../bonsai/BonsaiWorldStateProvider.java | 26 ++- .../BonsaiCachedWorldStorageManager.java | 11 +- .../NoOpBonsaiCachedWorldStorageManager.java | 3 +- ...nsaiSnapshotWorldStateKeyValueStorage.java | 9 + .../bonsai/worldview/BonsaiWorldState.java | 72 +++++--- .../common/DiffBasedWorldStateProvider.java | 17 ++ .../diffbased/common/StorageSubscriber.java | 2 + .../DiffBasedCachedWorldStorageManager.java | 22 ++- .../DiffBasedWorldStateKeyValueStorage.java | 5 + .../common/trielog/TrieLogManager.java | 40 ++++- .../common/worldview/DiffBasedWorldState.java | 52 ++++-- .../worldview/DiffBasedWorldStateConfig.java | 79 +++++++++ .../BlockImportExceptionHandlingTest.java | 4 +- .../ethereum/chain/ChainDataPrunerTest.java | 2 + .../bonsai/AbstractIsolationTests.java | 10 ++ .../diffbased/bonsai/LogRollingTests.java | 19 +- .../trie/diffbased/bonsai/RollingImport.java | 4 +- .../worldview/BonsaiWorldStateTest.java | 4 +- .../WorldStateDownloaderBenchmark.java | 4 +- .../eth/sync/AbstractSyncTargetManager.java | 14 ++ .../eth/sync/PipelineChainDownloader.java | 1 + .../evmtool/EvmToolCommandOptionsModule.java | 2 +- .../internal/PeerDiscoveryController.java | 1 + .../internal/RecursivePeerRefreshState.java | 20 +++ .../BonsaiReferenceTestWorldState.java | 7 +- .../besu/ethereum/trie/NoOpMerkleTrie.java | 123 +++++++++++++ plugin-api/build.gradle | 2 +- .../hyperledger/besu/plugin/BesuPlugin.java | 3 + .../plugin/services/BesuConfiguration.java | 15 ++ .../besu/plugin/services/BesuEvents.java | 8 + .../plugin/services/BlockchainService.java | 34 ++++ .../besu/plugin/services/TrieLogService.java | 3 +- .../besu/plugin/services/p2p/P2PService.java | 27 +++ .../services/rlp/RlpConverterService.java | 74 ++++++++ .../services/sync/SynchronizationService.java | 62 +++++++ .../sync/WorldStateConfiguration.java | 26 +++ .../TransactionPoolService.java | 26 +++ .../services/trielogs/TrieLogProvider.java | 27 +++ 65 files changed, 1425 insertions(+), 131 deletions(-) create mode 100644 besu/src/main/java/org/hyperledger/besu/services/P2PServiceImpl.java create mode 100644 besu/src/main/java/org/hyperledger/besu/services/RlpConverterServiceImpl.java create mode 100644 besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java create mode 100644 besu/src/main/java/org/hyperledger/besu/services/TransactionPoolServiceImpl.java create mode 100644 besu/src/test/java/org/hyperledger/besu/services/RlpConverterServiceImplTest.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java create mode 100644 ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/NoOpMerkleTrie.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/p2p/P2PService.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rlp/RlpConverterService.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/SynchronizationService.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/transactionpool/TransactionPoolService.java diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 073e0bd1d1b..0448d324e64 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -180,11 +180,10 @@ public void startNode(final BesuNode node) { .from(node.getMiningParameters()) .transactionSelectionService(transactionSelectionServiceImpl) .build(); - commonPluginConfiguration.init( - dataDir, - dataDir.resolve(DATABASE_PATH), - node.getDataStorageConfiguration(), - miningParameters); + commonPluginConfiguration + .init(dataDir, dataDir.resolve(DATABASE_PATH), node.getDataStorageConfiguration()) + .withMiningParameters(miningParameters); + final BesuPluginContextImpl besuPluginContext = besuPluginContextMap.computeIfAbsent( node, diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java index c9487ebcd67..32a5a0fbf4a 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java @@ -274,7 +274,9 @@ public NodeConfiguration getConfiguration() { private PrivacyStorageProvider createKeyValueStorageProvider( final Path dataLocation, final Path dbLocation) { final var besuConfiguration = new BesuConfigurationImpl(); - besuConfiguration.init(dataLocation, dbLocation, null, besuConfig.getMiningParameters()); + besuConfiguration + .init(dataLocation, dbLocation, null) + .withMiningParameters(besuConfig.getMiningParameters()); return new PrivacyKeyValueStorageProviderBuilder() .withStorageFactory( new RocksDBKeyValuePrivacyStorageFactory( diff --git a/besu/src/main/java/org/hyperledger/besu/Runner.java b/besu/src/main/java/org/hyperledger/besu/Runner.java index 32c4a46ddeb..4444f7acf72 100644 --- a/besu/src/main/java/org/hyperledger/besu/Runner.java +++ b/besu/src/main/java/org/hyperledger/besu/Runner.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolEvictionService; 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.ethstats.EthStatsService; import org.hyperledger.besu.metrics.MetricsService; @@ -422,6 +423,15 @@ Optional getLocalEnode() { return networkRunner.getNetwork().getLocalEnode(); } + /** + * get P2PNetwork service. + * + * @return p2p network service. + */ + public P2PNetwork getP2PNetwork() { + return networkRunner.getNetwork(); + } + @FunctionalInterface private interface SynchronousShutdown { /** diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index ccbc619b5ac..bd47630fad6 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -172,21 +172,29 @@ import org.hyperledger.besu.plugin.services.exception.StorageException; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; 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.storage.DataStorageFormat; import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory; 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.BesuEventsImpl; import org.hyperledger.besu.services.BesuPluginContextImpl; import org.hyperledger.besu.services.BlockchainServiceImpl; +import org.hyperledger.besu.services.P2PServiceImpl; import org.hyperledger.besu.services.PermissioningServiceImpl; import org.hyperledger.besu.services.PicoCLIOptionsImpl; import org.hyperledger.besu.services.PrivacyPluginServiceImpl; +import org.hyperledger.besu.services.RlpConverterServiceImpl; import org.hyperledger.besu.services.RpcEndpointServiceImpl; import org.hyperledger.besu.services.SecurityModuleServiceImpl; import org.hyperledger.besu.services.StorageServiceImpl; +import org.hyperledger.besu.services.SynchronizationServiceImpl; import org.hyperledger.besu.services.TraceServiceImpl; +import org.hyperledger.besu.services.TransactionPoolServiceImpl; import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl; import org.hyperledger.besu.services.TransactionSelectionServiceImpl; import org.hyperledger.besu.services.TransactionSimulationServiceImpl; @@ -1161,12 +1169,15 @@ public void run() { final var runner = buildRunner(); runner.startExternalServices(); - startPlugins(); + startPlugins(runner); validatePluginOptions(); setReleaseMetrics(); preSynchronization(); runner.startEthereumMainLoop(); + + besuPluginContext.afterExternalServicesMainLoop(); + runner.awaitStop(); } catch (final Exception e) { @@ -1327,7 +1338,7 @@ private Runner buildRunner() { pidPath); } - private void startPlugins() { + private void startPlugins(final Runner runner) { blockchainServiceImpl.init( besuController.getProtocolContext(), besuController.getProtocolSchedule()); transactionSimulationServiceImpl.init( @@ -1348,6 +1359,26 @@ private void startPlugins() { besuController.getProtocolContext().getBadBlockManager())); 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( TraceService.class, new TraceServiceImpl( @@ -1653,11 +1684,11 @@ private void validateRpcWsOptions() { private void validateChainDataPruningParams() { if (unstableChainPruningOptions.getChainDataPruningEnabled() && unstableChainPruningOptions.getChainDataPruningBlocksRetained() - < ChainPruningOptions.DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED) { + < unstableChainPruningOptions.getChainDataPruningBlocksRetainedLimit()) { throw new ParameterException( this.commandLine, "--Xchain-pruning-blocks-retained must be >= " - + ChainPruningOptions.DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED); + + unstableChainPruningOptions.getChainDataPruningBlocksRetainedLimit()); } } @@ -1843,11 +1874,10 @@ public BesuController buildController() { * @return instance of BesuControllerBuilder */ public BesuControllerBuilder getControllerBuilder() { - pluginCommonConfiguration.init( - dataDir(), - dataDir().resolve(DATABASE_PATH), - getDataStorageConfiguration(), - miningParametersSupplier.get()); + pluginCommonConfiguration + .init(dataDir(), dataDir().resolve(DATABASE_PATH), getDataStorageConfiguration()) + .withMiningParameters(getMiningParameters()) + .withJsonRpcHttpOptions(jsonRpcHttpOptions); final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); return controllerBuilderFactory .fromEthNetworkConfig(updateNetworkConfig(network), getDefaultSyncModeIfNotSet()) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/JsonRpcHttpOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/JsonRpcHttpOptions.java index a47c5e9ce2d..026b83b5537 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/JsonRpcHttpOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/JsonRpcHttpOptions.java @@ -475,6 +475,15 @@ public List getRpcHttpApis() { 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. * diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java index 8eaed2d084c..0a59ef9b04e 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/ChainPruningOptions.java @@ -28,10 +28,17 @@ public class ChainPruningOptions implements CLIOptions private static final String CHAIN_PRUNING_ENABLED_FLAG = "--Xchain-pruning-enabled"; private static final String CHAIN_PRUNING_BLOCKS_RETAINED_FLAG = "--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"; - /** 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. */ public static final int DEFAULT_CHAIN_DATA_PRUNING_FREQUENCY = 256; @@ -47,11 +54,21 @@ public class ChainPruningOptions implements CLIOptions hidden = true, names = {CHAIN_PRUNING_BLOCKS_RETAINED_FLAG}, description = - "The number of recent blocks for which to keep the chain data. Must be >= " - + DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED + "The number of recent blocks for which to keep the chain data. Should be >= " + + 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})") - private final Long chainDataPruningBlocksRetained = - DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED; + private final Long chainDataPruningBlocksRetainedLimit = + CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED_LIMIT; @CommandLine.Option( hidden = true, @@ -91,11 +108,21 @@ public Long getChainDataPruningBlocksRetained() { return chainDataPruningBlocksRetained; } + /** + * Get the configured number of retained blocks for chain pruning. + * + * @return the number of retained blocks + */ + public Long getChainDataPruningBlocksRetainedLimit() { + return chainDataPruningBlocksRetainedLimit; + } + @Override public ChainPrunerConfiguration toDomainObject() { return new ChainPrunerConfiguration( chainDataPruningEnabled, chainDataPruningBlocksRetained, + chainDataPruningBlocksRetainedLimit, chainDataPruningBlocksFrequency.getValue()); } @@ -106,6 +133,8 @@ public List getCLIOptions() { chainDataPruningEnabled.toString(), CHAIN_PRUNING_BLOCKS_RETAINED_FLAG, chainDataPruningBlocksRetained.toString(), + CHAIN_PRUNING_BLOCKS_RETAINED_LIMIT_FLAG, + chainDataPruningBlocksRetainedLimit.toString(), CHAIN_PRUNING_FREQUENCY_FLAG, chainDataPruningBlocksFrequency.toString()); } diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index d801528cf55..322f596e160 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -610,16 +610,6 @@ public BesuController build() { blockchain, worldStateArchive, protocolSchedule, this::createConsensusContext); 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( protocolContext.getWorldStateArchive()); @@ -668,6 +658,16 @@ public BesuController build() { final boolean fullSyncDisabled = !SyncMode.isFullSync(syncConfig.getSyncMode()); 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 = TransactionPoolFactory.createTransactionPool( protocolSchedule, diff --git a/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java index 875929da3c2..0adbda23b74 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BesuConfigurationImpl.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.services; +import org.hyperledger.besu.cli.options.stable.JsonRpcHttpOptions; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; @@ -21,13 +22,18 @@ import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import java.nio.file.Path; +import java.util.Optional; /** A concrete implementation of BesuConfiguration which is used in Besu plugin framework. */ public class BesuConfigurationImpl implements BesuConfiguration { private Path storagePath; private Path dataPath; private DataStorageConfiguration dataStorageConfiguration; - private MiningParameters miningParameters; + + // defaults + private MiningParameters miningParameters = MiningParameters.newDefault(); + private Optional rpcHttpHost = Optional.of("http://localhost"); + private Optional rpcHttpPort = Optional.of(8545); /** Default Constructor. */ public BesuConfigurationImpl() {} @@ -38,17 +44,49 @@ public BesuConfigurationImpl() {} * @param dataPath The Path representing data folder * @param storagePath The path representing storage folder * @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 storagePath, - final DataStorageConfiguration dataStorageConfiguration, - final MiningParameters miningParameters) { + final DataStorageConfiguration dataStorageConfiguration) { this.dataPath = dataPath; this.storagePath = storagePath; 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; + 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 getRpcHttpHost() { + return rpcHttpHost; + } + + @Override + public Optional getRpcHttpPort() { + return rpcHttpPort; } @Override diff --git a/besu/src/main/java/org/hyperledger/besu/services/BesuEventsImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BesuEventsImpl.java index 5e6a63df407..aeb7025872a 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BesuEventsImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BesuEventsImpl.java @@ -114,6 +114,11 @@ public void removeBlockReorgListener(final long listenerIdentifier) { blockchain.removeObserver(listenerIdentifier); } + @Override + public long addInitialSyncCompletionListener(final InitialSyncCompletionListener listener) { + return syncState.subscribeCompletionReached(listener); + } + @Override public long addTransactionAddedListener(final TransactionAddedListener listener) { return transactionPool.subscribePendingTransactions(listener::onTransactionAdded); diff --git a/besu/src/main/java/org/hyperledger/besu/services/BesuPluginContextImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BesuPluginContextImpl.java index e7108a02d1a..6aa64ac5106 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BesuPluginContextImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BesuPluginContextImpl.java @@ -262,6 +262,25 @@ public void startPlugins() { 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 pluginsIterator = registeredPlugins.iterator(); + + while (pluginsIterator.hasNext()) { + final BesuPlugin plugin = pluginsIterator.next(); + try { + plugin.afterExternalServicePostMainLoop(); + } finally { + pluginsIterator.remove(); + } + } + } + /** Stop plugins. */ public void stopPlugins() { checkState( diff --git a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java index c6d37ad6ae9..5005e5f7ccd 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java @@ -17,17 +17,22 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; 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.feemarket.BaseFeeMarket; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; 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.BlockHeader; +import org.hyperledger.besu.plugin.data.TransactionReceipt; import org.hyperledger.besu.plugin.services.BlockchainService; +import java.util.List; import java.util.Optional; import java.util.function.Supplier; +import java.util.stream.Collectors; /** The Blockchain service implementation. */ @Unstable @@ -35,9 +40,7 @@ public class BlockchainServiceImpl implements BlockchainService { private ProtocolContext protocolContext; private ProtocolSchedule protocolSchedule; - - /** Create a new instance */ - public BlockchainServiceImpl() {} + private MutableBlockchain blockchain; /** * Instantiates a new Blockchain service. @@ -48,6 +51,7 @@ public BlockchainServiceImpl() {} public void init(final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule) { this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; + this.blockchain = protocolContext.getBlockchain(); } /** @@ -91,6 +95,43 @@ public Optional getNextBlockBaseFee() { feeMarket.targetGasUsed(chainHeadHeader))); } + @Override + public Optional> 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 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 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 getSafeBlock() { + return blockchain.getSafeBlock(); + } + + @Override + public Optional getFinalizedBlock() { + return blockchain.getFinalized(); + } + private static BlockContext blockContext( final Supplier blockHeaderSupplier, final Supplier blockBodySupplier) { diff --git a/besu/src/main/java/org/hyperledger/besu/services/P2PServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/P2PServiceImpl.java new file mode 100644 index 00000000000..dc1fb0833a8 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/P2PServiceImpl.java @@ -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(); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/services/RlpConverterServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/RlpConverterServiceImpl.java new file mode 100644 index 00000000000..53b3541a5b0 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/RlpConverterServiceImpl.java @@ -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)); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java new file mode 100644 index 00000000000..898ede5d0d4 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java @@ -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 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 worldStateBlockHash = worldStateStorage.getWorldStateBlockHash(); + final Optional 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(); + } + } + }); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/services/TransactionPoolServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TransactionPoolServiceImpl.java new file mode 100644 index 00000000000..16d033ac9e4 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/TransactionPoolServiceImpl.java @@ -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(); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java index 7a4f05ad7fa..dc5b7003c84 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java @@ -137,7 +137,9 @@ private PrivacyStorageProvider createKeyValueStorageProvider( final DataStorageConfiguration dataStorageConfiguration, final MiningParameters miningParameters) { final var besuConfiguration = new BesuConfigurationImpl(); - besuConfiguration.init(dataDir, dbDir, dataStorageConfiguration, miningParameters); + besuConfiguration + .init(dataDir, dbDir, dataStorageConfiguration) + .withMiningParameters(miningParameters); return new PrivacyKeyValueStorageProviderBuilder() .withStorageFactory( new RocksDBKeyValuePrivacyStorageFactory( diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index f0125174d27..f6c6aac5f2f 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -391,7 +391,9 @@ private StorageProvider createKeyValueStorageProvider( final DataStorageConfiguration dataStorageConfiguration, final MiningParameters miningParameters) { final var besuConfiguration = new BesuConfigurationImpl(); - besuConfiguration.init(dataDir, dbDir, dataStorageConfiguration, miningParameters); + besuConfiguration + .init(dataDir, dbDir, dataStorageConfiguration) + .withMiningParameters(miningParameters); return new KeyValueStorageProviderBuilder() .withStorageFactory( new RocksDBKeyValueStorageFactory( diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index 5216db7036b..1dfb5f449b7 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -127,6 +127,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -214,7 +215,7 @@ public abstract class CommandTestAbstract { @Mock protected TransactionSelectionServiceImpl txSelectionService; @Mock protected SecurityModuleServiceImpl securityModuleService; @Mock protected SecurityModule securityModule; - @Mock protected BesuConfigurationImpl commonPluginConfiguration; + @Spy protected BesuConfigurationImpl commonPluginConfiguration = new BesuConfigurationImpl(); @Mock protected KeyValueStorageFactory rocksDBStorageFactory; @Mock protected PrivacyKeyValueStorageFactory rocksDBSPrivacyStorageFactory; @Mock protected PicoCLIOptions cliOptions; diff --git a/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java index 12f36c9f6ec..5efeed50b24 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java @@ -30,7 +30,6 @@ import org.hyperledger.besu.ethereum.ConsensusContext; import org.hyperledger.besu.ethereum.ProtocolContext; 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.MutableBlockchain; import org.hyperledger.besu.ethereum.core.MiningParameters; @@ -68,7 +67,7 @@ public class ConsensusScheduleBesuControllerBuilderTest { private @Mock ProtocolSchedule protocolSchedule1; private @Mock ProtocolSchedule protocolSchedule2; private @Mock ProtocolSchedule protocolSchedule3; - private @Mock NoopMiningCoordinator miningCoordinator1; + private @Mock MiningCoordinator miningCoordinator1; private @Mock BftMiningCoordinator miningCoordinator2; @Test diff --git a/besu/src/test/java/org/hyperledger/besu/services/RlpConverterServiceImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/RlpConverterServiceImplTest.java new file mode 100644 index 00000000000..7a3bdbbfe6b --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/services/RlpConverterServiceImplTest.java @@ -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()); + } +} diff --git a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingMiningCoordinatorTest.java b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingMiningCoordinatorTest.java index 640691f0d3e..f3edea81e6c 100644 --- a/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingMiningCoordinatorTest.java +++ b/consensus/common/src/test/java/org/hyperledger/besu/consensus/common/MigratingMiningCoordinatorTest.java @@ -30,7 +30,6 @@ import org.hyperledger.besu.consensus.common.bft.blockcreation.BftMiningCoordinator; import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler; 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.Blockchain; import org.hyperledger.besu.ethereum.core.Block; @@ -122,7 +121,7 @@ public void stopShouldUnregisterThisCoordinatorAsObserver() { @Test public void onBlockAddedShouldNotDelegateWhenDelegateIsNoop() { - NoopMiningCoordinator mockNoopCoordinator = mock(NoopMiningCoordinator.class); + MiningCoordinator mockNoopCoordinator = mock(MiningCoordinator.class); coordinatorSchedule = createCoordinatorSchedule(mockNoopCoordinator, coordinator2); when(blockHeader.getNumber()).thenReturn(GENESIS_BLOCK_NUMBER); diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobGas.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobGas.java index a64e79b19dd..9ac72b6d8ac 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobGas.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobGas.java @@ -16,6 +16,7 @@ import java.math.BigInteger; +import com.fasterxml.jackson.annotation.JsonValue; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.BaseUInt64Value; import org.apache.tuweni.units.bigints.UInt64; @@ -123,6 +124,7 @@ public BigInteger getAsBigInteger() { return toBigInteger(); } + @JsonValue @Override public String toHexString() { return super.toHexString(); @@ -140,6 +142,6 @@ public String toShortHexString() { * @return the blob gas */ public static BlobGas fromQuantity(final Quantity quantity) { - return BlobGas.wrap((Bytes) quantity); + return BlobGas.of(quantity.getAsBigInteger()); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/ChainPrunerConfiguration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/ChainPrunerConfiguration.java index 19e2e37b363..67ad7f0a277 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/ChainPrunerConfiguration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/ChainPrunerConfiguration.java @@ -16,15 +16,20 @@ public class ChainPrunerConfiguration { public static final ChainPrunerConfiguration DEFAULT = - new ChainPrunerConfiguration(false, 7200, 256); + new ChainPrunerConfiguration(false, 7200, 7200, 256); private final boolean enabled; private final long blocksRetained; private final long blocksFrequency; + private final long blocksRetainedLimit; 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.blocksRetained = blocksRetained; + this.blocksRetainedLimit = blocksRetainedLimit; this.blocksFrequency = blocksFrequency; } @@ -32,6 +37,10 @@ public long getChainPruningBlocksRetained() { return blocksRetained; } + public long getBlocksRetainedLimit() { + return blocksRetainedLimit; + } + public boolean getChainPruningEnabled() { return enabled; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java index 0515deeb005..032ccb9f21f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java @@ -469,7 +469,8 @@ public synchronized void unsafeSetChainHead( updater.commit(); } - private Difficulty calculateTotalDifficulty(final BlockHeader blockHeader) { + @Override + public Difficulty calculateTotalDifficulty(final BlockHeader blockHeader) { if (blockHeader.getNumber() == BlockHeader.GENESIS_BLOCK_NUMBER) { return blockHeader.getDifficulty(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/MutableBlockchain.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/MutableBlockchain.java index da42e25afc3..5213974be31 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/MutableBlockchain.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/MutableBlockchain.java @@ -56,6 +56,8 @@ void unsafeImportBlock( void unsafeSetChainHead(final BlockHeader blockHeader, final Difficulty totalDifficulty); + Difficulty calculateTotalDifficulty(final BlockHeader blockHeader); + /** * Rolls back the canonical chainhead to the specified block number. * diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java index f12024e11a1..46d2f0847a3 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java @@ -309,7 +309,7 @@ public static org.hyperledger.besu.ethereum.core.BlockHeader convertPluginBlockH .map(h -> Hash.fromHexString(h.toHexString())) .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 .getRequestsRoot() diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java index 79855c1e52c..78bcb417e37 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.forest.storage.ForestWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.forest.worldview.ForestMutableWorldState; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; @@ -72,7 +73,8 @@ private static MutableWorldState createGenesisBonsaiWorldState() { bonsaiCachedMerkleTrieLoader, new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage), new NoOpTrieLogManager(), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); } /** diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java index d08821ca2ac..e4b7ea991f3 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -54,8 +55,11 @@ public BonsaiWorldStateProvider( super(worldStateKeyValueStorage, blockchain, maxLayersToLoad, pluginContext); this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; provideCachedWorldStorageManager( - new BonsaiCachedWorldStorageManager(this, worldStateKeyValueStorage)); - loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration)); + new BonsaiCachedWorldStorageManager( + this, worldStateKeyValueStorage, this::cloneBonsaiWorldStateConfig)); + loadPersistedState( + new BonsaiWorldState( + this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig)); } @VisibleForTesting @@ -69,14 +73,16 @@ public BonsaiWorldStateProvider( super(worldStateKeyValueStorage, blockchain, trieLogManager); this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; provideCachedWorldStorageManager(bonsaiCachedWorldStorageManager); - loadPersistedState(new BonsaiWorldState(this, worldStateKeyValueStorage, evmConfiguration)); + loadPersistedState( + new BonsaiWorldState( + this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig)); } public BonsaiCachedMerkleTrieLoader getCachedMerkleTrieLoader() { return bonsaiCachedMerkleTrieLoader; } - private BonsaiWorldStateKeyValueStorage getWorldStateKeyValueStorage() { + private BonsaiWorldStateKeyValueStorage getBonsaiWorldStateKeyValueStorage() { return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage; } @@ -89,13 +95,13 @@ private BonsaiWorldStateKeyValueStorage getWorldStateKeyValueStorage() { public void prepareStateHealing(final Address address, final Bytes location) { final Set keysToDelete = new HashSet<>(); final BonsaiWorldStateKeyValueStorage.Updater updater = - getWorldStateKeyValueStorage().updater(); + getBonsaiWorldStateKeyValueStorage().updater(); final Hash accountHash = address.addressHash(); final StoredMerklePatriciaTrie accountTrie = new StoredMerklePatriciaTrie<>( (l, h) -> { final Optional node = - getWorldStateKeyValueStorage().getAccountStateTrieNode(l, h); + getBonsaiWorldStateKeyValueStorage().getAccountStateTrieNode(l, h); if (node.isPresent()) { keysToDelete.add(l); } @@ -115,7 +121,7 @@ public void prepareStateHealing(final Address address, final Bytes location) { new StoredMerklePatriciaTrie<>( (l, h) -> { Optional node = - getWorldStateKeyValueStorage() + getBonsaiWorldStateKeyValueStorage() .getAccountStorageTrieNode(accountHash, l, h); if (node.isPresent()) { keysToDelete.add(Bytes.concatenate(accountHash, l)); @@ -139,6 +145,10 @@ public void prepareStateHealing(final Address address, final Bytes location) { keysToDelete.forEach(updater::removeAccountStateTrieNode); updater.commit(); - getWorldStateKeyValueStorage().downgradeToPartialFlatDbMode(); + getBonsaiWorldStateKeyValueStorage().downgradeToPartialFlatDbMode(); + } + + private DiffBasedWorldStateConfig cloneBonsaiWorldStateConfig() { + return new DiffBasedWorldStateConfig(defaultWorldStateConfig); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java index cb081ea8785..60cf25e880c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/BonsaiCachedWorldStorageManager.java @@ -23,14 +23,18 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import java.util.function.Supplier; + public class BonsaiCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager { public BonsaiCachedWorldStorageManager( final BonsaiWorldStateProvider archive, - final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) { - super(archive, worldStateKeyValueStorage); + final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, + final Supplier defaultBonsaiWorldStateConfigSupplier) { + super(archive, worldStateKeyValueStorage, defaultBonsaiWorldStateConfigSupplier); } @Override @@ -41,7 +45,8 @@ public DiffBasedWorldState createWorldState( return new BonsaiWorldState( (BonsaiWorldStateProvider) archive, (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage, - evmConfiguration); + evmConfiguration, + defaultBonsaiWorldStateConfigSupplier.get()); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java index daecab0e483..a054b437037 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/cache/NoOpBonsaiCachedWorldStorageManager.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; 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.DiffBasedWorldStateConfig; import java.util.Optional; import java.util.function.Function; @@ -26,7 +27,7 @@ public class NoOpBonsaiCachedWorldStorageManager extends BonsaiCachedWorldStorag public NoOpBonsaiCachedWorldStorageManager( final BonsaiWorldStateKeyValueStorage bonsaiWorldStateKeyValueStorage) { - super(null, bonsaiWorldStateKeyValueStorage); + super(null, bonsaiWorldStateKeyValueStorage, DiffBasedWorldStateConfig::new); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java index 5934f88f2a2..2437118d640 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/storage/BonsaiSnapshotWorldStateKeyValueStorage.java @@ -203,6 +203,15 @@ public void onClearTrieLog() { } } + @Override + public void onClearTrie() { + try { + doClose(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + @Override protected synchronized void doClose() throws Exception { if (!isClosedGet()) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java index 30b3d8440bc..ad838aa528d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldState.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.trie.MerkleTrie; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; +import org.hyperledger.besu.ethereum.trie.NoOpMerkleTrie; import org.hyperledger.besu.ethereum.trie.NodeLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiAccount; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider; @@ -34,6 +35,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.preload.StorageConsumingMap; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; @@ -63,13 +65,15 @@ public class BonsaiWorldState extends DiffBasedWorldState { public BonsaiWorldState( final BonsaiWorldStateProvider archive, final BonsaiWorldStateKeyValueStorage worldStateKeyValueStorage, - final EvmConfiguration evmConfiguration) { + final EvmConfiguration evmConfiguration, + final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { this( worldStateKeyValueStorage, archive.getCachedMerkleTrieLoader(), archive.getCachedWorldStorageManager(), archive.getTrieLogManager(), - evmConfiguration); + evmConfiguration, + diffBasedWorldStateConfig); } public BonsaiWorldState( @@ -77,21 +81,32 @@ public BonsaiWorldState( final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader, final DiffBasedCachedWorldStorageManager cachedWorldStorageManager, final TrieLogManager trieLogManager, - final EvmConfiguration evmConfiguration) { - super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager); + final EvmConfiguration evmConfiguration, + final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { + super( + worldStateKeyValueStorage, + cachedWorldStorageManager, + trieLogManager, + diffBasedWorldStateConfig); this.bonsaiCachedMerkleTrieLoader = bonsaiCachedMerkleTrieLoader; + this.worldStateKeyValueStorage = worldStateKeyValueStorage; this.setAccumulator( new BonsaiWorldStateUpdateAccumulator( this, (addr, value) -> bonsaiCachedMerkleTrieLoader.preLoadAccount( - worldStateKeyValueStorage, worldStateRootHash, addr), + getWorldStateStorage(), worldStateRootHash, addr), (addr, value) -> - bonsaiCachedMerkleTrieLoader.preLoadStorageSlot( + this.bonsaiCachedMerkleTrieLoader.preLoadStorageSlot( getWorldStateStorage(), addr, value), evmConfiguration)); } + @Override + public Optional getCode(@Nonnull final Address address, final Hash codeHash) { + return getWorldStateStorage().getCode(codeHash, address.addressHash()); + } + @Override public BonsaiWorldStateKeyValueStorage getWorldStateStorage() { return (BonsaiWorldStateKeyValueStorage) worldStateKeyValueStorage; @@ -129,7 +144,7 @@ private Hash internalCalculateRootHash( updateCode(maybeStateUpdater, worldStateUpdater); // next walk the account trie - final StoredMerklePatriciaTrie accountTrie = + final MerkleTrie accountTrie = createTrie( (location, hash) -> bonsaiCachedMerkleTrieLoader.getAccountStateTrieNode( @@ -157,7 +172,7 @@ private Hash internalCalculateRootHash( private void updateTheAccounts( final Optional maybeStateUpdater, final BonsaiWorldStateUpdateAccumulator worldStateUpdater, - final StoredMerklePatriciaTrie accountTrie) { + final MerkleTrie accountTrie) { for (final Map.Entry> accountUpdate : worldStateUpdater.getAccountsToUpdate().entrySet()) { final Bytes accountKey = accountUpdate.getKey(); @@ -234,7 +249,7 @@ private void updateAccountStorageState( || worldStateUpdater.getStorageToClear().contains(updatedAddress)) ? Hash.EMPTY_TRIE_HASH : accountOriginal.getStorageRoot(); - final StoredMerklePatriciaTrie storageTrie = + final MerkleTrie storageTrie = createTrie( (location, key) -> bonsaiCachedMerkleTrieLoader.getAccountStorageTrieNode( @@ -277,8 +292,11 @@ private void updateAccountStorageState( (location, key, value) -> writeStorageTrieNode( bonsaiUpdater, updatedAddressHash, location, key, value))); - final Hash newStorageRoot = Hash.wrap(storageTrie.getRootHash()); - accountUpdated.setStorageRoot(newStorageRoot); + // only use storage root of the trie when trie is enabled + if (!worldStateConfig.isTrieDisabled()) { + final Hash newStorageRoot = Hash.wrap(storageTrie.getRootHash()); + accountUpdated.setStorageRoot(newStorageRoot); + } } } // for manicured tries and composting, trim and compost here @@ -347,13 +365,6 @@ public Hash frontierRootHash() { accumulator.copy()); } - @Override - public MutableWorldState freeze() { - this.isFrozen = true; - this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage()); - return this; - } - @Override public Account get(final Address address) { return getWorldStateStorage() @@ -362,11 +373,6 @@ public Account get(final Address address) { .orElse(null); } - @Override - public Optional getCode(@Nonnull final Address address, final Hash codeHash) { - return getWorldStateStorage().getCode(codeHash, address.addressHash()); - } - protected Optional getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) { return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash); } @@ -423,16 +429,26 @@ public UInt256 getPriorStorageValue(final Address address, final UInt256 storage @Override public Map getAllAccountStorage(final Address address, final Hash rootHash) { - final StoredMerklePatriciaTrie storageTrie = + final MerkleTrie storageTrie = createTrie( (location, key) -> getStorageTrieNode(address.addressHash(), location, key), rootHash); return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE); } - private StoredMerklePatriciaTrie createTrie( - final NodeLoader nodeLoader, final Bytes32 rootHash) { - return new StoredMerklePatriciaTrie<>( - nodeLoader, rootHash, Function.identity(), Function.identity()); + @Override + public MutableWorldState freeze() { + this.worldStateConfig.setFrozen(true); + this.worldStateKeyValueStorage = new BonsaiWorldStateLayerStorage(getWorldStateStorage()); + return this; + } + + private MerkleTrie 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) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java index ad7b06b149a..857ec0b079d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; @@ -54,6 +55,7 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive { protected DiffBasedWorldState persistedState; protected final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage; + protected final DiffBasedWorldStateConfig defaultWorldStateConfig; public DiffBasedWorldStateProvider( final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, @@ -70,6 +72,7 @@ public DiffBasedWorldStateProvider( maxLayersToLoad.orElse(DiffBasedCachedWorldStorageManager.RETAINED_LAYERS), pluginContext); this.blockchain = blockchain; + this.defaultWorldStateConfig = new DiffBasedWorldStateConfig(); } public DiffBasedWorldStateProvider( @@ -81,6 +84,7 @@ public DiffBasedWorldStateProvider( // TODO: de-dup constructors this.trieLogManager = trieLogManager; this.blockchain = blockchain; + this.defaultWorldStateConfig = new DiffBasedWorldStateConfig(); } protected void provideCachedWorldStorageManager( @@ -252,6 +256,19 @@ public MutableWorldState getMutable() { return persistedState; } + public DiffBasedWorldStateConfig getDefaultWorldStateConfig() { + return defaultWorldStateConfig; + } + + public void disableTrie() { + defaultWorldStateConfig.setTrieDisabled(true); + worldStateKeyValueStorage.clearTrie(); + } + + public DiffBasedWorldStateKeyValueStorage getWorldStateKeyValueStorage() { + return worldStateKeyValueStorage; + } + public TrieLogManager getTrieLogManager() { return trieLogManager; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/StorageSubscriber.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/StorageSubscriber.java index 51ab65bd16c..258df5c5b9c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/StorageSubscriber.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/StorageSubscriber.java @@ -21,5 +21,7 @@ default void onClearFlatDatabaseStorage() {} default void onClearTrieLog() {} + default void onClearTrie() {} + default void onCloseStorage() {} } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java index 8ead22bf5bf..160c7ac1e3e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/cache/DiffBasedCachedWorldStorageManager.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.evm.internal.EvmConfiguration; import java.util.ArrayList; @@ -33,6 +34,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.function.Supplier; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; @@ -46,6 +48,7 @@ public abstract class DiffBasedCachedWorldStorageManager implements StorageSubsc LoggerFactory.getLogger(DiffBasedCachedWorldStorageManager.class); private final DiffBasedWorldStateProvider archive; private final EvmConfiguration evmConfiguration; + protected final Supplier defaultBonsaiWorldStateConfigSupplier; private final Cache stateRootToBlockHeaderCache = Caffeine.newBuilder() .maximumSize(RETAINED_LAYERS) @@ -59,18 +62,26 @@ private DiffBasedCachedWorldStorageManager( final DiffBasedWorldStateProvider archive, final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final Map cachedWorldStatesByHash, - final EvmConfiguration evmConfiguration) { + final EvmConfiguration evmConfiguration, + final Supplier defaultBonsaiWorldStateConfigSupplier) { worldStateKeyValueStorage.subscribe(this); this.rootWorldStateStorage = worldStateKeyValueStorage; this.cachedWorldStatesByHash = cachedWorldStatesByHash; this.archive = archive; this.evmConfiguration = evmConfiguration; + this.defaultBonsaiWorldStateConfigSupplier = defaultBonsaiWorldStateConfigSupplier; } public DiffBasedCachedWorldStorageManager( final DiffBasedWorldStateProvider archive, - final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) { - this(archive, worldStateKeyValueStorage, new ConcurrentHashMap<>(), EvmConfiguration.DEFAULT); + final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, + final Supplier defaultBonsaiWorldStateConfigSupplier) { + this( + archive, + worldStateKeyValueStorage, + new ConcurrentHashMap<>(), + EvmConfiguration.DEFAULT, + defaultBonsaiWorldStateConfigSupplier); } public synchronized void addCachedLayer( @@ -263,6 +274,11 @@ public void onClearTrieLog() { this.cachedWorldStatesByHash.clear(); } + @Override + public void onClearTrie() { + this.cachedWorldStatesByHash.clear(); + } + @Override public void onCloseStorage() { this.cachedWorldStatesByHash.clear(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedWorldStateKeyValueStorage.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedWorldStateKeyValueStorage.java index af568035451..84441ca05fb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedWorldStateKeyValueStorage.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/storage/DiffBasedWorldStateKeyValueStorage.java @@ -174,6 +174,11 @@ public void clearTrieLog() { trieLogStorage.clear(); } + public void clearTrie() { + subscribers.forEach(StorageSubscriber::onClearTrie); + composedWorldStateStorage.clear(TRIE_BRANCH_STORAGE); + } + public void clearFlatDatabase() { subscribers.forEach(StorageSubscriber::onClearFlatDatabaseStorage); getFlatDbStrategy().resetOnResync(composedWorldStateStorage); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java index 9ae6cb38f81..70d45f546db 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java @@ -34,6 +34,7 @@ import java.util.stream.LongStream; import java.util.stream.Stream; +import org.apache.tuweni.bytes.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -147,15 +148,46 @@ private TrieLogFactory setupTrieLogFactory(final BesuContext pluginContext) { trieLogService.getObservers().forEach(trieLogObservers::subscribe); // return the TrieLogFactory implementation from the TrieLogService - return trieLogService.getTrieLogFactory(); - } else { - // Otherwise default to TrieLogFactoryImpl - return new TrieLogFactoryImpl(); + if (trieLogService.getTrieLogFactory().isPresent()) { + return trieLogService.getTrieLogFactory().get(); + } } + // Otherwise default to TrieLogFactoryImpl + return new TrieLogFactoryImpl(); } private TrieLogProvider getTrieLogProvider() { return new TrieLogProvider() { + @Override + public Optional getRawTrieLogLayer(final Hash blockHash) { + return rootWorldStateStorage.getTrieLog(blockHash).map(Bytes::wrap); + } + + @Override + public Optional 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 public Optional getTrieLogLayer(final Hash blockHash) { return TrieLogManager.this.getTrieLogLayer(blockHash); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java index db536cbc7a7..76a8fbd6377 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldState.java @@ -60,12 +60,13 @@ public abstract class DiffBasedWorldState protected Hash worldStateRootHash; protected Hash worldStateBlockHash; - protected boolean isFrozen; + protected DiffBasedWorldStateConfig worldStateConfig; protected DiffBasedWorldState( final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedCachedWorldStorageManager cachedWorldStorageManager, - final TrieLogManager trieLogManager) { + final TrieLogManager trieLogManager, + final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { this.worldStateKeyValueStorage = worldStateKeyValueStorage; this.worldStateRootHash = Hash.wrap( @@ -76,11 +77,12 @@ protected DiffBasedWorldState( Bytes32.wrap(worldStateKeyValueStorage.getWorldStateBlockHash().orElse(Hash.ZERO))); this.cachedWorldStorageManager = cachedWorldStorageManager; this.trieLogManager = trieLogManager; + this.worldStateConfig = diffBasedWorldStateConfig; } /** * 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. */ @@ -134,6 +136,15 @@ public DiffBasedWorldStateUpdateAccumulator getAccumulator() { 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 public void persist(final BlockHeader blockHeader) { final Optional maybeBlockHeader = Optional.ofNullable(blockHeader); @@ -151,19 +162,32 @@ public void persist(final BlockHeader blockHeader) { Runnable saveTrieLog = () -> {}; try { - final Hash newWorldStateRootHash = - calculateRootHash(isFrozen ? Optional.empty() : Optional.of(stateUpdater), accumulator); + final Hash calculatedRootHash; + + 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 // then persist the TrieLog for that transition. // If specified but not a direct descendant simply store the new block hash. if (blockHeader != null) { - verifyWorldStateRoot(newWorldStateRootHash, blockHeader); + verifyWorldStateRoot(calculatedRootHash, blockHeader); saveTrieLog = () -> { - trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this); + trieLogManager.saveTrieLog(localCopy, calculatedRootHash, blockHeader, this); // not save a frozen state in the cache - if (!isFrozen) { - cachedWorldStorageManager.addCachedLayer(blockHeader, newWorldStateRootHash, this); + if (!worldStateConfig.isFrozen()) { + cachedWorldStorageManager.addCachedLayer(blockHeader, calculatedRootHash, this); } }; @@ -178,8 +202,8 @@ public void persist(final BlockHeader blockHeader) { stateUpdater .getWorldStateTransaction() - .put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, newWorldStateRootHash.toArrayUnsafe()); - worldStateRootHash = newWorldStateRootHash; + .put(TRIE_BRANCH_STORAGE, WORLD_ROOT_HASH_KEY, calculatedRootHash.toArrayUnsafe()); + worldStateRootHash = calculatedRootHash; success = true; } finally { if (success) { @@ -194,7 +218,7 @@ public void persist(final BlockHeader blockHeader) { } protected void verifyWorldStateRoot(final Hash calculatedStateRoot, final BlockHeader header) { - if (!calculatedStateRoot.equals(header.getStateRoot())) { + if (!worldStateConfig.isTrieDisabled() && !calculatedStateRoot.equals(header.getStateRoot())) { throw new RuntimeException( "World State Root does not match expected value, header " + header.getStateRoot().toHexString() @@ -210,7 +234,7 @@ public WorldUpdater updater() { @Override public Hash rootHash() { - if (isFrozen && accumulator.isAccumulatorStateChanged()) { + if (worldStateConfig.isFrozen() && accumulator.isAccumulatorStateChanged()) { worldStateRootHash = calculateRootHash(Optional.empty(), accumulator.copy()); accumulator.resetAccumulatorStateChanged(); } @@ -285,7 +309,7 @@ public void close() { try { if (!isPersisted()) { this.worldStateKeyValueStorage.close(); - if (isFrozen) { + if (worldStateConfig.isFrozen()) { closeFrozenStorage(); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java new file mode 100644 index 00000000000..cab7f3f8736 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/DiffBasedWorldStateConfig.java @@ -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; + } +} diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java index 6af78e59903..6c84b29b478 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java @@ -46,6 +46,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; @@ -100,7 +101,8 @@ class BlockImportExceptionHandlingTest { (BonsaiWorldStateProvider) worldStateArchive, (BonsaiWorldStateKeyValueStorage) worldStateStorageCoordinator.worldStateKeyValueStorage(), - EvmConfiguration.DEFAULT)); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig())); private final BadBlockManager badBlockManager = new BadBlockManager(); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java index 78ab15eb686..556e4edefc7 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/ChainDataPrunerTest.java @@ -48,6 +48,7 @@ public void singleChainPruning() { new ChainDataPrunerStorage(new InMemoryKeyValueStorage()), 512, 0, + // completed new BlockingExecutor()); Block genesisBlock = gen.genesisBlock(); final MutableBlockchain blockchain = @@ -87,6 +88,7 @@ public void forkPruning() { new ChainDataPrunerStorage(new InMemoryKeyValueStorage()), 512, 0, + // completed new BlockingExecutor()); Block genesisBlock = gen.genesisBlock(); final MutableBlockchain blockchain = diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java index 0dee834f1cb..d9b9d5d1955 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java @@ -199,6 +199,16 @@ protected StorageProvider createKeyValueStorageProvider() { .withCommonConfiguration( new BesuConfiguration() { + @Override + public Optional getRpcHttpHost() { + return Optional.empty(); + } + + @Override + public Optional getRpcHttpPort() { + return Optional.empty(); + } + @Override public Path getStoragePath() { return tempData.resolve("database"); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java index 5c0dbbf7259..e43d464474c 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/LogRollingTests.java @@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -162,7 +163,8 @@ void simpleRollForwardTest() { archive, new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -178,7 +180,8 @@ provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFI secondProvider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final BonsaiWorldStateUpdateAccumulator secondUpdater = (BonsaiWorldStateUpdateAccumulator) secondWorldState.updater(); @@ -210,7 +213,8 @@ void rollForwardTwice() { archive, new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -234,7 +238,8 @@ provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFI secondProvider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final BonsaiWorldStateUpdateAccumulator secondUpdater = (BonsaiWorldStateUpdateAccumulator) secondWorldState.updater(); @@ -267,7 +272,8 @@ void rollBackOnce() { archive, new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -298,7 +304,8 @@ provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFI secondProvider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater secondUpdater = secondWorldState.updater(); final MutableAccount secondMutableAccount = diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java index 0c2c1898927..09e21138fd3 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/RollingImport.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogLayer; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -57,7 +58,8 @@ public static void main(final String[] arg) throws IOException { archive, new BonsaiWorldStateKeyValueStorage( provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final SegmentedInMemoryKeyValueStorage worldStateKeyValueStorage = (SegmentedInMemoryKeyValueStorage) provider.getStorageBySegmentIdentifiers( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java index 0757b40dbbb..b342172b1ba 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/worldview/BonsaiWorldStateTest.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; 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.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.evm.internal.EvmConfiguration; import java.util.HashMap; @@ -61,7 +62,8 @@ void setup() { new BonsaiWorldState( InMemoryKeyValueStorageProvider.createBonsaiInMemoryWorldStateArchive(blockchain), bonsaiWorldStateKeyValueStorage, - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); } @ParameterizedTest diff --git a/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java b/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java index 1fc9046ec72..04d4af81a94 100644 --- a/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java +++ b/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java @@ -24,7 +24,6 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockHeader; 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.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; @@ -165,8 +164,7 @@ public Optional downloadWorldState() { private StorageProvider createKeyValueStorageProvider(final Path dataDir, final Path dbDir) { final var besuConfiguration = new BesuConfigurationImpl(); - besuConfiguration.init( - dataDir, dbDir, DataStorageConfiguration.DEFAULT_CONFIG, MiningParameters.newDefault()); + besuConfiguration.init(dataDir, dbDir, DataStorageConfiguration.DEFAULT_CONFIG); return new KeyValueStorageProviderBuilder() .withStorageFactory( new RocksDBKeyValueStorageFactory( diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java index 9c6b9327e4b..f5b5f978cb3 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java @@ -28,6 +28,7 @@ import java.time.Duration; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +37,8 @@ public abstract class AbstractSyncTargetManager { private static final Logger LOG = LoggerFactory.getLogger(AbstractSyncTargetManager.class); + private final AtomicBoolean cancelled = new AtomicBoolean(false); + private final SynchronizerConfiguration config; private final ProtocolSchedule protocolSchedule; private final ProtocolContext protocolContext; @@ -56,6 +59,9 @@ protected AbstractSyncTargetManager( } public CompletableFuture findSyncTarget() { + if (isCancelled()) { + return completedFuture(null); + } return selectBestAvailableSyncTarget() .thenCompose( maybeBestPeer -> { @@ -99,6 +105,10 @@ public CompletableFuture findSyncTarget() { }); } + public synchronized void cancel() { + cancelled.set(true); + } + protected Optional finalizeSelectedSyncTarget(final SyncTarget syncTarget) { return Optional.of(syncTarget); } @@ -115,5 +125,9 @@ private CompletableFuture waitForNewPeer() { .timeout(WaitForPeerTask.create(ethContext, metricsSystem), Duration.ofSeconds(5)); } + private boolean isCancelled() { + return cancelled.get(); + } + public abstract boolean shouldContinueDownloading(); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PipelineChainDownloader.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PipelineChainDownloader.java index e40b28efad6..bfec1435ce4 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PipelineChainDownloader.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/PipelineChainDownloader.java @@ -85,6 +85,7 @@ public CompletableFuture start() { @Override public synchronized void cancel() { cancelled.set(true); + syncTargetManager.cancel(); if (currentDownloadPipeline != null) { currentDownloadPipeline.abort(); } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java index 017320aca1a..fe229dc3cf3 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java @@ -87,7 +87,7 @@ String provideKeyValueStorageName() { @Singleton BesuConfiguration provideBesuConfiguration() { 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; } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/PeerDiscoveryController.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/PeerDiscoveryController.java index 8eb07e43385..5d0fee18453 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/PeerDiscoveryController.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/PeerDiscoveryController.java @@ -260,6 +260,7 @@ public CompletableFuture stop() { l.clear(); }); inflightInteractions.clear(); + recursivePeerRefreshState.cancel(); return CompletableFuture.completedFuture(null); } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/RecursivePeerRefreshState.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/RecursivePeerRefreshState.java index 0f3073dfd19..3329dad4ce8 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/RecursivePeerRefreshState.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/internal/RecursivePeerRefreshState.java @@ -105,6 +105,10 @@ private void addInitialPeers(final List initialPeers) { } private void bondingInitiateRound() { + if (!iterativeSearchInProgress) { + // cancelled so we can ignore + return; + } currentRoundTimeout.ifPresent(RoundTimeout::cancelTimeout); final List candidates = bondingRoundCandidates(); if (candidates.isEmpty()) { @@ -137,6 +141,10 @@ private void performIfNotCancelled(final Runnable action, final AtomicBoolean ca } private void bondingCancelOutstandingRequests() { + if (!iterativeSearchInProgress) { + // cancelled so we can ignore + return; + } LOG.debug("Bonding round timed out"); for (final Map.Entry entry : oneTrueMap.entrySet()) { final MetadataPeer metadataPeer = entry.getValue(); @@ -149,6 +157,10 @@ private void bondingCancelOutstandingRequests() { } private void neighboursInitiateRound() { + if (!iterativeSearchInProgress) { + // cancelled so we can ignore + return; + } currentRoundTimeout.ifPresent(RoundTimeout::cancelTimeout); final List candidates = neighboursRoundCandidates(); if (candidates.isEmpty() || reachedMaximumNumberOfRounds()) { @@ -172,6 +184,10 @@ private void neighboursInitiateRound() { } private void neighboursCancelOutstandingRequests() { + if (!iterativeSearchInProgress) { + // cancelled so we can ignore + return; + } LOG.debug("Neighbours round timed out"); for (final Map.Entry entry : oneTrueMap.entrySet()) { final MetadataPeer metadataPeer = entry.getValue(); @@ -218,6 +234,10 @@ void onNeighboursReceived(final DiscoveryPeer peer, final List pe } void onBondingComplete(final DiscoveryPeer peer) { + if (!iterativeSearchInProgress) { + // cancelled so we can ignore + return; + } final MetadataPeer iterationParticipant = oneTrueMap.get(peer.getId()); if (iterationParticipant == null) { return; diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java index 8acdea1170a..e374f5c020f 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BonsaiReferenceTestWorldState.java @@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogAddedEvent; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -66,7 +67,8 @@ protected BonsaiReferenceTestWorldState( bonsaiCachedMerkleTrieLoader, cachedWorldStorageManager, trieLogManager, - evmConfiguration); + evmConfiguration, + new DiffBasedWorldStateConfig()); this.refTestStorage = worldStateKeyValueStorage; this.preImageProxy = preImageProxy; this.evmConfiguration = evmConfiguration; @@ -194,7 +196,8 @@ private BonsaiWorldState createBonsaiWorldState(final boolean isFrozen) { bonsaiCachedMerkleTrieLoader, cachedWorldStorageManager, trieLogManager, - evmConfiguration); + evmConfiguration, + new DiffBasedWorldStateConfig()); if (isFrozen) { bonsaiWorldState.freeze(); // freeze state } diff --git a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/NoOpMerkleTrie.java b/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/NoOpMerkleTrie.java new file mode 100644 index 00000000000..53d0ac5b58a --- /dev/null +++ b/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/NoOpMerkleTrie.java @@ -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 The type of values of this trie. + */ +public class NoOpMerkleTrie implements MerkleTrie { + + public NoOpMerkleTrie() {} + + @Override + public Optional get(final K key) { + return Optional.empty(); + } + + @Override + public Optional getPath(final K path) { + return Optional.empty(); + } + + @Override + public Proof 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 putVisitor) { + // noop + } + + @Override + public void remove(final K key) { + // noop + } + + @Override + public void removePath(final K path, final PathNodeVisitor 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 commitVisitor) { + // Nothing to do here + } + + @Override + public Map entriesFrom(final Bytes32 startKeyHash, final int limit) { + return new HashMap<>(); + } + + @Override + public Map entriesFrom(final Function, Map> handler) { + return new HashMap<>(); + } + + @Override + public void visitAll(final Consumer> nodeConsumer) { + // noop + } + + @Override + public CompletableFuture visitAll( + final Consumer> nodeConsumer, final ExecutorService executorService) { + return CompletableFuture.completedFuture(null); + } + + @Override + public void visitLeafs(final TrieIterator.LeafHandler handler) { + // nopop + } +} diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index f61fe316bf3..e38237d7c3f 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -70,7 +70,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'xU0LMvStiFihBKBxkfNHB7oIg0PUHWkPuv2yt1GVC94=' + knownHash = 'wMhttXj2aWFgpN9msxHz/FwQVovpYRxNysnZEpwZYxg=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/BesuPlugin.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/BesuPlugin.java index 9c9dc44bf02..952f1fb074d 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/BesuPlugin.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/BesuPlugin.java @@ -63,6 +63,9 @@ default void beforeExternalServices() {} */ 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 * RPC endpoint. If not overridden this method does nothing for convenience. The plugin should diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuConfiguration.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuConfiguration.java index ca92a12430f..c10a697384f 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuConfiguration.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuConfiguration.java @@ -20,10 +20,25 @@ import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import java.nio.file.Path; +import java.util.Optional; /** Generally useful configuration provided by Besu. */ public interface BesuConfiguration extends BesuService { + /** + * Get the configured RPC http host. + * + * @return the configured RPC http host. + */ + Optional getRpcHttpHost(); + + /** + * Get the configured RPC http port. + * + * @return the configured RPC http port. + */ + Optional getRpcHttpPort(); + /** * Location of the working directory of the storage in the file system running the client. * diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuEvents.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuEvents.java index 911eff3b593..ab9c4eb782d 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuEvents.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BesuEvents.java @@ -93,6 +93,14 @@ public interface BesuEvents extends BesuService { */ 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. * diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BlockchainService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BlockchainService.java index af6d14f546c..69a2e6a8220 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BlockchainService.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BlockchainService.java @@ -17,9 +17,12 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; 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.BlockHeader; +import org.hyperledger.besu.plugin.data.TransactionReceipt; +import java.util.List; import java.util.Optional; /** A service that plugins can use to query blocks by number */ @@ -40,6 +43,23 @@ public interface BlockchainService extends BesuService { */ Hash getChainHeadHash(); + /** + * Get the receipts for a block by block hash + * + * @param blockHash the block hash + * @return the transaction receipts + */ + Optional> 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 receipts); + /** * 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 */ Optional getNextBlockBaseFee(); + + /** + * Get the block hash of the safe block + * + * @return the block hash of the safe block + */ + Optional getSafeBlock(); + + /** + * Get the block hash of the finalized block + * + * @return the block hash of the finalized block + */ + Optional getFinalizedBlock(); } diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TrieLogService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TrieLogService.java index 2c5c38c5498..5230d6a6642 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TrieLogService.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/TrieLogService.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.plugin.services.trielogs.TrieLogProvider; import java.util.List; +import java.util.Optional; /** * A service interface for registering observers for trie log events. @@ -39,7 +40,7 @@ public interface TrieLogService extends BesuService { * * @return the TrieLogFactory implementation */ - TrieLogFactory getTrieLogFactory(); + Optional getTrieLogFactory(); /** * Configure a TrieLogProvider implementation to use for retrieving stored TrieLogs. diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/p2p/P2PService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/p2p/P2PService.java new file mode 100644 index 00000000000..0e9e46e799a --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/p2p/P2PService.java @@ -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(); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rlp/RlpConverterService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rlp/RlpConverterService.java new file mode 100644 index 00000000000..016fab7fa46 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/rlp/RlpConverterService.java @@ -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); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/SynchronizationService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/SynchronizationService.java new file mode 100644 index 00000000000..ad9682429d0 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/SynchronizationService.java @@ -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(); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java new file mode 100644 index 00000000000..3f66ffb86e1 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/sync/WorldStateConfiguration.java @@ -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(); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/transactionpool/TransactionPoolService.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/transactionpool/TransactionPoolService.java new file mode 100644 index 00000000000..01b1f5768b3 --- /dev/null +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/transactionpool/TransactionPoolService.java @@ -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(); +} diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/trielogs/TrieLogProvider.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/trielogs/TrieLogProvider.java index 86a9906cf08..b20e73283cb 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/trielogs/TrieLogProvider.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/services/trielogs/TrieLogProvider.java @@ -19,8 +19,19 @@ import java.util.List; import java.util.Optional; +import org.apache.tuweni.bytes.Bytes; + /** Trielog provider interface for a given block hash. */ 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. * @@ -30,6 +41,14 @@ public interface TrieLogProvider { */ > Optional 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 getRawTrieLogLayer(final Hash blockHash); + /** * Returns the TrieLog layer for the given block number. * @@ -39,6 +58,14 @@ public interface TrieLogProvider { */ > Optional 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 getRawTrieLogLayer(final long blockNumber); + /** * Returns the TrieLog layers for the given block number range. * From 5415463a33c3a662b118b19948a89fbb333da963 Mon Sep 17 00:00:00 2001 From: Gabriel-Trintinalia Date: Fri, 24 May 2024 04:55:51 +1000 Subject: [PATCH 02/42] Rename methods and variables to match json (#7134) Signed-off-by: Gabriel-Trintinalia --- .../parameters/WithdrawalRequestParameter.java | 4 ++-- .../besu/ethereum/core/WithdrawalRequest.java | 18 +++++++++--------- .../encoding/WithdrawalRequestEncoder.java | 2 +- .../WithdrawalRequestContractHelper.java | 4 ++-- .../WithdrawalRequestContractHelperTest.java | 5 +++-- plugin-api/build.gradle | 2 +- .../besu/plugin/data/WithdrawalRequest.java | 2 +- 7 files changed, 19 insertions(+), 18 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java index d4786e18072..79c0251e838 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java @@ -45,7 +45,7 @@ public static WithdrawalRequestParameter fromWithdrawalRequest( final WithdrawalRequest withdrawalRequest) { return new WithdrawalRequestParameter( withdrawalRequest.getSourceAddress().toHexString(), - withdrawalRequest.getValidatorPubKey().toHexString(), + withdrawalRequest.getValidatorPublicKey().toHexString(), withdrawalRequest.getAmount().toShortHexString()); } @@ -92,7 +92,7 @@ public String toString() { + "sourceAddress='" + sourceAddress + '\'' - + ", validatorPubKey='" + + ", validatorPublicKey='" + validatorPublicKey + '\'' + ", amount='" diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/WithdrawalRequest.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/WithdrawalRequest.java index c9dbd0df67b..decdf22c736 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/WithdrawalRequest.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/WithdrawalRequest.java @@ -26,13 +26,13 @@ public class WithdrawalRequest extends Request implements org.hyperledger.besu.plugin.data.WithdrawalRequest { private final Address sourceAddress; - private final BLSPublicKey validatorPubKey; + private final BLSPublicKey validatorPublicKey; private final GWei amount; public WithdrawalRequest( - final Address sourceAddress, final BLSPublicKey validatorPubKey, final GWei amount) { + final Address sourceAddress, final BLSPublicKey validatorPublicKey, final GWei amount) { this.sourceAddress = sourceAddress; - this.validatorPubKey = validatorPubKey; + this.validatorPublicKey = validatorPublicKey; this.amount = amount; } @@ -47,8 +47,8 @@ public Address getSourceAddress() { } @Override - public PublicKey getValidatorPubKey() { - return validatorPubKey; + public PublicKey getValidatorPublicKey() { + return validatorPublicKey; } @Override @@ -61,8 +61,8 @@ public String toString() { return "WithdrawalRequest{" + "sourceAddress=" + sourceAddress - + " validatorPubKey=" - + validatorPubKey + + " validatorPublicKey=" + + validatorPublicKey + " amount=" + amount + '}'; @@ -78,12 +78,12 @@ public boolean equals(final Object o) { } final WithdrawalRequest that = (WithdrawalRequest) o; return Objects.equals(sourceAddress, that.sourceAddress) - && Objects.equals(validatorPubKey, that.validatorPubKey) + && Objects.equals(validatorPublicKey, that.validatorPublicKey) && Objects.equals(amount, that.amount); } @Override public int hashCode() { - return Objects.hash(sourceAddress, validatorPubKey, amount); + return Objects.hash(sourceAddress, validatorPublicKey, amount); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoder.java index 2a8fbb6eee4..26be22d4882 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoder.java @@ -48,7 +48,7 @@ private static void encodeWithdrawalRequest( final WithdrawalRequest withdrawalRequest, final RLPOutput rlpOutput) { rlpOutput.startList(); rlpOutput.writeBytes(withdrawalRequest.getSourceAddress()); - rlpOutput.writeBytes(withdrawalRequest.getValidatorPubKey()); + rlpOutput.writeBytes(withdrawalRequest.getValidatorPublicKey()); rlpOutput.writeUInt64Scalar(withdrawalRequest.getAmount()); rlpOutput.endList(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java index 5ef0a699893..3cbe952d004 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java @@ -150,7 +150,7 @@ private static List peekExpectedWithdrawalRequests( queueHeadIndex.plus(i).multiply(WITHDRAWAL_REQUEST_STORAGE_SLOT_SIZE)); final Address sourceAddress = Address.wrap(account.getStorageValue(queueStorageSlot).toBytes().slice(12, 20)); - final BLSPublicKey validatorPubKey = + final BLSPublicKey validatorPublicKey = BLSPublicKey.wrap( Bytes.concatenate( account @@ -162,7 +162,7 @@ private static List peekExpectedWithdrawalRequests( UInt64.fromBytes(account.getStorageValue(queueStorageSlot.plus(2)).slice(16, 8)); withdrawalRequests.add( - new WithdrawalRequest(sourceAddress, validatorPubKey, GWei.of(amount))); + new WithdrawalRequest(sourceAddress, validatorPublicKey, GWei.of(amount))); } return withdrawalRequests; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelperTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelperTest.java index 1c0485b5982..6d21744e7bd 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelperTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelperTest.java @@ -186,13 +186,14 @@ private void loadContractStorage( Bytes.fromHexString("0x000000000000000000000000"), request.getSourceAddress()))); // validator_pubkey contract.setStorageValue( - UInt256.valueOf(offset++), UInt256.fromBytes(request.getValidatorPubKey().slice(0, 32))); + UInt256.valueOf(offset++), + UInt256.fromBytes(request.getValidatorPublicKey().slice(0, 32))); contract.setStorageValue( // set public key to slot, with 16 bytes padding on the right UInt256.valueOf(offset++), UInt256.fromBytes( Bytes.concatenate( - request.getValidatorPubKey().slice(32, 16), + request.getValidatorPublicKey().slice(32, 16), request.getAmount().toBytes(), // 8 bytes for amount Bytes.fromHexString("0x0000000000000000")))); } diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index e38237d7c3f..a25774205b7 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -70,7 +70,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'wMhttXj2aWFgpN9msxHz/FwQVovpYRxNysnZEpwZYxg=' + knownHash = 'zgPAgf+ZxefbnCE9aYEQ5QoeBVsHySi3u+BlhHNHqn8=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/WithdrawalRequest.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/WithdrawalRequest.java index 7f9f5d15e09..eeadd80418d 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/WithdrawalRequest.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/WithdrawalRequest.java @@ -38,7 +38,7 @@ public interface WithdrawalRequest { * * @return public key of validator */ - PublicKey getValidatorPubKey(); + PublicKey getValidatorPublicKey(); /** * The amount for withdrawal From a31ffc9b032355c7fa1a31c28ea0a649bb64235f Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Fri, 24 May 2024 00:38:23 +0200 Subject: [PATCH 03/42] Update Gradle plugins (#7137) Signed-off-by: Fabio Di Fabio --- build.gradle | 10 +- gradle/verification-metadata.xml | 1103 +++--------------------------- 2 files changed, 116 insertions(+), 997 deletions(-) diff --git a/build.gradle b/build.gradle index 9b5e75d5351..74c06e8fe3f 100644 --- a/build.gradle +++ b/build.gradle @@ -23,11 +23,11 @@ import java.text.SimpleDateFormat import java.util.regex.Pattern plugins { - id 'com.diffplug.spotless' version '6.23.3' - id 'com.github.ben-manes.versions' version '0.50.0' - id 'com.github.jk1.dependency-license-report' version '2.5' - id 'com.jfrog.artifactory' version '5.1.11' - id 'io.spring.dependency-management' version '1.1.4' + id 'com.diffplug.spotless' version '6.25.0' + id 'com.github.ben-manes.versions' version '0.51.0' + id 'com.github.jk1.dependency-license-report' version '2.7' + id 'com.jfrog.artifactory' version '5.2.0' + id 'io.spring.dependency-management' version '1.1.5' id 'me.champeau.jmh' version '0.7.2' apply false id 'net.ltgt.errorprone' version '3.1.0' id 'maven-publish' diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 1fd79baf6f2..7ad666233f6 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -49,41 +49,41 @@ - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + @@ -328,12 +328,12 @@ - - - + + + - - + + @@ -347,9 +347,9 @@ - - - + + + @@ -381,17 +381,17 @@ - - - + + + - - + + - - - + + + @@ -746,9 +746,6 @@ - - - @@ -834,20 +831,12 @@ - - - - - - - - - - - + + + - - + + @@ -866,14 +855,9 @@ - - - - - - - - + + + @@ -910,14 +894,6 @@ - - - - - - - - @@ -939,11 +915,6 @@ - - - - - @@ -1156,9 +1127,9 @@ - - - + + + @@ -1248,9 +1219,6 @@ - - - @@ -1274,6 +1242,11 @@ + + + + + @@ -1297,14 +1270,6 @@ - - - - - - - - @@ -1404,6 +1369,14 @@ + + + + + + + + @@ -1412,11 +1385,6 @@ - - - - - @@ -2522,17 +2490,17 @@ - - - + + + - - - + + + - - + + @@ -3598,9 +3566,6 @@ - - - @@ -3691,14 +3656,6 @@ - - - - - - - - @@ -3707,14 +3664,6 @@ - - - - - - - - @@ -3723,14 +3672,6 @@ - - - - - - - - @@ -3739,14 +3680,6 @@ - - - - - - - - @@ -3755,14 +3688,6 @@ - - - - - - - - @@ -3771,14 +3696,6 @@ - - - - - - - - @@ -3795,14 +3712,6 @@ - - - - - - - - @@ -4027,22 +3936,6 @@ - - - - - - - - - - - - - - - - @@ -4051,14 +3944,6 @@ - - - - - - - - @@ -4067,14 +3952,6 @@ - - - - - - - - @@ -4083,14 +3960,6 @@ - - - - - - - - @@ -4099,14 +3968,6 @@ - - - - - - - - @@ -4123,22 +3984,6 @@ - - - - - - - - - - - - - - - - @@ -4147,14 +3992,6 @@ - - - - - - - - @@ -4171,22 +4008,6 @@ - - - - - - - - - - - - - - - - @@ -4195,14 +4016,6 @@ - - - - - - - - @@ -4211,14 +4024,6 @@ - - - - - - - - @@ -4227,14 +4032,6 @@ - - - - - - - - @@ -4243,14 +4040,6 @@ - - - - - - - - @@ -4259,14 +4048,6 @@ - - - - - - - - @@ -4275,14 +4056,6 @@ - - - - - - - - @@ -4299,22 +4072,6 @@ - - - - - - - - - - - - - - - - @@ -4323,14 +4080,6 @@ - - - - - - - - @@ -4339,14 +4088,6 @@ - - - - - - - - @@ -4355,14 +4096,6 @@ - - - - - - - - @@ -4371,14 +4104,6 @@ - - - - - - - - @@ -4387,14 +4112,6 @@ - - - - - - - - @@ -4403,14 +4120,6 @@ - - - - - - - - @@ -4419,14 +4128,6 @@ - - - - - - - - @@ -4435,14 +4136,6 @@ - - - - - - - - @@ -4451,14 +4144,6 @@ - - - - - - - - @@ -4467,14 +4152,6 @@ - - - - - - - - @@ -4483,14 +4160,6 @@ - - - - - - - - @@ -4499,14 +4168,6 @@ - - - - - - - - @@ -4515,14 +4176,6 @@ - - - - - - - - @@ -4531,14 +4184,6 @@ - - - - - - - - @@ -4547,14 +4192,6 @@ - - - - - - - - @@ -4563,14 +4200,6 @@ - - - - - - - - @@ -4579,14 +4208,6 @@ - - - - - - - - @@ -4595,14 +4216,6 @@ - - - - - - - - @@ -4611,14 +4224,6 @@ - - - - - - - - @@ -4627,14 +4232,6 @@ - - - - - - - - @@ -4643,14 +4240,6 @@ - - - - - - - - @@ -4659,14 +4248,6 @@ - - - - - - - - @@ -4675,14 +4256,6 @@ - - - - - - - - @@ -4691,14 +4264,6 @@ - - - - - - - - @@ -4707,14 +4272,6 @@ - - - - - - - - @@ -4731,14 +4288,6 @@ - - - - - - - - @@ -4747,22 +4296,6 @@ - - - - - - - - - - - - - - - - @@ -4771,14 +4304,6 @@ - - - - - - - - @@ -4787,14 +4312,6 @@ - - - - - - - - @@ -4803,14 +4320,6 @@ - - - - - - - - @@ -4827,22 +4336,6 @@ - - - - - - - - - - - - - - - - @@ -4851,14 +4344,6 @@ - - - - - - - - @@ -4867,14 +4352,6 @@ - - - - - - - - @@ -4891,22 +4368,6 @@ - - - - - - - - - - - - - - - - @@ -4915,14 +4376,6 @@ - - - - - - - - @@ -4931,22 +4384,6 @@ - - - - - - - - - - - - - - - - @@ -4955,14 +4392,6 @@ - - - - - - - - @@ -4971,14 +4400,6 @@ - - - - - - - - @@ -4987,14 +4408,6 @@ - - - - - - - - @@ -5011,30 +4424,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -5051,14 +4440,6 @@ - - - - - - - - @@ -5067,14 +4448,6 @@ - - - - - - - - @@ -5083,14 +4456,6 @@ - - - - - - - - @@ -5099,14 +4464,6 @@ - - - - - - - - @@ -5115,14 +4472,6 @@ - - - - - - - - @@ -5131,14 +4480,6 @@ - - - - - - - - @@ -5147,14 +4488,6 @@ - - - - - - - - @@ -5171,14 +4504,6 @@ - - - - - - - - @@ -5187,22 +4512,6 @@ - - - - - - - - - - - - - - - - @@ -5211,14 +4520,6 @@ - - - - - - - - @@ -5227,14 +4528,6 @@ - - - - - - - - @@ -5243,14 +4536,6 @@ - - - - - - - - @@ -5259,14 +4544,6 @@ - - - - - - - - @@ -5275,14 +4552,6 @@ - - - - - - - - @@ -5291,14 +4560,6 @@ - - - - - - - - @@ -5307,14 +4568,6 @@ - - - - - - - - @@ -5323,14 +4576,6 @@ - - - - - - - - @@ -5347,22 +4592,6 @@ - - - - - - - - - - - - - - - - @@ -5371,14 +4600,6 @@ - - - - - - - - @@ -5387,14 +4608,6 @@ - - - - - - - - @@ -5511,14 +4724,6 @@ - - - - - - - - @@ -5535,14 +4740,6 @@ - - - - - - - - @@ -5551,14 +4748,6 @@ - - - - - - - - @@ -5567,14 +4756,6 @@ - - - - - - - - @@ -5583,14 +4764,6 @@ - - - - - - - - @@ -5599,14 +4772,6 @@ - - - - - - - - @@ -5781,6 +4946,11 @@ + + + + + @@ -5789,6 +4959,14 @@ + + + + + + + + @@ -5800,11 +4978,6 @@ - - - - - @@ -5829,6 +5002,9 @@ + + + @@ -5837,6 +5013,9 @@ + + + @@ -5862,16 +5041,6 @@ - - - - - - - - - - @@ -5975,44 +5144,36 @@ - - - - - - - - - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + @@ -6783,14 +5944,6 @@ - - - - - - - - @@ -6818,7 +5971,7 @@ - + @@ -6851,11 +6004,6 @@ - - - - - @@ -6921,14 +6069,6 @@ - - - - - - - - @@ -6937,14 +6077,6 @@ - - - - - - - - @@ -6953,24 +6085,11 @@ - - - - - - - - - - - - - From bdcea2d20671c2957a662ad48e3c218c32fe468b Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Mon, 27 May 2024 23:18:06 +1000 Subject: [PATCH 04/42] 24.5.2 changelog (#7143) Signed-off-by: Sally MacFarlane --- CHANGELOG.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fe0cbbc3c2..176f56decae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,17 +4,36 @@ ### Breaking Changes +### Additions and Improvements + +### Bug fixes +- Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) + +## 24.5.2 + +### Upcoming Breaking Changes +- Version 24.5.x will be the last series to support Java 17. Next release after versions 24.5.x will require Java 21 to build and run. +- Receipt compaction will be enabled by default in a future version of Besu. After this change it will not be possible to downgrade to the previous Besu version. +- PKI-backed QBFT will be removed in a future version of Besu. Other forms of QBFT will remain unchanged. + ### Additions and Improvements - Remove deprecated Goerli testnet [#7049](https://github.com/hyperledger/besu/pull/7049) - Default bonsai to use full-flat db and code-storage-by-code-hash [#6984](https://github.com/hyperledger/besu/pull/6894) - New RPC methods miner_setExtraData and miner_getExtraData [#7078](https://github.com/hyperledger/besu/pull/7078) - Disconnect peers that have multiple discovery ports since they give us bad neighbours [#7089](https://github.com/hyperledger/besu/pull/7089) +### Known Issues +- [Frequency: occasional < 10%] Chain download halt. Only affects new syncs (new nodes syncing from scratch). Symptom: Block import halts, despite having a full set of peers and world state downloading finishing. Generally restarting besu will resolve the issue. We are tracking this in [#6884](https://github.com/hyperledger/besu/pull/6884) + ### Bug fixes - Fix parsing `gasLimit` parameter when its value is > `Long.MAX_VALUE` [#7116](https://github.com/hyperledger/besu/pull/7116) -- Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) - Skip validation of withdrawals when importing BFT blocks since withdrawals don't apply to BFT chains [#7115](https://github.com/hyperledger/besu/pull/7115) +### Download Links +https://github.com/hyperledger/besu/releases/tag/24.5.2 +https://github.com/hyperledger/besu/releases/download/24.5.2/besu-24.5.2.tar.gz / sha256 4049bf48022ae073065b46e27088399dfb22035e9134ed4ac2c86dd8c5b5fbe9 +https://github.com/hyperledger/besu/releases/download/24.5.2/besu-24.5.2.zip / sha256 23966b501a69e320e8f8f46a3d103ccca45b53f8fee35a6543bd9a260b5784ee + ## 24.5.1 ### Breaking Changes From 067164f7b55ed7fd44336bf3a0d204ef15668648 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Tue, 28 May 2024 01:13:00 +0200 Subject: [PATCH 05/42] Update JUnit test reports on PR merged on main (#7141) Signed-off-by: Fabio Di Fabio --- .github/workflows/acceptance-tests.yml | 14 ++++++- .github/workflows/pre-review.yml | 12 +++++- .github/workflows/update-test-reports.yml | 51 +++++++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/update-test-reports.yml diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index baca556b196..c05e4d5f4f0 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -45,14 +45,24 @@ jobs: run: ./gradlew acceptanceTestNotPrivacy --test-dry-run -Dorg.gradle.parallel=true -Dorg.gradle.caching=true - name: Extract current test list run: mkdir tmp; find . -type f -name TEST-*.xml | xargs -I{} bash -c "xmlstarlet sel -t -v '/testsuite/@name' '{}'; echo ' acceptanceTestNotPrivacy'" | tee tmp/currentTests.list - - name: get acceptance test reports + - name: Get acceptance test reports (Support transition) # can be removed after PR is merged uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d + continue-on-error: true with: branch: main name_is_regexp: true - name: 'acceptance-node-\d*\d-test-results' + name: 'acceptance-node-\d+-test-results' path: tmp/junit-xml-reports-downloaded if_no_artifact_found: true + - name: Get acceptance test reports + uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d + continue-on-error: true + with: + branch: main + workflow: update-test-reports.yml + name: acceptance-test-results + path: tmp/junit-xml-reports-downloaded + if_no_artifact_found: ignore - name: Split tests run: .github/workflows/splitTestsByTime.sh tmp/junit-xml-reports-downloaded "tmp/junit-xml-reports-downloaded/acceptance-node-.*-test-results" "TEST-" ${{env.total-runners}} ${{ matrix.runner_index }} > testList.txt - name: format gradle args diff --git a/.github/workflows/pre-review.yml b/.github/workflows/pre-review.yml index ac3b3f3ce23..034e0da2fe5 100644 --- a/.github/workflows/pre-review.yml +++ b/.github/workflows/pre-review.yml @@ -104,14 +104,24 @@ jobs: run: ./gradlew test --test-dry-run -Dorg.gradle.parallel=true -Dorg.gradle.caching=true - name: Extract current test list run: mkdir tmp; find . -type f -name TEST-*.xml | xargs -I{} bash -c "xmlstarlet sel -t -v '/testsuite/@name' '{}'; echo '{}' | sed 's#\./\(.*\)/build/test-results/.*# \1#'" | tee tmp/currentTests.list - - name: get unit test reports + - name: Get unit test reports (Support transition) # can be removed after PR is merged uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d + continue-on-error: true with: branch: main name_is_regexp: true name: 'unit-.*-test-results' path: tmp/junit-xml-reports-downloaded if_no_artifact_found: true + - name: Get unit test reports + uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d + continue-on-error: true + with: + branch: main + workflow: update-test-reports.yml + name: unit-test-results + path: tmp/junit-xml-reports-downloaded + if_no_artifact_found: ignore - name: Split tests run: .github/workflows/splitTestsByTime.sh tmp/junit-xml-reports-downloaded "tmp/junit-xml-reports-downloaded/unit-.*-test-results" "build/test-results" ${{env.total-runners}} ${{ matrix.runner_index }} > testList.txt - name: Upload Timing diff --git a/.github/workflows/update-test-reports.yml b/.github/workflows/update-test-reports.yml new file mode 100644 index 00000000000..cb57ac97164 --- /dev/null +++ b/.github/workflows/update-test-reports.yml @@ -0,0 +1,51 @@ +name: update-test-reports + +on: + push: + branches: + - main + +jobs: + syncTestReports: + if: github.repository == 'hyperledger/besu' + runs-on: ubuntu-22.04 + steps: + - name: Get latest merge PR number + id: latest_merged_pr_number + run: echo "PULL_REQUEST_NUMBER=$(gh pr list --repo hyperledger/besu --base main --state merged --limit 1 --json number | jq '.[].number')" >> "$GITHUB_OUTPUT" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Get unit test reports from latest merged PR + uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d + with: + workflow: pre-review.yml + workflow_conclusion: success + pr: ${{ env.LATEST_MERGED_PR_NUMBER }} + name_is_regexp: true + name: 'unit-\d+-test-results' + path: unit-test-results + if_no_artifact_found: fail + env: + LATEST_MERGED_PR_NUMBER: ${{ steps.latest_merged_pr_number.outputs.PULL_REQUEST_NUMBER }} + - name: Upload unit test results + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 + with: + name: unit-test-results + path: 'unit-test-results/**/test-results/**/TEST-*.xml' + - name: Get acceptance test reports from latest merged PR + uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d + with: + workflow: acceptance-tests.yml + workflow_conclusion: success + pr: ${{ env.LATEST_MERGED_PR_NUMBER }} + name_is_regexp: true + name: 'acceptance-node-\d+-test-results' + path: acceptance-test-results + if_no_artifact_found: fail + env: + LATEST_MERGED_PR_NUMBER: ${{ steps.latest_merged_pr_number.outputs.PULL_REQUEST_NUMBER }} + - name: Upload acceptance test results + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 + with: + name: acceptance-test-results + path: 'acceptance-test-results/**/test-results/**/TEST-*.xml' From 7a5a3e0957f4c65c34359bad2245952c72322f9e Mon Sep 17 00:00:00 2001 From: Gabriel-Trintinalia Date: Tue, 28 May 2024 17:55:38 +1000 Subject: [PATCH 06/42] Minor improvements to EIP-7685 (#7142) Signed-off-by: Gabriel-Trintinalia --- .../besu/datatypes/RequestType.java | 16 ++++----- .../engine/RequestValidatorProvider.java | 2 +- .../internal/results/BlockResultFactory.java | 22 +++--------- .../engine/AbstractEngineNewPayloadTest.java | 2 +- .../engine/EngineNewPayloadV4Test.java | 4 +-- .../AbstractBlockCreatorTest.java | 2 +- .../besu/ethereum/mainnet/BodyValidation.java | 2 +- .../ethereum/mainnet/ProtocolSpecBuilder.java | 2 +- .../requests/DepositRequestProcessor.java | 4 +-- .../mainnet/requests/DepositsValidator.java | 5 ++- .../mainnet/requests/RequestProcessor.java | 2 +- .../mainnet/requests/RequestUtil.java | 19 ++++++++++ .../RequestsValidatorCoordinator.java | 4 +++ .../requests/WithdrawalRequestProcessor.java | 4 +-- .../requests/WithdrawalRequestValidator.java | 7 ++-- .../BlockImportExceptionHandlingTest.java | 2 +- .../core/encoding/DepositEncoderTest.java | 35 ++++++++++++------- .../WithdrawalRequestEncoderTest.java | 27 +++++++++----- .../mainnet/AbstractBlockProcessorTest.java | 2 +- .../mainnet/MainnetBlockProcessorTest.java | 2 +- 20 files changed, 101 insertions(+), 64 deletions(-) diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/RequestType.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/RequestType.java index b1cddb44040..628baa6d5f7 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/RequestType.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/RequestType.java @@ -14,8 +14,6 @@ */ package org.hyperledger.besu.datatypes; -import java.util.Arrays; - /** Enum representing different types of requests with associated serialized type values. */ public enum RequestType { /** DEPOSITS */ @@ -47,12 +45,12 @@ public byte getSerializedType() { * RequestType}. */ public static RequestType of(final int serializedTypeValue) { - return Arrays.stream(RequestType.values()) - .filter(requestType -> requestType.typeValue == serializedTypeValue) - .findFirst() - .orElseThrow( - () -> - new IllegalArgumentException( - String.format("Unsupported request type: 0x%02X", serializedTypeValue))); + return switch (serializedTypeValue) { + case 0x00 -> DEPOSIT; + case 0x01 -> WITHDRAWAL; + default -> + throw new IllegalArgumentException( + String.format("Unsupported request type: 0x%02X", serializedTypeValue)); + }; } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/RequestValidatorProvider.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/RequestValidatorProvider.java index a86f4ca5eac..505d3695186 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/RequestValidatorProvider.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/RequestValidatorProvider.java @@ -66,6 +66,6 @@ private static RequestsValidatorCoordinator getRequestValidatorCoordinator( final ProtocolSpec protocolSchedule) { return Optional.ofNullable(protocolSchedule) .map(ProtocolSpec::getRequestsValidatorCoordinator) - .orElseGet(() -> new RequestsValidatorCoordinator.Builder().build()); + .orElseGet(RequestsValidatorCoordinator::empty); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java index 15b3a9c2c21..aff5713afc6 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java @@ -14,6 +14,9 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; +import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getDepositRequests; +import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getWithdrawalRequests; + import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EngineGetPayloadBodiesResultV1.PayloadBody; @@ -24,12 +27,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockValueCalculator; import org.hyperledger.besu.ethereum.core.BlockWithReceipts; -import org.hyperledger.besu.ethereum.core.Deposit; -import org.hyperledger.besu.ethereum.core.Request; -import org.hyperledger.besu.ethereum.core.WithdrawalRequest; import org.hyperledger.besu.ethereum.core.encoding.EncodingContext; import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder; -import org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil; import java.util.ArrayList; import java.util.List; @@ -176,23 +175,12 @@ public EngineGetPayloadResultV4 payloadTransactionCompleteV4( blockWithReceipts.getHeader(), txs, blockWithReceipts.getBlock().getBody().getWithdrawals(), - getDepositRequest(blockWithReceipts.getBlock().getBody().getRequests()), - getWithdrawalRequest(blockWithReceipts.getBlock().getBody().getRequests()), + getDepositRequests(blockWithReceipts.getBlock().getBody().getRequests()), + getWithdrawalRequests(blockWithReceipts.getBlock().getBody().getRequests()), Quantity.create(blockValue), blobsBundleV1); } - private Optional> getDepositRequest(final Optional> requests) { - return requests.map( - requestList -> RequestUtil.filterRequestsOfType(requestList, Deposit.class)); - } - - private Optional> getWithdrawalRequest( - final Optional> requests) { - return requests.map( - requestList -> RequestUtil.filterRequestsOfType(requestList, WithdrawalRequest.class)); - } - public BlockResult transactionHash(final BlockWithMetadata blockWithMetadata) { return transactionHash(blockWithMetadata, false); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java index dc40b164a4a..dba31f7f0d6 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java @@ -521,7 +521,7 @@ protected void assertValidResponse(final BlockHeader mockHeader, final JsonRpcRe } private void mockProhibitedRequestsValidator() { - var validator = new RequestsValidatorCoordinator.Builder().build(); + var validator = RequestsValidatorCoordinator.empty(); when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(validator); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java index 679a274cbc5..276eaf6b611 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java @@ -158,7 +158,7 @@ public void shouldReturnInvalidIfDepositsIsNotNull_WhenDepositsProhibited() { final List deposits = List.of(); lenient() .when(protocolSpec.getRequestsValidatorCoordinator()) - .thenReturn(new RequestsValidatorCoordinator.Builder().build()); + .thenReturn(RequestsValidatorCoordinator.empty()); var resp = resp( @@ -311,7 +311,7 @@ protected JsonRpcResponse resp(final EnginePayloadParameter payload) { } private void mockProhibitedRequestsValidator() { - var validator = new RequestsValidatorCoordinator.Builder().build(); + var validator = RequestsValidatorCoordinator.empty(); when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(validator); } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index 00576d493f8..103b8fdb667 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -134,7 +134,7 @@ void findDepositsFromReceipts() { UInt64.valueOf(539967)); final List expectedDeposits = List.of(expectedDeposit); - final Optional> depositsFromReceipts = + var depositsFromReceipts = new DepositRequestProcessor(DEFAULT_DEPOSIT_CONTRACT_ADDRESS).process(null, receipts); assertThat(depositsFromReceipts.get()).isEqualTo(expectedDeposits); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java index 86392b86d6b..15e8c3c804f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BodyValidation.java @@ -89,7 +89,7 @@ public static Hash withdrawalsRoot(final List withdrawals) { } /** - * Generates the request root for a list of requests + * Generates the requests root for a list of requests * * @param requests list of request * @return the requests root diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java index 61fba7b1fdc..f79c6a874bb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java @@ -78,7 +78,7 @@ public class ProtocolSpecBuilder { new WithdrawalsValidator.ProhibitedWithdrawals(); private WithdrawalsProcessor withdrawalsProcessor; private RequestsValidatorCoordinator requestsValidatorCoordinator = - new RequestsValidatorCoordinator.Builder().build(); + RequestsValidatorCoordinator.empty(); private RequestProcessorCoordinator requestProcessorCoordinator; protected BlockHashProcessor blockHashProcessor; private FeeMarket feeMarket = FeeMarket.legacy(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java index 16109946dfd..766ce1f94e0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java @@ -39,13 +39,13 @@ public DepositRequestProcessor(final Address depositContractAddress) { } @Override - public Optional> process( + public Optional> process( final MutableWorldState ignored, final List transactionReceipts) { if (depositContractAddress.isEmpty()) { return Optional.empty(); } List deposits = findDepositsFromReceipts(transactionReceipts); - return Optional.of(deposits.stream().map(r -> (Request) r).toList()); + return Optional.of(deposits); } @VisibleForTesting diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositsValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositsValidator.java index 1c6c3ca21c8..6a2d3bdc587 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositsValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositsValidator.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.mainnet.requests; +import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getDepositRequests; + import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Deposit; @@ -23,6 +25,7 @@ import org.hyperledger.besu.evm.log.Log; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -75,7 +78,7 @@ public boolean validateDeposits( @Override public boolean validate( final Block block, final List requests, final List receipts) { - var deposits = RequestUtil.filterRequestsOfType(requests, Deposit.class); + var deposits = getDepositRequests(Optional.of(requests)).orElse(Collections.emptyList()); return validateDeposits(block, deposits, receipts); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestProcessor.java index c365e0d754b..d09b3c47d18 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestProcessor.java @@ -22,7 +22,7 @@ import java.util.Optional; public interface RequestProcessor { - Optional> process( + Optional> process( final MutableWorldState mutableWorldState, final List transactionReceipts); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java index 54478bfef85..3d85fc48f52 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java @@ -14,7 +14,9 @@ */ package org.hyperledger.besu.ethereum.mainnet.requests; +import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.Request; +import org.hyperledger.besu.ethereum.core.WithdrawalRequest; import java.util.ArrayList; import java.util.Collections; @@ -40,6 +42,23 @@ public static List filterRequestsOfType( return requests.stream().filter(requestType::isInstance).map(requestType::cast).toList(); } + public static Optional> getDepositRequests(final Optional> requests) { + return requests.map(r -> filterRequestsOfType(r, Deposit.class)); + } + + public static Optional> getWithdrawalRequests( + final Optional> requests) { + return requests.map(r -> filterRequestsOfType(r, WithdrawalRequest.class)); + } + + /** + * Combines two optional lists of requests into a single optional list. + * + * @param maybeDeposits Optional list of deposit requests. + * @param maybeWithdrawalRequest Optional list of withdrawal requests. + * @return An Optional containing the combined list of requests, or an empty Optional if both + * inputs are empty. + */ public static Optional> combine( final Optional> maybeDeposits, final Optional> maybeWithdrawalRequest) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestsValidatorCoordinator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestsValidatorCoordinator.java index f6800f95c3b..7b8f5cf4973 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestsValidatorCoordinator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestsValidatorCoordinator.java @@ -41,6 +41,10 @@ public class RequestsValidatorCoordinator { private static final Logger LOG = LoggerFactory.getLogger(RequestsValidatorCoordinator.class); private final ImmutableSortedMap validators; + public static RequestsValidatorCoordinator empty() { + return new Builder().build(); + } + /** * Constructs a new RequestsDelegateValidator with a mapping of request types to their respective * validators. diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestProcessor.java index f9c029d5153..9803f23f3f9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestProcessor.java @@ -25,7 +25,7 @@ public class WithdrawalRequestProcessor implements RequestProcessor { @Override - public Optional> process( + public Optional> process( final MutableWorldState mutableWorldState, final List transactionReceipts) { @@ -33,6 +33,6 @@ public Optional> process( WithdrawalRequestContractHelper.popWithdrawalRequestsFromQueue(mutableWorldState).stream() .toList(); - return Optional.of(withdrawalRequests.stream().map(r -> (Request) r).toList()); + return Optional.of(withdrawalRequests); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestValidator.java index b1fc88196c9..d5f04e6ef74 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/WithdrawalRequestValidator.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.mainnet.requests; +import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getWithdrawalRequests; + import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Request; @@ -45,7 +47,7 @@ private boolean validateWithdrawalRequestsInBlock( block .getBody() .getRequests() - .map(requests -> RequestUtil.filterRequestsOfType(requests, WithdrawalRequest.class)) + .flatMap(requests -> getWithdrawalRequests(Optional.of(requests))) .orElse(Collections.emptyList()); // TODO Do we need to allow for customization? (e.g. if the value changes in the next fork) @@ -74,7 +76,8 @@ private boolean validateWithdrawalRequestsInBlock( @Override public boolean validate( final Block block, final List requests, final List receipts) { - var withdrawalRequests = RequestUtil.filterRequestsOfType(requests, WithdrawalRequest.class); + var withdrawalRequests = + getWithdrawalRequests(Optional.of(requests)).orElse(Collections.emptyList()); return validateWithdrawalRequestsInBlock(block, withdrawalRequests); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java index 6c84b29b478..d2d1fed8b73 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/BlockImportExceptionHandlingTest.java @@ -114,7 +114,7 @@ public void setup() { when(protocolContext.getWorldStateArchive()).thenReturn(worldStateArchive); when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); when(protocolSpec.getRequestsValidatorCoordinator()) - .thenReturn(new RequestsValidatorCoordinator.Builder().build()); + .thenReturn(RequestsValidatorCoordinator.empty()); when(protocolSpec.getBlockHashProcessor()).thenReturn(new FrontierBlockHashProcessor()); mainnetBlockValidator = new MainnetBlockValidator( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoderTest.java index fc9027cdbab..7b4052cffb3 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoderTest.java @@ -27,24 +27,35 @@ import org.junit.jupiter.api.Test; class DepositEncoderTest { + private final String expectedDepositEncodedBytes = + "f8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501"; + + final Deposit deposit = + new Deposit( + BLSPublicKey.fromHexString( + "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), + Bytes32.fromHexString( + "0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"), + GWei.of(32000000000L), + BLSSignature.fromHexString( + "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), + UInt64.ONE); + @Test void shouldEncodeDeposit() { - final Deposit deposit = - new Deposit( - BLSPublicKey.fromHexString( - "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), - Bytes32.fromHexString( - "0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"), - GWei.of(32000000000L), - BLSSignature.fromHexString( - "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), - UInt64.ONE); - final Bytes encoded = DepositEncoder.encodeOpaqueBytes(deposit); + assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedDepositEncodedBytes)); + } + @Test + void shouldEncodeDepositRequest() { + final Bytes encoded = RequestEncoder.encodeOpaqueBytes(deposit); + // Request encoding is Request = RequestType ++ RequestData assertThat(encoded) .isEqualTo( Bytes.fromHexString( - "0xf8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501")); + String.format( + "0x%02X%s", + deposit.getType().getSerializedType(), expectedDepositEncodedBytes))); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoderTest.java index 3f9eb0e8668..14c9cfacef2 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/WithdrawalRequestEncoderTest.java @@ -25,20 +25,31 @@ import org.junit.jupiter.api.Test; class WithdrawalRequestEncoderTest { + + private final String expectedEncodedBytes = + "f84794763c396673f9c391dce3361a9a71c8e161388000b0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e05"; + + final WithdrawalRequest withdrawalRequest = + new WithdrawalRequest( + Address.fromHexString("0x763c396673F9c391DCe3361A9A71C8E161388000"), + BLSPublicKey.fromHexString( + "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), + GWei.of(5)); + @Test void shouldEncodeWithdrawalRequest() { - final WithdrawalRequest withdrawalRequest = - new WithdrawalRequest( - Address.fromHexString("0x763c396673F9c391DCe3361A9A71C8E161388000"), - BLSPublicKey.fromHexString( - "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), - GWei.of(5)); - final Bytes encoded = WithdrawalRequestEncoder.encodeOpaqueBytes(withdrawalRequest); + assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedEncodedBytes)); + } + @Test + void shouldEncodeRequest() { + final Bytes encoded = RequestEncoder.encodeOpaqueBytes(withdrawalRequest); assertThat(encoded) .isEqualTo( Bytes.fromHexString( - "0xf84794763c396673f9c391dce3361a9a71c8e161388000b0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e05")); + String.format( + "0x%02X%s", + withdrawalRequest.getType().getSerializedType(), expectedEncodedBytes))); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java index 2db101ab659..2a66c6e1151 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorTest.java @@ -70,7 +70,7 @@ void baseSetup() { lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); lenient() .when(protocolSpec.getRequestsValidatorCoordinator()) - .thenReturn(new RequestsValidatorCoordinator.Builder().build()); + .thenReturn(RequestsValidatorCoordinator.empty()); lenient() .when(protocolSpec.getBlockHashProcessor()) .thenReturn(new FrontierBlockHashProcessor()); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java index 9f2092ea81b..a06aece37bd 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockProcessorTest.java @@ -51,7 +51,7 @@ public class MainnetBlockProcessorTest extends AbstractBlockProcessorTest { public void setup() { when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); when(protocolSpec.getRequestsValidatorCoordinator()) - .thenReturn(new RequestsValidatorCoordinator.Builder().build()); + .thenReturn(RequestsValidatorCoordinator.empty()); when(protocolSpec.getBlockHashProcessor()).thenReturn(new FrontierBlockHashProcessor()); } From 3c57ca28218122fe0efe9ee6cf628d1133729214 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Tue, 28 May 2024 17:03:34 +0200 Subject: [PATCH 07/42] Fix acceptance reports path and how to get the latest merged PR (#7147) Signed-off-by: Fabio Di Fabio --- .github/workflows/acceptance-tests.yml | 2 ++ .github/workflows/pre-review.yml | 2 ++ .github/workflows/splitTestsByTime.sh | 6 ++++++ .github/workflows/update-test-reports.yml | 4 ++-- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index c05e4d5f4f0..c188c9564e6 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -87,6 +87,8 @@ jobs: path: '*.txt' - name: run acceptance tests run: ./gradlew acceptanceTestNotPrivacy `cat gradleArgs.txt` -Dorg.gradle.parallel=true -Dorg.gradle.caching=true + - name: Remove downloaded test results + run: rm -rf tmp/junit-xml-reports-downloaded - name: Upload Acceptance Test Results uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 with: diff --git a/.github/workflows/pre-review.yml b/.github/workflows/pre-review.yml index 034e0da2fe5..0628d2ee667 100644 --- a/.github/workflows/pre-review.yml +++ b/.github/workflows/pre-review.yml @@ -143,6 +143,8 @@ jobs: path: testList.txt - name: run unit tests run: cat testList.txt | xargs -P 1 ./gradlew -Dorg.gradle.parallel=true -Dorg.gradle.caching=true + - name: Remove downloaded test results + run: rm -rf tmp/junit-xml-reports-downloaded - name: Upload Unit Test Results uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 with: diff --git a/.github/workflows/splitTestsByTime.sh b/.github/workflows/splitTestsByTime.sh index 0e39484441d..3ef075d6b97 100755 --- a/.github/workflows/splitTestsByTime.sh +++ b/.github/workflows/splitTestsByTime.sh @@ -46,6 +46,12 @@ for line in "${sorted[@]}"; do module_dir=${line_parts[2]} test_with_module="$test_name $module_dir" + # temp deduplication during the transition phase + if grep -F -q --line-regexp "$test_with_module" tmp/processedTests.list + then + continue + fi + # Does the test still exists? if grep -F -q --line-regexp "$test_with_module" tmp/currentTests.list then diff --git a/.github/workflows/update-test-reports.yml b/.github/workflows/update-test-reports.yml index cb57ac97164..fd0266dd5c8 100644 --- a/.github/workflows/update-test-reports.yml +++ b/.github/workflows/update-test-reports.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Get latest merge PR number id: latest_merged_pr_number - run: echo "PULL_REQUEST_NUMBER=$(gh pr list --repo hyperledger/besu --base main --state merged --limit 1 --json number | jq '.[].number')" >> "$GITHUB_OUTPUT" + run: echo "PULL_REQUEST_NUMBER=$(gh pr list --repo hyperledger/besu --base main --state merged --json "number,mergedAt" --search "sort:updated-desc" --jq 'max_by(.mergedAt)|.number')" >> "$GITHUB_OUTPUT" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Get unit test reports from latest merged PR @@ -48,4 +48,4 @@ jobs: uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 with: name: acceptance-test-results - path: 'acceptance-test-results/**/test-results/**/TEST-*.xml' + path: 'acceptance-test-results/**/TEST-*.xml' From fb25f180b0cbccb0a813a85d295db79fc03b357d Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 28 May 2024 20:16:04 -0600 Subject: [PATCH 08/42] Pectra devnet 0 EEST support (#7123) * Pectra devnet 0 EEST support Add the required fields to the t8n responses to enable ethereum execution spec tests to fill tests using Besu. Signed-off-by: Danno Ferrin * tests Signed-off-by: Danno Ferrin * spotless Signed-off-by: Danno Ferrin * fix issue with warm state crossing transaciton boundaries in t8n tool Signed-off-by: Danno Ferrin * test results change when bugs a re fixed Signed-off-by: Danno Ferrin * fix changed method name Signed-off-by: Danno Ferrin --------- Signed-off-by: Danno Ferrin --- .../WithdrawalRequestContractHelper.java | 5 +- .../hyperledger/besu/evmtool/T8nExecutor.java | 105 ++++-- .../besu/evmtool/t8n/prague-deposit.json | 281 +++++++++++++++ .../besu/evmtool/t8n/prague-withdrawal.json | 336 ++++++++++++++++++ 4 files changed, 698 insertions(+), 29 deletions(-) create mode 100644 ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json create mode 100644 ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal.json diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java index 3cbe952d004..6bb0e81a75e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/WithdrawalRequestContractHelper.java @@ -44,6 +44,9 @@ public class WithdrawalRequestContractHelper { public static final Address WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = Address.fromHexString("0x00A3ca265EBcb825B45F985A16CEFB49958cE017"); + /** private constructor to prevent instantiations */ + private WithdrawalRequestContractHelper() {} + @VisibleForTesting // Storage slot to store the difference between number of withdrawal requests since last block and // target withdrawal requests @@ -82,7 +85,7 @@ public static List popWithdrawalRequestsFromQueue( final MutableWorldState mutableWorldState) { final WorldUpdater worldUpdater = mutableWorldState.updater(); final MutableAccount account = worldUpdater.getAccount(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS); - if (Hash.EMPTY.equals(account.getCodeHash())) { + if (account == null || Hash.EMPTY.equals(account.getCodeHash())) { return List.of(); } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java index e5d3e2c0b9f..ee84eba4d17 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java @@ -32,13 +32,17 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.ethereum.core.WithdrawalRequest; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; +import org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.referencetests.BonsaiReferenceTestWorldState; import org.hyperledger.besu.ethereum.referencetests.ReferenceTestEnv; @@ -63,10 +67,11 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; import java.util.Spliterator; import java.util.Spliterators; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; import java.util.stream.StreamSupport; import com.fasterxml.jackson.databind.JsonNode; @@ -160,7 +165,8 @@ protected static List extractTransactions( false) .map(JsonNode::textValue) .toList(); - var accessListEntry = AccessListEntry.createAccessListEntry(address, storageKeys); + AccessListEntry accessListEntry = + AccessListEntry.createAccessListEntry(address, storageKeys); entries.add(accessListEntry); } builder.accessList(entries); @@ -260,15 +266,17 @@ static T8nResult runTest( .getBlockHashProcessor() .processBlockHashes(blockchain, worldState, referenceTestEnv); - final WorldUpdater worldStateUpdater = worldState.updater(); + final WorldUpdater rootWorldStateUpdater = worldState.updater(); List receipts = new ArrayList<>(); List invalidTransactions = new ArrayList<>(rejections); List validTransactions = new ArrayList<>(); ArrayNode receiptsArray = objectMapper.createArrayNode(); long gasUsed = 0; long blobGasUsed = 0; - for (int i = 0; i < transactions.size(); i++) { - Transaction transaction = transactions.get(i); + final WorldUpdater worldStateUpdater = rootWorldStateUpdater.updater(); + for (int transactionIndex = 0; transactionIndex < transactions.size(); transactionIndex++) { + worldStateUpdater.markTransactionBoundary(); + Transaction transaction = transactions.get(transactionIndex); final Stopwatch timer = Stopwatch.createStarted(); GasCalculator gasCalculator = protocolSpec.getGasCalculator(); @@ -277,7 +285,7 @@ static T8nResult runTest( if (blobGasUsed > blobGasLimit) { invalidTransactions.add( new RejectedTransaction( - i, + transactionIndex, String.format( "blob gas (%d) would exceed block maximum %d", blobGasUsed, blobGasLimit))); continue; @@ -286,7 +294,7 @@ static T8nResult runTest( final TransactionProcessingResult result; try { - tracer = tracerManager.getManagedTracer(i, transaction.getHash()); + tracer = tracerManager.getManagedTracer(transactionIndex, transaction.getHash()); tracer.tracePrepareTransaction(worldStateUpdater, transaction); tracer.traceStartTransaction(worldStateUpdater, transaction); result = @@ -318,7 +326,8 @@ static T8nResult runTest( } if (result.isInvalid()) { invalidTransactions.add( - new RejectedTransaction(i, result.getValidationResult().getErrorMessage())); + new RejectedTransaction( + transactionIndex, result.getValidationResult().getErrorMessage())); continue; } validTransactions.add(transaction); @@ -354,8 +363,20 @@ static T8nResult runTest( receiptObject.putNull("logs"); } else { ArrayNode logsArray = receiptObject.putArray("logs"); - for (Log log : result.getLogs()) { - logsArray.addPOJO(log); + List logs = result.getLogs(); + for (int logIndex = 0; logIndex < logs.size(); logIndex++) { + Log log = logs.get(logIndex); + var obj = logsArray.addObject(); + obj.put("address", log.getLogger().toHexString()); + var topics = obj.putArray("topics"); + log.getTopics().forEach(topic -> topics.add(topic.toHexString())); + obj.put("data", log.getData().toHexString()); + obj.put("blockNumber", blockHeader.getNumber()); + obj.put("transactionHash", transaction.getHash().toHexString()); + obj.put("transactionIndex", String.format("0x%x", transactionIndex)); + obj.put("blockHash", blockHeader.getHash().toHexString()); + obj.put("logIndex", String.format("0x%x", logIndex)); + obj.put("removed", "false"); } } receiptObject.put("transactionHash", transaction.getHash().toHexString()); @@ -363,7 +384,9 @@ static T8nResult runTest( "contractAddress", transaction.contractAddress().orElse(Address.ZERO).toHexString()); receiptObject.put("gasUsed", gasUsedInTransaction.toQuantityHexString()); receiptObject.put("blockHash", Hash.ZERO.toHexString()); - receiptObject.put("transactionIndex", Bytes.ofUnsignedLong(i).toQuantityHexString()); + receiptObject.put( + "transactionIndex", Bytes.ofUnsignedLong(transactionIndex).toQuantityHexString()); + worldStateUpdater.commit(); } final ObjectNode resultObject = objectMapper.createObjectNode(); @@ -375,12 +398,12 @@ static T8nResult runTest( (rewardString == null) ? protocolSpec.getBlockReward() : Wei.of(Long.decode(rewardString)); - worldStateUpdater + rootWorldStateUpdater .getOrCreateSenderAccount(blockHeader.getCoinbase()) .incrementBalance(reward); } - worldStateUpdater.commit(); + rootWorldStateUpdater.commit(); // Invoke the withdrawal processor to handle CL withdrawals. if (!referenceTestEnv.getWithdrawals().isEmpty()) { try { @@ -425,19 +448,45 @@ static T8nResult runTest( blockHeader .getWithdrawalsRoot() .ifPresent(wr -> resultObject.put("withdrawalsRoot", wr.toHexString())); - AtomicLong bgHolder = new AtomicLong(blobGasUsed); - blockHeader - .getExcessBlobGas() - .ifPresent( - ebg -> { - resultObject.put( - "currentExcessBlobGas", - calculateExcessBlobGasForParent(protocolSpec, blockHeader) - .toBytes() - .toQuantityHexString()); - resultObject.put( - "blobGasUsed", Bytes.ofUnsignedLong(bgHolder.longValue()).toQuantityHexString()); - }); + var maybeExcessBlobGas = blockHeader.getExcessBlobGas(); + if (maybeExcessBlobGas.isPresent()) { + resultObject.put( + "currentExcessBlobGas", + calculateExcessBlobGasForParent(protocolSpec, blockHeader) + .toBytes() + .toQuantityHexString()); + resultObject.put("blobGasUsed", Bytes.ofUnsignedLong(blobGasUsed).toQuantityHexString()); + } + + var requestProcessorCoordinator = protocolSpec.getRequestProcessorCoordinator(); + if (requestProcessorCoordinator.isPresent()) { + var rpc = requestProcessorCoordinator.get(); + Optional> maybeRequests = rpc.process(worldState, receipts); + Hash requestRoot = BodyValidation.requestsRoot(maybeRequests.orElse(List.of())); + + resultObject.put("requestsRoot", requestRoot.toHexString()); + var deposits = resultObject.putArray("depositRequests"); + RequestUtil.filterRequestsOfType(maybeRequests.orElse(List.of()), Deposit.class) + .forEach( + deposit -> { + var obj = deposits.addObject(); + obj.put("pubkey", deposit.getPubkey().toHexString()); + obj.put("withdrawalCredentials", deposit.getWithdrawalCredentials().toHexString()); + obj.put("amount", deposit.getAmount().toHexString()); + obj.put("signature", deposit.getSignature().toHexString()); + obj.put("index", deposit.getIndex().toHexString()); + }); + + var withdrawlRequests = resultObject.putArray("withdrawalRequests"); + RequestUtil.filterRequestsOfType(maybeRequests.orElse(List.of()), WithdrawalRequest.class) + .forEach( + wr -> { + var obj = withdrawlRequests.addObject(); + obj.put("sourceAddress", wr.getSourceAddress().toHexString()); + obj.put("validatorPublicKey", wr.getValidatorPublicKey().toHexString()); + obj.put("amount", wr.getAmount().toHexString()); + }); + } ObjectNode allocObject = objectMapper.createObjectNode(); worldState @@ -445,12 +494,12 @@ static T8nResult runTest( .sorted(Comparator.comparing(o -> o.getAddress().get().toHexString())) .forEach( a -> { - var account = worldState.get(a.getAddress().get()); + Account account = worldState.get(a.getAddress().get()); ObjectNode accountObject = allocObject.putObject(account.getAddress().toHexString()); if (account.getCode() != null && !account.getCode().isEmpty()) { accountObject.put("code", account.getCode().toHexString()); } - var storageEntries = + List> storageEntries = account.storageEntriesFrom(Bytes32.ZERO, Integer.MAX_VALUE).values().stream() .map( e -> diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json new file mode 100644 index 00000000000..80e415b3fc2 --- /dev/null +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json @@ -0,0 +1,281 @@ +{ + "cli": [ + "t8n", + "--input.alloc=stdin", + "--input.txs=stdin", + "--input.env=stdin", + "--output.result=stdout", + "--output.alloc=stdout", + "--output.body=stdout", + "--state.fork=Prague", + "--state.chainid=1", + "--state.reward=0" + ], + "stdin": { + "alloc": { + "0x00000000219ab540356cbb839cbe05303d7705fa": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033", + "storage": { + "0x22": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x23": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x24": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x25": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x26": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x27": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x28": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x29": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x2a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x2b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x2c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x2d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x2e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x2f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x30": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x31": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x32": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x33": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x34": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x35": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x36": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x37": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x38": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x39": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x3a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x3b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x3c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x3d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x3e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x3f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x40": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + } + }, + "0x00a3ca265ebcb825b45f985a16cefb49958ce017": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd", + "storage": {} + }, + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0xad78ebc5ac62000000", + "code": "0x", + "storage": {} + } + }, + "txs": [ + { + "type": "0x0", + "chainId": "0x1", + "nonce": "0x0", + "gasPrice": "0x7", + "gas": "0xf4240", + "to": "0x00000000219ab540356cbb839cbe05303d7705fa", + "value": "0x1bc16d674ec800000", + "input": "0x22895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000011085acb6376c2707b118225da41825974c12b5924a05c6a53b988c9cbc33c55b050000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", + "v": "0x25", + "r": "0xffeb1d6e7ef8e9ee9b64dcdc3b056f9a1d2b94c1572f1949954e712364604575", + "s": "0x3d0f42bad795205de84db8d4ab10b9abd0d081ffe560cbf45f6c281768112a69", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }, + { + "type": "0x0", + "chainId": "0x1", + "nonce": "0x1", + "gasPrice": "0x7", + "gas": "0xf4240", + "to": "0x00000000219ab540356cbb839cbe05303d7705fa", + "value": "0x1bc16d674ec800000", + "input": "0x22895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000011085acb6376c2707b118225da41825974c12b5924a05c6a53b988c9cbc33c55b050000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", + "v": "0x26", + "r": "0x5bb08e348c9c4b0a2e15d04f4a89d1a210d013205de8d3d93e38e5c1b0c8d8ab", + "s": "0x4300c0f575d9908d2cbc3413ab82895678bb8f3ef356224dd1e7cb972f2c4855", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "env": { + "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentGasLimit": "100000000000000000", + "currentNumber": "1", + "currentTimestamp": "12", + "currentRandom": "0", + "currentDifficulty": "0", + "parentDifficulty": "0", + "parentTimestamp": "0", + "parentBaseFee": "7", + "parentGasUsed": "0", + "parentGasLimit": "100000000000000000", + "parentUncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "parentBlobGasUsed": "0", + "parentExcessBlobGas": "0", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockHashes": { + "0": "0xe4fb5d47f70d54b4f36777ea4c882cf767f93d8f8170285d97a1b8275dfe4dbb" + }, + "ommers": [], + "withdrawals": [], + "parentHash": "0xe4fb5d47f70d54b4f36777ea4c882cf767f93d8f8170285d97a1b8275dfe4dbb" + } + }, + "stdout": { + "alloc": { + "0x00000000219ab540356cbb839cbe05303d7705fa": { + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x85acb6376c2707b118225da41825974c12b5924a05c6a53b988c9cbc33c55b05", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x2f93f18b1befc457f659e486ce25bbe413fe3943ee7634d2afbe83dc512c3d7a", + "0x0000000000000000000000000000000000000000000000000000000000000020": "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + }, + "balance": "0x3782dace9d9000000", + "nonce": "0x1" + }, + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000c" + }, + "balance": "0x0", + "nonce": "0x1" + }, + "0x00a3ca265ebcb825b45f985a16cefb49958ce017": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd", + "balance": "0x0", + "nonce": "0x1" + }, + "0x25a219378dad9b3503c8268c9ca836a52427a4fb": { + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0xe4fb5d47f70d54b4f36777ea4c882cf767f93d8f8170285d97a1b8275dfe4dbb" + }, + "balance": "0x0" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0xaa00be18c288efd690", + "nonce": "0x2" + } + }, + "body": "0xf90404f901ff8007830f42409400000000219ab540356cbb839cbe05303d7705fa8901bc16d674ec800000b9019422895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000011085acb6376c2707b118225da41825974c12b5924a05c6a53b988c9cbc33c55b05000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000325a0ffeb1d6e7ef8e9ee9b64dcdc3b056f9a1d2b94c1572f1949954e712364604575a03d0f42bad795205de84db8d4ab10b9abd0d081ffe560cbf45f6c281768112a69f901ff0107830f42409400000000219ab540356cbb839cbe05303d7705fa8901bc16d674ec800000b9019422895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000011085acb6376c2707b118225da41825974c12b5924a05c6a53b988c9cbc33c55b05000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000326a05bb08e348c9c4b0a2e15d04f4a89d1a210d013205de8d3d93e38e5c1b0c8d8aba04300c0f575d9908d2cbc3413ab82895678bb8f3ef356224dd1e7cb972f2c4855", + "result": { + "stateRoot": "0x0dd3e32e0081ff7ca5a0236b257676f277999ec2b8da5b31e19400715de907f1", + "txRoot": "0x2b790bf82ef7259a0e4513d1b89a77d81e99672ba68758ef2ba3fde32851d023", + "receiptsRoot": "0x9c8d7a917ecb3ff2566f264abbf39131e51b08b07eb2b69cb46989d79d985593", + "logsHash": "0x43e31613bfefc1f55d8b3ca2b61f933f3838d523dc11cb5d7ffdd2ecf0ab5d49", + "logsBloom": "0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000020000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000", + "receipts": [ + { + "root": "0x", + "status": "0x1", + "cumulativeGasUsed": "0x1431e", + "logsBloom": "0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000020000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000", + "logs": [ + { + "address": "0x00000000219ab540356cbb839cbe05303d7705fa", + "topics": [ + "0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080040597307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": 1, + "transactionHash": "0x1fe5fcd93d503a72e93ef0a4249e6d9c983cecf33474684f62ece959fc3e8212", + "transactionIndex": "0x0", + "blockHash": "0xb7b43f46d6ee34eaaad5ab38807b451e0e85bacbe59893afc625550aa7c65262", + "logIndex": "0x0", + "removed": "false" + } + ], + "transactionHash": "0x1fe5fcd93d503a72e93ef0a4249e6d9c983cecf33474684f62ece959fc3e8212", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x1431e", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0" + }, + { + "root": "0x", + "status": "0x1", + "cumulativeGasUsed": "0x24f10", + "logsBloom": "0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000020000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000", + "logs": [ + { + "address": "0x00000000219ab540356cbb839cbe05303d7705fa", + "topics": [ + "0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080040597307000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000080100000000000000000000000000000000000000000000000000000000000000", + "blockNumber": 1, + "transactionHash": "0x3059d7dbc2df8a05442e50ea529419277c2f45582534f452d2d5676d93273c7d", + "transactionIndex": "0x1", + "blockHash": "0xb7b43f46d6ee34eaaad5ab38807b451e0e85bacbe59893afc625550aa7c65262", + "logIndex": "0x0", + "removed": "false" + } + ], + "transactionHash": "0x3059d7dbc2df8a05442e50ea529419277c2f45582534f452d2d5676d93273c7d", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x10bf2", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x1" + } + ], + "currentDifficulty": null, + "gasUsed": "0x24f10", + "currentBaseFee": "0x7", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "currentExcessBlobGas": "0x0", + "blobGasUsed": "0x0", + "requestsRoot": "0xfba41d6600776bec2258a06e4bc00a34f7a2a1bc0aa802976d038ef4e3379d29", + "depositRequests": [ + { + "pubkey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "withdrawalCredentials": "0x0000000000000000000000000000000000000000000000000000000000000002", + "amount": "0x0000000773594000", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", + "index": "0x0000000000000000" + }, + { + "pubkey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "withdrawalCredentials": "0x0000000000000000000000000000000000000000000000000000000000000002", + "amount": "0x0000000773594000", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", + "index": "0x0000000000000001" + } + ], + "withdrawalRequests": [] + } + } +} \ No newline at end of file diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal.json new file mode 100644 index 00000000000..85ad0d7e9ab --- /dev/null +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal.json @@ -0,0 +1,336 @@ +{ + "cli": [ + "t8n", + "--input.alloc=stdin", + "--input.txs=stdin", + "--input.env=stdin", + "--output.result=stdout", + "--output.alloc=stdout", + "--output.body=stdout", + "--state.fork=Prague", + "--state.chainid=1", + "--state.reward=0" + ], + "stdin": { + "alloc": { + "0x00000000219ab540356cbb839cbe05303d7705fa": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033", + "storage": { + "0x22": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x23": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x24": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x25": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x26": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x27": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x28": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x29": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x2a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x2b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x2c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x2d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x2e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x2f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x30": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x31": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x32": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x33": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x34": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x35": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x36": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x37": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x38": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x39": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x3a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x3b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x3c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x3d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x3e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x3f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x40": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + } + }, + "0x00a3ca265ebcb825b45f985a16cefb49958ce017": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd", + "storage": { + } + }, + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "nonce": "0x01", + "balance": "0x00", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "storage": {} + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "nonce": "0x00", + "balance": "0xad78ebc5ac62000000", + "code": "0x", + "storage": {} + }, + "0x0000000000000000000000000000000000000200": { + "nonce": "0x01", + "balance": "0xad78ebc5ac62000000", + "code": "0x60386000600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386038600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386070600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f150603860a8600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f150603860e0600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610118600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610150600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610188600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386101c0600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386101f8600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610230600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610268600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386102a0600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386102d8600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610310600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610348600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f150", + "storage": {} + } + }, + "txs": [ + { + "type": "0x0", + "chainId": "0x1", + "nonce": "0x0", + "gasPrice": "0x7", + "gas": "0xf4240", + "to": "0x0000000000000000000000000000000000000200", + "value": "0x0", + "input": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009fffffffffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bfffffffffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dfffffffffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000", + "v": "0x26", + "r": "0x963cb6620fe5828cbc93bb7139d3f4501067d76275dff648bf48c3c100ca8dd4", + "s": "0x4ac396104a5be4643406718f59a6e74d62a32777f5f6135e55e805e87612013c", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + } + ], + "env": { + "currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentGasLimit": "100000000000000000", + "currentNumber": "1", + "currentTimestamp": "12", + "currentRandom": "0", + "currentDifficulty": "0", + "parentDifficulty": "0", + "parentTimestamp": "0", + "parentBaseFee": "7", + "parentGasUsed": "0", + "parentGasLimit": "100000000000000000", + "parentUncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "parentBlobGasUsed": "0", + "parentExcessBlobGas": "0", + "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockHashes": { + "0": "0x10715cfbefdb8a0cb2f7d7ca5ee6d1ea65515ecb41cff0a22d1e11716a9d27fb" + }, + "ommers": [], + "withdrawals": [], + "parentHash": "0x10715cfbefdb8a0cb2f7d7ca5ee6d1ea65515ecb41cff0a22d1e11716a9d27fb" + } + }, + "stdout": { + "alloc": { + "0x0000000000000000000000000000000000000200": { + "code": "0x60386000600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386038600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386070600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f150603860a8600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f150603860e0600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610118600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610150600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610188600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386101c0600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386101f8600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610230600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610268600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386102a0600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f15060386102d8600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610310600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f1506038610348600037600060006038600060017300a3ca265ebcb825b45f985a16cefb49958ce017620f4240f150", + "balance": "0xad78ebc5ac61fffff0", + "nonce": "0x1" + }, + "0x00000000219ab540356cbb839cbe05303d7705fa": { + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + }, + "balance": "0x0", + "nonce": "0x1" + }, + "0x000f3df6d732807ef1319fb7b8bb8522d0beac02": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x000000000000000000000000000000000000000000000000000000000000000c" + }, + "balance": "0x0", + "nonce": "0x1" + }, + "0x00a3ca265ebcb825b45f985a16cefb49958ce017": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe146090573615156028575f545f5260205ff35b366038141561012e5760115f54600182026001905f5b5f82111560595781019083028483029004916001019190603e565b90939004341061012e57600154600101600155600354806003026004013381556001015f3581556001016020359055600101600355005b6003546002548082038060101160a4575060105b5f5b81811460dd5780604c02838201600302600401805490600101805490600101549160601b83528260140152906034015260010160a6565b910180921460ed579060025560f8565b90505f6002555f6003555b5f548061049d141561010757505f5b60015460028282011161011c5750505f610122565b01600290035b5f555f600155604c025ff35b5f5ffd", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000006": "0x00000000000000000000000000000001fffffffffffffffe0000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000007": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000009": "0x0000000000000000000000000000000200000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x000000000000000000000000000000000000000000000000000000000000000c": "0x00000000000000000000000000000003fffffffffffffffe0000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x000000000000000000000000000000000000000000000000000000000000000f": "0x0000000000000000000000000000000400000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000010": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000012": "0x00000000000000000000000000000005fffffffffffffffe0000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000013": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000015": "0x0000000000000000000000000000000600000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000016": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000018": "0x00000000000000000000000000000007fffffffffffffffe0000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000019": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x000000000000000000000000000000000000000000000000000000000000001b": "0x0000000000000000000000000000000800000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000001c": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x000000000000000000000000000000000000000000000000000000000000001e": "0x00000000000000000000000000000009fffffffffffffffe0000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000001f": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000021": "0x0000000000000000000000000000000a00000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000022": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0x0000000000000000000000000000000bfffffffffffffffe0000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0x0000000000000000000000000000000c00000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x0000000000000000000000000000000dfffffffffffffffe0000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0x0000000000000000000000000000000e00000000000000000000000000000000", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0x0000000000000000000000000000000ffffffffffffffffe0000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x0000000000000000000000000000000000000000000000000000000000000200", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x0000000000000000000000000000001000000000000000000000000000000000" + }, + "balance": "0x10", + "nonce": "0x1" + }, + "0x25a219378dad9b3503c8268c9ca836a52427a4fb": { + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x10715cfbefdb8a0cb2f7d7ca5ee6d1ea65515ecb41cff0a22d1e11716a9d27fb" + }, + "balance": "0x0" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0xad78ebc5ac619bbcea", + "nonce": "0x1" + } + }, + "body": "0xf903e5f903e28007830f424094000000000000000000000000000000000000020080b90380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009fffffffffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bfffffffffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dfffffffffffffffe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000026a0963cb6620fe5828cbc93bb7139d3f4501067d76275dff648bf48c3c100ca8dd4a04ac396104a5be4643406718f59a6e74d62a32777f5f6135e55e805e87612013c", + "result": { + "stateRoot": "0xf682e4f8f820f44fb43a20c3db274bc3c9fcb9e52cc1af3c3ea7cb21fdb2250b", + "txRoot": "0x8521df63211790726b6f1a437bb0fd4b27c00e13e7678d324c4cfddb8d834ad2", + "receiptsRoot": "0x4bd8bd5580caf4ed45f873794ad7ff9d6fd2363ae529269b17b891b68d349d75", + "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "receipts": [ + { + "root": "0x", + "status": "0x1", + "cumulativeGasUsed": "0xe52ba", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": null, + "transactionHash": "0x04a2d3f252dcc98edb684f7f15b572aaf980d0c2eea4c620a9f1ff1d275b2207", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0xe52ba", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0" + } + ], + "currentDifficulty": null, + "gasUsed": "0xe52ba", + "currentBaseFee": "0x7", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "currentExcessBlobGas": "0x0", + "blobGasUsed": "0x0", + "requestsRoot": "0x415d33e444f917658fd3bd6d3d8d88a1f501f9b83ace92ddacac823252c9fa47", + "depositRequests": [], + "withdrawalRequests": [ + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002", + "amount": "0x0000000000000000" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004", + "amount": "0x0000000000000000" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006", + "amount": "0x0000000000000000" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008", + "amount": "0x0000000000000000" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a", + "amount": "0x0000000000000000" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c", + "amount": "0x0000000000000000" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e", + "amount": "0x0000000000000000" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f", + "amount": "0xfffffffffffffffe" + }, + { + "sourceAddress": "0x0000000000000000000000000000000000000200", + "validatorPublicKey": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010", + "amount": "0x0000000000000000" + } + ] + } + } +} \ No newline at end of file From 2df721619a61e0eb2c9bedb8e72bbedc21b50c07 Mon Sep 17 00:00:00 2001 From: Gabriel-Trintinalia Date: Wed, 29 May 2024 13:39:44 +1000 Subject: [PATCH 09/42] [MINOR] Rename deposit to depositRequest (#7145) Signed-off-by: Gabriel-Trintinalia --- .../engine/AbstractEngineNewPayload.java | 12 ++-- .../methods/engine/EngineNewPayloadV4.java | 2 +- ...eter.java => DepositRequestParameter.java} | 28 ++++---- .../parameters/EnginePayloadParameter.java | 12 ++-- .../results/EngineGetPayloadResultV4.java | 25 +++---- .../engine/AbstractEngineGetPayloadTest.java | 6 +- .../engine/AbstractEngineNewPayloadTest.java | 22 +++---- .../engine/EngineGetPayloadV4Test.java | 4 +- .../engine/EngineNewPayloadV3Test.java | 4 +- .../engine/EngineNewPayloadV4Test.java | 52 ++++++++------- .../DepositParameterTestFixture.java | 8 +-- ...> DepositRequestRequestParameterTest.java} | 14 ++-- .../AbstractBlockCreatorTest.java | 40 ++++++------ .../besu/ethereum/core/BlockBody.java | 2 +- .../{Deposit.java => DepositRequest.java} | 7 +- ...ecoder.java => DepositRequestDecoder.java} | 14 ++-- ...ncoder.java => DepositRequestEncoder.java} | 16 ++--- .../core/encoding/RequestDecoder.java | 2 +- .../core/encoding/RequestEncoder.java | 2 +- .../requests/DepositRequestProcessor.java | 13 ++-- ...ator.java => DepositRequestValidator.java} | 34 +++++----- .../requests/MainnetRequestsValidator.java | 2 +- .../mainnet/requests/RequestUtil.java | 15 +++-- ... => DepositRequestRequestDecoderTest.java} | 22 +++---- ... => DepositRequestRequestEncoderTest.java} | 14 ++-- ....java => DepositRequestValidatorTest.java} | 65 ++++++++++--------- .../MainnetBlockBodyValidatorTest.java | 8 ++- .../task/GetBodiesFromPeerTaskTest.java | 6 +- .../hyperledger/besu/evmtool/T8nExecutor.java | 4 +- plugin-api/build.gradle | 2 +- .../{Deposit.java => DepositRequest.java} | 2 +- 31 files changed, 237 insertions(+), 222 deletions(-) rename ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/{DepositParameter.java => DepositRequestParameter.java} (83%) rename ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/{DepositParameterTest.java => DepositRequestRequestParameterTest.java} (88%) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/{Deposit.java => DepositRequest.java} (94%) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/{DepositDecoder.java => DepositRequestDecoder.java} (86%) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/{DepositEncoder.java => DepositRequestEncoder.java} (73%) rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/{DepositsValidator.java => DepositRequestValidator.java} (68%) rename ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/{DepositDecoderTest.java => DepositRequestRequestDecoderTest.java} (88%) rename ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/{DepositEncoderTest.java => DepositRequestRequestEncoderTest.java} (87%) rename ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/{DepositsValidatorTest.java => DepositRequestValidatorTest.java} (83%) rename plugin-api/src/main/java/org/hyperledger/besu/plugin/data/{Deposit.java => DepositRequest.java} (98%) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index d2faf8e7d86..e8134fdb1a5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -35,7 +35,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalRequestParameter; @@ -161,12 +161,12 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) reqId, new JsonRpcError(INVALID_PARAMS, "Invalid withdrawals")); } - final Optional> maybeDeposits = - Optional.ofNullable(blockParam.getDeposits()) - .map(ds -> ds.stream().map(DepositParameter::toDeposit).collect(toList())); + final Optional> maybeDepositRequests = + Optional.ofNullable(blockParam.getDepositRequests()) + .map(ds -> ds.stream().map(DepositRequestParameter::toDeposit).collect(toList())); if (!getDepositRequestValidator( protocolSchedule.get(), blockParam.getTimestamp(), blockParam.getBlockNumber()) - .validateParameter(maybeDeposits)) { + .validateParameter(maybeDepositRequests)) { return new JsonRpcErrorResponse( reqId, new JsonRpcError(INVALID_PARAMS, "Invalid deposit request")); } @@ -186,7 +186,7 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) } Optional> maybeRequests = - RequestUtil.combine(maybeDeposits, maybeWithdrawalRequests); + RequestUtil.combine(maybeDepositRequests, maybeWithdrawalRequests); if (mergeContext.get().isSyncing()) { LOG.debug("We are syncing"); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java index 83d406106fd..93060821f80 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4.java @@ -63,7 +63,7 @@ protected ValidationResult validateParameters( } else if (maybeBeaconBlockRootParam.isEmpty()) { return ValidationResult.invalid( RpcErrorType.INVALID_PARAMS, "Missing parent beacon block root field"); - } else if (payloadParameter.getDeposits() == null) { + } else if (payloadParameter.getDepositRequests() == null) { return ValidationResult.invalid(RpcErrorType.INVALID_PARAMS, "Missing deposit field"); } else { return ValidationResult.valid(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositRequestParameter.java similarity index 83% rename from ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameter.java rename to ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositRequestParameter.java index e2a3a4d207d..39d6476ca46 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositRequestParameter.java @@ -17,7 +17,7 @@ import org.hyperledger.besu.datatypes.BLSPublicKey; import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import java.util.Objects; @@ -28,7 +28,7 @@ import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt64; -public class DepositParameter { +public class DepositRequestParameter { private final String pubkey; @@ -39,7 +39,7 @@ public class DepositParameter { private final String index; @JsonCreator - public DepositParameter( + public DepositRequestParameter( @JsonProperty("pubkey") final String pubkey, @JsonProperty("withdrawalCredentials") final String withdrawalCredentials, @JsonProperty("amount") final String amount, @@ -52,17 +52,17 @@ public DepositParameter( this.index = index; } - public static DepositParameter fromDeposit(final Deposit deposit) { - return new DepositParameter( - deposit.getPubkey().toString(), - deposit.getWithdrawalCredentials().toString(), - deposit.getAmount().toShortHexString(), - deposit.getSignature().toString(), - deposit.getIndex().toBytes().toQuantityHexString()); + public static DepositRequestParameter fromDeposit(final DepositRequest depositRequest) { + return new DepositRequestParameter( + depositRequest.getPubkey().toString(), + depositRequest.getWithdrawalCredentials().toString(), + depositRequest.getAmount().toShortHexString(), + depositRequest.getSignature().toString(), + depositRequest.getIndex().toBytes().toQuantityHexString()); } - public Deposit toDeposit() { - return new Deposit( + public DepositRequest toDeposit() { + return new DepositRequest( BLSPublicKey.fromHexString(pubkey), Bytes32.fromHexString(withdrawalCredentials), GWei.fromHexString(amount), @@ -108,7 +108,7 @@ public String getIndex() { public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final DepositParameter that = (DepositParameter) o; + final DepositRequestParameter that = (DepositRequestParameter) o; return Objects.equals(pubkey, that.pubkey) && Objects.equals(withdrawalCredentials, that.withdrawalCredentials) && Objects.equals(amount, that.amount) @@ -123,7 +123,7 @@ public int hashCode() { @Override public String toString() { - return "DepositParameter{" + return "DepositRequestParameter{" + "pubKey='" + pubkey + '\'' diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java index a264c60edf3..4fd24e15a6f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java @@ -43,7 +43,7 @@ public class EnginePayloadParameter { private final List withdrawals; private final Long blobGasUsed; private final String excessBlobGas; - private final List deposits; + private final List depositRequests; private final List withdrawalRequests; /** @@ -66,7 +66,7 @@ public class EnginePayloadParameter { * @param withdrawals Array of Withdrawal * @param blobGasUsed QUANTITY, 64 Bits * @param excessBlobGas QUANTITY, 64 Bits - * @param deposits List of deposit parameters. + * @param depositRequests List of deposit parameters. * @param withdrawalRequestParameters List of withdrawal requests parameters. */ @JsonCreator @@ -88,7 +88,7 @@ public EnginePayloadParameter( @JsonProperty("withdrawals") final List withdrawals, @JsonProperty("blobGasUsed") final UnsignedLongParameter blobGasUsed, @JsonProperty("excessBlobGas") final String excessBlobGas, - @JsonProperty("depositRequests") final List deposits, + @JsonProperty("depositRequests") final List depositRequests, @JsonProperty("withdrawalRequests") final List withdrawalRequestParameters) { this.blockHash = blockHash; @@ -108,7 +108,7 @@ public EnginePayloadParameter( this.withdrawals = withdrawals; this.blobGasUsed = blobGasUsed == null ? null : blobGasUsed.getValue(); this.excessBlobGas = excessBlobGas; - this.deposits = deposits; + this.depositRequests = depositRequests; this.withdrawalRequests = withdrawalRequestParameters; } @@ -180,8 +180,8 @@ public String getExcessBlobGas() { return excessBlobGas; } - public List getDeposits() { - return deposits; + public List getDepositRequests() { + return depositRequests; } public List getWithdrawalRequests() { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java index 03a5082dad7..133fbabe609 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadResultV4.java @@ -14,11 +14,11 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalRequestParameter; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.core.WithdrawalRequest; @@ -42,12 +42,12 @@ public EngineGetPayloadResultV4( final BlockHeader header, final List transactions, final Optional> withdrawals, - final Optional> deposits, + final Optional> depositRequests, final Optional> withdrawalRequests, final String blockValue, final BlobsBundleV1 blobsBundle) { this.executionPayload = - new PayloadResult(header, transactions, withdrawals, deposits, withdrawalRequests); + new PayloadResult(header, transactions, withdrawals, depositRequests, withdrawalRequests); this.blockValue = blockValue; this.blobsBundle = blobsBundle; this.shouldOverrideBuilder = false; @@ -94,14 +94,14 @@ public static class PayloadResult { protected final List transactions; private final List withdrawals; - private final List deposits; + private final List depositRequests; private final List withdrawalRequests; public PayloadResult( final BlockHeader header, final List transactions, final Optional> withdrawals, - final Optional> deposits, + final Optional> depositRequests, final Optional> withdrawalRequests) { this.blockNumber = Quantity.create(header.getNumber()); this.blockHash = header.getHash().toString(); @@ -125,10 +125,13 @@ public PayloadResult( .map(WithdrawalParameter::fromWithdrawal) .collect(Collectors.toList())) .orElse(null); - this.deposits = - deposits + this.depositRequests = + depositRequests .map( - ds -> ds.stream().map(DepositParameter::fromDeposit).collect(Collectors.toList())) + ds -> + ds.stream() + .map(DepositRequestParameter::fromDeposit) + .collect(Collectors.toList())) .orElse(null); this.withdrawalRequests = withdrawalRequests @@ -216,8 +219,8 @@ public List getWithdrawals() { } @JsonGetter(value = "depositRequests") - public List getDeposits() { - return deposits; + public List getDepositRequests() { + return depositRequests; } @JsonGetter(value = "withdrawalRequests") diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java index f0479bd7d2e..77952f6dc69 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java @@ -105,7 +105,7 @@ public AbstractEngineGetPayloadTest() { Collections.emptyList(), Optional.of(Collections.emptyList()), Optional.empty())); - private static final Block mockBlockWithDeposits = + private static final Block mockBlockWithDepositRequests = new Block( mockHeader, new BlockBody( @@ -116,8 +116,8 @@ public AbstractEngineGetPayloadTest() { protected static final BlockWithReceipts mockBlockWithReceiptsAndWithdrawals = new BlockWithReceipts(mockBlockWithWithdrawals, Collections.emptyList()); - protected static final BlockWithReceipts mockBlockWithReceiptsAndDeposits = - new BlockWithReceipts(mockBlockWithDeposits, Collections.emptyList()); + protected static final BlockWithReceipts mockBlockWithReceiptsAndDepositRequests = + new BlockWithReceipts(mockBlockWithDepositRequests, Collections.emptyList()); @Mock protected ProtocolContext protocolContext; diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java index dba31f7f0d6..26d0dad955d 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java @@ -38,7 +38,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; @@ -54,7 +54,7 @@ import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.core.WithdrawalRequest; @@ -410,7 +410,7 @@ protected EnginePayloadParameter mockEnginePayload( final BlockHeader header, final List txs, final List withdrawals, - final List deposits, + final List depositRequests, final List withdrawalRequests) { return new EnginePayloadParameter( header.getHash(), @@ -430,18 +430,18 @@ protected EnginePayloadParameter mockEnginePayload( withdrawals, header.getBlobGasUsed().map(UnsignedLongParameter::new).orElse(null), header.getExcessBlobGas().map(BlobGas::toHexString).orElse(null), - deposits, + depositRequests, withdrawalRequests); } protected BlockHeader setupValidPayload( final BlockProcessingResult value, final Optional> maybeWithdrawals, - final Optional> maybeDeposits, + final Optional> maybeDepositRequests, final Optional> maybeWithdrawalRequests) { BlockHeader mockHeader = - createBlockHeader(maybeWithdrawals, maybeDeposits, maybeWithdrawalRequests); + createBlockHeader(maybeWithdrawals, maybeDepositRequests, maybeWithdrawalRequests); when(blockchain.getBlockByHash(mockHeader.getHash())).thenReturn(Optional.empty()); // when(blockchain.getBlockHeader(mockHeader.getParentHash())) // .thenReturn(Optional.of(mock(BlockHeader.class))); @@ -474,21 +474,21 @@ protected JsonRpcError fromErrorResp(final JsonRpcResponse resp) { protected BlockHeader createBlockHeader( final Optional> maybeWithdrawals, - final Optional> maybeDeposits, + final Optional> maybeDepositRequests, final Optional> maybeWithdrawalRequests) { - return createBlockHeaderFixture(maybeWithdrawals, maybeDeposits, maybeWithdrawalRequests) + return createBlockHeaderFixture(maybeWithdrawals, maybeDepositRequests, maybeWithdrawalRequests) .buildHeader(); } protected BlockHeaderTestFixture createBlockHeaderFixture( final Optional> maybeWithdrawals, - final Optional> maybeDeposits, + final Optional> maybeDepositRequests, final Optional> maybeWithdrawalRequests) { Optional> maybeRequests; - if (maybeDeposits.isPresent() || maybeWithdrawalRequests.isPresent()) { + if (maybeDepositRequests.isPresent() || maybeWithdrawalRequests.isPresent()) { List requests = new ArrayList<>(); - maybeDeposits.ifPresent(requests::addAll); + maybeDepositRequests.ifPresent(requests::addAll); maybeWithdrawalRequests.ifPresent(requests::addAll); maybeRequests = Optional.of(requests); } else { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java index 68828619c90..e8e4e821a37 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java @@ -71,7 +71,7 @@ public void before() { super.before(); lenient() .when(mergeContext.retrieveBlockById(mockPid)) - .thenReturn(Optional.of(mockBlockWithReceiptsAndDeposits)); + .thenReturn(Optional.of(mockBlockWithReceiptsAndDepositRequests)); when(protocolContext.safeConsensusContext(Mockito.any())).thenReturn(Optional.of(mergeContext)); this.method = new EngineGetPayloadV4( @@ -146,7 +146,7 @@ public void shouldReturnBlockForKnownPayloadId() { assertThat(r.getResult()).isInstanceOf(EngineGetPayloadResultV4.class); final EngineGetPayloadResultV4 res = (EngineGetPayloadResultV4) r.getResult(); assertThat(res.getExecutionPayload().getWithdrawals()).isNotNull(); - assertThat(res.getExecutionPayload().getDeposits()).isNotNull(); + assertThat(res.getExecutionPayload().getDepositRequests()).isNotNull(); assertThat(res.getExecutionPayload().getWithdrawalRequests()).isNotNull(); assertThat(res.getExecutionPayload().getHash()) .isEqualTo(header.getHash().toString()); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java index 4604c8487c1..98a71ebf35d 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java @@ -44,7 +44,7 @@ import org.hyperledger.besu.ethereum.core.BlobTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionTestFixture; import org.hyperledger.besu.ethereum.core.Withdrawal; @@ -150,7 +150,7 @@ public void shouldValidVersionedHash_whenListIsEmpty() { @Override protected BlockHeader createBlockHeader( final Optional> maybeWithdrawals, - final Optional> maybeDeposits, + final Optional> maybeDepositRequests, final Optional> maybeWithdrawalRequests) { BlockHeader parentBlockHeader = new BlockHeaderTestFixture() diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java index 276eaf6b611..86b096cf1e8 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java @@ -33,19 +33,19 @@ import org.hyperledger.besu.ethereum.BlockProcessingResult; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositParameter; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.DepositRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalRequestParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.core.WithdrawalRequest; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; -import org.hyperledger.besu.ethereum.mainnet.requests.DepositsValidator; +import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestValidator; import org.hyperledger.besu.ethereum.mainnet.requests.RequestsValidatorCoordinator; import org.hyperledger.besu.ethereum.mainnet.requests.WithdrawalRequestValidator; import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; @@ -92,8 +92,8 @@ public void shouldReturnExpectedMethodName() { } @Test - public void shouldReturnValidIfDepositsIsNull_WhenDepositsProhibited() { - final List deposits = null; + public void shouldReturnValidIfDepositRequestsIsNull_WhenDepositRequestsProhibited() { + final List depositRequests = null; mockProhibitedRequestsValidator(); BlockHeader mockHeader = @@ -108,22 +108,23 @@ public void shouldReturnValidIfDepositsIsNull_WhenDepositsProhibited() { when(mergeCoordinator.getLatestValidAncestor(mockHeader)) .thenReturn(Optional.of(mockHeader.getHash())); - var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, deposits, null)); + var resp = + resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, depositRequests, null)); assertValidResponse(mockHeader, resp); } @Test - public void shouldReturnInvalidIfDepositsIsNull_WhenDepositsAllowed() { - final List deposits = null; - mockAllowedDepositsRequestValidator(); + public void shouldReturnInvalidIfDepositRequestsIsNull_WhenDepositRequestsAllowed() { + final List depositRequests = null; + mockAllowedDepositRequestsRequestValidator(); var resp = resp( mockEnginePayload( createBlockHeader(Optional.empty(), Optional.empty(), Optional.empty()), Collections.emptyList(), null, - deposits, + depositRequests, null)); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -131,15 +132,16 @@ public void shouldReturnInvalidIfDepositsIsNull_WhenDepositsAllowed() { } @Test - public void shouldReturnValidIfDepositsIsNotNull_WhenDepositsAllowed() { - final List depositsParam = List.of(DEPOSIT_PARAM_1); - final List deposits = List.of(DEPOSIT_PARAM_1.toDeposit()); + public void shouldReturnValidIfDepositRequestsIsNotNull_WhenDepositRequestsAllowed() { + final List depositRequestsParam = List.of(DEPOSIT_PARAM_1); + final List depositRequests = List.of(DEPOSIT_PARAM_1.toDeposit()); - mockAllowedDepositsRequestValidator(); + mockAllowedDepositRequestsRequestValidator(); BlockHeader mockHeader = setupValidPayload( new BlockProcessingResult( - Optional.of(new BlockProcessingOutputs(null, List.of(), Optional.of(deposits)))), + Optional.of( + new BlockProcessingOutputs(null, List.of(), Optional.of(depositRequests)))), Optional.empty(), Optional.of(List.of(DEPOSIT_PARAM_1.toDeposit())), Optional.empty()); @@ -148,14 +150,16 @@ public void shouldReturnValidIfDepositsIsNotNull_WhenDepositsAllowed() { when(mergeCoordinator.getLatestValidAncestor(mockHeader)) .thenReturn(Optional.of(mockHeader.getHash())); var resp = - resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, depositsParam, null)); + resp( + mockEnginePayload( + mockHeader, Collections.emptyList(), null, depositRequestsParam, null)); assertValidResponse(mockHeader, resp); } @Test - public void shouldReturnInvalidIfDepositsIsNotNull_WhenDepositsProhibited() { - final List deposits = List.of(); + public void shouldReturnInvalidIfDepositRequestsIsNotNull_WhenDepositRequestsProhibited() { + final List depositRequests = List.of(); lenient() .when(protocolSpec.getRequestsValidatorCoordinator()) .thenReturn(RequestsValidatorCoordinator.empty()); @@ -167,7 +171,7 @@ public void shouldReturnInvalidIfDepositsIsNotNull_WhenDepositsProhibited() { Optional.empty(), Optional.of(Collections.emptyList()), Optional.empty()), Collections.emptyList(), null, - deposits, + depositRequests, null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); @@ -264,7 +268,7 @@ public void shouldReturnValidIfWithdrawalRequestsIsNotNull_WhenWithdrawalRequest @Override protected BlockHeader createBlockHeader( final Optional> maybeWithdrawals, - final Optional> maybeDeposits, + final Optional> maybeDepositRequests, final Optional> maybeWithdrawalRequests) { BlockHeader parentBlockHeader = new BlockHeaderTestFixture() @@ -275,9 +279,9 @@ protected BlockHeader createBlockHeader( .buildHeader(); Optional> maybeRequests; - if (maybeDeposits.isPresent() || maybeWithdrawalRequests.isPresent()) { + if (maybeDepositRequests.isPresent() || maybeWithdrawalRequests.isPresent()) { List requests = new ArrayList<>(); - maybeDeposits.ifPresent(requests::addAll); + maybeDepositRequests.ifPresent(requests::addAll); maybeWithdrawalRequests.ifPresent(requests::addAll); maybeRequests = Optional.of(requests); } else { @@ -315,10 +319,10 @@ private void mockProhibitedRequestsValidator() { when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(validator); } - private void mockAllowedDepositsRequestValidator() { + private void mockAllowedDepositRequestsRequestValidator() { var validator = new RequestsValidatorCoordinator.Builder() - .addValidator(RequestType.DEPOSIT, new DepositsValidator(depositContractAddress)) + .addValidator(RequestType.DEPOSIT, new DepositRequestValidator(depositContractAddress)) .build(); when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(validator); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameterTestFixture.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameterTestFixture.java index 575b73c73b3..f3f5f420bbb 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameterTestFixture.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameterTestFixture.java @@ -16,14 +16,14 @@ public class DepositParameterTestFixture { - public static final DepositParameter DEPOSIT_PARAM_1 = + public static final DepositRequestParameter DEPOSIT_PARAM_1 = createDeposit( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e", "0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483", "0x773594000", "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5", "0x1"); - static final DepositParameter DEPOSIT_PARAM_2 = + static final DepositRequestParameter DEPOSIT_PARAM_2 = createDeposit( "0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243", "0x006a8dc800c6d8dd6977ef53264e2d030350f0145a91bcd167b4f1c3ea21b271", @@ -31,12 +31,12 @@ public class DepositParameterTestFixture { "0x801b08ca107b623eca32ee9f9111b4e50eb9cfe19e38204b72de7dc04c5a5e00f61bab96f10842576f66020ce851083f1583dd9a6b73301bea6c245cf51f27cf96aeb018852c5f70bf485d16b957cfe49ca008913346b431e7653ae3ddb23b07", "0x3"); - private static DepositParameter createDeposit( + private static DepositRequestParameter createDeposit( final String pubKey, final String withdrawalCredentials, final String amount, final String signature, final String index) { - return new DepositParameter(pubKey, withdrawalCredentials, amount, signature, index); + return new DepositRequestParameter(pubKey, withdrawalCredentials, amount, signature, index); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameterTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositRequestRequestParameterTest.java similarity index 88% rename from ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameterTest.java rename to ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositRequestRequestParameterTest.java index 56dfed3fd4b..ce5780641be 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositParameterTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/DepositRequestRequestParameterTest.java @@ -20,18 +20,18 @@ import org.hyperledger.besu.datatypes.BLSPublicKey; import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt64; import org.junit.jupiter.api.Test; -public class DepositParameterTest { +public class DepositRequestRequestParameterTest { @Test public void toDeposit() { - Deposit expected = - new Deposit( + DepositRequest expected = + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( @@ -45,8 +45,8 @@ public void toDeposit() { @Test public void fromDeposit() { - Deposit deposit = - new Deposit( + DepositRequest depositRequest = + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( @@ -56,6 +56,6 @@ public void fromDeposit() { "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), UInt64.ONE); - assertThat(DepositParameter.fromDeposit(deposit)).isEqualTo(DEPOSIT_PARAM_1); + assertThat(DepositRequestParameter.fromDeposit(depositRequest)).isEqualTo(DEPOSIT_PARAM_1); } } diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index 103b8fdb667..856bf874b20 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -47,7 +47,7 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; @@ -76,7 +76,7 @@ import org.hyperledger.besu.ethereum.mainnet.WithdrawalsProcessor; import org.hyperledger.besu.ethereum.mainnet.feemarket.CancunFeeMarket; import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestProcessor; -import org.hyperledger.besu.ethereum.mainnet.requests.DepositsValidator; +import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestValidator; import org.hyperledger.besu.ethereum.mainnet.requests.RequestProcessorCoordinator; import org.hyperledger.besu.ethereum.mainnet.requests.RequestsValidatorCoordinator; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -106,7 +106,7 @@ abstract class AbstractBlockCreatorTest { protected EthScheduler ethScheduler = new DeterministicEthScheduler(); @Test - void findDepositsFromReceipts() { + void findDepositRequestsFromReceipts() { BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); TransactionReceipt receiptWithoutDeposit1 = blockDataGenerator.receipt(); TransactionReceipt receiptWithoutDeposit2 = blockDataGenerator.receipt(); @@ -122,8 +122,8 @@ void findDepositsFromReceipts() { List receipts = List.of(receiptWithoutDeposit1, receiptWithDeposit, receiptWithoutDeposit2); - Deposit expectedDeposit = - new Deposit( + DepositRequest expectedDepositRequest = + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( @@ -132,17 +132,17 @@ void findDepositsFromReceipts() { BLSSignature.fromHexString( "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), UInt64.valueOf(539967)); - final List expectedDeposits = List.of(expectedDeposit); + final List expectedDepositRequests = List.of(expectedDepositRequest); - var depositsFromReceipts = + var depositRequestsFromReceipts = new DepositRequestProcessor(DEFAULT_DEPOSIT_CONTRACT_ADDRESS).process(null, receipts); - assertThat(depositsFromReceipts.get()).isEqualTo(expectedDeposits); + assertThat(depositRequestsFromReceipts.get()).isEqualTo(expectedDepositRequests); } @Test - void withAllowedDepositsAndContractAddress_DepositsAreParsed() { + void withAllowedDepositRequestsAndContractAddress_DepositRequestsAreParsed() { final AbstractBlockCreator blockCreator = - blockCreatorWithAllowedDeposits(DEFAULT_DEPOSIT_CONTRACT_ADDRESS); + blockCreatorWithAllowedDepositRequests(DEFAULT_DEPOSIT_CONTRACT_ADDRESS); final BlockCreationResult blockCreationResult = blockCreator.createBlock( @@ -154,15 +154,15 @@ void withAllowedDepositsAndContractAddress_DepositsAreParsed() { 1L, false); - List deposits = emptyList(); - final Hash requestsRoot = BodyValidation.requestsRoot(deposits); + List depositRequests = emptyList(); + final Hash requestsRoot = BodyValidation.requestsRoot(depositRequests); assertThat(blockCreationResult.getBlock().getHeader().getRequestsRoot()).hasValue(requestsRoot); - assertThat(blockCreationResult.getBlock().getBody().getRequests()).hasValue(deposits); + assertThat(blockCreationResult.getBlock().getBody().getRequests()).hasValue(depositRequests); } @Test - void withAllowedDepositsAndNoContractAddress_DepositsAreNotParsed() { - final AbstractBlockCreator blockCreator = blockCreatorWithAllowedDeposits(null); + void withAllowedDepositRequestsAndNoContractAddress_DepositRequestsAreNotParsed() { + final AbstractBlockCreator blockCreator = blockCreatorWithAllowedDepositRequests(null); final BlockCreationResult blockCreationResult = blockCreator.createBlock( @@ -179,8 +179,8 @@ void withAllowedDepositsAndNoContractAddress_DepositsAreNotParsed() { } @Test - void withProhibitedDeposits_DepositsAreNotParsed() { - final AbstractBlockCreator blockCreator = blockCreatorWithProhibitedDeposits(); + void withProhibitedDepositRequests_DepositRequestsAreNotParsed() { + final AbstractBlockCreator blockCreator = blockCreatorWithProhibitedDepositRequests(); final BlockCreationResult blockCreationResult = blockCreator.createBlock( @@ -196,7 +196,7 @@ void withProhibitedDeposits_DepositsAreNotParsed() { assertThat(blockCreationResult.getBlock().getBody().getRequests()).isEmpty(); } - private AbstractBlockCreator blockCreatorWithAllowedDeposits( + private AbstractBlockCreator blockCreatorWithAllowedDepositRequests( final Address depositContractAddress) { final ProtocolSpecAdapters protocolSpecAdapters = ProtocolSpecAdapters.create( @@ -207,7 +207,7 @@ private AbstractBlockCreator blockCreatorWithAllowedDeposits( new RequestsValidatorCoordinator.Builder() .addValidator( RequestType.DEPOSIT, - new DepositsValidator((depositContractAddress))) + new DepositRequestValidator((depositContractAddress))) .build()) .requestProcessorCoordinator( new RequestProcessorCoordinator.Builder() @@ -218,7 +218,7 @@ private AbstractBlockCreator blockCreatorWithAllowedDeposits( return createBlockCreator(protocolSpecAdapters); } - private AbstractBlockCreator blockCreatorWithProhibitedDeposits() { + private AbstractBlockCreator blockCreatorWithProhibitedDepositRequests() { final ProtocolSpecAdapters protocolSpecAdapters = ProtocolSpecAdapters.create(0, specBuilder -> specBuilder); return createBlockCreator(protocolSpecAdapters); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockBody.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockBody.java index c14722edc24..4b8ab926137 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockBody.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockBody.java @@ -147,7 +147,7 @@ public static BlockBody readWrappedBodyFrom( /** * Read all fields from the block body expecting no list wrapping them. An example of a valid body - * would be: [txs],[ommers],[withdrawals],[deposits] this method is called directly when importing + * would be: [txs],[ommers],[withdrawals],[requests] this method is called directly when importing * a single block * * @param input The RLP-encoded input diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Deposit.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/DepositRequest.java similarity index 94% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Deposit.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/DepositRequest.java index 6a6476069e3..a005fa831e0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Deposit.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/DepositRequest.java @@ -25,7 +25,8 @@ import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt64; -public class Deposit extends Request implements org.hyperledger.besu.plugin.data.Deposit { +public class DepositRequest extends Request + implements org.hyperledger.besu.plugin.data.DepositRequest { private final BLSPublicKey pubkey; private final Bytes32 depositWithdrawalCredentials; @@ -33,7 +34,7 @@ public class Deposit extends Request implements org.hyperledger.besu.plugin.data private final BLSSignature signature; private final UInt64 index; - public Deposit( + public DepositRequest( final BLSPublicKey pubkey, final Bytes32 depositWithdrawalCredentials, final GWei amount, @@ -96,7 +97,7 @@ public String toString() { public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final Deposit that = (Deposit) o; + final DepositRequest that = (DepositRequest) o; return Objects.equals(pubkey, that.pubkey) && Objects.equals(depositWithdrawalCredentials, that.depositWithdrawalCredentials) && Objects.equals(amount, that.amount) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestDecoder.java similarity index 86% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoder.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestDecoder.java index 05fd5498e96..85b56e1a573 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestDecoder.java @@ -17,8 +17,8 @@ import org.hyperledger.besu.datatypes.BLSPublicKey; import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; -import org.hyperledger.besu.ethereum.core.Deposit; import org.hyperledger.besu.ethereum.core.DepositContract; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.evm.log.Log; @@ -30,9 +30,9 @@ import org.apache.tuweni.units.bigints.UInt64; import org.web3j.tx.Contract; -public class DepositDecoder { +public class DepositRequestDecoder { - public static Deposit decode(final RLPInput rlpInput) { + public static DepositRequest decode(final RLPInput rlpInput) { rlpInput.enterList(); final BLSPublicKey publicKey = BLSPublicKey.readFrom(rlpInput); final Bytes32 depositWithdrawalCredential = Bytes32.wrap(rlpInput.readBytes()); @@ -41,10 +41,10 @@ public static Deposit decode(final RLPInput rlpInput) { final UInt64 index = UInt64.valueOf(rlpInput.readBigIntegerScalar()); rlpInput.leaveList(); - return new Deposit(publicKey, depositWithdrawalCredential, amount, signature, index); + return new DepositRequest(publicKey, depositWithdrawalCredential, amount, signature, index); } - public static Deposit decodeFromLog(final Log log) { + public static DepositRequest decodeFromLog(final Log log) { Contract.EventValuesWithLog eventValues = DepositContract.staticExtractDepositEventWithLog(log); final byte[] rawPublicKey = (byte[]) eventValues.getNonIndexedValues().get(0).getValue(); final byte[] rawWithdrawalCredential = @@ -53,7 +53,7 @@ public static Deposit decodeFromLog(final Log log) { final byte[] rawSignature = (byte[]) eventValues.getNonIndexedValues().get(3).getValue(); final byte[] rawIndex = (byte[]) eventValues.getNonIndexedValues().get(4).getValue(); - return new Deposit( + return new DepositRequest( BLSPublicKey.wrap(Bytes.wrap(rawPublicKey)), Bytes32.wrap(Bytes.wrap(rawWithdrawalCredential)), GWei.of( @@ -64,7 +64,7 @@ public static Deposit decodeFromLog(final Log log) { UInt64.valueOf(Bytes.wrap(rawIndex).reverse().toLong())); } - public static Deposit decodeOpaqueBytes(final Bytes input) { + public static DepositRequest decodeOpaqueBytes(final Bytes input) { return decode(RLP.input(input)); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestEncoder.java similarity index 73% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoder.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestEncoder.java index f40a28a6320..a99b0b761ce 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestEncoder.java @@ -14,25 +14,25 @@ */ package org.hyperledger.besu.ethereum.core.encoding; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPOutput; import org.apache.tuweni.bytes.Bytes; -public class DepositEncoder { +public class DepositRequestEncoder { public static void encode(final Request request, final RLPOutput rlpOutput) { - if (!(request instanceof Deposit deposit)) { + if (!(request instanceof DepositRequest depositRequest)) { throw new IllegalArgumentException("The provided request is not of type deposit."); } rlpOutput.startList(); - rlpOutput.writeBytes(deposit.getPubkey()); - rlpOutput.writeBytes(deposit.getWithdrawalCredentials()); - rlpOutput.writeUInt64Scalar(deposit.getAmount()); - rlpOutput.writeBytes(deposit.getSignature()); - rlpOutput.writeUInt64Scalar(deposit.getIndex()); + rlpOutput.writeBytes(depositRequest.getPubkey()); + rlpOutput.writeBytes(depositRequest.getWithdrawalCredentials()); + rlpOutput.writeUInt64Scalar(depositRequest.getAmount()); + rlpOutput.writeBytes(depositRequest.getSignature()); + rlpOutput.writeUInt64Scalar(depositRequest.getIndex()); rlpOutput.endList(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestDecoder.java index 1eb85cc4aa8..4953cbb84ff 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestDecoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestDecoder.java @@ -41,7 +41,7 @@ interface Decoder { RequestType.WITHDRAWAL, WithdrawalRequestDecoder::decode, RequestType.DEPOSIT, - DepositDecoder::decode); + DepositRequestDecoder::decode); /** * Decodes a request from its RLP encoded bytes. diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestEncoder.java index d62d924a3cb..4f79da453ca 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestEncoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/RequestEncoder.java @@ -38,7 +38,7 @@ interface Encoder { RequestType.WITHDRAWAL, WithdrawalRequestEncoder::encode, RequestType.DEPOSIT, - DepositEncoder::encode); + DepositRequestEncoder::encode); /** * Encodes a Request into the provided RLPOutput. diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java index 766ce1f94e0..ce3ed6a5f65 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestProcessor.java @@ -15,11 +15,11 @@ package org.hyperledger.besu.ethereum.mainnet.requests; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.TransactionReceipt; -import org.hyperledger.besu.ethereum.core.encoding.DepositDecoder; +import org.hyperledger.besu.ethereum.core.encoding.DepositRequestDecoder; import java.util.Collections; import java.util.List; @@ -44,19 +44,20 @@ public Optional> process( if (depositContractAddress.isEmpty()) { return Optional.empty(); } - List deposits = findDepositsFromReceipts(transactionReceipts); - return Optional.of(deposits); + List depositRequests = findDepositRequestsFromReceipts(transactionReceipts); + return Optional.of(depositRequests); } @VisibleForTesting - List findDepositsFromReceipts(final List transactionReceipts) { + List findDepositRequestsFromReceipts( + final List transactionReceipts) { return depositContractAddress .map( address -> transactionReceipts.stream() .flatMap(receipt -> receipt.getLogsList().stream()) .filter(log -> address.equals(log.getLogger())) - .map(DepositDecoder::decodeFromLog) + .map(DepositRequestDecoder::decodeFromLog) .toList()) .orElse(Collections.emptyList()); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositsValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestValidator.java similarity index 68% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositsValidator.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestValidator.java index 6a2d3bdc587..6c9eedf305d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositsValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/DepositRequestValidator.java @@ -18,10 +18,10 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.Block; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.TransactionReceipt; -import org.hyperledger.besu.ethereum.core.encoding.DepositDecoder; +import org.hyperledger.besu.ethereum.core.encoding.DepositRequestDecoder; import org.hyperledger.besu.evm.log.Log; import java.util.ArrayList; @@ -32,44 +32,46 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class DepositsValidator implements RequestValidator { +public class DepositRequestValidator implements RequestValidator { - private static final Logger LOG = LoggerFactory.getLogger(DepositsValidator.class); + private static final Logger LOG = LoggerFactory.getLogger(DepositRequestValidator.class); private final Address depositContractAddress; - public DepositsValidator(final Address depositContractAddress) { + public DepositRequestValidator(final Address depositContractAddress) { this.depositContractAddress = depositContractAddress; } @Override - public boolean validateParameter(final Optional> deposits) { - return deposits.isPresent(); + public boolean validateParameter(final Optional> depositRequests) { + return depositRequests.isPresent(); } - public boolean validateDeposits( + public boolean validateDepositRequests( final Block block, - final List actualDeposits, + final List actualDepositRequests, final List receipts) { - List expectedDeposits = new ArrayList<>(); + List expectedDepositRequests = new ArrayList<>(); for (TransactionReceipt receipt : receipts) { for (Log log : receipt.getLogsList()) { if (depositContractAddress.equals(log.getLogger())) { - Deposit deposit = DepositDecoder.decodeFromLog(log); - expectedDeposits.add(deposit); + DepositRequest depositRequest = DepositRequestDecoder.decodeFromLog(log); + expectedDepositRequests.add(depositRequest); } } } - boolean isValid = actualDeposits.equals(expectedDeposits); + boolean isValid = actualDepositRequests.equals(expectedDepositRequests); if (!isValid) { LOG.warn( "Deposits validation failed. Deposits from block body do not match deposits from logs. Block hash: {}", block.getHash()); LOG.debug( - "Deposits from logs: {}, deposits from block body: {}", expectedDeposits, actualDeposits); + "Deposits from logs: {}, deposits from block body: {}", + expectedDepositRequests, + actualDepositRequests); } return isValid; @@ -78,7 +80,7 @@ public boolean validateDeposits( @Override public boolean validate( final Block block, final List requests, final List receipts) { - var deposits = getDepositRequests(Optional.of(requests)).orElse(Collections.emptyList()); - return validateDeposits(block, deposits, receipts); + var depositRequests = getDepositRequests(Optional.of(requests)).orElse(Collections.emptyList()); + return validateDepositRequests(block, depositRequests, receipts); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/MainnetRequestsValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/MainnetRequestsValidator.java index 9f9b4539d00..56e47aea50b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/MainnetRequestsValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/MainnetRequestsValidator.java @@ -22,7 +22,7 @@ public static RequestsValidatorCoordinator pragueRequestsValidator( final Address depositContractAddress) { return new RequestsValidatorCoordinator.Builder() .addValidator(RequestType.WITHDRAWAL, new WithdrawalRequestValidator()) - .addValidator(RequestType.DEPOSIT, new DepositsValidator(depositContractAddress)) + .addValidator(RequestType.DEPOSIT, new DepositRequestValidator(depositContractAddress)) .build(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java index 3d85fc48f52..459fdbe110a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestUtil.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet.requests; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.WithdrawalRequest; @@ -42,8 +42,9 @@ public static List filterRequestsOfType( return requests.stream().filter(requestType::isInstance).map(requestType::cast).toList(); } - public static Optional> getDepositRequests(final Optional> requests) { - return requests.map(r -> filterRequestsOfType(r, Deposit.class)); + public static Optional> getDepositRequests( + final Optional> requests) { + return requests.map(r -> filterRequestsOfType(r, DepositRequest.class)); } public static Optional> getWithdrawalRequests( @@ -54,19 +55,19 @@ public static Optional> getWithdrawalRequests( /** * Combines two optional lists of requests into a single optional list. * - * @param maybeDeposits Optional list of deposit requests. + * @param maybeDepositRequests Optional list of deposit requests. * @param maybeWithdrawalRequest Optional list of withdrawal requests. * @return An Optional containing the combined list of requests, or an empty Optional if both * inputs are empty. */ public static Optional> combine( - final Optional> maybeDeposits, + final Optional> maybeDepositRequests, final Optional> maybeWithdrawalRequest) { - if (maybeDeposits.isEmpty() && maybeWithdrawalRequest.isEmpty()) { + if (maybeDepositRequests.isEmpty() && maybeWithdrawalRequest.isEmpty()) { return Optional.empty(); } List requests = new ArrayList<>(); - maybeDeposits.ifPresent(requests::addAll); + maybeDepositRequests.ifPresent(requests::addAll); maybeWithdrawalRequest.ifPresent(requests::addAll); return Optional.of(requests); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestRequestDecoderTest.java similarity index 88% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoderTest.java rename to ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestRequestDecoderTest.java index 131cd089972..0a6cee956d1 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositDecoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestRequestDecoderTest.java @@ -20,7 +20,7 @@ import org.hyperledger.besu.datatypes.BLSPublicKey; import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.evm.log.Log; import org.hyperledger.besu.evm.log.LogTopic; @@ -31,11 +31,11 @@ import org.apache.tuweni.units.bigints.UInt64; import org.junit.jupiter.api.Test; -class DepositDecoderTest { +class DepositRequestRequestDecoderTest { @Test void shouldDecodeDeposit() { - final Deposit expectedDeposit = - new Deposit( + final DepositRequest expectedDepositRequest = + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( @@ -45,12 +45,12 @@ void shouldDecodeDeposit() { "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), UInt64.ONE); - final Deposit deposit = - DepositDecoder.decodeOpaqueBytes( + final DepositRequest depositRequest = + DepositRequestDecoder.decodeOpaqueBytes( Bytes.fromHexString( "0xf8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501")); - assertThat(deposit).isEqualTo(expectedDeposit); + assertThat(depositRequest).isEqualTo(expectedDepositRequest); } @Test @@ -65,10 +65,10 @@ void shouldDecodeDepositFromLog() { "0x00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483000000000000000000000000000000000000000000000000000000000000000800405973070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb500000000000000000000000000000000000000000000000000000000000000083f3d080000000000000000000000000000000000000000000000000000000000"); final Log log = new Log(address, data, topics); - final Deposit deposit = DepositDecoder.decodeFromLog(log); + final DepositRequest depositRequest = DepositRequestDecoder.decodeFromLog(log); - final Deposit expectedDeposit = - new Deposit( + final DepositRequest expectedDepositRequest = + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( @@ -78,6 +78,6 @@ void shouldDecodeDepositFromLog() { "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), UInt64.valueOf(539967)); - assertThat(deposit).isEqualTo(expectedDeposit); + assertThat(depositRequest).isEqualTo(expectedDepositRequest); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestRequestEncoderTest.java similarity index 87% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoderTest.java rename to ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestRequestEncoderTest.java index 7b4052cffb3..8f0de595f68 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositEncoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/DepositRequestRequestEncoderTest.java @@ -19,19 +19,19 @@ import org.hyperledger.besu.datatypes.BLSPublicKey; import org.hyperledger.besu.datatypes.BLSSignature; import org.hyperledger.besu.datatypes.GWei; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.units.bigints.UInt64; import org.junit.jupiter.api.Test; -class DepositEncoderTest { +class DepositRequestRequestEncoderTest { private final String expectedDepositEncodedBytes = "f8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501"; - final Deposit deposit = - new Deposit( + final DepositRequest depositRequest = + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( @@ -43,19 +43,19 @@ class DepositEncoderTest { @Test void shouldEncodeDeposit() { - final Bytes encoded = DepositEncoder.encodeOpaqueBytes(deposit); + final Bytes encoded = DepositRequestEncoder.encodeOpaqueBytes(depositRequest); assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedDepositEncodedBytes)); } @Test void shouldEncodeDepositRequest() { - final Bytes encoded = RequestEncoder.encodeOpaqueBytes(deposit); + final Bytes encoded = RequestEncoder.encodeOpaqueBytes(depositRequest); // Request encoding is Request = RequestType ++ RequestData assertThat(encoded) .isEqualTo( Bytes.fromHexString( String.format( "0x%02X%s", - deposit.getType().getSerializedType(), expectedDepositEncodedBytes))); + depositRequest.getType().getSerializedType(), expectedDepositEncodedBytes))); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositRequestValidatorTest.java similarity index 83% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidatorTest.java rename to ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositRequestValidatorTest.java index 99eae1437a6..0360032388b 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositsValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/DepositRequestValidatorTest.java @@ -23,10 +23,10 @@ import org.hyperledger.besu.datatypes.RequestType; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockDataGenerator; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.TransactionReceipt; -import org.hyperledger.besu.ethereum.mainnet.requests.DepositsValidator; +import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestValidator; import org.hyperledger.besu.ethereum.mainnet.requests.RequestsValidatorCoordinator; import org.hyperledger.besu.ethereum.mainnet.requests.WithdrawalRequestValidator; import org.hyperledger.besu.evm.log.Log; @@ -41,20 +41,20 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -public class DepositsValidatorTest { +public class DepositRequestValidatorTest { private final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); - private static Deposit DEPOSIT_1; - private static Deposit DEPOSIT_2; + private static DepositRequest depositRequest1; + private static DepositRequest depositRequest2; private static Log LOG_1; private static Log LOG_2; private static Address DEPOSIT_CONTRACT_ADDRESS; private static RequestsValidatorCoordinator requestsValidatorCoordinator; - private static DepositsValidator depositsValidator; + private static DepositRequestValidator depositRequestValidator; @BeforeAll public static void setup() { - DEPOSIT_1 = - new Deposit( + depositRequest1 = + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( @@ -64,8 +64,8 @@ public static void setup() { "0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"), UInt64.valueOf(539967)); - DEPOSIT_2 = - new Deposit( + depositRequest2 = + new DepositRequest( BLSPublicKey.fromHexString( "0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243"), Bytes32.fromHexString( @@ -97,8 +97,8 @@ public static void setup() { } @Test - public void validateAllowedDeposits() { - final List request = List.of(DEPOSIT_1, DEPOSIT_2); + public void validateAllowedDepositRequests() { + final List request = List.of(depositRequest1, depositRequest2); final BlockDataGenerator.BlockOptions blockOptions = BlockDataGenerator.BlockOptions.create() .setRequests(Optional.of(request)) @@ -113,9 +113,9 @@ public void validateAllowedDeposits() { } @Test - public void validateAllowedDepositsSeparateReceipts() { + public void validateAllowedDepositRequestsSeparateReceipts() { - final List requests = List.of(DEPOSIT_1, DEPOSIT_2); + final List requests = List.of(depositRequest1, depositRequest2); final BlockDataGenerator.BlockOptions blockOptions = BlockDataGenerator.BlockOptions.create() @@ -135,9 +135,9 @@ public void validateAllowedDepositsSeparateReceipts() { } @Test - public void invalidateAllowedDeposits() { + public void invalidateAllowedDepositRequests() { final BlockDataGenerator.BlockOptions blockOptions = - BlockDataGenerator.BlockOptions.create().setRequests(Optional.of(List.of(DEPOSIT_1))); + BlockDataGenerator.BlockOptions.create().setRequests(Optional.of(List.of(depositRequest1))); final Block block = blockDataGenerator.block(blockOptions); final TransactionReceipt receipt1 = @@ -149,10 +149,10 @@ public void invalidateAllowedDeposits() { } @Test - public void invalidateAllowedDepositsMissingLogInReceipt() { + public void invalidateAllowedDepositRequestsMissingLogInReceipt() { final BlockDataGenerator.BlockOptions blockOptions = BlockDataGenerator.BlockOptions.create() - .setRequests(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + .setRequests(Optional.of(List.of(depositRequest1, depositRequest2))); final Block block = blockDataGenerator.block(blockOptions); final TransactionReceipt receipt1 = @@ -164,9 +164,9 @@ public void invalidateAllowedDepositsMissingLogInReceipt() { } @Test - public void invalidateAllowedDepositsExtraLogInReceipt() { + public void invalidateAllowedDepositRequestsExtraLogInReceipt() { final BlockDataGenerator.BlockOptions blockOptions = - BlockDataGenerator.BlockOptions.create().setRequests(Optional.of(List.of(DEPOSIT_1))); + BlockDataGenerator.BlockOptions.create().setRequests(Optional.of(List.of(depositRequest1))); final Block block = blockDataGenerator.block(blockOptions); final TransactionReceipt receipt1 = @@ -178,10 +178,10 @@ public void invalidateAllowedDepositsExtraLogInReceipt() { } @Test - public void invalidateAllowedDepositsWrongOrder() { + public void invalidateAllowedDepositRequestsWrongOrder() { final BlockDataGenerator.BlockOptions blockOptions = BlockDataGenerator.BlockOptions.create() - .setRequests(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + .setRequests(Optional.of(List.of(depositRequest1, depositRequest2))); final Block block = blockDataGenerator.block(blockOptions); final TransactionReceipt receipt1 = @@ -193,11 +193,11 @@ public void invalidateAllowedDepositsWrongOrder() { } @Test - public void invalidateAllowedDepositsMismatchContractAddress() { + public void invalidateAllowedDepositRequestsMismatchContractAddress() { final BlockDataGenerator.BlockOptions blockOptions = BlockDataGenerator.BlockOptions.create() - .setRequests(Optional.of(List.of(DEPOSIT_1, DEPOSIT_2))); + .setRequests(Optional.of(List.of(depositRequest1, depositRequest2))); final Block block = blockDataGenerator.block(blockOptions); final TransactionReceipt receipt1 = @@ -210,24 +210,25 @@ public void invalidateAllowedDepositsMismatchContractAddress() { @Test public void validateAllowedDepositParams() { - final Optional> deposits = Optional.of(List.of(DEPOSIT_1, DEPOSIT_2)); - assertThat(depositsValidator.validateParameter(deposits)).isTrue(); + final Optional> depositRequests = + Optional.of(List.of(depositRequest1, depositRequest2)); + assertThat(depositRequestValidator.validateParameter(depositRequests)).isTrue(); - final Optional> emptyDeposits = Optional.of(List.of()); - assertThat(depositsValidator.validateParameter(emptyDeposits)).isTrue(); + final Optional> emptyDepositRequests = Optional.of(List.of()); + assertThat(depositRequestValidator.validateParameter(emptyDepositRequests)).isTrue(); } @Test public void invalidateAllowedDepositParams() { - final Optional> deposits = Optional.empty(); - assertThat(depositsValidator.validateParameter(deposits)).isFalse(); + final Optional> depositRequests = Optional.empty(); + assertThat(depositRequestValidator.validateParameter(depositRequests)).isFalse(); } static RequestsValidatorCoordinator createAllowDepositValidator() { - depositsValidator = new DepositsValidator(DEPOSIT_CONTRACT_ADDRESS); + depositRequestValidator = new DepositRequestValidator(DEPOSIT_CONTRACT_ADDRESS); return new RequestsValidatorCoordinator.Builder() .addValidator(RequestType.WITHDRAWAL, new WithdrawalRequestValidator()) - .addValidator(RequestType.DEPOSIT, depositsValidator) + .addValidator(RequestType.DEPOSIT, depositRequestValidator) .build(); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java index dfc1f2d0436..c116d545d80 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockBodyValidatorTest.java @@ -28,7 +28,7 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.Withdrawal; -import org.hyperledger.besu.ethereum.mainnet.requests.DepositsValidator; +import org.hyperledger.besu.ethereum.mainnet.requests.DepositRequestValidator; import org.hyperledger.besu.ethereum.mainnet.requests.RequestsValidatorCoordinator; import org.hyperledger.besu.evm.log.LogsBloomFilter; @@ -53,7 +53,7 @@ class MainnetBlockBodyValidatorTest { @Mock private ProtocolSchedule protocolSchedule; @Mock private ProtocolSpec protocolSpec; @Mock private WithdrawalsValidator withdrawalsValidator; - @Mock private DepositsValidator depositsValidator; + @Mock private DepositRequestValidator depositRequestValidator; @Mock private RequestsValidatorCoordinator requestValidator; @BeforeEach @@ -64,7 +64,9 @@ public void setUp() { lenient().when(withdrawalsValidator.validateWithdrawals(any())).thenReturn(true); lenient().when(withdrawalsValidator.validateWithdrawalsRoot(any())).thenReturn(true); - lenient().when(depositsValidator.validateDeposits(any(), any(), any())).thenReturn(true); + lenient() + .when(depositRequestValidator.validateDepositRequests(any(), any(), any())) + .thenReturn(true); lenient().when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(requestValidator); lenient().when(requestValidator.validate(any(), any(), any())).thenReturn(true); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBodiesFromPeerTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBodiesFromPeerTaskTest.java index b6c635551dd..b8546ad532d 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBodiesFromPeerTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBodiesFromPeerTaskTest.java @@ -24,7 +24,7 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.core.WithdrawalRequest; @@ -89,9 +89,9 @@ public void assertBodyIdentifierUsesWithdrawalsToGenerateBodyIdentifiers() { } @Test - public void assertBodyIdentifierUsesDepositsToGenerateBodyIdentifiers() { + public void assertBodyIdentifierUsesDepositRequestsToGenerateBodyIdentifiers() { final Request deposit = - new Deposit( + new DepositRequest( BLSPublicKey.fromHexString( "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"), Bytes32.fromHexString( diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java index ee84eba4d17..6e48aaf82ca 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java @@ -32,7 +32,7 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.Deposit; +import org.hyperledger.besu.ethereum.core.DepositRequest; import org.hyperledger.besu.ethereum.core.Request; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionReceipt; @@ -466,7 +466,7 @@ static T8nResult runTest( resultObject.put("requestsRoot", requestRoot.toHexString()); var deposits = resultObject.putArray("depositRequests"); - RequestUtil.filterRequestsOfType(maybeRequests.orElse(List.of()), Deposit.class) + RequestUtil.filterRequestsOfType(maybeRequests.orElse(List.of()), DepositRequest.class) .forEach( deposit -> { var obj = deposits.addObject(); diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index a25774205b7..fd7f3291b3b 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -70,7 +70,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'zgPAgf+ZxefbnCE9aYEQ5QoeBVsHySi3u+BlhHNHqn8=' + knownHash = 'p8jZoKgvi9o8JpVLXTlwh9HoIot4A62hKFHwSOaTF+k=' } check.dependsOn('checkAPIChanges') diff --git a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/Deposit.java b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/DepositRequest.java similarity index 98% rename from plugin-api/src/main/java/org/hyperledger/besu/plugin/data/Deposit.java rename to plugin-api/src/main/java/org/hyperledger/besu/plugin/data/DepositRequest.java index 6ad30217ac7..096554d3c74 100644 --- a/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/Deposit.java +++ b/plugin-api/src/main/java/org/hyperledger/besu/plugin/data/DepositRequest.java @@ -27,7 +27,7 @@ * to beacon chain. */ @Unstable -public interface Deposit { +public interface DepositRequest { /** * Public key of the address that sends the deposit From d7c028966dfaa1db6f6178f772ccf6c6c698ed3a Mon Sep 17 00:00:00 2001 From: Chaminda Divitotawela Date: Thu, 30 May 2024 12:22:37 +1000 Subject: [PATCH 10/42] Release process has been broken down to pre-release and release to allow user testing. This is not required and adds additional step. Release workflows are combined into a single release workflow which trigger on a release (#7152) Signed-off-by: Chaminda Divitotawela --- .github/workflows/artifacts.yml | 120 ---------------- .github/workflows/docker.yml | 123 ---------------- .github/workflows/release.yml | 239 +++++++++++++++++++++++++++++++- 3 files changed, 238 insertions(+), 244 deletions(-) delete mode 100644 .github/workflows/artifacts.yml delete mode 100644 .github/workflows/docker.yml diff --git a/.github/workflows/artifacts.yml b/.github/workflows/artifacts.yml deleted file mode 100644 index 657c4ebcbae..00000000000 --- a/.github/workflows/artifacts.yml +++ /dev/null @@ -1,120 +0,0 @@ - -name: release artifacts - -on: - release: - types: - - prereleased -env: - GRADLE_OPTS: "-Dorg.gradle.parallel=true -Dorg.gradle.caching=true" - -jobs: - artifacts: - runs-on: ubuntu-22.04 - permissions: - contents: write - outputs: - tarSha: ${{steps.hashes.outputs.tarSha}} - zipSha: ${{steps.hashes.outputs.zipSha}} - steps: - - name: checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Set up JDK 17 - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 - with: - distribution: 'temurin' - java-version: '17' - - name: setup gradle - uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 - with: - cache-disabled: true - - name: assemble release - run: - ./gradlew -Prelease.releaseVersion=${{github.event.release.name}} -Pversion=${{github.event.release.name}} assemble - - name: hashes - id: hashes - run: | - cd build/distributions - echo "zipSha=$(shasum -a 256 besu*.zip)" - echo "tarSha=$(shasum -a 256 besu*.tar.gz)" - echo "zipSha=$(shasum -a 256 besu*.zip)" >> $GITHUB_OUTPUT - echo "tarSha=$(shasum -a 256 besu*.tar.gz)" >> $GITHUB_OUTPUT - - name: upload tarball - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 - with: - path: 'build/distributions/besu*.tar.gz' - name: besu-${{ github.event.release.name }}.tar.gz - compression-level: 0 - - name: upload zipfile - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 - with: - path: 'build/distributions/besu*.zip' - name: besu-${{ github.event.release.name }}.zip - compression-level: 0 - - testWindows: - runs-on: windows-2022 - needs: artifacts - timeout-minutes: 10 - steps: - - name: Set up Java - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 - with: - distribution: adopt - java-version: 17 - - name: Download zip - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe - with: - pattern: besu-*.zip - merge-multiple: true - - name: test Besu - run: | - dir - unzip besu-*.zip -d besu-tmp - cd besu-tmp - mv besu-* ../besu - cd .. - besu\bin\besu.bat --help - besu\bin\besu.bat --version - publish: - runs-on: ubuntu-22.04 - needs: [artifacts, testWindows] - permissions: - contents: write - steps: - - name: Download archives - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe - with: - pattern: besu-* - merge-multiple: true - path: 'build/distributions' - - name: Upload Release assets - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 - with: - append_body: true - files: | - build/distributions/besu*.tar.gz - build/distributions/besu*.zip - body: | - ${{needs.artifacts.outputs.tarSha}} - ${{needs.artifacts.outputs.zipSha}} - artifactoryPublish: - runs-on: ubuntu-22.04 - needs: artifacts - steps: - - name: checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Set up JDK 17 - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 - with: - distribution: 'temurin' - java-version: '17' - - name: setup gradle - uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 - with: - cache-disabled: true - - name: Artifactory Publish - env: - ARTIFACTORY_USER: ${{ secrets.BESU_ARTIFACTORY_USER }} - ARTIFACTORY_KEY: ${{ secrets.BESU_ARTIFACTORY_TOKEN }} - run: ./gradlew -Prelease.releaseVersion=${{ github.event.release.name }} -Pversion=${{github.event.release.name}} artifactoryPublish \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index 5cb78f215d4..00000000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: docker -on: - release: - types: - - prereleased -env: - registry: docker.io - -jobs: - hadolint: - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Set up Java - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 - with: - distribution: temurin - java-version: 17 - - name: setup gradle - uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 - with: - cache-disabled: true - - name: hadoLint - run: docker run --rm -i hadolint/hadolint < docker/Dockerfile - buildDocker: - needs: hadolint - permissions: - contents: read - packages: write - - strategy: - fail-fast: false - matrix: - platform: - - ubuntu-22.04 - - [self-hosted, ARM64] - runs-on: ${{ matrix.platform }} - steps: - - name: Prepare - id: prep - run: | - platform=${{ matrix.platform }} - if [ "$platform" = 'ubuntu-22.04' ]; then - echo "PLATFORM_PAIR=linux-amd64" >> $GITHUB_OUTPUT - echo "ARCH=amd64" >> $GITHUB_OUTPUT - else - echo "PLATFORM_PAIR=linux-arm64" >> $GITHUB_OUTPUT - echo "ARCH=arm64" >> $GITHUB_OUTPUT - fi - - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: short sha - id: shortSha - run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - name: Set up Java - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 - with: - distribution: temurin - java-version: 17 - - name: setup gradle - uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 - with: - cache-disabled: true - - name: install goss - run: | - mkdir -p docker/reports - curl -L https://github.com/aelsabbahy/goss/releases/download/v0.4.4/goss-${{ steps.prep.outputs.PLATFORM_PAIR }} -o ./docker/tests/goss-${{ steps.prep.outputs.PLATFORM_PAIR }} - - name: login to ${{ env.registry }} - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d - with: - registry: ${{ env.registry }} - username: ${{ secrets.DOCKER_USER_RW }} - password: ${{ secrets.DOCKER_PASSWORD_RW }} - - name: build and test docker - uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 - env: - architecture: ${{ steps.prep.outputs.ARCH }} - with: - cache-disabled: true - arguments: testDocker -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{github.event.release.name}} -Prelease.releaseVersion=${{ github.event.release.name }} - - name: publish - env: - architecture: ${{ steps.prep.outputs.ARCH }} - run: ./gradlew --no-daemon dockerUpload -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{github.event.release.name}} -Prelease.releaseVersion=${{ github.event.release.name }} - multiArch: - needs: buildDocker - runs-on: ubuntu-22.04 - permissions: - contents: read - packages: write - steps: - - name: Checkout Repo - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Set up Java - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 - with: - distribution: temurin - java-version: 17 - - name: setup gradle - uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 - with: - cache-disabled: true - - name: login to ${{ env.registry }} - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d - with: - registry: ${{ env.registry }} - username: ${{ secrets.DOCKER_USER_RW }} - password: ${{ secrets.DOCKER_PASSWORD_RW }} - - name: multi-arch docker - run: ./gradlew manifestDocker -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{github.event.release.name}} -Prelease.releaseVersion=${{ github.event.release.name }} - amendNotes: - needs: multiArch - runs-on: ubuntu-22.04 - permissions: - contents: write - steps: - - name: add pull command to release notes - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 - with: - append_body: true - body: | - `docker pull ${{env.registry}}/${{secrets.DOCKER_ORG}}/besu:${{github.event.release.name}}` diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8d8b4c8e79c..2e703623ebf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,11 +1,248 @@ -name: release besu +name: release + on: release: types: [released] + env: registry: docker.io + GRADLE_OPTS: "-Dorg.gradle.parallel=true -Dorg.gradle.caching=true" + jobs: + artifacts: + runs-on: ubuntu-22.04 + permissions: + contents: write + outputs: + tarSha: ${{steps.hashes.outputs.tarSha}} + zipSha: ${{steps.hashes.outputs.zipSha}} + steps: + - name: checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - name: Set up JDK 17 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 + with: + distribution: 'temurin' + java-version: '17' + - name: setup gradle + uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 + with: + cache-disabled: true + - name: assemble release + run: + ./gradlew -Prelease.releaseVersion=${{github.event.release.name}} -Pversion=${{github.event.release.name}} assemble + - name: hashes + id: hashes + run: | + cd build/distributions + echo "zipSha=$(shasum -a 256 besu*.zip)" + echo "tarSha=$(shasum -a 256 besu*.tar.gz)" + echo "zipSha=$(shasum -a 256 besu*.zip)" >> $GITHUB_OUTPUT + echo "tarSha=$(shasum -a 256 besu*.tar.gz)" >> $GITHUB_OUTPUT + - name: upload tarball + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 + with: + path: 'build/distributions/besu*.tar.gz' + name: besu-${{ github.event.release.name }}.tar.gz + compression-level: 0 + - name: upload zipfile + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 + with: + path: 'build/distributions/besu*.zip' + name: besu-${{ github.event.release.name }}.zip + compression-level: 0 + + testWindows: + runs-on: windows-2022 + needs: artifacts + timeout-minutes: 10 + steps: + - name: Set up Java + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 + with: + distribution: adopt + java-version: 17 + - name: Download zip + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe + with: + pattern: besu-*.zip + merge-multiple: true + - name: test Besu + run: | + dir + unzip besu-*.zip -d besu-tmp + cd besu-tmp + mv besu-* ../besu + cd .. + besu\bin\besu.bat --help + besu\bin\besu.bat --version + + publish: + runs-on: ubuntu-22.04 + needs: [testWindows] + permissions: + contents: write + steps: + - name: Download archives + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe + with: + pattern: besu-* + merge-multiple: true + path: 'build/distributions' + - name: Upload Release assets + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 + with: + append_body: true + files: | + build/distributions/besu*.tar.gz + build/distributions/besu*.zip + body: | + ${{needs.artifacts.outputs.tarSha}} + ${{needs.artifacts.outputs.zipSha}} + + + + artifactoryPublish: + runs-on: ubuntu-22.04 + needs: artifacts + steps: + - name: checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - name: Set up JDK 17 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 + with: + distribution: 'temurin' + java-version: '17' + - name: setup gradle + uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 + with: + cache-disabled: true + - name: Artifactory Publish + env: + ARTIFACTORY_USER: ${{ secrets.BESU_ARTIFACTORY_USER }} + ARTIFACTORY_KEY: ${{ secrets.BESU_ARTIFACTORY_TOKEN }} + run: ./gradlew -Prelease.releaseVersion=${{ github.event.release.name }} -Pversion=${{github.event.release.name}} artifactoryPublish + + hadolint: + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - name: Set up Java + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 + with: + distribution: temurin + java-version: 17 + - name: setup gradle + uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 + with: + cache-disabled: true + - name: hadoLint + run: docker run --rm -i hadolint/hadolint < docker/Dockerfile + + buildDocker: + needs: hadolint + permissions: + contents: read + packages: write + + strategy: + fail-fast: false + matrix: + platform: + - ubuntu-22.04 + - [self-hosted, ARM64] + runs-on: ${{ matrix.platform }} + steps: + - name: Prepare + id: prep + run: | + platform=${{ matrix.platform }} + if [ "$platform" = 'ubuntu-22.04' ]; then + echo "PLATFORM_PAIR=linux-amd64" >> $GITHUB_OUTPUT + echo "ARCH=amd64" >> $GITHUB_OUTPUT + else + echo "PLATFORM_PAIR=linux-arm64" >> $GITHUB_OUTPUT + echo "ARCH=arm64" >> $GITHUB_OUTPUT + fi + - name: Checkout Repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - name: short sha + id: shortSha + run: echo "sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + - name: Set up Java + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 + with: + distribution: temurin + java-version: 17 + - name: setup gradle + uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 + with: + cache-disabled: true + - name: install goss + run: | + mkdir -p docker/reports + curl -L https://github.com/aelsabbahy/goss/releases/download/v0.4.4/goss-${{ steps.prep.outputs.PLATFORM_PAIR }} -o ./docker/tests/goss-${{ steps.prep.outputs.PLATFORM_PAIR }} + - name: login to ${{ env.registry }} + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d + with: + registry: ${{ env.registry }} + username: ${{ secrets.DOCKER_USER_RW }} + password: ${{ secrets.DOCKER_PASSWORD_RW }} + - name: build and test docker + uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 + env: + architecture: ${{ steps.prep.outputs.ARCH }} + with: + cache-disabled: true + arguments: testDocker -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{github.event.release.name}} -Prelease.releaseVersion=${{ github.event.release.name }} + - name: publish + env: + architecture: ${{ steps.prep.outputs.ARCH }} + run: ./gradlew --no-daemon dockerUpload -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{github.event.release.name}} -Prelease.releaseVersion=${{ github.event.release.name }} + + multiArch: + needs: buildDocker + runs-on: ubuntu-22.04 + permissions: + contents: read + packages: write + steps: + - name: Checkout Repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - name: Set up Java + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 + with: + distribution: temurin + java-version: 17 + - name: setup gradle + uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 + with: + cache-disabled: true + - name: login to ${{ env.registry }} + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d + with: + registry: ${{ env.registry }} + username: ${{ secrets.DOCKER_USER_RW }} + password: ${{ secrets.DOCKER_PASSWORD_RW }} + - name: multi-arch docker + run: ./gradlew manifestDocker -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{github.event.release.name}} -Prelease.releaseVersion=${{ github.event.release.name }} + + amendNotes: + needs: multiArch + runs-on: ubuntu-22.04 + permissions: + contents: write + steps: + - name: add pull command to release notes + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 + with: + append_body: true + body: | + `docker pull ${{env.registry}}/${{secrets.DOCKER_ORG}}/besu:${{github.event.release.name}}` + dockerPromoteX64: + needs: multiArch runs-on: ubuntu-22.04 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 From 812886660fd23413dc7c9ef8f609c13e9cd711cc Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Thu, 30 May 2024 14:44:55 +0200 Subject: [PATCH 11/42] Cleanup transition steps used to update test reports on main (#7158) Signed-off-by: Fabio Di Fabio --- .github/workflows/acceptance-tests.yml | 13 ++----------- .github/workflows/pre-review.yml | 9 --------- .github/workflows/splitTestsByTime.sh | 2 +- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index c188c9564e6..38a4272bdc4 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -12,7 +12,7 @@ concurrency: env: GRADLE_OPTS: "-Xmx6g" - total-runners: 10 + total-runners: 12 jobs: acceptanceTestEthereum: @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: true matrix: - runner_index: [0,1,2,3,4,5,6,7,8,9] + runner_index: [0,1,2,3,4,5,6,7,8,9,10,11] steps: - name: Checkout Repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 @@ -45,15 +45,6 @@ jobs: run: ./gradlew acceptanceTestNotPrivacy --test-dry-run -Dorg.gradle.parallel=true -Dorg.gradle.caching=true - name: Extract current test list run: mkdir tmp; find . -type f -name TEST-*.xml | xargs -I{} bash -c "xmlstarlet sel -t -v '/testsuite/@name' '{}'; echo ' acceptanceTestNotPrivacy'" | tee tmp/currentTests.list - - name: Get acceptance test reports (Support transition) # can be removed after PR is merged - uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d - continue-on-error: true - with: - branch: main - name_is_regexp: true - name: 'acceptance-node-\d+-test-results' - path: tmp/junit-xml-reports-downloaded - if_no_artifact_found: true - name: Get acceptance test reports uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d continue-on-error: true diff --git a/.github/workflows/pre-review.yml b/.github/workflows/pre-review.yml index 0628d2ee667..ce7d0e7c137 100644 --- a/.github/workflows/pre-review.yml +++ b/.github/workflows/pre-review.yml @@ -104,15 +104,6 @@ jobs: run: ./gradlew test --test-dry-run -Dorg.gradle.parallel=true -Dorg.gradle.caching=true - name: Extract current test list run: mkdir tmp; find . -type f -name TEST-*.xml | xargs -I{} bash -c "xmlstarlet sel -t -v '/testsuite/@name' '{}'; echo '{}' | sed 's#\./\(.*\)/build/test-results/.*# \1#'" | tee tmp/currentTests.list - - name: Get unit test reports (Support transition) # can be removed after PR is merged - uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d - continue-on-error: true - with: - branch: main - name_is_regexp: true - name: 'unit-.*-test-results' - path: tmp/junit-xml-reports-downloaded - if_no_artifact_found: true - name: Get unit test reports uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d continue-on-error: true diff --git a/.github/workflows/splitTestsByTime.sh b/.github/workflows/splitTestsByTime.sh index 3ef075d6b97..219d2d74e78 100755 --- a/.github/workflows/splitTestsByTime.sh +++ b/.github/workflows/splitTestsByTime.sh @@ -46,7 +46,7 @@ for line in "${sorted[@]}"; do module_dir=${line_parts[2]} test_with_module="$test_name $module_dir" - # temp deduplication during the transition phase + # deduplication check to avoid executing a test multiple time if grep -F -q --line-regexp "$test_with_module" tmp/processedTests.list then continue From e68c4e1d804733518166d92f780ac66ff66edf28 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Thu, 30 May 2024 11:24:12 -0600 Subject: [PATCH 12/42] Undo #6819 - make yParity and v match (#7139) Undo PR #6819 - for 2030 and 1559 transactions both v and yParity will be provided, and they will be the same number. Signed-off-by: Danno Ferrin --- CHANGELOG.md | 1 + .../pojoadapter/TransactionAdapter.java | 9 +++++- .../results/TransactionCompleteResult.java | 2 +- .../results/TransactionPendingResult.java | 2 +- .../PendingTransactionDetailResult.java | 2 +- .../api/graphql/eth_getBlock_frontier.json | 29 +++++++++++++++++++ .../api/graphql/eth_getBlock_shanghai.json | 10 ++++++- .../api/graphql/eth_getTransaction_type2.json | 2 +- ...th_getBlockByNumber_complete_shanghai.json | 2 +- .../besu/ethereum/core/Transaction.java | 8 ++--- 10 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_frontier.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 176f56decae..d4021309744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ ### Bug fixes - Fix parsing `gasLimit` parameter when its value is > `Long.MAX_VALUE` [#7116](https://github.com/hyperledger/besu/pull/7116) - Skip validation of withdrawals when importing BFT blocks since withdrawals don't apply to BFT chains [#7115](https://github.com/hyperledger/besu/pull/7115) +- Make `v` abd `yParity` match in type 1 and 2 transactions in JSON-RPC and GraphQL [#7139](https://github.com/hyperledger/besu/pull/7139) ### Download Links https://github.com/hyperledger/besu/releases/tag/24.5.2 diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java index b0854e761c1..6e98afc90e5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java @@ -16,6 +16,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.graphql.GraphQLContextType; @@ -248,7 +249,13 @@ public BigInteger getS() { } public Optional getV() { - return Optional.ofNullable(transactionWithMetadata.getTransaction().getV()); + BigInteger v = transactionWithMetadata.getTransaction().getV(); + return Optional.ofNullable( + v == null + && (transactionWithMetadata.getTransaction().getType().getEthSerializedType() + < TransactionType.BLOB.getEthSerializedType()) + ? transactionWithMetadata.getTransaction().getYParity() + : v); } public Optional getYParity() { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionCompleteResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionCompleteResult.java index 003ee07ce36..c8260d090c0 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionCompleteResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionCompleteResult.java @@ -126,7 +126,7 @@ public TransactionCompleteResult(final TransactionWithMetadata tx) { this.v = (transactionType == TransactionType.ACCESS_LIST || transactionType == TransactionType.EIP1559) - ? Quantity.create(transaction.getV()) + ? Quantity.create(transaction.getYParity()) : null; } this.value = Quantity.create(transaction.getValue()); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionPendingResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionPendingResult.java index 62302808af3..2cbf5dd2255 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionPendingResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionPendingResult.java @@ -116,7 +116,7 @@ public TransactionPendingResult(final Transaction transaction) { this.v = (transactionType == TransactionType.ACCESS_LIST || transactionType == TransactionType.EIP1559) - ? Quantity.create(transaction.getV()) + ? Quantity.create(transaction.getYParity()) : null; } this.value = Quantity.create(transaction.getValue()); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java index acbcb85ff11..68f75ee4ecf 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java @@ -73,7 +73,7 @@ public PendingTransactionDetailResult(final Transaction tx) { this.v = (transactionType == TransactionType.ACCESS_LIST || transactionType == TransactionType.EIP1559) - ? Quantity.create(tx.getV()) + ? Quantity.create(tx.getYParity()) : null; } this.value = Quantity.create(tx.getValue()); diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_frontier.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_frontier.json new file mode 100644 index 00000000000..335121ac896 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_frontier.json @@ -0,0 +1,29 @@ +{ + "request": "{block (number: 32) { difficulty extraData miner { address } mixHash nonce stateRoot totalDifficulty transactions { gasPrice type yParity v r s} }} ", + "response": { + "data": { + "block": { + "difficulty": "0x207c0", + "extraData": "0x", + "miner": { + "address": "0x8888f1f195afa192cfee860698584c030f4c9db1" + }, + "mixHash": "0x4edd77bfff565659bb0ae09421918e4def65d938a900eb94230eb01f5ce80c99", + "nonce": "0xdb063000b00e8026", + "stateRoot": "0xf65f3dd13f72f5fa5607a5224691419969b4f4bae7a00a6cdb853f2ca9eeb1be", + "totalDifficulty": "0x427c00", + "transactions": [ + { + "gasPrice": "0x1", + "type": "0x0", + "yParity": null, + "v": "0x1b", + "r": "0x705b002a7df60707d33812e0298411721be20ea5a2f533707295140d89263b79", + "s": "0x78024390784f24160739533b3ceea2698289a02afd9cc768581b4aa3d5f4b105" + } + ] + } + } + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json index 3e98251971b..add2edd6507 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_shanghai.json @@ -1,5 +1,5 @@ { - "request": "{block (number : 33) { baseFeePerGas difficulty extraData miner { address } mixHash nonce stateRoot totalDifficulty withdrawalsRoot withdrawals { address amount index validator } }} ", + "request": "{block (number : 33) { baseFeePerGas difficulty extraData miner { address } mixHash nonce stateRoot totalDifficulty transactions { r s v yParity } withdrawalsRoot withdrawals { address amount index validator } }} ", "response": { "data": { "block": { @@ -13,6 +13,14 @@ "nonce": "0x0000000000000000", "stateRoot": "0x0d3c456bb68669bad05da3a1a766daab236c9df1da8f74edf5ebe9383f00084c", "totalDifficulty": "0x427c00", + "transactions": [ + { + "r": "0x8abbfbd4c5f2a13a8d5ed394ac50bac7d678f83a23f645818492f76e8ee17ab3", + "s": "0x7bd38c6929235f775d68b45bd7dea7981264f9a265b6bea97b070e15be88389c", + "v": "0x0", + "yParity": "0x0" + } + ], "withdrawalsRoot": "0x37945ab58d2712a26df2a38d217e822694927e29b30d5993d7a53ccea618d1f3", "withdrawals": [ { diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json index c2c00330ff0..d4c557f4bf1 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getTransaction_type2.json @@ -17,7 +17,7 @@ "type": "0x2", "status": "0x1", "yParity": "0x0", - "v": "0x25" + "v": "0x0" } } }, diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getBlockByNumber_complete_shanghai.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getBlockByNumber_complete_shanghai.json index 481dda711a9..fb77fccd598 100644 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getBlockByNumber_complete_shanghai.json +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getBlockByNumber_complete_shanghai.json @@ -58,7 +58,7 @@ "type": "0x2", "value": "0x0", "yParity": "0x0", - "v" : "0x25", + "v" : "0x0", "r": "0x8abbfbd4c5f2a13a8d5ed394ac50bac7d678f83a23f645818492f76e8ee17ab3", "s": "0x7bd38c6929235f775d68b45bd7dea7981264f9a265b6bea97b070e15be88389c" } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index a373a9b6fec..7ca349721f9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -495,14 +495,10 @@ public BigInteger getS() { @Override public BigInteger getV() { - if (transactionType != null - && transactionType != TransactionType.FRONTIER - && transactionType != TransactionType.ACCESS_LIST - && transactionType != TransactionType.EIP1559) { - // Newer transaction type lacks V, so return null + if (transactionType != null && transactionType != TransactionType.FRONTIER) { + // EIP-2718 typed transaction, use yParity: return null; } else { - // Mandatory for legacy, optional for EIP-2930 and EIP-1559 TXes, prohibited for all others. final BigInteger recId = BigInteger.valueOf(signature.getRecId()); return chainId .map(bigInteger -> recId.add(REPLAY_PROTECTED_V_BASE).add(TWO.multiply(bigInteger))) From 64de9f2eda5451589d8fc363f75eed19e4f6cc3e Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Fri, 31 May 2024 11:45:40 +1000 Subject: [PATCH 13/42] Fix timestamp validation test (#7124) * +1 on the timestamp Signed-off-by: Sally MacFarlane --------- Signed-off-by: Sally MacFarlane Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../headervalidationrules/TimestampValidationRuleTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java index 24dc4987afe..42ffea95061 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java @@ -102,7 +102,8 @@ public void headerNewerThanCurrentSystemFailsValidation() { final BlockHeader parent = headerBuilder.buildHeader(); // Create header for validation with a timestamp in the future (1 second too far away) - headerBuilder.timestamp(parent.getTimestamp() + acceptableClockDrift + 1); + // (+1 to avoid spurious failures) + headerBuilder.timestamp(parent.getTimestamp() + acceptableClockDrift + 2); final BlockHeader header = headerBuilder.buildHeader(); assertThat(uut00.validate(header, parent)).isFalse(); @@ -124,7 +125,7 @@ public void futureHeadersAreValidIfTimestampWithinTolerance() { TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS)); final BlockHeader parent = headerBuilder.buildHeader(); - // Create header for validation with a timestamp in the future (1 second too far away) + // Create header for validation with a timestamp an acceptable amount in the future // (-1) to prevent spurious failures headerBuilder.timestamp(parent.getTimestamp() + acceptableClockDrift - 1); final BlockHeader header = headerBuilder.buildHeader(); From b0823c41fe20052a2f3416c97f6a5f5be44b1f4f Mon Sep 17 00:00:00 2001 From: ahamlat Date: Fri, 31 May 2024 05:27:37 +0200 Subject: [PATCH 14/42] Add metrics to DefaultBlockchain to get TPS and Mgas/s (#7105) * Add gasUsedCounter and numberOfTransactionsCounter counters to DefaultBlockchain Signed-off-by: Ameziane H * Make the attributes final Signed-off-by: Ameziane H * Spotless Signed-off-by: Ameziane H * Add a changelog entry Signed-off-by: Ameziane H --------- Signed-off-by: Ameziane H Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 1 + .../ethereum/chain/DefaultBlockchain.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4021309744..ebe02cc0a55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Breaking Changes ### Additions and Improvements +- Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) ### Bug fixes - Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java index 032ccb9f21f..04eaaa6a353 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java @@ -33,6 +33,7 @@ import org.hyperledger.besu.metrics.BesuMetricCategory; import org.hyperledger.besu.metrics.prometheus.PrometheusMetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem; +import org.hyperledger.besu.plugin.services.metrics.Counter; import org.hyperledger.besu.util.InvalidConfigurationException; import org.hyperledger.besu.util.Subscribers; @@ -83,6 +84,9 @@ public class DefaultBlockchain implements MutableBlockchain { private final Optional>> transactionReceiptsCache; private final Optional> totalDifficultyCache; + private final Counter gasUsedCounter; + private final Counter numberOfTransactionsCounter; + private DefaultBlockchain( final Optional genesisBlock, final BlockchainStorage blockchainStorage, @@ -117,6 +121,7 @@ private DefaultBlockchain( "blockchain_height", "The current height of the canonical chain", this::getChainHeadBlockNumber); + metricsSystem.createGauge( BesuMetricCategory.BLOCKCHAIN, "difficulty_total", @@ -135,6 +140,10 @@ private DefaultBlockchain( "Gas used by the current chain head block", () -> getChainHeadHeader().getGasUsed()); + gasUsedCounter = + metricsSystem.createCounter( + BesuMetricCategory.BLOCKCHAIN, "chain_head_gas_used_counter", "Counter for Gas used"); + metricsSystem.createLongGauge( BesuMetricCategory.BLOCKCHAIN, "chain_head_gas_limit", @@ -147,6 +156,12 @@ private DefaultBlockchain( "Number of transactions in the current chain head block", () -> chainHeadTransactionCount); + numberOfTransactionsCounter = + metricsSystem.createCounter( + BesuMetricCategory.BLOCKCHAIN, + "chain_head_transaction_count_counter", + "Counter for the number of transactions"); + metricsSystem.createIntegerGauge( BesuMetricCategory.BLOCKCHAIN, "chain_head_ommer_count", @@ -524,6 +539,10 @@ private BlockAddedEvent handleNewHead( updater.setChainHead(newBlockHash); indexTransactionForBlock( updater, newBlockHash, blockWithReceipts.getBlock().getBody().getTransactions()); + gasUsedCounter.inc(blockWithReceipts.getHeader().getGasUsed()); + numberOfTransactionsCounter.inc( + blockWithReceipts.getBlock().getBody().getTransactions().size()); + return BlockAddedEvent.createForHeadAdvancement( blockWithReceipts.getBlock(), LogWithMetadata.generate( From 6f3650fc511e255079a5d56449543027bb555da4 Mon Sep 17 00:00:00 2001 From: Gabriel-Trintinalia Date: Fri, 31 May 2024 14:37:50 +1000 Subject: [PATCH 15/42] [MINOR] - Vertx and Netty minor version bumps (#7156) Signed-off-by: Gabriel-Trintinalia --- .../GraphQLHttpServiceHostWhitelistTest.java | 6 +- .../JsonRpcHttpServiceHostAllowlistTest.java | 6 +- .../websocket/WebSocketHostAllowlistTest.java | 6 +- gradle/verification-metadata.xml | 541 ++++++++---------- gradle/versions.gradle | 10 +- 5 files changed, 252 insertions(+), 317 deletions(-) diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceHostWhitelistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceHostWhitelistTest.java index c2fb617fbb8..ec33bd92689 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceHostWhitelistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceHostWhitelistTest.java @@ -155,8 +155,8 @@ private int doRequest(final String hostname) throws IOException { @Test public void requestWithMalformedHostIsRejected() throws IOException { graphQLConfig.setHostsAllowlist(hostsWhitelist); - Assertions.assertThat(doRequest("ally:friend")).isEqualTo(403); - Assertions.assertThat(doRequest("ally:123456")).isEqualTo(403); - Assertions.assertThat(doRequest("ally:friend:1234")).isEqualTo(403); + Assertions.assertThat(doRequest("ally:friend")).isEqualTo(400); + Assertions.assertThat(doRequest("ally:123456")).isEqualTo(400); + Assertions.assertThat(doRequest("ally:friend:1234")).isEqualTo(400); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java index a261ff2351a..af5228dc06e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java @@ -206,8 +206,8 @@ private int doRequest(final String hostname) throws IOException { @Test public void requestWithMalformedHostIsRejected() throws IOException { jsonRpcConfig.setHostsAllowlist(hostsAllowlist); - assertThat(doRequest("ally:friend")).isEqualTo(403); - assertThat(doRequest("ally:123456")).isEqualTo(403); - assertThat(doRequest("ally:friend:1234")).isEqualTo(403); + assertThat(doRequest("ally:friend")).isEqualTo(400); + assertThat(doRequest("ally:123456")).isEqualTo(400); + assertThat(doRequest("ally:friend:1234")).isEqualTo(400); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketHostAllowlistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketHostAllowlistTest.java index a53ef3d1421..3ac348c01a1 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketHostAllowlistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketHostAllowlistTest.java @@ -196,9 +196,9 @@ public void websocketRequestWithMalformedHostIsRejected(final String hostname) { public void httpRequestWithMalformedHostIsRejected() throws Throwable { webSocketConfiguration.setAuthenticationEnabled(false); webSocketConfiguration.setHostsAllowlist(hostsAllowlist); - doHttpRequestAndVerify(testContext, "ally:friend", 403); - doHttpRequestAndVerify(testContext, "ally:123456", 403); - doHttpRequestAndVerify(testContext, "ally:friend:1234", 403); + doHttpRequestAndVerify(testContext, "ally:friend", 400); + doHttpRequestAndVerify(testContext, "ally:123456", 400); + doHttpRequestAndVerify(testContext, "ally:friend:1234", 400); } private void doHttpRequestAndVerify( diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7ad666233f6..c6e7701e625 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -1664,12 +1664,12 @@ - - - + + + - - + + @@ -1677,9 +1677,9 @@ - - - + + + @@ -1687,64 +1687,44 @@ - - - + + + - - - - - - - - - - - - + + - - - + + + - - + + - - - + + + - - - - - - - + + - - - + + + - - + + - - - + + + - - - - - - - + + @@ -1752,104 +1732,84 @@ - - - - - - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - - - - + + - - - + + + - - + + - - - - - - + + + - - - - + + - - - - - - + + + - - - - + + - - - + + + - - + + @@ -1857,25 +1817,20 @@ - - - + + + - - - - - - - + + - - - + + + - - + + @@ -1883,59 +1838,44 @@ - - - + + + - - - + + + - - - - + + - - - + + + - - + + - - - + + + - - - - - - - - - - - - - - - + + - - - + + + - - + + - - + + @@ -1959,96 +1899,91 @@ - - - - - - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + @@ -2636,49 +2571,49 @@ - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + @@ -2686,9 +2621,9 @@ - - - + + + @@ -2701,12 +2636,12 @@ - - - + + + - - + + @@ -2735,49 +2670,49 @@ - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 427e6e81897..ba924e50950 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -69,11 +69,11 @@ dependencyManagement { dependency 'io.kubernetes:client-java:18.0.1' - dependency 'io.netty:netty-all:4.1.104.Final' + dependency 'io.netty:netty-all:4.1.110.Final' dependency 'io.netty:netty-tcnative-boringssl-static:2.0.62.Final' - dependency group: 'io.netty', name: 'netty-transport-native-epoll', version:'4.1.104.Final', classifier: 'linux-x86_64' - dependency group: 'io.netty', name: 'netty-transport-native-kqueue', version:'4.1.104.Final', classifier: 'osx-x86_64' - dependency 'io.netty:netty-transport-native-unix-common:4.1.104.Final' + dependency group: 'io.netty', name: 'netty-transport-native-epoll', version:'4.1.110.Final', classifier: 'linux-x86_64' + dependency group: 'io.netty', name: 'netty-transport-native-kqueue', version:'4.1.110.Final', classifier: 'osx-x86_64' + dependency 'io.netty:netty-transport-native-unix-common:4.1.110.Final' dependency 'io.opentelemetry:opentelemetry-api:1.33.0' dependency 'io.opentelemetry:opentelemetry-exporter-otlp:1.33.0' @@ -116,7 +116,7 @@ dependencyManagement { entry 'tuweni-units' } - dependencySet(group: 'io.vertx', version: '4.5.4') { + dependencySet(group: 'io.vertx', version: '4.5.8') { entry 'vertx-auth-jwt' entry 'vertx-codegen' entry 'vertx-core' From bd32e2c6e1e22d4890d6325661f5056b6934c1f2 Mon Sep 17 00:00:00 2001 From: Matt Whitehead Date: Tue, 4 Jun 2024 01:07:00 +0100 Subject: [PATCH 16/42] Include currently active EVM version in `admin_nodeInfo` response (#7127) * Include currently active EVM version in node info response Signed-off-by: Matthew Whitehead * Remove println, add changelog entry Signed-off-by: Matthew Whitehead --------- Signed-off-by: Matthew Whitehead --- CHANGELOG.md | 1 + .../internal/methods/AdminNodeInfo.java | 9 ++++++++- .../jsonrpc/methods/AdminJsonRpcMethods.java | 9 +++++++-- .../jsonrpc/methods/JsonRpcMethodsFactory.java | 3 ++- .../internal/methods/AdminNodeInfoTest.java | 18 ++++++++++++++++-- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebe02cc0a55..7da419e86a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Additions and Improvements - Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) +- `admin_nodeInfo` JSON/RPC call returns the currently active EVM version [#7127](https://github.com/hyperledger/besu/pull/7127) ### Bug fixes - Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfo.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfo.java index 8515f9ba1bb..f1633db7841 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfo.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfo.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.chain.ChainHead; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.nat.NatService; import org.hyperledger.besu.nat.core.domain.NatPortMapping; @@ -47,6 +48,7 @@ public class AdminNodeInfo implements JsonRpcMethod { private final P2PNetwork peerNetwork; private final BlockchainQueries blockchainQueries; private final NatService natService; + private final ProtocolSchedule protocolSchedule; public AdminNodeInfo( final String clientVersion, @@ -54,13 +56,15 @@ public AdminNodeInfo( final GenesisConfigOptions genesisConfigOptions, final P2PNetwork peerNetwork, final BlockchainQueries blockchainQueries, - final NatService natService) { + final NatService natService, + final ProtocolSchedule protocolSchedule) { this.peerNetwork = peerNetwork; this.clientVersion = clientVersion; this.genesisConfigOptions = genesisConfigOptions; this.blockchainQueries = blockchainQueries; this.networkId = networkId; this.natService = natService; + this.protocolSchedule = protocolSchedule; } @Override @@ -126,6 +130,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { "network", networkId))); + response.put( + "activeFork", protocolSchedule.getByBlockHeader(chainHead.getBlockHeader()).getName()); + return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), response); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java index 286758cb762..437f64f1df2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/AdminJsonRpcMethods.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.PluginsReloadConfiguration; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -48,6 +49,7 @@ public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods { private final Map namedPlugins; private final EthPeers ethPeers; private final Optional enodeDnsConfiguration; + private final ProtocolSchedule protocolSchedule; public AdminJsonRpcMethods( final String clientVersion, @@ -58,7 +60,8 @@ public AdminJsonRpcMethods( final Map namedPlugins, final NatService natService, final EthPeers ethPeers, - final Optional enodeDnsConfiguration) { + final Optional enodeDnsConfiguration, + final ProtocolSchedule protocolSchedule) { this.clientVersion = clientVersion; this.networkId = networkId; this.genesisConfigOptions = genesisConfigOptions; @@ -68,6 +71,7 @@ public AdminJsonRpcMethods( this.natService = natService; this.ethPeers = ethPeers; this.enodeDnsConfiguration = enodeDnsConfiguration; + this.protocolSchedule = protocolSchedule; } @Override @@ -86,7 +90,8 @@ protected Map create() { genesisConfigOptions, p2pNetwork, blockchainQueries, - natService), + natService, + protocolSchedule), new AdminPeers(ethPeers), new AdminChangeLogLevel(), new AdminGenerateLogBloomCache(blockchainQueries), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index c4cfd226905..924889ef47a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -97,7 +97,8 @@ public Map methods( namedPlugins, natService, ethPeers, - enodeDnsConfiguration), + enodeDnsConfiguration, + protocolSchedule), new DebugJsonRpcMethods( blockchainQueries, protocolContext, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java index 20284cb5de3..07fc060655b 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminNodeInfoTest.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; @@ -33,6 +34,8 @@ import org.hyperledger.besu.ethereum.chain.ChainHead; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; @@ -67,6 +70,8 @@ public class AdminNodeInfoTest { @Mock private BlockchainQueries blockchainQueries; @Mock private NatService natService; @Mock private BlockHeader blockHeader; + @Mock private ProtocolSchedule protocolSchedule; + @Mock private ProtocolSpec protocolSpec; private AdminNodeInfo method; @@ -93,6 +98,8 @@ public void setup() { when(blockchainQueries.getBlockHashByNumber(anyLong())).thenReturn(Optional.of(Hash.EMPTY)); when(blockchain.getChainHead()).thenReturn(testChainHead); when(natService.queryExternalIPAddress(anyString())).thenReturn("1.2.3.4"); + when(protocolSpec.getName()).thenReturn("London"); + when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); method = new AdminNodeInfo( "testnet/1.0/this/that", @@ -100,7 +107,8 @@ public void setup() { genesisConfigOptions, p2pNetwork, blockchainQueries, - natService); + natService, + protocolSchedule); } @Test @@ -110,6 +118,7 @@ public void shouldReturnCorrectResult() { final JsonRpcRequestContext request = adminNodeInfo(); final Map expected = new HashMap<>(); + expected.put("activeFork", "London"); expected.put( "enode", "enode://0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807@1.2.3.4:30303?discport=7890"); @@ -161,6 +170,7 @@ public void shouldReturnCorrectResultWhenIsNatEnvironment() { final JsonRpcRequestContext request = adminNodeInfo(); final Map expected = new HashMap<>(); + expected.put("activeFork", "London"); expected.put( "enode", "enode://0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807@3.4.5.6:8081?discport=8080"); @@ -207,6 +217,7 @@ public void handlesLocalEnodeWithListeningAndDiscoveryDisabled() { final JsonRpcRequestContext request = adminNodeInfo(); final Map expected = new HashMap<>(); + expected.put("activeFork", "London"); expected.put( "enode", "enode://0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807@1.2.3.4:0"); @@ -253,6 +264,7 @@ public void handlesLocalEnodeWithListeningDisabled() { final JsonRpcRequestContext request = adminNodeInfo(); final Map expected = new HashMap<>(); + expected.put("activeFork", "London"); expected.put( "enode", "enode://0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807@1.2.3.4:0?discport=7890"); @@ -299,6 +311,7 @@ public void handlesLocalEnodeWithDiscoveryDisabled() { final JsonRpcRequestContext request = adminNodeInfo(); final Map expected = new HashMap<>(); + expected.put("activeFork", "London"); expected.put( "enode", "enode://0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807@1.2.3.4:7890?discport=0"); @@ -387,7 +400,8 @@ public void returnsClassicForkBlocks() { genesisClassicConfigOptions, p2pNetwork, blockchainQueries, - natService); + natService, + protocolSchedule); final JsonRpcRequestContext request = adminNodeInfo(); From e4daf6ada2d828963579a190300919e2bd0be726 Mon Sep 17 00:00:00 2001 From: daniellehrner Date: Tue, 4 Jun 2024 16:15:11 +0200 Subject: [PATCH 17/42] update besu-native to 0.8.5 (#7172) Signed-off-by: Daniel Lehrner --- gradle/verification-metadata.xml | 62 ++++++++++++++++---------------- gradle/versions.gradle | 2 +- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index c6e7701e625..55df9903318 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1,5 +1,5 @@ - + true false @@ -4659,12 +4659,12 @@ - - - + + + - - + + @@ -4675,44 +4675,44 @@ - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + diff --git a/gradle/versions.gradle b/gradle/versions.gradle index ba924e50950..4fa7f871320 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -156,7 +156,7 @@ dependencyManagement { dependency 'org.openjdk.jol:jol-core:0.17' dependency 'tech.pegasys:jc-kzg-4844:1.0.0' - dependencySet(group: 'org.hyperledger.besu', version: '0.8.4') { + dependencySet(group: 'org.hyperledger.besu', version: '0.8.5') { entry 'arithmetic' entry 'ipa-multipoint' entry 'bls12-381' From 9d8c191911fd500d0d14c29d17f52334244845b7 Mon Sep 17 00:00:00 2001 From: krsh24 Date: Wed, 5 Jun 2024 05:53:45 +0800 Subject: [PATCH 18/42] Error out on permissions config accounts-allowlist validation errors. [#7138] (#7161) * Error out on permissions config accounts-allowlist validation errors. Signed-off-by: krishnannarayanan * Fixing compilation errors Signed-off-by: krishnannarayanan * Incorrect file check in Signed-off-by: krishnannarayanan --------- Signed-off-by: krishnannarayanan --- ...untLocalConfigPermissioningController.java | 8 ++++- ...ocalConfigPermissioningControllerTest.java | 35 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningController.java b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningController.java index c62ed9d6b0b..cb1aa2fd0a1 100644 --- a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningController.java +++ b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningController.java @@ -84,7 +84,13 @@ public AccountLocalConfigPermissioningController( private void readAccountsFromConfig(final LocalPermissioningConfiguration configuration) { if (configuration != null && configuration.isAccountAllowlistEnabled()) { if (!configuration.getAccountAllowlist().isEmpty()) { - addAccounts(configuration.getAccountAllowlist()); + AllowlistOperationResult result = addAccounts(configuration.getAccountAllowlist()); + if (result != AllowlistOperationResult.SUCCESS) { + throw new IllegalStateException( + String.format( + "Error reloading permissions file. Invalid accounts allowlist, validation failed due to \"%s\"", + result)); + } } } } diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningControllerTest.java index 1c823b83a83..db98cd95acc 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/AccountLocalConfigPermissioningControllerTest.java @@ -17,6 +17,7 @@ import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -108,6 +109,40 @@ public void whenLoadingAccountsFromConfigShouldNormalizeAccountsToLowerCase() { .containsExactly("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"); } + @Test + public void whenLoadingDuplicateAccountsFromConfigShouldThrowError() { + when(permissioningConfig.isAccountAllowlistEnabled()).thenReturn(true); + when(permissioningConfig.getAccountAllowlist()) + .thenReturn( + List.of( + "0xcb88953e60948e3a76fa658d65b7c2d5043c6409", + "0xdd76406b124f9e3ae9fbeb47e4d8dc0ab143902d", + "0x432132e8561785c33afe931762cf8eeb9c80e3ad", + "0xcb88953e60948e3a76fa658d65b7c2d5043c6409")); + + assertThrows( + IllegalStateException.class, + () -> { + controller = + new AccountLocalConfigPermissioningController( + permissioningConfig, allowlistPersistor, metricsSystem); + }); + } + + @Test + public void whenLoadingInvalidAccountsFromConfigShouldThrowError() { + when(permissioningConfig.isAccountAllowlistEnabled()).thenReturn(true); + when(permissioningConfig.getAccountAllowlist()).thenReturn(List.of("0x0", "0xzxy")); + + assertThrows( + IllegalStateException.class, + () -> { + controller = + new AccountLocalConfigPermissioningController( + permissioningConfig, allowlistPersistor, metricsSystem); + }); + } + @Test public void whenPermConfigContainsEmptyListOfAccountsContainsShouldReturnFalse() { when(permissioningConfig.isAccountAllowlistEnabled()).thenReturn(true); From e4902af05e311c9017d453a121d6b3cd0e74c3fd Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 5 Jun 2024 10:21:02 +1000 Subject: [PATCH 19/42] feat: Node discovery via DNS (#7129) - Node discovery via DNS module as a vertex verticle (code adapted from Tuweni) - Mock DNS server in unit tests. --------- Signed-off-by: Usman Saleem Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 1 + NOTICE | 19 ++ NOTICE.md | 0 ethereum/p2p/build.gradle | 4 +- .../ethereum/p2p/discovery/dns/DNSDaemon.java | 107 +++++++ .../p2p/discovery/dns/DNSDaemonListener.java | 32 ++ .../ethereum/p2p/discovery/dns/DNSEntry.java | 279 ++++++++++++++++++ .../p2p/discovery/dns/DNSResolver.java | 237 +++++++++++++++ .../p2p/discovery/dns/DNSVisitor.java | 32 ++ .../ethereum/p2p/discovery/dns/KVReader.java | 49 +++ .../p2p/network/DefaultP2PNetwork.java | 37 ++- .../p2p/discovery/dns/DNSDaemonTest.java | 121 ++++++++ .../p2p/discovery/dns/DNSEntryTest.java | 71 +++++ .../p2p/discovery/dns/KVReaderTest.java | 40 +++ .../discovery/dns/MockDnsServerVerticle.java | 205 +++++++++++++ .../p2p/network/DefaultP2PNetworkTest.java | 29 +- .../resources/discovery/dns/dns-records.json | 137 +++++++++ gradle/versions.gradle | 1 - 18 files changed, 1376 insertions(+), 25 deletions(-) create mode 100644 NOTICE delete mode 100644 NOTICE.md create mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java create mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonListener.java create mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntry.java create mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java create mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSVisitor.java create mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReader.java create mode 100644 ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java create mode 100644 ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntryTest.java create mode 100644 ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReaderTest.java create mode 100644 ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/MockDnsServerVerticle.java create mode 100644 ethereum/p2p/src/test/resources/discovery/dns/dns-records.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 7da419e86a4..49d43191302 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Default bonsai to use full-flat db and code-storage-by-code-hash [#6984](https://github.com/hyperledger/besu/pull/6894) - New RPC methods miner_setExtraData and miner_getExtraData [#7078](https://github.com/hyperledger/besu/pull/7078) - Disconnect peers that have multiple discovery ports since they give us bad neighbours [#7089](https://github.com/hyperledger/besu/pull/7089) +- Port Tuweni dns-discovery into Besu. [#7129](https://github.com/hyperledger/besu/pull/7129) ### Known Issues - [Frequency: occasional < 10%] Chain download halt. Only affects new syncs (new nodes syncing from scratch). Symptom: Block import halts, despite having a full set of peers and world state downloading finishing. Generally restarting besu will resolve the issue. We are tracking this in [#6884](https://github.com/hyperledger/besu/pull/6884) diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000000..af5acfe009e --- /dev/null +++ b/NOTICE @@ -0,0 +1,19 @@ +Hyperledger Besu +Copyright contributors to Hyperledger Besu. + +This product includes software adapted from Tuweni. (https://tuweni.tmio.io/) +Copyright 2023-2024 The Machine Consultancy LLC +Licensed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) + +The following NOTICE file content is provided by Tuweni: +------------------------------------------------------------ +This product includes code developed under the Apache Tuweni incubation project. + +Copyright 2019-2023 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +In addition, this product includes software developed by +Copyright 2018-2019 ConsenSys, Inc. +------------------------------------------------------------ diff --git a/NOTICE.md b/NOTICE.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ethereum/p2p/build.gradle b/ethereum/p2p/build.gradle index 7f56178978d..21bfdc6bf54 100644 --- a/ethereum/p2p/build.gradle +++ b/ethereum/p2p/build.gradle @@ -50,9 +50,6 @@ dependencies { implementation('io.tmio:tuweni-devp2p') { exclude group:'ch.qos.logback', module:'logback-classic' } - implementation('io.tmio:tuweni-dns-discovery'){ - exclude group:'ch.qos.logback', module:'logback-classic' - } implementation 'io.tmio:tuweni-io' implementation 'io.tmio:tuweni-rlp' implementation 'io.tmio:tuweni-units' @@ -84,6 +81,7 @@ dependencies { } testImplementation 'io.vertx:vertx-codegen' testImplementation 'io.vertx:vertx-unit' + testImplementation 'io.vertx:vertx-junit5' testImplementation 'org.assertj:assertj-core' testImplementation 'org.awaitility:awaitility' testImplementation 'org.junit.jupiter:junit-jupiter' diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java new file mode 100644 index 00000000000..d17c846be79 --- /dev/null +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java @@ -0,0 +1,107 @@ +/* + * 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.p2p.discovery.dns; + +import java.util.List; +import java.util.Optional; + +import io.vertx.core.AbstractVerticle; +import org.apache.tuweni.devp2p.EthereumNodeRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// Adapted from https://github.com/tmio/tuweni and licensed under Apache 2.0 +/** + * Resolves DNS records over time, refreshing records. This is written as a Vertx Verticle which + * allows to run outside the Vertx event loop + */ +public class DNSDaemon extends AbstractVerticle { + private static final Logger LOG = LoggerFactory.getLogger(DNSDaemon.class); + private final String enrLink; + private final long seq; + private final long initialDelay; + private final long delay; + private final Optional listener; + private final Optional dnsServer; + private Optional periodicTaskId = Optional.empty(); + private DNSResolver dnsResolver; + + /** + * Creates a new DNSDaemon. + * + * @param enrLink the ENR link to start with, of the form enrtree://PUBKEY@domain + * @param listener Listener notified when records are read and whenever they are updated. + * @param seq the sequence number of the root record. If the root record seq is higher, proceed + * with visit. + * @param initialDelay the delay in milliseconds before the first poll of DNS records. + * @param delay the delay in milliseconds at which to poll DNS records. If negative or zero, it + * runs only once. + * @param dnsServer the DNS server to use for DNS query. If null, the default DNS server will be + * used. + */ + public DNSDaemon( + final String enrLink, + final DNSDaemonListener listener, + final long seq, + final long initialDelay, + final long delay, + final String dnsServer) { + this.enrLink = enrLink; + this.listener = Optional.ofNullable(listener); + this.seq = seq; + this.initialDelay = initialDelay; + this.delay = delay; + this.dnsServer = Optional.ofNullable(dnsServer); + } + + /** Starts the DNSDaemon. */ + @Override + public void start() { + if (vertx == null) { + throw new IllegalStateException("DNSDaemon must be deployed as a vertx verticle."); + } + + LOG.info("Starting DNSDaemon for {}, using {} DNS host.", enrLink, dnsServer.orElse("default")); + dnsResolver = new DNSResolver(vertx, enrLink, seq, dnsServer); + if (delay > 0) { + periodicTaskId = Optional.of(vertx.setPeriodic(initialDelay, delay, this::refreshENRRecords)); + } else { + // do one-shot resolution + refreshENRRecords(0L); + } + } + + /** Stops the DNSDaemon. */ + @Override + public void stop() { + LOG.info("Stopping DNSDaemon for {}", enrLink); + periodicTaskId.ifPresent(vertx::cancelTimer); + dnsResolver.close(); + } + + /** + * Refresh enr records by calling dnsResolver and updating the listeners. + * + * @param taskId the task id of the periodic task + */ + void refreshENRRecords(final Long taskId) { + LOG.debug("Refreshing DNS records"); + final long startTime = System.nanoTime(); + final List ethereumNodeRecords = dnsResolver.collectAll(); + final long endTime = System.nanoTime(); + LOG.debug("Time taken to DNSResolver.collectAll: {} ms", (endTime - startTime) / 1_000_000); + listener.ifPresent(it -> it.newRecords(dnsResolver.sequence(), ethereumNodeRecords)); + } +} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonListener.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonListener.java new file mode 100644 index 00000000000..cfa51d4eb73 --- /dev/null +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonListener.java @@ -0,0 +1,32 @@ +/* + * 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.p2p.discovery.dns; + +import java.util.List; + +import org.apache.tuweni.devp2p.EthereumNodeRecord; + +// Adapted from https://github.com/tmio/tuweni and licensed under Apache 2.0 +/** Callback listening to updates of the DNS records. */ +@FunctionalInterface +public interface DNSDaemonListener { + /** + * Callback called when the seq is updated on the DNS server + * + * @param seq the update identifier of the records + * @param records the records stored on the server + */ + void newRecords(long seq, List records); +} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntry.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntry.java new file mode 100644 index 00000000000..bb85a3612f3 --- /dev/null +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntry.java @@ -0,0 +1,279 @@ +/* + * 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.p2p.discovery.dns; + +import static org.hyperledger.besu.ethereum.p2p.discovery.dns.KVReader.readKV; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.crypto.SECP256K1; +import org.apache.tuweni.devp2p.EthereumNodeRecord; +import org.apache.tuweni.io.Base32; +import org.apache.tuweni.io.Base64URLSafe; +import org.bouncycastle.math.ec.ECPoint; + +// Adapted from https://github.com/tmio/tuweni and licensed under Apache 2.0 +/** Intermediate format to write DNS entries */ +public interface DNSEntry { + + /** + * Read a DNS entry from a String. + * + * @param serialized the serialized form of a DNS entry + * @return DNS entry if found + * @throws IllegalArgumentException if the record cannot be read + */ + static DNSEntry readDNSEntry(final String serialized) { + final String record = trimQuotes(serialized); + final String prefix = getPrefix(record); + return switch (prefix) { + case "enrtree-root" -> new ENRTreeRoot(readKV(record)); + case "enrtree-branch" -> new ENRTree(record.substring(prefix.length() + 1)); + case "enr" -> new ENRNode(readKV(record)); + case "enrtree" -> new ENRTreeLink(record); + default -> + throw new IllegalArgumentException( + serialized + " should contain enrtree-branch, enr, enrtree-root or enrtree"); + }; + } + + private static String trimQuotes(final String str) { + if (str.startsWith("\"") && str.endsWith("\"")) { + return str.substring(1, str.length() - 1); + } + return str; + } + + private static String getPrefix(final String input) { + final String[] parts = input.split(":", 2); + return parts.length > 0 ? parts[0] : ""; + } + + /** Represents a node in the ENR record. */ + class ENRNode implements DNSEntry { + + private final EthereumNodeRecord nodeRecord; + + /** + * Constructs ENRNode with the given attributes. + * + * @param attrs the attributes of the node + */ + public ENRNode(final Map attrs) { + if (attrs == null) { + throw new IllegalArgumentException("ENRNode attributes cannot be null"); + } + nodeRecord = + Optional.ofNullable(attrs.get("enr")) + .map(Base64URLSafe::decode) + .map(EthereumNodeRecord::fromRLP) + .orElseThrow(() -> new IllegalArgumentException("Invalid ENR record")); + } + + /** + * Ethereum node record. + * + * @return the instance of EthereumNodeRecord + */ + public EthereumNodeRecord nodeRecord() { + return nodeRecord; + } + + @Override + public String toString() { + return nodeRecord.toString(); + } + } + + /** Root of the ENR tree */ + class ENRTreeRoot implements DNSEntry { + private final String version; + private final Long seq; + private final SECP256K1.Signature sig; + private final String enrRoot; + private final String linkRoot; + + /** + * Creates a new ENRTreeRoot + * + * @param attrs The attributes of the root + */ + public ENRTreeRoot(final Map attrs) { + if (attrs == null) { + throw new IllegalArgumentException("ENRNode attributes cannot be null"); + } + + version = + Optional.ofNullable(attrs.get("enrtree-root")) + .orElseThrow(() -> new IllegalArgumentException("Missing attribute enrtree-root")); + seq = + Optional.ofNullable(attrs.get("seq")) + .map(Long::parseLong) + .orElseThrow(() -> new IllegalArgumentException("Missing attribute seq")); + sig = + Optional.ofNullable(attrs.get("sig")) + .map(Base64URLSafe::decode) + .map( + sigBytes -> + SECP256K1.Signature.fromBytes( + Bytes.concatenate( + sigBytes, Bytes.wrap(new byte[Math.max(0, 65 - sigBytes.size())])))) + .orElseThrow(() -> new IllegalArgumentException("Missing attribute sig")); + enrRoot = + Optional.ofNullable(attrs.get("e")) + .orElseThrow(() -> new IllegalArgumentException("Missing attribute e")); + linkRoot = + Optional.ofNullable(attrs.get("l")) + .orElseThrow(() -> new IllegalArgumentException("Missing attribute l")); + } + + /** + * Gets sequence + * + * @return sequence + */ + public Long seq() { + return seq; + } + + /** + * Link root. + * + * @return the link root. + */ + public String linkRoot() { + return linkRoot; + } + + /** + * ENR root. + * + * @return the enr root. + */ + public String enrRoot() { + return enrRoot; + } + + /** + * Signature. + * + * @return SECP256K1 signature + */ + public SECP256K1.Signature sig() { + return sig; + } + + @Override + public String toString() { + return String.format( + "enrtree-root:%s e=%s l=%s seq=%d sig=%s", + version, enrRoot, linkRoot, seq, Base64URLSafe.encode(sig.bytes())); + } + + /** + * Returns the signed content of the root + * + * @return the signed content + */ + public String signedContent() { + return String.format("enrtree-root:%s e=%s l=%s seq=%d", version, enrRoot, linkRoot, seq); + } + } + + /** Represents a branch in the ENR record. */ + class ENRTree implements DNSEntry { + private final List entries; + + /** + * Constructs ENRTree with the given entries. + * + * @param entriesAsString the entries of the branch + */ + public ENRTree(final String entriesAsString) { + entries = + Arrays.stream(entriesAsString.split("[,\"]")) + .filter(it -> it.length() > 4) + .collect(Collectors.toList()); + } + + /** + * Entries of the branch. + * + * @return the entries of the branch + */ + public List entries() { + return entries; + } + + @Override + public String toString() { + return "enrtree-branch:" + String.join(",", entries); + } + } + + /** Class representing an ENR Tree link */ + class ENRTreeLink implements DNSEntry { + private final String domainName; + private final String encodedPubKey; + private final SECP256K1.PublicKey pubKey; + + /** + * Creates a new ENRTreeLink + * + * @param enrTreeLink The URI representing ENR Tree link + */ + public ENRTreeLink(final String enrTreeLink) { + final URI uri = URI.create(enrTreeLink); + this.domainName = uri.getHost(); + this.encodedPubKey = uri.getUserInfo(); + this.pubKey = fromBase32(encodedPubKey); + } + + private static SECP256K1.PublicKey fromBase32(final String base32) { + final byte[] keyBytes = Base32.decodeBytes(base32); + final ECPoint ecPoint = SECP256K1.Parameters.CURVE.getCurve().decodePoint(keyBytes); + return SECP256K1.PublicKey.fromBytes(Bytes.wrap(ecPoint.getEncoded(false)).slice(1)); + } + + /** + * Decoded SECP256K1 public key. + * + * @return derived SECP256K1.PublicKey + */ + public SECP256K1.PublicKey publicKey() { + return pubKey; + } + + /** + * Domain name. + * + * @return the domain name + */ + public String domainName() { + return domainName; + } + + @Override + public String toString() { + return String.format("enrtree://%s@%s", encodedPubKey, domainName); + } + } +} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java new file mode 100644 index 00000000000..d42304ed043 --- /dev/null +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java @@ -0,0 +1,237 @@ +/* + * 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.p2p.discovery.dns; + +import org.hyperledger.besu.crypto.Hash; +import org.hyperledger.besu.ethereum.p2p.discovery.dns.DNSEntry.ENRNode; +import org.hyperledger.besu.ethereum.p2p.discovery.dns.DNSEntry.ENRTreeLink; +import org.hyperledger.besu.ethereum.p2p.discovery.dns.DNSEntry.ENRTreeRoot; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; + +import com.google.common.base.Splitter; +import io.vertx.core.Vertx; +import io.vertx.core.dns.DnsClient; +import io.vertx.core.dns.DnsClientOptions; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.crypto.SECP256K1; +import org.apache.tuweni.devp2p.EthereumNodeRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// Adapted from https://github.com/tmio/tuweni and licensed under Apache 2.0 +/** Resolves a set of ENR nodes from a host name. */ +public class DNSResolver implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(DNSResolver.class); + private final ExecutorService rawTxtRecordsExecutor = Executors.newSingleThreadExecutor(); + private final String enrLink; + private long seq; + private final DnsClient dnsClient; + + /** + * Creates a new DNSResolver. + * + * @param vertx Vertx instance which is used to create DNS Client + * @param enrLink the ENR link to start with, of the form enrtree://PUBKEY@domain + * @param seq the sequence number of the root record. If the root record seq is higher, proceed + * with visit. + * @param dnsServer the DNS server to use for DNS query. If empty, the default DNS server will be + * used. + */ + public DNSResolver( + final Vertx vertx, final String enrLink, final long seq, final Optional dnsServer) { + this.enrLink = enrLink; + this.seq = seq; + final DnsClientOptions dnsClientOptions = + dnsServer.map(DNSResolver::buildDnsClientOptions).orElseGet(DnsClientOptions::new); + dnsClient = vertx.createDnsClient(dnsClientOptions); + } + + private static DnsClientOptions buildDnsClientOptions(final String server) { + final List hostPort = Splitter.on(":").splitToList(server); + final DnsClientOptions dnsClientOptions = new DnsClientOptions(); + dnsClientOptions.setHost(hostPort.get(0)); + if (hostPort.size() > 1) { + try { + int port = Integer.parseInt(hostPort.get(1)); + dnsClientOptions.setPort(port); + } catch (NumberFormatException e) { + LOG.trace("Invalid port number {}, ignoring", hostPort.get(1)); + } + } + return dnsClientOptions; + } + + /** + * Convenience method to read all ENRs, from a top-level record. + * + * @return all ENRs collected + */ + public List collectAll() { + final List nodes = new ArrayList<>(); + final DNSVisitor visitor = nodes::add; + visitTree(new ENRTreeLink(enrLink), visitor); + if (!nodes.isEmpty()) { + LOG.debug("Resolved {} nodes from DNS for enr link {}", nodes.size(), enrLink); + } else { + LOG.debug("No nodes resolved from DNS"); + } + return Collections.unmodifiableList(nodes); + } + + /** + * Sequence number of the root record. + * + * @return the current sequence number of the root record + */ + public long sequence() { + return seq; + } + + /** + * Reads a complete tree of record, starting with the top-level record. + * + * @param link the ENR link to start with + * @param visitor the visitor that will look at each record + */ + private void visitTree(final ENRTreeLink link, final DNSVisitor visitor) { + Optional optionalEntry = resolveRecord(link.domainName()); + if (optionalEntry.isEmpty()) { + LOG.debug("No DNS record found for {}", link.domainName()); + return; + } + + final DNSEntry dnsEntry = optionalEntry.get(); + if (!(dnsEntry instanceof ENRTreeRoot treeRoot)) { + LOG.debug("Root entry {} is not an ENR tree root", dnsEntry); + return; + } + + if (!checkSignature(treeRoot, link.publicKey(), treeRoot.sig())) { + LOG.debug("ENR tree root {} failed signature check", link.domainName()); + return; + } + if (treeRoot.seq() <= seq) { + LOG.debug("ENR tree root seq {} is not higher than {}, aborting", treeRoot.seq(), seq); + return; + } + seq = treeRoot.seq(); + + internalVisit(treeRoot.enrRoot(), link.domainName(), visitor); + internalVisit(treeRoot.linkRoot(), link.domainName(), visitor); + } + + private boolean internalVisit( + final String entryName, final String domainName, final DNSVisitor visitor) { + final Optional optionalDNSEntry = resolveRecord(entryName + "." + domainName); + if (optionalDNSEntry.isEmpty()) { + LOG.debug("No DNS record found for {}", entryName + "." + domainName); + return true; + } + + final DNSEntry entry = optionalDNSEntry.get(); + if (entry instanceof ENRNode node) { + // TODO: this always return true because the visitor is reference to list.add + return visitor.visit(node.nodeRecord()); + } else if (entry instanceof DNSEntry.ENRTree tree) { + for (String e : tree.entries()) { + // TODO: When would this ever return false? + boolean keepGoing = internalVisit(e, domainName, visitor); + if (!keepGoing) { + return false; + } + } + } else if (entry instanceof ENRTreeLink link) { + visitTree(link, visitor); + } else { + LOG.debug("Unsupported type of node {}", entry); + } + return true; + } + + /** + * Resolves one DNS record associated with the given domain name. + * + * @param domainName the domain name to query + * @return the DNS entry read from the domain. Empty if no record is found. + */ + Optional resolveRecord(final String domainName) { + return resolveRawRecord(domainName).map(DNSEntry::readDNSEntry); + } + + /** + * Resolves the first TXT record for a domain name and returns it. + * + * @param domainName the name of the DNS domain to query + * @return the first TXT entry of the DNS record. Empty if no record is found. + */ + Optional resolveRawRecord(final String domainName) { + // vertx-dns is async, kotlin coroutines allows us to await, similarly Java 21 new thread + // model would also allow us to await. For now, we will use CountDownLatch to block the + // current thread until the DNS resolution is complete. + LOG.debug("Resolving TXT records on domain: {}", domainName); + final CountDownLatch latch = new CountDownLatch(1); + final AtomicReference> record = new AtomicReference<>(Optional.empty()); + rawTxtRecordsExecutor.submit( + () -> { + dnsClient + .resolveTXT(domainName) + .onComplete( + ar -> { + if (ar.succeeded()) { + LOG.trace( + "TXT record resolved on domain {}. Result: {}", domainName, ar.result()); + record.set(ar.result().stream().findFirst()); + } else { + LOG.trace( + "TXT record not resolved on domain {}, because: {}", + domainName, + ar.cause().getMessage()); + } + latch.countDown(); + }); + }); + + try { + // causes the worker thread to wait. Once we move to Java 21, this can be simplified. + latch.await(); + } catch (InterruptedException e) { + LOG.debug("Interrupted while waiting for DNS resolution"); + } + + return record.get(); + } + + private boolean checkSignature( + final ENRTreeRoot root, final SECP256K1.PublicKey pubKey, final SECP256K1.Signature sig) { + Bytes32 hash = + Hash.keccak256(Bytes.wrap(root.signedContent().getBytes(StandardCharsets.UTF_8))); + return SECP256K1.verifyHashed(hash, sig, pubKey); + } + + @Override + public void close() { + rawTxtRecordsExecutor.shutdown(); + } +} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSVisitor.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSVisitor.java new file mode 100644 index 00000000000..c6ea0a77ed7 --- /dev/null +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSVisitor.java @@ -0,0 +1,32 @@ +/* + * 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.p2p.discovery.dns; + +import org.apache.tuweni.devp2p.EthereumNodeRecord; + +// Adapted from https://github.com/tmio/tuweni and licensed under Apache 2.0 +/** + * Reads ENR (Ethereum Node Records) entries passed in from DNS. The visitor may decide to stop the + * visit by returning false. + */ +public interface DNSVisitor { + /** + * Visit a new ENR record. + * + * @param enr the ENR record read from DNS + * @return true to continue visiting, false otherwise + */ + boolean visit(final EthereumNodeRecord enr); +} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReader.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReader.java new file mode 100644 index 00000000000..63123b3ee41 --- /dev/null +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReader.java @@ -0,0 +1,49 @@ +/* + * 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.p2p.discovery.dns; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +// Adapted from https://github.com/tmio/tuweni and licensed under Apache 2.0 +/** Read Key value pairs from a DNS record */ +public class KVReader { + private KVReader() {} + + /** + * Read a key value pair from a DNS record + * + * @param record the record to read + * @return the key value pair + */ + public static Map readKV(final String record) { + return Arrays.stream(record.split("\\s+")) + .map( + it -> { + // if it contains an = or :, split into Map.entry from the first occurrence + if (it.contains("=")) { + return it.split("=", 2); + } else if (it.contains(":")) { + return it.split(":", 2); + } else { + // this should not happen, as the record should be well-formed + return new String[] {it}; + } + }) + .filter(kv -> kv.length == 2) + .collect(Collectors.toMap(kv -> kv[0], kv -> kv[1])); + } +} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java index d4a0e3daaba..573effa173a 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java @@ -27,6 +27,8 @@ import org.hyperledger.besu.ethereum.p2p.discovery.PeerDiscoveryAgent; import org.hyperledger.besu.ethereum.p2p.discovery.PeerDiscoveryStatus; import org.hyperledger.besu.ethereum.p2p.discovery.VertxPeerDiscoveryAgent; +import org.hyperledger.besu.ethereum.p2p.discovery.dns.DNSDaemon; +import org.hyperledger.besu.ethereum.p2p.discovery.dns.DNSDaemonListener; import org.hyperledger.besu.ethereum.p2p.discovery.internal.PeerTable; import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeerPrivileges; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; @@ -69,17 +71,20 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import com.google.common.annotations.VisibleForTesting; +import io.vertx.core.DeploymentOptions; +import io.vertx.core.Future; +import io.vertx.core.ThreadingModel; import io.vertx.core.Vertx; +import org.apache.commons.lang3.tuple.Pair; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.devp2p.EthereumNodeRecord; -import org.apache.tuweni.discovery.DNSDaemon; -import org.apache.tuweni.discovery.DNSDaemonListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -147,7 +152,8 @@ public class DefaultP2PNetwork implements P2PNetwork { private final CountDownLatch shutdownLatch = new CountDownLatch(2); private final Duration shutdownTimeout = Duration.ofSeconds(15); private final Vertx vertx; - private DNSDaemon dnsDaemon; + private final AtomicReference>> dnsDaemonRef = + new AtomicReference<>(Optional.empty()); /** * Creates a peer networking service for production purposes. @@ -227,15 +233,26 @@ public void start() { LOG.info( "Starting DNS discovery with DNS Server override {}", dnsServer)); - dnsDaemon = + final DNSDaemon dnsDaemon = new DNSDaemon( disco, createDaemonListener(), 0L, + 1000L, // start after 1 second 600000L, - config.getDnsDiscoveryServerOverride().orElse(null), - vertx); - dnsDaemon.start(); + config.getDnsDiscoveryServerOverride().orElse(null)); + + // TODO: Java 21, we can move to Virtual Thread model + final DeploymentOptions options = + new DeploymentOptions() + .setThreadingModel(ThreadingModel.WORKER) + .setInstances(1) + .setWorkerPoolSize(1); + + final Future deployId = vertx.deployVerticle(dnsDaemon, options); + final String dnsDaemonDeployId = + deployId.toCompletionStage().toCompletableFuture().join(); + dnsDaemonRef.set(Optional.of(Pair.of(dnsDaemonDeployId, dnsDaemon))); }); final int listeningPort = rlpxAgent.start().join(); @@ -282,7 +299,9 @@ public void stop() { return; } - getDnsDaemon().ifPresent(DNSDaemon::close); + // since dnsDaemon is a vertx verticle, vertx.close will undeploy it. + // However, we can safely call stop as well. + dnsDaemonRef.get().map(Pair::getRight).ifPresent(DNSDaemon::stop); peerConnectionScheduler.shutdownNow(); peerDiscoveryAgent.stop().whenComplete((res, err) -> shutdownLatch.countDown()); @@ -339,7 +358,7 @@ public boolean removeMaintainedConnectionPeer(final Peer peer) { @VisibleForTesting Optional getDnsDaemon() { - return Optional.ofNullable(dnsDaemon); + return dnsDaemonRef.get().map(Pair::getRight); } @VisibleForTesting diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java new file mode 100644 index 00000000000..cb465093d07 --- /dev/null +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java @@ -0,0 +1,121 @@ +/* + * 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.p2p.discovery.dns; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.security.Security; +import java.util.concurrent.atomic.AtomicInteger; + +import io.vertx.core.DeploymentOptions; +import io.vertx.core.ThreadingModel; +import io.vertx.core.Vertx; +import io.vertx.junit5.Checkpoint; +import io.vertx.junit5.VertxExtension; +import io.vertx.junit5.VertxTestContext; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(VertxExtension.class) +class DNSDaemonTest { + private static final String holeskyEnr = + "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net"; + // private static MockDNSServer mockDNSServer; + private final MockDnsServerVerticle mockDnsServerVerticle = new MockDnsServerVerticle(); + private DNSDaemon dnsDaemon; + + @BeforeAll + static void setup() throws IOException { + Security.addProvider(new BouncyCastleProvider()); + } + + @BeforeEach + @DisplayName("Deploy Mock Dns Server Verticle") + void prepare(final Vertx vertx, final VertxTestContext vertxTestContext) { + vertx.deployVerticle(mockDnsServerVerticle, vertxTestContext.succeedingThenComplete()); + } + + @Test + @DisplayName("Test DNS Daemon with a mock DNS server") + void testDNSDaemon(final Vertx vertx, final VertxTestContext testContext) + throws InterruptedException { + final Checkpoint checkpoint = testContext.checkpoint(); + dnsDaemon = + new DNSDaemon( + holeskyEnr, + (seq, records) -> checkpoint.flag(), + 0, + 0, + 0, + "localhost:" + mockDnsServerVerticle.port()); + + final DeploymentOptions options = + new DeploymentOptions().setThreadingModel(ThreadingModel.WORKER).setWorkerPoolSize(1); + vertx.deployVerticle(dnsDaemon, options); + } + + @Test + @DisplayName("Test DNS Daemon with periodic lookup to a mock DNS server") + void testDNSDaemonPeriodic(final Vertx vertx, final VertxTestContext testContext) + throws InterruptedException { + // checkpoint should be flagged twice + final Checkpoint checkpoint = testContext.checkpoint(2); + final AtomicInteger pass = new AtomicInteger(0); + dnsDaemon = + new DNSDaemon( + holeskyEnr, + (seq, records) -> { + switch (pass.incrementAndGet()) { + case 1: + testContext.verify( + () -> { + assertThat(seq).isEqualTo(932); + assertThat(records).hasSize(115); + }); + break; + case 2: + testContext.verify( + () -> { + assertThat(seq).isEqualTo(932); + assertThat(records).isEmpty(); + }); + break; + default: + testContext.failNow("Third pass is not expected"); + } + checkpoint.flag(); + }, + 0, + 1, // initial delay + 300, // second lookup after 300 ms (due to Mock DNS server, we are very quick). + "localhost:" + mockDnsServerVerticle.port()); + + final DeploymentOptions options = + new DeploymentOptions().setThreadingModel(ThreadingModel.WORKER).setWorkerPoolSize(1); + vertx.deployVerticle(dnsDaemon, options); + } + + @AfterEach + @DisplayName("Check that the vertx worker verticle is still there") + void lastChecks(final Vertx vertx) { + assertThat(vertx.deploymentIDs()).isNotEmpty().hasSize(2); + } +} diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntryTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntryTest.java new file mode 100644 index 00000000000..2197bf279ca --- /dev/null +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSEntryTest.java @@ -0,0 +1,71 @@ +/* + * 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.p2p.discovery.dns; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.security.Security; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class DNSEntryTest { + @BeforeAll + static void setup() { + Security.addProvider(new BouncyCastleProvider()); + } + + @Test + void enrTreeRootIsParsed() { + final String txtRecord = + "\"enrtree-root:v1 e=KVKZLGARGADDZSMCF65QQMEWLE l=FDXN3SN67NA5DKA4J2GOK7BVQI seq=919 sig=braPmdwMk-g65lQxums6hEy553s3bWMoecW0QQ0IdykIoM9i3We0bxFT0IDONPaFcRePcN-yaOpt8GBfeQ4qDAE\""; + final DNSEntry entry = DNSEntry.readDNSEntry(txtRecord); + assertThat(entry).isInstanceOf(DNSEntry.ENRTreeRoot.class); + final DNSEntry.ENRTreeRoot enrTreeRoot = (DNSEntry.ENRTreeRoot) entry; + assertThat(enrTreeRoot.enrRoot()).isEqualTo("KVKZLGARGADDZSMCF65QQMEWLE"); + assertThat(enrTreeRoot.linkRoot()).isEqualTo("FDXN3SN67NA5DKA4J2GOK7BVQI"); + assertThat(enrTreeRoot.seq()).isEqualTo(919); + } + + @Test + void enrTreeBranchIsParsed() { + final String txtRecord = + "\"enrtree-branch:HVKDJGU7SZMOAMNLBJYQBSKZTM,PVSVWO3NLKHTBAIWOY2NB67RFI," + + "6TCKCNWXNGBMNFTGSRKNRO4ERA,37NSKCRJVI5XRRHWLTHW4A6OX4,NV3IJMKDVQHHALY6MAVMPYN6ZU," + + "SZCFDMTYOERMIVOUXEWXSGDVEY,FZ26UT4LSG7D2NRX7SV6P3S6BI,7TWNYLCOQ7FEM4IG65WOTL4MVE," + + "6OJXGI7NJUESOLL2OZPS4B\" \"EC6Q,437FN4NSGMGFQLAXYWPX5JNACI,FCA7LN6NCO5IAWPG5FH7LX6XJA," + + "EYBOZ2NZSHDWDSNHV66XASXOHM,FUVRJMMMKJMCL4L4EBEOWCSOFA\""; + final DNSEntry entry = DNSEntry.readDNSEntry(txtRecord); + + assertThat(entry).isInstanceOf(DNSEntry.ENRTree.class); + assertThat(((DNSEntry.ENRTree) entry).entries()) + .containsExactly( + "HVKDJGU7SZMOAMNLBJYQBSKZTM", + "PVSVWO3NLKHTBAIWOY2NB67RFI", + "6TCKCNWXNGBMNFTGSRKNRO4ERA", + "37NSKCRJVI5XRRHWLTHW4A6OX4", + "NV3IJMKDVQHHALY6MAVMPYN6ZU", + "SZCFDMTYOERMIVOUXEWXSGDVEY", + "FZ26UT4LSG7D2NRX7SV6P3S6BI", + "7TWNYLCOQ7FEM4IG65WOTL4MVE", + "6OJXGI7NJUESOLL2OZPS4B", + "437FN4NSGMGFQLAXYWPX5JNACI", + "FCA7LN6NCO5IAWPG5FH7LX6XJA", + "EYBOZ2NZSHDWDSNHV66XASXOHM", + "FUVRJMMMKJMCL4L4EBEOWCSOFA") + .doesNotContain("EC6Q"); + } +} diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReaderTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReaderTest.java new file mode 100644 index 00000000000..2f1ecaf293c --- /dev/null +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/KVReaderTest.java @@ -0,0 +1,40 @@ +/* + * 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.p2p.discovery.dns; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +public class KVReaderTest { + // copied from `dig all.holesky.ethdisco.net txt` + private static final String txtRecord = + "enrtree-root:v1 e=KVKZLGARGADDZSMCF65QQMEWLE l=FDXN3SN67NA5DKA4J2GOK7BVQI seq=919 sig=braPmdwMk-g65lQxums6hEy553s3bWMoecW0QQ0IdykIoM9i3We0bxFT0IDONPaFcRePcN-yaOpt8GBfeQ4qDAE"; + + @Test + void parseTXTRecord() { + final Map kv = KVReader.readKV(txtRecord); + assertThat(kv) + .containsEntry("enrtree-root", "v1") + .containsEntry("e", "KVKZLGARGADDZSMCF65QQMEWLE") + .containsEntry("l", "FDXN3SN67NA5DKA4J2GOK7BVQI") + .containsEntry("seq", "919") + .containsEntry( + "sig", + "braPmdwMk-g65lQxums6hEy553s3bWMoecW0QQ0IdykIoM9i3We0bxFT0IDONPaFcRePcN-yaOpt8GBfeQ4qDAE"); + } +} diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/MockDnsServerVerticle.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/MockDnsServerVerticle.java new file mode 100644 index 00000000000..f9bd7ea5cff --- /dev/null +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/MockDnsServerVerticle.java @@ -0,0 +1,205 @@ +/* + * 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.p2p.discovery.dns; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import com.google.common.base.Splitter; +import com.google.common.io.Resources; +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Promise; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.datagram.DatagramPacket; +import io.vertx.core.datagram.DatagramSocket; +import io.vertx.core.datagram.DatagramSocketOptions; +import io.vertx.core.json.JsonObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Mock DNS server verticle. */ +public class MockDnsServerVerticle extends AbstractVerticle { + private static final Logger LOG = LoggerFactory.getLogger(MockDnsServerVerticle.class); + private final Map txtRecords = new HashMap<>(); + private int dnsPort; + + @Override + public void start(final Promise startPromise) throws Exception { + final DatagramSocket datagramSocket = vertx.createDatagramSocket(new DatagramSocketOptions()); + datagramSocket.handler(packet -> handleDatagramPacket(datagramSocket, packet)); + + final String dnsEntriesJsonPath = + Path.of(Resources.getResource("discovery/dns/dns-records.json").toURI()).toString(); + LOG.debug("Reading DNS entries from: {}", dnsEntriesJsonPath); + vertx + .fileSystem() + .readFile(dnsEntriesJsonPath) + .compose( + buffer -> { + final JsonObject dnsEntries = new JsonObject(buffer.toString()); + final Map jsonMap = dnsEntries.getMap(); + jsonMap.forEach((key, value) -> txtRecords.put(key, value.toString())); + + // start the server + return datagramSocket.listen(0, "127.0.0.1"); + }) + .onComplete( + res -> { + if (res.succeeded()) { + LOG.info("Mock Dns Server is now listening {}", res.result().localAddress()); + dnsPort = res.result().localAddress().port(); + startPromise.complete(); + } else { + startPromise.fail(res.cause()); + } + }); + } + + @Override + public void stop() { + LOG.info("Stopping Mock DNS Server"); + } + + private void handleDatagramPacket(final DatagramSocket socket, final DatagramPacket packet) { + LOG.debug("Packet Received"); + Buffer data = packet.data(); + final short queryId = getQueryId(data); + final String queryName = extractQueryName(data.getBytes()); + + final Buffer response; + if (txtRecords.containsKey(queryName)) { + LOG.debug("Query name found {}", queryName); + response = createTXTResponse(queryId, queryName, txtRecords.get(queryName)); + } else { + LOG.debug("Query name not found: {}", queryName); + response = createErrorResponse(queryId, queryName); + } + + socket.send(response, packet.sender().port(), packet.sender().host()); + } + + private String extractQueryName(final byte[] buffer) { + StringBuilder queryName = new StringBuilder(); + int index = 12; // Skip the DNS header + + while (index < buffer.length) { + int labelLength = buffer[index] & 0xFF; + + if (labelLength == 0) { + break; + } + + index++; + + for (int i = 0; i < labelLength; i++) { + char c = (char) (buffer[index + i] & 0xFF); + queryName.append(c); + } + + index += labelLength; + + if (index < buffer.length && buffer[index] != 0) { + queryName.append("."); + } + } + + return queryName.toString(); + } + + private Buffer createTXTResponse( + final short queryId, final String queryName, final String txtRecord) { + final Buffer buffer = Buffer.buffer(); + + // Write DNS header + buffer.appendShort(queryId); // Query Identifier + buffer.appendShort((short) 0x8180); // Flags (Standard query response, No error) + buffer.appendShort((short) 1); // Questions count + buffer.appendShort((short) 1); // Answers count + buffer.appendShort((short) 0); // Authority RRs count + buffer.appendShort((short) 0); // Additional RRs count + + // Write query name + final Iterable queryLabels = Splitter.on(".").split(queryName); + for (String label : queryLabels) { + buffer.appendByte((byte) label.length()); + buffer.appendString(label); + } + buffer.appendByte((byte) 0); // End of query name + + // Write query type and class + buffer.appendShort((short) 16); // Type (TXT) + buffer.appendShort((short) 1); // Class (IN) + + // Write answer + for (String label : queryLabels) { + buffer.appendByte((byte) label.length()); + buffer.appendString(label.toLowerCase(Locale.ROOT)); + } + buffer.appendByte((byte) 0); // End of answer name + + buffer.appendShort((short) 16); // TXT record type + buffer.appendShort((short) 1); // Class (IN) + buffer.appendInt(60); // TTL (60 seconds) + + int txtRecordsLength = txtRecord.getBytes(UTF_8).length; + buffer.appendShort((short) (txtRecordsLength + 1)); // Data length + buffer.appendByte((byte) txtRecordsLength); // TXT record length + buffer.appendString(txtRecord); + + return buffer; + } + + private Buffer createErrorResponse(final short queryId, final String queryName) { + Buffer buffer = Buffer.buffer(); + + // Write DNS header + buffer.appendShort(queryId); // Query Identifier + buffer.appendShort((short) 0x8183); // Flags (Standard query response, NXDOMAIN error) + buffer.appendShort((short) 1); // Questions count + buffer.appendShort((short) 0); // Answers count + buffer.appendShort((short) 0); // Authority RRs count + buffer.appendShort((short) 0); // Additional RRs count + + // Write query name + for (String label : Splitter.on(".").split(queryName)) { + buffer.appendByte((byte) label.length()); + buffer.appendString(label); + } + buffer.appendByte((byte) 0); // End of query name + + // Write query type and class + buffer.appendShort((short) 16); // Type (TXT) + buffer.appendShort((short) 1); // Class (IN) + + return buffer; + } + + private short getQueryId(final Buffer queryData) { + return (short) ((queryData.getByte(0) & 0xff) << 8 | (queryData.getByte(1) & 0xff)); + } + + /** + * Mock server local port + * + * @return server port + */ + public int port() { + return dnsPort; + } +} diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java index 68a4f76b582..88b9197262a 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java @@ -57,9 +57,7 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; -import io.vertx.core.Context; import io.vertx.core.Vertx; -import io.vertx.core.dns.DnsClient; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.crypto.SECP256K1; import org.assertj.core.api.Assertions; @@ -335,16 +333,21 @@ public void shouldStartDnsDiscoveryWhenDnsURLIsConfigured() { final NetworkingConfiguration dnsConfig = when(spy(config).getDiscovery()).thenReturn(disco).getMock(); - Vertx vertx = mock(Vertx.class); - when(vertx.createDnsClient(any())).thenReturn(mock(DnsClient.class)); - when(vertx.getOrCreateContext()).thenReturn(mock(Context.class)); + final Vertx vertx = Vertx.vertx(); // use real instance // spy on DefaultP2PNetwork final DefaultP2PNetwork testClass = (DefaultP2PNetwork) builder().vertx(vertx).config(dnsConfig).build(); testClass.start(); - assertThat(testClass.getDnsDaemon()).isPresent(); + try { + // the actual lookup won't work because of mock discovery url, however, a valid DNSDaemon + // should be created. + assertThat(testClass.getDnsDaemon()).isPresent(); + } finally { + testClass.stop(); + vertx.close(); + } } @Test @@ -358,17 +361,19 @@ public void shouldUseDnsServerOverrideIfPresent() { doReturn(disco).when(dnsConfig).getDiscovery(); doReturn(Optional.of("localhost")).when(dnsConfig).getDnsDiscoveryServerOverride(); - Vertx vertx = mock(Vertx.class); - when(vertx.createDnsClient(any())).thenReturn(mock(DnsClient.class)); - when(vertx.getOrCreateContext()).thenReturn(mock(Context.class)); - + Vertx vertx = Vertx.vertx(); // use real instance final DefaultP2PNetwork testClass = (DefaultP2PNetwork) builder().config(dnsConfig).vertx(vertx).build(); testClass.start(); // ensure we used the dns server override config when building DNSDaemon: - assertThat(testClass.getDnsDaemon()).isPresent(); - verify(dnsConfig, times(2)).getDnsDiscoveryServerOverride(); + try { + assertThat(testClass.getDnsDaemon()).isPresent(); + verify(dnsConfig, times(2)).getDnsDiscoveryServerOverride(); + } finally { + testClass.stop(); + vertx.close(); + } } private DefaultP2PNetwork network() { diff --git a/ethereum/p2p/src/test/resources/discovery/dns/dns-records.json b/ethereum/p2p/src/test/resources/discovery/dns/dns-records.json new file mode 100644 index 00000000000..e51da66dbb7 --- /dev/null +++ b/ethereum/p2p/src/test/resources/discovery/dns/dns-records.json @@ -0,0 +1,137 @@ +{ + "all.holesky.ethdisco.net" : "enrtree-root:v1 e=QXOF2GWVHBKMKW57Y2KSKWYNFQ l=FDXN3SN67NA5DKA4J2GOK7BVQI seq=932 sig=DuA35BkYo9-FBwJ6MPxdNnYfcGMSGunAKUyfNN2gYQhYDBCPFZkr_cfe40Wspl2Vl76w6Ccs-B8ZrXpI_YymrAA", + "I56MJYJBMXTZZEPBQR6HWNAH7A.all.holesky.ethdisco.net" : "enr:-KO4QCTGqfxu7eEfe6M83e3bQLUgkKWGCdv6Ib5D0gCuQkkvbq1D0CN8UmHgpsddZNKHa2iBl3EIiGhaLBs_NKTxGQuGAYranLv7g2V0aMfGhJsZKtCAgmlkgnY0gmlwhCKH3xKJc2VjcDI1NmsxoQMHuEvotUinJNm_8Vz7412P1yKZ6r5iz9EcYj-9v3weRYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "IPSUCB6CICZIW6SERKZL7FFTIM.all.holesky.ethdisco.net" : "enr:-KO4QD47Vx9bnFcvE6JNAhrLz6GGgPk9GaJtP95ogjSOFHxlcZjnrT5TQzW9Jyx99XO9rzhK6WSvgdFoA9_54QPQcUaGAYxBy9opg2V0aMfGhJsZKtCAgmlkgnY0gmlwhIe1TLKJc2VjcDI1NmsxoQKMO6bMfiH5DnJNFZgSqUEi6uHNnH2_bMh7hwVXRWTMl4RzbmFwwIN0Y3CCdqmDdWRwgnap", + "QJM2RVJT7USPDSI5VVFGGDW6JM.all.holesky.ethdisco.net" : "enr:-Ji4QHWntDnLOi4S9GKmF4HY7WrnJuJGaIBrnM3Y75G-8EUpZExnUkaZJtlmzOeJs6WAcYsissKSybUG5rSEiad0s86ByoNldGjHxoSbGSrQgIJpZIJ2NIJpcISLY0UEiXNlY3AyNTZrMaED5hLZweFA_nvWEc-Q7Vxqf2lIYxScF-F4ORxs-rVyHZKDdGNwgtn5g3VkcILZ-Q", + "C7SDD5OPASV7B2XUOXF5NLBBKU.all.holesky.ethdisco.net" : "enr:-KO4QLo95TIKo_axZA9xafYgl9jQ2ZTDFCQ29znjUwp-6zPUe6o8L9NO3X3n3uMZH8bFGnRmoIhyHLxNoOp2BU6O7xGGAYwoJEiug2V0aMfGhJsZKtCAgmlkgnY0gmlwhKEjElWJc2VjcDI1NmsxoQPIffRacW7k1QukSBfJ8leopO1M5wOv89G06m0SAQDB8oRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "AUQGHXRAP7J3AGI6TUOQVYTYLY.all.holesky.ethdisco.net" : "enr:-KO4QGuiAZHlxH7T5XPcPpRTovca50B0pzDLkgJ-zaxkjT_PO6zsAWQezB-b53yAnqx01Jdj5tQWsvWoaNVfiFw3iw6GAY1nSgXzg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEp2jJuJc2VjcDI1NmsxoQMTiH7XteYOVAHiXAZoacUjo5JYLhQINeFMbPbEY9sA84RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "WLME2JINTIQACAMD5WZUQ4PRJI.all.holesky.ethdisco.net" : "enr:-J24QIMYTLuDOO1F5w8AL_WGXU6CZmzi05W35Rz8PuVT8b6vUqmUatifQtzuL2Q7REuRY5kYNurUbLHscGx3j1zjTmmGAYrbbtBig2V0aMfGhJsZKtCAgmlkgnY0gmlwhETp6VKJc2VjcDI1NmsxoQKrwy6w-9JGp3dagVeXMZEd3iZGff-rEVTqd4gmkhBRBIN0Y3CCdl-DdWRwgnZf", + "5JAERI2BPJN45X7IK6SWZOZ2FI.all.holesky.ethdisco.net" : "enr:-KO4QEsCIXXCDLUsTbUOT3ILg3rpga0gZXaG9_YT9_kFk97iRwu_Pr4RlhDvdkg4Y4bl9SBVzP9bFtL7H9AU7QxE7OeGAY1lbo59g2V0aMfGhJsZKtCAgmlkgnY0gmlwhA3Xl1-Jc2VjcDI1NmsxoQPsZi79eOcjTI3Xa2GCBiXRCgtm7wFo19cVlmhQSZ-i64RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "J7ZIDKH7CKVIYY244QVU6RMPDM.all.holesky.ethdisco.net" : "enr:-KO4QN942TWYsHn5c2-vZhoeXwELvI2zVg2eHk6nzoyTN8Cwcb8n-4_cwQPIU5p7DsuOehtu-raiGxYm4vE_6WUhT6yGAY1ClkGgg2V0aMfGhJsZKtCAgmlkgnY0gmlwhJBbb1yJc2VjcDI1NmsxoQKemKJgEuvyzZofyTm82rbw716cyTA2hf6zSJ73kzl_ZIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "FFM67SMD4N3SK4ZQTY2HOMU4F4.all.holesky.ethdisco.net" : "enr:-KO4QG4O1MBSzBHtShtqoXXeAycBqcDpuBK2BBwIuK_Qppz5OpJC6Ga3-qDEQJQOtbEYm0yXMhenb50Get_H6Bu9SbGGAY16lghqg2V0aMfGhJsZKtCAgmlkgnY0gmlwhA_rV76Jc2VjcDI1NmsxoQJ1vrJ4fwXiDAhSqIJwbELp2ktd9A0zRLws1li91-aBmoRzbmFwwIN0Y3CCdmCDdWRwgnZg", + "GZVG4EONSAY6M7SMLJXDCFUF5Q.all.holesky.ethdisco.net" : "enr:-KO4QErAUNKF003oZAYn8UUocPIuq2MTpxHV3gHfrNkThYPbZ366m-mlvXezUX5JDA5iJE-LTWWEPh8JqjEDah5kVimGAYxA2nMcg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFtWv2Jc2VjcDI1NmsxoQMCgMWZQXkPyMKdwnzdBxQe6rcs25guZtULvfzDjhE71oRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "3AVV65MYCJ7AGFUCKXT2UX2DSQ.all.holesky.ethdisco.net" : "enr:-KO4QEaesvQ1kySNS_mnQfiBr4DZQmkhHmqKEGRQvgyd5K3lNDm3vjs9cMMVTY9FgENpP1o0UGBsapNNfvXIN2gaudGGAY3ulUKIg2V0aMfGhJsZKtCAgmlkgnY0gmlwhDIjTkmJc2VjcDI1NmsxoQNVbUX0SvjLX7d7psFtTTNkKT7x_zHl3f4bSVQrkbK1YoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "QDCV4SQTQAGHHA3DRA2TR4LNMY.all.holesky.ethdisco.net" : "enr:-KO4QFVXTftQWqwggnKZlVzFmnQz-U5jzIx37kQSltdvU5kuYQHT1mboaEBh92lS0BUvn-aBzLmHu7wX6hhs2xdGw-6GAYrk72-Hg2V0aMfGhJsZKtCAgmlkgnY0gmlwhCJSHduJc2VjcDI1NmsxoQNGPGIxN3h_R3TiUe0Ud2WazTigmsK028DXXuVLna9rtoRzbmFwwIN0Y3CCdTWDdWRwgnU1", + "366Y3UIIKK2G5CUS7CHNPZMPEM.all.holesky.ethdisco.net" : "enr:-KO4QK1ecw-CGrDDZ4YwFrhgqctD0tWMHKJhUVxsS4um3aUFe3yBHRtVL9uYKk16DurN1IdSKTOB1zNCvjBybjZ_KAqGAYtJ5U8wg2V0aMfGhJsZKtCAgmlkgnY0gmlwhA_MtDmJc2VjcDI1NmsxoQNXD7fj3sscyOKBiHYy14igj1vJYWdKYZH7n3T8qRpIcYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "LHFO3FXNRHB5B3YSTKUALGMEAI.all.holesky.ethdisco.net" : "enr:-KO4QEuoZibAJnKlhcAENpJiju6nVH5J2or_xnVnX_eputCuTHBVtNJmoRKgDBU0idG4kbxFPPKaWRQ3TdYeIbsAAV-GAYrax-PMg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKIOJc2VjcDI1NmsxoQNCYX5kXJqI2deaVOtsTmUQka7dIocapHSAfnNn_CTL2YRzbmFwwIN0Y3CCdmCDdWRwgnZg", + "3PMAED3BC2HUS7AMEPGJDKENQY.all.holesky.ethdisco.net" : "enr:-KO4QFMsKiZk64UQsyLVHrxTpTpmdZYzuI-Xgy0gut5NgLulRvbrgQDmdrAT2PQuxK8K9AiplRzJ_i8CtseBD_d2bwGGAYx9HQirg2V0aMfGhJsZKtCAgmlkgnY0gmlwhLBn3miJc2VjcDI1NmsxoQJSdj6d-7J6YsK6vZwRl_zzMSCKauLadYxL8zfjjzOQZYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "4PFOQY7RKTNLRPXQXKKXD3K6LY.all.holesky.ethdisco.net" : "enr:-KO4QJ8BuQCt7gBXU_26FNx8waHuCzCkG54mErQoBAJrYaw_bdUJT0yQA0vG8gr-dUoS77OX0D4tD-R6e30832ncLMaGAYrbEjQ3g2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEV4tiJc2VjcDI1NmsxoQJHEsWJ3CoSi-1JgkeSogpyRqYvBaJI77-soOcbmB_nyYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "GUBLA7OPRPBMYMQ76EXDMB7BHY.all.holesky.ethdisco.net" : "enr:-KO4QIFA0MiYPPyzvlUqi5j1dL1RGz6MdFhhLN30iXeNc1JfCS1QqTJciby7ZhlQYwFdVMuk_ptgu530WxiQR-UmZpWGAY2ia8cWg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEt3l4OJc2VjcDI1NmsxoQJRcQCiMhxUex-gtsxf2IWJ6nGita_F8BaPZxTwE310WIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "VN7EWW4RMUZM6KUOQ43GJ33DWM.all.holesky.ethdisco.net" : "enr:-KO4QI3OPqietyANJtQ9_RUOU6ELbwDgTn39MufjLJ9BEzkwTxEgDcgYekeisrchGWzrzTC8T_2zowbuQhZlTkqNXB2GAY39ItF5g2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFsBbiJc2VjcDI1NmsxoQLa2k_Jy-sjrZ-0305yX_F1ZxDNNfCKIImoL5tyDN3cEYRzbmFwwIN0Y3CCdl6DdWRwgnZe", + "FDXN3SN67NA5DKA4J2GOK7BVQI.all.holesky.ethdisco.net" : "enrtree-branch:", + "QDMF4HIR2UEXRJVOX4UJPJTPKA.all.holesky.ethdisco.net" : "enr:-KO4QCeMBK9Ur5AHbkdov7TdALRsHzc48RXNtvR861fcmcxPYH59PthmWiT_pQHfVOH3x9-HK2bG8_h2jm46sZyJ6UeGAY2ZCasag2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFs7nOJc2VjcDI1NmsxoQLT22lM9abRweZb93jeMd4jvuRsXnjQFT2oY5a0rb0cvoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "3JSDZJCCWKIEBGPH5EI5VZF4RQ.all.holesky.ethdisco.net" : "enrtree-branch:4PFOQY7RKTNLRPXQXKKXD3K6LY,3AVV65MYCJ7AGFUCKXT2UX2DSQ,5JAERI2BPJN45X7IK6SWZOZ2FI,YUZZDZD57PTNEIB5QL3FEXK2ZA,TMY2W2YBNCXUUNA3Y7QXWVQLRE,MJB42632KKOPGJ2KNY3GPKP66I,QXRV67JYJNOYJDPC5CTKUVG76M,QJM2RVJT7USPDSI5VVFGGDW6JM,I33RZWBACJHNDEXG2RRXMX", + "A63OP4WTCB3HGDZE4NGDEID6Z4.all.holesky.ethdisco.net" : "enrtree-branch:QXKEJG4XZEQSXNUY7JJYCATPEI,HIDVATDVB36L2MASAWA7SBJAII,CHFGCI2RQS3XFN2MKFP6G2ZM4U,GSONRYZILMGUJEN3PYQXYD6GYQ,OSHAABXYJSRWW35VOMYHZUKJXU,RUJF27NEYDBNQAFMI6K6SKDVRY,TXAFU343ACQLSVIMT5LYG3W2AE,R6EQA5KQEQM77JJXB4BHHTDF6Y,CF25LCQ452FBTR24CZU4C2", + "N7HAL5M6HNZBGTWM3LWFDRX4WU.all.holesky.ethdisco.net" : "enr:-Je4QI2f2MAXFFi0Q3--GhXVZwNP-jI-G6XwmiDXxT-iobTTKOBJCyWUPk5WSoTtRS2ABqJmTAK8jflXBWLHuY7AueRFg2V0aMfGhP1PAWuAgmlkgnY0gmlwhDmAXJmJc2VjcDI1NmsxoQIc4YD6HsNIoj2HVJJDzr3cSfNtcEBRLtk5kgwXNH0q8YN0Y3CCXoeDdWRwgl6H", + "QXOF2GWVHBKMKW57Y2KSKWYNFQ.all.holesky.ethdisco.net" : "enrtree-branch:A63OP4WTCB3HGDZE4NGDEID6Z4,PL27G47LAASBPPAMXUDIJ3OCRQ", + "23B5UFB3JWETLIKE5Q6B2B5MWA.all.holesky.ethdisco.net" : "enr:-KO4QGjsmd6RDlGYHJu2JnI-Lf4TZ8s1yJtLDvvtp_Kw6xIwNn7_Ti_FmEHfWbaSyy0Icl4jlErvH-LrEmi9PCzB27uGAY0MEI03g2V0aMfGhJsZKtCAgmlkgnY0gmlwhNXvxn6Jc2VjcDI1NmsxoQOzxdn7S7O58IiaWGk4n3MsiB816GGv_bAd_PM9FkWeZIRzbmFwwIN0Y3CCVTyDdWRwglU8", + "TXAFU343ACQLSVIMT5LYG3W2AE.all.holesky.ethdisco.net" : "enrtree-branch:3EMD3PTQYRFVNFBQ73BYFL4AEQ,PMLO73ISEK4Z6IRPOSWIUUKF64,5NHWEAJHKSAO5DIIYAZ7MQJVSE,LNO6EN3Y2LJA5YOJMEMODAJFWM,23B5UFB3JWETLIKE5Q6B2B5MWA,HQ5S2EHH762PSKVTHWNQ6346NI,O25DXMPE4UEZ6SFMQRBGL2E2I4,2WHIXLN5QX3JEK3SSH7MXKTJMU,WQDLDQ7U74Y2HM5LHVCOCY", + "PMLO73ISEK4Z6IRPOSWIUUKF64.all.holesky.ethdisco.net" : "enr:-KO4QBxZ1JFNQEopzO-wMumFIw4fGHkuPZkuCLvgcz0X8L8yKWUkQ-UiS7-KHBCjGOby7yjR6m7m9dqoQvlHejBncSWGAYv2B0KZg2V0aMfGhJsZKtCAgmlkgnY0gmlwhA_ML-SJc2VjcDI1NmsxoQMEi6SKsKUVTnxDWKc1Go6ZG8o5nEapNJBaWAd_YC26R4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "CDXRYZFKH6OUWTA2IJ2MYIMYPM.all.holesky.ethdisco.net" : "enr:-KO4QExy2s5Uh2eTEJtsODBEOcPZZN-CYY0WEr_8nA_uK43QV3iqmFzfXJ-29zootm5F-E-DrjzTObp2tw_klTXPRu-GAY2ZtbV8g2V0aMfGhJsZKtCAgmlkgnY0gmlwhBJ2VQmJc2VjcDI1NmsxoQJuk1X-4JUVQT-mguV7dSGSUC-RoxdnTyOmD-VrfRFQyYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "CTDMY3ALJA7FRKVS4MCTAJRRH4.all.holesky.ethdisco.net" : "enrtree-branch:UIGSNQMHERWJIZCP2OLUXSZ3KM,I56MJYJBMXTZZEPBQR6HWNAH7A,IZNO6JEFTYHQWWF3LJ2M66P7II", + "GSONRYZILMGUJEN3PYQXYD6GYQ.all.holesky.ethdisco.net" : "enrtree-branch:V4A7I7I2SFVUDFFH7AGPFXACBA,67FFSS5IYEYRGUYFEWGIJDIMII,NXU6DU7HEM2L4DN6G2VHHFT72I,3T4CNEKYCJP2PJ3EQVJSFKHH44,KYTZHQX2PSOGY6RQTCVTUKTS7E,GUBLA7OPRPBMYMQ76EXDMB7BHY,HGROZTZI7YPDW5F37QVUPQEBG4,AB27AIPX5Q5J6UAXQ6C2QFTYZA,7UIVPNORDS3RPPTLSNGYAN", + "IPU725BUGL4HIOTSOIH3KZG5ZA.all.holesky.ethdisco.net" : "enr:-KO4QLf3R97a5p3pRgY1AeN1DisWZUTnHbIMt2aPh0zvq8QIZguS9EiujNa71YXqJgxw7ztz3YmwJMWuPuhfWqSkxqWGAYrayxVYg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKIOJc2VjcDI1NmsxoQIHu5vOuFNLO8814yybwdh03yUQzfPTTyeK_X44Gz5jx4RzbmFwwIN0Y3CCdn6DdWRwgnZ-", + "V5LTO36DCXU2JCCSSJ76E35OFU.all.holesky.ethdisco.net" : "enr:-KO4QMLA20nV5gEPR5ugJWkqHSkU89wLsjSVlpdbjuXGueHRY_VJ7gfCBuPbnyxN3Y0rYJThJU7b7IAA1yBfcRx6Uo-GAYrbDOlPg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKGuJc2VjcDI1NmsxoQNZKgK-Lr-g81vUAH_bV24PDyOwNQaNPgAOBEA3qV3JxYRzbmFwwIN0Y3CCdnSDdWRwgnZ0", + "2SA643JTHJ75ZVPFHAKLXI2WXQ.all.holesky.ethdisco.net" : "enr:-KO4QEPFY3aDBt5F3VQU5qcGZED8Xr-J9v1Fi4CcGpx7q_fydrJM8h0RqAXSdcJbr03b7ysPaOR4mNUTRou4kjPsu7yGAY4QKOX4g2V0aMfGhJsZKtCAgmlkgnY0gmlwhCO4xmuJc2VjcDI1NmsxoQKaOskToHERfimE_ei_VPRsh3fimBlYooVb80PVt0k-aIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "V52J3WKNVGG56JFRKYDLSZREJY.all.holesky.ethdisco.net" : "enr:-KO4QMC1Y7Fl44QyBr8KDFTyd1IQ_h0w67Igms87RDJeZJuXbc74aIVNkOeK0t3_zEJAT2spttSVu8tKDeV-cdiPE42GAY3KEqdCg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFsGDWJc2VjcDI1NmsxoQN24zvy5pQRtLA5_iKLgnTwXjI3T1KldFTOyp7Dk6dCRoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "3PYSNKXWWSRBWV377EFNYINHSA.all.holesky.ethdisco.net" : "enr:-KO4QODvXk9lfhLNmdyttodPJQOIYQM36Rl9OZsFBZ4vMjaJcoJUXxTQCMqGLNTWmFh-1oEy0XoYKgPy4tywLZZcB8CGAYsolPILg2V0aMfGhJsZKtCAgmlkgnY0gmlwhIe1OV6Jc2VjcDI1NmsxoQPj1f0OOW-g_vRGcihewV9-kcsQZdwXBHy4r8vwinurzoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "ZV5CYUMJPF4XSTFHOG65622KEE.all.holesky.ethdisco.net" : "enr:-KO4QDd2Ia2HHxIk_v5zyXOs6LIkR7a3wVUmipLZnQTJJMZtTNVY5PnRonxr_GAQ3nqG5R8f-eiyoYprxN1XjsfRlnyGAY2jAkZPg2V0aMfGhJsZKtCAgmlkgnY0gmlwhJ7cbM2Jc2VjcDI1NmsxoQLx82Y08wCtO72z_znVjHxPl3hBz1YBlPokUpsLFKRHJ4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "DQYYUE7KVEXGEYBH4V2QHI6P7M.all.holesky.ethdisco.net" : "enr:-KO4QBhk9j1k2tfVrwV4yVRS9jn2zwS9KKADlhqvMsZsqdXFZiz0s-vCAnqtkDfszY9peGDBiWulLdNe6KFuvqgxgy6GAYtHL5rAg2V0aMfGhJsZKtCAgmlkgnY0gmlwhDmBAQqJc2VjcDI1NmsxoQLXrL6FtBz248tpC2_DxJs2HsvtHdSoNsZIBwth_MMu94RzbmFwwIN0Y3CCdmqDdWRwgnZq", + "MZGQKIQKIOFO3W2GJURJUXVYMQ.all.holesky.ethdisco.net" : "enr:-KO4QI7ESDG0rx7lEU_FFFFkALgNr9roSDrKDOzmEdxTHwsxKj5ozskjEjwFPrShowZbzTTYCp-NRhhw3uhcmKCYy0GGAY1lomwig2V0aMfGhJsZKtCAgmlkgnY0gmlwhCUbQPGJc2VjcDI1NmsxoQMV_yyKYF25xvgoJARC1swzb0S0llZJEmMLRHoINSR81YRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "MJB42632KKOPGJ2KNY3GPKP66I.all.holesky.ethdisco.net" : "enr:-KO4QEBK_p981nqXnme4a2sYvHW2FOz_OwLwstllVRvE8w-dVnDBrHxVZg7XSQwseErDQpfUgYMnBPMzpsx_bDUui5eGAY09OSoRg2V0aMfGhJsZKtCAgmlkgnY0gmlwhLzWgw-Jc2VjcDI1NmsxoQM2fE-8xAAaBUMu7dwviv_y8osp0rYMaKtaGBnbUba_J4RzbmFwwIN0Y3CCdl2DdWRwgnZd", + "QY2XP6FTX7QKFNP6TNZ2MOHZKQ.all.holesky.ethdisco.net" : "enr:-KO4QFsIg8OnqK5HJhhCaEuUTJ7RkLcTAXnUOOcaK63Ra2Kya2HsYSRgM1jRyr9utt3ib83q4fsU_IOg7kuR1jf2u2SGAYray1Tfg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKI2Jc2VjcDI1NmsxoQJiD81UDxWESi3paPaopKxnoF5vf0GAxlroaPr6bSIykIRzbmFwwIN0Y3CCdn6DdWRwgnZ-", + "3A6T36TYZJBFLOHMJOJGL5SPXA.all.holesky.ethdisco.net" : "enr:-KO4QEVn1fwLQuOHSsRVS6bBIv7Nhr39Ze03wqUhwdgEn0IUeEB9TZAx6d9E-C0tBkQdEnbwld1YxEsB9gRY0Od13nGGAYzxMuKBg2V0aMfGhJsZKtCAgmlkgnY0gmlwhAW9up-Jc2VjcDI1NmsxoQKNkgm76tKKtumISB2-1oGEHv_mZtMVh7JGrSmvlX5qqYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "WRRS22MCKTZ4YS3ZLPUJEUAHUI.all.holesky.ethdisco.net" : "enr:-KO4QG6_DN_yg3WbcE7jc_tGXK9dLJPplfz0cbzCRwT8v5o6BBk_e_ER73cttVRyYkkvBDyw-akwTHYxjCe2Jp7OWuiGAYrbEiVVg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEV49OJc2VjcDI1NmsxoQKYHwvu1PazCFKpleCUgYvxialsHK6_iLwC_R2i3J70fYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "BAY6SKB2RTQCM7RTSHAFQ6TTBQ.all.holesky.ethdisco.net" : "enr:-KO4QIo--Wic2Dyk2II8x2uTPNOFY3CRZ8wmABP5qOhmZv4LXvAfbdISPp7HDrJwrejs032LHH5rhUY5l8bj9-M-_u2GAY3GDGQWg2V0aMfGhJsZKtCAgmlkgnY0gmlwhI6E2M-Jc2VjcDI1NmsxoQM46NJn0fjSRwgGkB0G1n7QQ9VyBDwiPXPX_xgM25tDOIRzbmFwwIN0Y3CCfEyDdWRwgnxM", + "5AOSND63QKPVT6EWNMALKAFC4I.all.holesky.ethdisco.net" : "enr:-KO4QKn6DlOQ0ybfLAfyPlyPssuWtP0Zu5FEUEgr3015XppiCP4yr9SeMgnpN90AVHJA5C61F3677GiO0N-JIXGfN2uGAYra2k7ag2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKJOJc2VjcDI1NmsxoQKgKJovbRS4hL3ugMVrevOCUGDS-ixgByq_tbh4T9oihIRzbmFwwIN0Y3CCdmCDdWRwgnZg", + "PL27G47LAASBPPAMXUDIJ3OCRQ.all.holesky.ethdisco.net" : "enrtree-branch:3JSDZJCCWKIEBGPH5EI5VZF4RQ,XTJ3PFTPBB3ATDDWAA6W7RRKMY,FTTHOFPRPIHMJNZA3VZUAW5TIM,DAVKEW6RQ5YTYHKCJ2A2J5GVCI,TGKURK5IPVCPXS4QPS2KZJCP3Q,RWRV55FT3DKDVGZK7AEU2DR77Y,CTDMY3ALJA7FRKVS4MCTAJRRH4", + "HQ5S2EHH762PSKVTHWNQ6346NI.all.holesky.ethdisco.net" : "enr:-KO4QK883RN_CIppuOvhzi0O3Qg-XzHUZsdKIEqLdvZMLN5BCV5QTqqxRzJjtXa7NZjBi22UQJUUlsrQ_3g3Uavv92aGAY1BRdWag2V0aMfGhJsZKtCAgmlkgnY0gmlwhFJkOnSJc2VjcDI1NmsxoQNAyMtRruAQcNn10ZReZiiZtPnk35o_oJEhabuBKi1gLoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "XPTWTOASNO4WEBXH74WCQ5EYTQ.all.holesky.ethdisco.net" : "enr:-KO4QEk3I50HU8omZLCYgSwXs1caXS-q06lC_GnJT30gbzlIEDWBldaoC83sg9aWTQ9DdkQStosOuYEb13gxTwp4tSKGAY5DOiDfg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEVX7SJc2VjcDI1NmsxoQPCijWe7yQtKeDfuj6WXiJZ6CZ88FGXKj6DGSWdq0E0qYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "HOXANHAMPVCFA2QR54VEMWCWPE.all.holesky.ethdisco.net" : "enr:-KO4QELWztCXUz9MCxD8zbh65aa6LwP3wubhdXJVdlyrl7QzFJkUXosDXndbQqtAT2qD5nXAFpBnz5MeUSZf_GfjkI-GAY16vTc2g2V0aMfGhJsZKtCAgmlkgnY0gmlwhCZhyOSJc2VjcDI1NmsxoQMGwfOevbfZOGp3bL_2AH1SBdx3zn2_l56uG_4CWDf66YRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "BBNHIHYBPXVQTDZQ4JXK4QYDMM.all.holesky.ethdisco.net" : "enr:-KO4QCMGWCueZIoaBJyNAqOo_1wJ-QmbQ-qlTQx_rfz0gzKjF8VqFc99Q3ZMcfpK2qdLtWZHoRoiCkstH9_rWAU49DaGAYrbEkgdg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEVzHeJc2VjcDI1NmsxoQIy6rguhP2KemBUH2HJyW-GPo8prt6Ay9gjX3GugxLuGIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "LHFTDS37XFOEXQKTWJGKWRLFWM.all.holesky.ethdisco.net" : "enr:-KO4QB0RN-qZSymbzZA-AlKT8213I60xJjVVwN-AWwjW9W9aLk-2aq8jW_jbgKnJY3c_wU26oBzYFBpOVcYKIV_nd16GAYwlWhtPg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMPJ9bKJc2VjcDI1NmsxoQKlc1OTSAanfHEsPtrKjZvkgQUuHFZon2GtnCRHlDRV7oRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "67FFSS5IYEYRGUYFEWGIJDIMII.all.holesky.ethdisco.net" : "enr:-KO4QHY48cNs9Lauv6W3XCDcuBvhJbmL-0MAASBah_V-jG6iODMGVIZ9xv4K3MHSqQQht3Fc39CjU5zoYROe6D8uOq2GAY2UXNmdg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMb0yKiJc2VjcDI1NmsxoQNjc7k9S4kjTIwltOf7EH2ZmK3vZiEBpxxNqondpU3qV4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "MOBGCDYGQA4CNBQZDPN52JC5E4.all.holesky.ethdisco.net" : "enr:-KO4QDuar8SHEX1o_kUIKB0IajdUqcRb3ZkZdr5_MIxT1BUkLVk8AelLTv-_ioVGRAwNIJTzT4m8nyzV1VbsjjpeZ0yGAYrXy6Pag2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKEeJc2VjcDI1NmsxoQLy0OM9Ze8JjVHZhLQg7XejbI5iedlSDZNRmtQdTy_X8oRzbmFwwIN0Y3CCdn6DdWRwgnZ-", + "ERETBCE2BAPJRSWIEUQV3QPP7M.all.holesky.ethdisco.net" : "enr:-KO4QJY9GUtSCCXanmC9p7LYAfqk7jOUF-zxl7zd2ce5lD_aSNk9KfzBbh-Hii3qMzv-2x4a0Xal7RQMzQv9BqCkUMeGAYw1cGzgg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEVR7SJc2VjcDI1NmsxoQPQjk4qnGis3WKuSQDD20H-9n9xKFTbnLsB1DhAteyYk4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "5AHKPN5NN5IHEH365X6OYZDHDE.all.holesky.ethdisco.net" : "enr:-KO4QM-W42wfRYcTwaegJy3SfjlCkZsQU8LhGcluTdxtFjqXOwsEE5kUewkPMe7qIQpwb2MAo5xTeRpnijbdYTaG37-GAYtxMJdhg2V0aMfGhJsZKtCAgmlkgnY0gmlwhKh3IxmJc2VjcDI1NmsxoQNDrMpeyQI2aO_yoNP41RAf_BHtckptN1l2QIWxgDKOC4RzbmFwwIN0Y3CCdl-DdWRwgnZi", + "FEORTRPBZJSNRB3XCLK7KCMACQ.all.holesky.ethdisco.net" : "enr:-KO4QDO4oH5cjhncisJSk1SyGmwJ5VFjNetXw4OSSqDKc0NMDGXYYl6wUjbhcvzADYDpE1Br3lRG-1xV6iA1OAyXSAqGAY1W3CQQg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEVfkOJc2VjcDI1NmsxoQKkjEwDL0wuG0AH3RWw1wRrYHdPa8OOL1Ko4DYcZeQjQoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "AB27AIPX5Q5J6UAXQ6C2QFTYZA.all.holesky.ethdisco.net" : "enr:-KO4QNZrQF9iyry46odExoUh3kkHjWWHS0iEEjc8n2R4Orq8Rov4Ar3ozsyWt9Z-dmBtpTfmAo3UYspLFcvtHNzwjPmGAYwWbywRg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFtbbyJc2VjcDI1NmsxoQLD-zctKWrecek1fu3o2IKHUY9rkd0BYeQHrzpqElk_1oRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "NHLNHXPRKOALUKH4MZ7CIVDONU.all.holesky.ethdisco.net" : "enr:-Je4QBgb-GKZRRjU2TAE_9KyBHC8ImLYDPG8KShRKx8gbKF3F-gpoHiyeprH42weMNSg6i8GeG-n0SxwWJRe6zyXj88og2V0aMfGhJsZKtCAgmlkgnY0gmlwhCV4sKqJc2VjcDI1NmsxoQNuVgNhx7pgtJotEBq56F9YFom-6szZ97gCkea35_lDkoN0Y3CCdl-DdWRwgnZf", + "XPX2T64BHDYLVGT5UC4GVIQIVY.all.holesky.ethdisco.net" : "enr:-KO4QMlMC7rvmM9tvHXvwo2Vj5x5FePlyvH_6lBSCgZHN8HcWqtppk1peQlK9Ge79ma4j3gx_zX0hgJvprIy1ehjXXCGAY3Mer4jg2V0aMfGhJsZKtCAgmlkgnY0gmlwhIe1FCCJc2VjcDI1NmsxoQL3IIF3eENfSsr5tih2ebcm3dWL-otLdZYqUvfJ-5_9U4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "NZCRGKUE7ZXSIS4MIQ4WUS76BA.all.holesky.ethdisco.net" : "enr:-Je4QDqwqlm7UBywmVlR5UkkrQrg5B3UpkFexP7ucg4RAsdlMiJ4J1S5jT8jp6je6igMZ3OOnggdpd6l7QtQeNBICycDg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFs6LuJc2VjcDI1NmsxoQMgMreR2XspGJphg3fToxGKcMwWPE3e0gyxcqiQNLQXNIN0Y3CCdTuDdWRwgnU7", + "OF3GRGFZUAJTH3T2R2EXSYAZOU.all.holesky.ethdisco.net" : "enr:-KO4QDPbolwwOMTwV02zqyVgJFxko-HI8UWOT_K9sDcWgHG9fRDWkbSbTw_l3bcIA2-q3054lrJ9cbkHABlMZbQskUKGAY1y5VBWg2V0aMfGhJsZKtCAgmlkgnY0gmlwhKI3BbaJc2VjcDI1NmsxoQP9bM-ylBjwT9ujG09A__0to5F3Qw4QSvY4_vgyQ0A7j4RzbmFwwIN0Y3CCVTyDdWRwglU8", + "7QEPEVJFOCL5A63GZLZ4IZNMOI.all.holesky.ethdisco.net" : "enr:-KO4QNGh--C3ckyCMlUP4u86lt292CLHOQ3YIwk5Jqzz5x3OID_7BfRn5qN-ZBoBY80XOhFyHuo4eKDCIowQgYMvVY6GAY5S1aoSg2V0aMfGhJsZKtCAgmlkgnY0gmlwhFhjBqqJc2VjcDI1NmsxoQKZpCZSQgSun9pLzGrdfLboslJbD-JxtTsR4JF860eZYYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "Z5DOK3IB5X3IBOVVIK5MQCDYNA.all.holesky.ethdisco.net" : "enr:-KO4QJjEv14HV0BgdPwIa0iO-xrrwoi9k9LJRw3utIUVib5dF6s_b3y8z0NP2VyUGsJDFOwuVQq6OC6hb5_hFUqnf1yGAY12fbSog2V0aMfGhJsZKtCAgmlkgnY0gmlwhCU8-mOJc2VjcDI1NmsxoQIT2maaVlQBw4oD4loM1Q7gygn42pTQn1Sydo74LtZAZYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "CHFGCI2RQS3XFN2MKFP6G2ZM4U.all.holesky.ethdisco.net" : "enrtree-branch:XIOWDM2BTMANILG2M4LCMO7W3M,4LPHENNNENCUT7P3MWTB5IFRTY,5NQ4MKTYBPBMTGUT5IKUAXEGBE,CVK4DBIVPD2JPJOPQJQX77ZAWU,WLME2JINTIQACAMD5WZUQ4PRJI,DQYYUE7KVEXGEYBH4V2QHI6P7M,45V6KFI4NL43JFTJHL77KP6MQA,QDMF4HIR2UEXRJVOX4UJPJTPKA,BMVEIV6PNSN6RK5XEU4R4K", + "3EMD3PTQYRFVNFBQ73BYFL4AEQ.all.holesky.ethdisco.net" : "enr:-Je4QFiHIu4B3YbbG75mlr58JRaqpGUQij1n1pN3zaHoWbGrShq8aYqipbkPLaINPTX02YBfchyACgLHgH9cMarIUapQg2V0aMfGhJsZKtCAgmlkgnY0gmlwhDNRao6Jc2VjcDI1NmsxoQJHJlekJODLxBDPwpVLBtTMizLq5o9JtXkD8MQpqAIUYoN0Y3CC2fmDdWRwgtn5", + "IZNO6JEFTYHQWWF3LJ2M66P7II.all.holesky.ethdisco.net" : "enr:-KO4QLmjLLs27xB9n9N2TNC32EhbxjdiR32rroemDty1dQJsBSZQOawi3-HGqWDRifXce49pv2WewtuzF5j54iiUfbaGAYrbEiX_g2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEV5riJc2VjcDI1NmsxoQO4pbsV79dSOLkBaOX5vcv6Amy9rH2xg1wW3OsKxVA7PoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "OA4ZFFGZNFUC3LIYCUDJOPVR6U.all.holesky.ethdisco.net" : "enr:-KO4QFuTcCcZkhGlEZ9YjHVURcwzRDKDu_o8RBID9eF5lmG9fb9ZHBHnz0E-tXO4TcPfwxEtefRAaAVPj9Ycdi3OeXuGAYraylBgg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKFKJc2VjcDI1NmsxoQJRTkcLLW6c3J6kd1b1siWyumgXACvQK7ViQjsgMFx0c4RzbmFwwIN0Y3CCdn6DdWRwgnZ-", + "ZCAW4EMBOL5EH4MSMW7FY6JMEE.all.holesky.ethdisco.net" : "enr:-KO4QHc4CzkY6KkiTGR6hTovOeJ8VJuUtjkq2-UMXwUijiKvAZOFVS_Nn_GHMVZ8Ppsu31rSLYAEFRu0tMJ-LIDdSjOGAY2sYroCg2V0aMfGhJsZKtCAgmlkgnY0gmlwhIrJyaeJc2VjcDI1NmsxoQN7HHah7WnGluJb0mqKelBJ8rpvKlBb9t7848BwJ4qau4RzbmFwwIN0Y3CCIB-DdWRwgiAf", + "CVK4DBIVPD2JPJOPQJQX77ZAWU.all.holesky.ethdisco.net" : "enr:-KO4QH3RGFoO4KTuq8gxJC_mjnPBqNaDvoX_xsuYbDOqvJA4CPJs6nifZuqE2sTB3O-kHvEI0dbFJ87FoWkKhgmXYuOGAYrbEhVBg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEEV7HyJc2VjcDI1NmsxoQM1AMXary_Hiw-yesOw24q7GwMH_DmNHHitFPU46foJ24RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "O4SSPZG3DFA7PHZ5L42DVOPWDM.all.holesky.ethdisco.net" : "enr:-KO4QMrNy68H-dYJbPM7snJ1UrV-TPXA012sdna6WktkfksMED9fE3g-kzp7gBgOFEdFi1KIiEv5MXXAoOt1KOMVc1eGAYw66STEg2V0aMfGhJsZKtCAgmlkgnY0gmlwhF_ZxOCJc2VjcDI1NmsxoQJUhK-aKtl-Gc3ZnfF2k7oLFXmpGCHEi1_fBxAEfc1P54RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "TGKURK5IPVCPXS4QPS2KZJCP3Q.all.holesky.ethdisco.net" : "enrtree-branch:E4GGBOZ5L2UFPAKJIPLNBA2MKA,OF3GRGFZUAJTH3T2R2EXSYAZOU,D4GT5QUSIVDVPURCUOLE4WITZI,O6EQKGUJOO2BQGMADYZHOSZXLA,WRRS22MCKTZ4YS3ZLPUJEUAHUI,3A6T36TYZJBFLOHMJOJGL5SPXA,XPTWTOASNO4WEBXH74WCQ5EYTQ,2XMYGJOCRIHHMHAFVRH3OES5QY,FYJOHHN6LBARRNNLI6SK42", + "UIGSNQMHERWJIZCP2OLUXSZ3KM.all.holesky.ethdisco.net" : "enr:-KO4QEvn7KsE7UDJ5F3HwtSmGNSy0JSYDLfp9uJRtq5WfSsuOdkfq3V7GVSDo7IfCTXYAtQfRwT9q88II0sajv-m_CKGAYulV6JLg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMwQ9ISJc2VjcDI1NmsxoQNVsiSzpuxjNDgNToi4u48-5kCgvsjuoUsvlG9VrnEjhoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "3T4CNEKYCJP2PJ3EQVJSFKHH44.all.holesky.ethdisco.net" : "enr:-KO4QKNzTVC-wa7whLxFFss7NzEFDdVuAjgEebNGGK9xTWKjHTjqmMNfY4_h90iqlSYM_LoGyH2FFXhbHT05zKyALMSGAYuqLQ8Sg2V0aMfGhJsZKtCAgmlkgnY0gmlwhA360gaJc2VjcDI1NmsxoQPSUi99W8lkrquAhLsmslwXU4-dxxVfied-w_yqYEXpU4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "5ZWIGTGKMFAFF4LAODABANSBOQ.all.holesky.ethdisco.net" : "enr:-KO4QFP5g9U1YtBLeJi56xoBll8E4eUJeAAYMoEg1l0xPXRybh0OYNZfteBjkHMwbucccNdGB0amzNR4XtxmAfjoFWKGAYrbEjd8g2V0aMfGhJsZKtCAgmlkgnY0gmlwhF_YY_eJc2VjcDI1NmsxoQJb-JLk8MFQQPMz3QI2ya4FtZdHqZ1Nm0xD4MtOYc9ifYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "7J7D5R4SH6LVDCFZ5ELOP46IP4.all.holesky.ethdisco.net" : "enr:-KO4QArnrdy9hfW8KHAwokQf-x0LbdoDQ4WoK0H2dXqhP4D-TflLF_Ywf2lh4ybXao8jjNSxC53MzmFPUI9A8k06XDqGAY2KrTRtg2V0aMfGhJsZKtCAgmlkgnY0gmlwhLWkyzGJc2VjcDI1NmsxoQKSAHhJOTtkBlasBECB1mrukuL6jqOEtxWkpH-PfDp8h4RzbmFwwIN0Y3CCequDdWRwgnqr", + "5NHWEAJHKSAO5DIIYAZ7MQJVSE.all.holesky.ethdisco.net" : "enr:-KO4QMiOfa0JolrO470F-mRKslpq85BBGRz_JjoAOOnLuUdxBObP7579igrB-YGSdaUtb3Ih9QXBHRAl0PWYmE5NW32GAYtIvzSsg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMF6nk2Jc2VjcDI1NmsxoQI57ZbbGPYfl0DtrsmjeKDosRG14eV2qLI8AE6FsP2oy4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "OGKXEQEVGNJ574WCU7KFNTXNQI.all.holesky.ethdisco.net" : "enr:-KO4QH_WNLhz4qmL-EOMCQFfhE3QOOvyG5uyX0RR77gYrsdcJnUxS5OBQWyMqhRQLO2P9htXeBxJ4kR9ez13qQRiBp6GAY3m5RB8g2V0aMfGhJsZKtCAgmlkgnY0gmlwhIj0RveJc2VjcDI1NmsxoQJFRRKo2aP4qXB8sZnA6_rJqKgo8FZGT2i3ipEzwXCayYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "D4GT5QUSIVDVPURCUOLE4WITZI.all.holesky.ethdisco.net" : "enr:-J24QAgjCyFyNsDJHJwpo6uy0l7yqJD5r6WF58M1T7_PqsyKC0t6y1iTsQX4Crz6iv5Ijc8LqPZIC6vhA_F5GqkdkgSGAYtfbIIbg2V0aMfGhJsZKtCAgmlkgnY0gmlwhCvIu-OJc2VjcDI1NmsxoQKq0Xs_18RfgehL1rawMx2B3VMaH9d-YNCY5kmHuaCnqYN0Y3CCdl-DdWRwgnZf", + "OOQAXEUVKR5EJ722HM2UANT3R4.all.holesky.ethdisco.net" : "enr:-KO4QBU5Jlmco2sEPOXNEctSfBJfxdgANrWXVLS-BVDQYrU3N_oaeceDQIH82zZ6BSi_F-FQpSKhEVYtPDxI1BA4OW-GAY5bg91Qg2V0aMfGhJsZKtCAgmlkgnY0gmlwhIrJH32Jc2VjcDI1NmsxoQMXPocPKx0wRocEEzASwUfzDLKd1f-Jifv2pyIu2M8vaIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "ZJOONJUDYAQ53XOJU4KG5W4ATM.all.holesky.ethdisco.net" : "enr:-KO4QBGQGqvIoSv3C7d-bCiMst5GGEvIQaQ5pAHs5On0MeNfcVjcZgd72l2UUoqf13HoKHUnVG37cmHw-11H4Y59F6iGAYrbEhVng2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFtO36Jc2VjcDI1NmsxoQJ3QRuoMLUn6djLfYCFTKSV8kUWRQTOethOOhLDW6ezdYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "INA5QYTPU6WIOBT7IC7U3WGDIY.all.holesky.ethdisco.net" : "enr:-KO4QDpTzc6voIJiaQO1T8cbJvPej2OvifSuuDkQVrAcC3imJXT9J9zt5DelQaMAeu_uk11kFFgYJHBAE88J2cvxYGqGAY1olkLcg2V0aMfGhJsZKtCAgmlkgnY0gmlwhLnRsD6Jc2VjcDI1NmsxoQKfdroTKrg5QqtuIyfF7LivDR4GjeBnA8xQrAg5ma4pzYRzbmFwwIN0Y3CCy_KDdWRwgsvy", + "HTMBFBAIZBACDG3EZZ4JVANCAY.all.holesky.ethdisco.net" : "enr:-KO4QHHstlNCTI8xMnZ5mcIRvd8lfo9YoVeyv4pqvhtkxGI5PhYqDDqu1W5XqHWCMcTt8fpVgu9KojZHcyi7fhQhPdyGAY2_zUcvg2V0aMfGhJsZKtCAgmlkgnY0gmlwhL5czy-Jc2VjcDI1NmsxoQJpsTl5abUECWCfSno785tWBNPiVCJ7GG4eQTf2Cf1qBIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "KEC4722NVHE3KX3IYNZC34C7NY.all.holesky.ethdisco.net" : "enr:-KO4QMjtE87kVQpcuRPXV31w7fsvyit4Fw995wyZ_h6uK8atWGOhXpsi3xXsBQLgJFBWmNHgTw-V4JvZNFZkFHLU_8mGAY5hRoXMg2V0aMfGhJsZKtCAgmlkgnY0gmlwhC1Mp4CJc2VjcDI1NmsxoQPETNdXN5Cshfr8-rIIMev6E_MGqD-jzqcXW2yfzT3C54RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "LNO6EN3Y2LJA5YOJMEMODAJFWM.all.holesky.ethdisco.net" : "enr:-KO4QMIX_--Ar7-XnFcUVlJpBBUfZdfNOftELgvHhCGvbLGTMT_Yqs2M15BCG0qoHsYkVBP5b4wd2wqNyNIfFaTtQ7qGAYrXxOTEg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKEeJc2VjcDI1NmsxoQKG05NXftvaats582r82_zpOi2C54WjSeYwxKfSNeSJaoRzbmFwwIN0Y3CCdmqDdWRwgnZq", + "R6EQA5KQEQM77JJXB4BHHTDF6Y.all.holesky.ethdisco.net" : "enrtree-branch:5AOSND63QKPVT6EWNMALKAFC4I,WAU46WR54TX2VBK4QM7NFTA73Y,BBNHIHYBPXVQTDZQ4JXK4QYDMM,OA4ZFFGZNFUC3LIYCUDJOPVR6U,KMY5HFBGCUDWN2ZXE6QNUQHGYY,OGKXEQEVGNJ574WCU7KFNTXNQI,CDXRYZFKH6OUWTA2IJ2MYIMYPM,IPU725BUGL4HIOTSOIH3KZG5ZA,G4MENE2MCGXFPYEBF7SQEU", + "45V6KFI4NL43JFTJHL77KP6MQA.all.holesky.ethdisco.net" : "enr:-Je4QEedukMKHefwNNtNam8wvx8_0GMFHLC9nA-TWWPMTZ9FD4C1CrjqFxLNruZPGL4T1ApKPtes_ApKbwwOEc4dNxIDg2V0aMfGhJsZKtCAgmlkgnY0gmlwhIrJ_vOJc2VjcDI1NmsxoQIKnge3StO67CequDTr_QwD_V_qhS7TnGO-tgE472AFroN0Y3CCdl-DdWRwgnZf", + "5RYAVZN3SSZZQ2KISUO7XDBPE4.all.holesky.ethdisco.net" : "enr:-KO4QGMFa1U36mwISUTSlJN8q2EKJSw4WHa6PAMrHkhL9-naVdAWmGuwfpel1E5_NBSnPWRsG8FzmmUH61iq8fodXcKGAYrbEkT3g2V0aMfGhJsZKtCAgmlkgnY0gmlwhEFtb_iJc2VjcDI1NmsxoQJ62Txw9OKK7DTE_CZRC6tX_223dks-FcinnSL1uXUbTYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "KMY5HFBGCUDWN2ZXE6QNUQHGYY.all.holesky.ethdisco.net" : "enr:-KO4QLBXgetH_VHZgzalnkfF-iibF4km3OCLzY1TK27U-yG0ZA7Z4C8DL-da5x65khpgvOBa8c2CXffZBdTtD2BZQCqGAYrg47Ahg2V0aMfGhJsZKtCAgmlkgnY0gmlwhJT7RHyJc2VjcDI1NmsxoQKeRdcysv01DZ_Mzk9t1jcWW-YTjP1fPIrHVpw9hc_Q_oRzbmFwwIN0Y3CCdn-DdWRwgnZ_", + "YUZZDZD57PTNEIB5QL3FEXK2ZA.all.holesky.ethdisco.net" : "enr:-KO4QKuFVKbKbtK1djMy6q3TLuAWYDAjoC20cYPdhcOk7PhUdA67TXr9vTGfZZ9AO7ivmQZyRW4w9TFk-29_xP72bkKGAY2EAMvIg2V0aMfGhJsZKtCAgmlkgnY0gmlwhF_ZKGKJc2VjcDI1NmsxoQN4FBojS_W4gviNwaTDsIXiBEGXaQMtUzxQHwKWDmMR74RzbmFwwIN0Y3CCequDdWRwgnqr", + "2XMYGJOCRIHHMHAFVRH3OES5QY.all.holesky.ethdisco.net" : "enr:-KO4QAMrUvclx-EHZrO6x4K6fWTwaKh2zS5oWJzVU6oZuzZ2GG5xdQky8tIrpUUSKGB6XGvr8TvmiS7Dimvxx9Hb1OOGAYy06xQvg2V0aMfGhP1PAWuAgmlkgnY0gmlwhEFsSLGJc2VjcDI1NmsxoQJiz0q4ywyhHvmXBrWbFykzflq_J6cmLFIbepO9PLBwhoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "5NQ4MKTYBPBMTGUT5IKUAXEGBE.all.holesky.ethdisco.net" : "enr:-Ke4QLrsveUYt2tacm5EZETFc1F3EyvNYfRRkRhljyeLMIzccRlPI1kKmBWuELQs5iAIRZgv92P3Fxx_zJ3xyUbN3muGAY0x7p4Ng2V0aMvKhMYaYJiEZRbqwIJpZIJ2NIJpcIRU94PXiXNlY3AyNTZrMaEDBxF5W6guB9qZoR-c_zuDUE1UHyaH0FMjJKHC9Jq4ji6Ec25hcMCDdGNwgnZfg3VkcIJ2Xw", + "6WAXAZL7FYKEJBZOPWIHCI4F6E.all.holesky.ethdisco.net" : "enr:-KO4QCagHy1Q7UED3AJfgVHxFKOn_DRS8UTUg0okE7fW8VTcDCW7wlzWufdWCtdUwHpnaf3EZpRn2YRuo9u4LS-Oh3qGAYrayS-wg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKI2Jc2VjcDI1NmsxoQJYC74L06jkGeWkmh1aSjeBYVvzDCWEvtbd111Vu8WiG4RzbmFwwIN0Y3CCdmqDdWRwgnZq", + "ZRVWX74UFHUWOPCC7LOPLYGIZA.all.holesky.ethdisco.net" : "enr:-KO4QBfm8BEr7OIRv6UT1t5mhE2szefodQuIIBKMFnyvbky_K-wff-l6pqLwfLyUblqFNxqM6Xtcnari4ItzO9236DuGAY08Swa9g2V0aMfGhJsZKtCAgmlkgnY0gmlwhC7r5ZiJc2VjcDI1NmsxoQIH5RAmLOvYi50mYcMnglYJlz-EC0E2YsetPVUzvbs5BYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "2WHIXLN5QX3JEK3SSH7MXKTJMU.all.holesky.ethdisco.net" : "enr:-KO4QF2wWLadNPZ_qwOIZkLxPEJjj3N23892JKdtSOeeC-X-V0bZsjQ3QqpidJviGT0WrBakFANcbSa9IqFSOslJLV6GAYrayMEMg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKIGJc2VjcDI1NmsxoQKQ_STV3aCaM5we4KxMPMpdG63xPZieKw8A36OR2tuouIRzbmFwwIN0Y3CCdmqDdWRwgnZq", + "I2Q5U7BDYSM7O3O2IKIRL3KTZY.all.holesky.ethdisco.net" : "enr:-KO4QIvQh_txoF6gwXTRsMzzvHPdwQrkCHQYt4egwTWqUNQiMQh1yJ71U8UXs8b9pP9R1mUDTaiQ7-e0eB2Zbvouyb-GAYvSz8f0g2V0aMfGhP1PAWuAgmlkgnY0gmlwhJVmk6SJc2VjcDI1NmsxoQIuT88b-jLJBI40hV4VY3YeJnmYT65v2QPjyzuNG5dyF4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "NQHD4WNRRGE5JHHX6IDKGIF7KU.all.holesky.ethdisco.net" : "enr:-KO4QMTq7zJT6fLS-LY7n3hWmcwJqxRJraGJcM60U9Cej2lRRE-u_KhOd9r712IBEOI39uiVQEXGdBZvc-dJIESUcOOGAY2dUsseg2V0aMfGhJsZKtCAgmlkgnY0gmlwhFD5eBSJc2VjcDI1NmsxoQO-UyE5ad7DaM-f7fZi4QEwjfxIR6HS-l-lTSlv4ZLdB4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "PX6K4ZETH5UX56IKHKL5TNOOMU.all.holesky.ethdisco.net" : "enr:-KO4QJqslvj0RYuX2CI61yCK7VuyY9Ik3c5EHtpkKehriXyqchhCDMx4sRuewcCAiWO_frsUevV9GXMPnsO2nzCrgFGGAY25poLHg2V0aMfGhJsZKtCAgmlkgnY0gmlwhKfrsZeJc2VjcDI1NmsxoQOe9l9K5UW0RAuQTH1q6CwG_UzbJyKLGSt4lUt5_tVmyIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "CK3HQLGRQATDVF5CEGHX4DVQRE.all.holesky.ethdisco.net" : "enr:-KO4QJy9FHDJZfMqgGGIVGn-j0rHI6JDjTWEo7sN1mBkzO68ZId8jkRQfgZ5dJkv4GGm2rsvrWk6OJYF0td7n0Ve9GqGAYu0QPj0g2V0aMfGhJsZKtCAgmlkgnY0gmlwhHTK4wuJc2VjcDI1NmsxoQIYyd-9-wdwfPPu6uRcnTKkQaCekdhR7488-2pxl36AZ4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "IDXHFSATDDENJYOYJC2TUSUYOY.all.holesky.ethdisco.net" : "enr:-KO4QNWpVQT5pw-oUuoa7JDOVs1KheGaPRAR_fIarAflnc1yHawwEpptaB5JWkRXgh-wJtk2KlHE5zGICXefHD23Z4qGAY2-EYHHg2V0aMfGhJsZKtCAgmlkgnY0gmlwhK35GlyJc2VjcDI1NmsxoQPV0hDwmz1HaZ4pLm1hzee38NMugxA_7j3v6hbxP_LRCIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "UYESJQUB2BHP2MSJNUSDRGXQ34.all.holesky.ethdisco.net" : "enr:-KO4QB9gKzGbKvqoPJZymq3AiwZvWSHOup-36D8ec3CwNZDFRoEmp64UmWaP0St3OXDIV4Q2Rm0MnelRnAjvn3HRfyyGAY5EPB9Jg2V0aMfGhJsZKtCAgmlkgnY0gmlwhIrJ3_qJc2VjcDI1NmsxoQKHt6N7ehDnwT8_lFh-C4KgqUplYwDvYy6rOP6DFRO8lYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "76OAILAEE52CRVMYFBIBMSEUXE.all.holesky.ethdisco.net" : "enr:-KO4QDRyM88zIGJ2P0Ya1W8fucbp8kRTbVzV8k_2eawB0W3ZHMQ3o0HlbXVw3j1rMgN167LmsaMt1iO015HMVKGT2GqGAY0rjdqhg2V0aMfGhP1PAWuAgmlkgnY0gmlwhKFhcJuJc2VjcDI1NmsxoQJ2emahe6-2fq_hQqxm99rgYi4TSzQ1ky4utO3Tcpe-yYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "NLYAF5XVTTQUOMK4LYUF3FXNPE.all.holesky.ethdisco.net" : "enr:-KO4QMiia-4vyLiHQQhxlbmCKdOTRqOiZin-BdAdi18LxNqqHEiuIQQ-F1dZu8sKi63vEk9zwr5gfMnxXQZCThEaiDSGAY2UmHG4g2V0aMfGhJsZKtCAgmlkgnY0gmlwhMb0_ESJc2VjcDI1NmsxoQLb1ZwjPQw7AjCvlHQpt9bmePVD85rbHbnFZ0naOB1RNYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "QXRV67JYJNOYJDPC5CTKUVG76M.all.holesky.ethdisco.net" : "enr:-KO4QN1MRyJdifSbU3Mg_GUI0_ApfQQ_BcPgDV0FXjVvk4iEWX6EgMjXkI62H1S0DFnyWeHnvr-caabqiKtlvbIBICyGAY5Cyclbg2V0aMfGhJsZKtCAgmlkgnY0gmlwhK9jhAaJc2VjcDI1NmsxoQL8tsMGtv3EuJfUdI8AzGBxYynVj2HlNoz4wi3COC4TTYRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "4LPHENNNENCUT7P3MWTB5IFRTY.all.holesky.ethdisco.net" : "enr:-KO4QF8nbKqJkOeYlF-akOVBYzusVwSjI_ra_t7TmM52mEisQLCwNAjujSSc9-6ECErhss-gVTgBDzhY5QmVcF0PuZOGAY3Li2SUg2V0aMfGhJsZKtCAgmlkgnY0gmlwhCL__BOJc2VjcDI1NmsxoQLHimHBtxJxch5bc20e_O8OdeN3UQx6TQQWqaYfyi66OYRzbmFwwIN0Y3CCdW-DdWRwgnVv", + "5FNWKKKVUPIHRKWZY5P33A7E74.all.holesky.ethdisco.net" : "enr:-KO4QMD5jLnGVTSO75tQPB1JOCFKmtSPRi5pmE7wMwjDRfVKdwpZJvr8qfv1WmfRnJFzH5qV2sfC187nT9mp-xE_-gGGAYupHwgxg2V0aMfGhJsZKtCAgmlkgnY0gmlwhE6KPgeJc2VjcDI1NmsxoQP9YVLocwkml9Z9YNDRpmzVceRY-Ts45qiPOBC1OsxuUIRzbmFwwIN0Y3CCdmmDdWRwgnZp", + "HIDVATDVB36L2MASAWA7SBJAII.all.holesky.ethdisco.net" : "enrtree-branch:N7HAL5M6HNZBGTWM3LWFDRX4WU,PX6K4ZETH5UX56IKHKL5TNOOMU,I2Q5U7BDYSM7O3O2IKIRL3KTZY,O4SSPZG3DFA7PHZ5L42DVOPWDM,Z5DOK3IB5X3IBOVVIK5MQCDYNA,ZJOONJUDYAQ53XOJU4KG5W4ATM,NLYAF5XVTTQUOMK4LYUF3FXNPE,XPX2T64BHDYLVGT5UC4GVIQIVY,AHB67R6KGAKWRSBL7CRAO3", + "FTTHOFPRPIHMJNZA3VZUAW5TIM.all.holesky.ethdisco.net" : "enrtree-branch:V52J3WKNVGG56JFRKYDLSZREJY,ZCAW4EMBOL5EH4MSMW7FY6JMEE,2SA643JTHJ75ZVPFHAKLXI2WXQ,5RYAVZN3SSZZQ2KISUO7XDBPE4,366Y3UIIKK2G5CUS7CHNPZMPEM,7J7D5R4SH6LVDCFZ5ELOP46IP4,7QEPEVJFOCL5A63GZLZ4IZNMOI,OOWRWZXNDJVJUCDDOJFOY4YB2Y,H6XMM4W6QZEQDAPVXGHJSU", + "O6EQKGUJOO2BQGMADYZHOSZXLA.all.holesky.ethdisco.net" : "enr:-KO4QAg_or5YgVU8ScSgcgvNmLMISW0LA4L5GtRLxmyVUlGRR4GNuEZ9q_tKtZdAbLH5B-FN2ie8hp0U6P90d39xtyWGAY3d9Tplg2V0aMfGhJsZKtCAgmlkgnY0gmlwhAMRsEKJc2VjcDI1NmsxoQJ7STjsgZvt1OOj5krr2l2iAwlY5AGl-dgTziPZsCd9qIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "XIOWDM2BTMANILG2M4LCMO7W3M.all.holesky.ethdisco.net" : "enr:-Je4QCvStdCVA-jcYsFoXmDXjXlp-Cd_9sSMdi9Y1LM3tGH2C3k49yrWy-Y2Jg93ikASYljvD9qVUES0T9q5htcbL60ag2V0aMfGhJsZKtCAgmlkgnY0gmlwhLkIa-2Jc2VjcDI1NmsxoQKcjBIYl8vFVYVBs5trEl-Zn3IE7u1ZiiV986p0QCrAL4N0Y3CCdl2DdWRwgnZd", + "OL6KYVYI7SGS7U34FW3RFBA76A.all.holesky.ethdisco.net" : "enr:-KO4QIlf7XLihA1hw9d44SB0ENJ40RT1RmF2KrT9a2kRZfZoWPdO1jRi3GNnNSCLDxLo-aFc6uaGi3zxhCD8lg1aZgSGAYuoht2-g2V0aMfGhJsZKtCAgmlkgnY0gmlwhDNR0MWJc2VjcDI1NmsxoQKFvOHK4c-F1tHwdgsUa2yru5RrWyiVP9kRLnrw1kXcd4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "NXU6DU7HEM2L4DN6G2VHHFT72I.all.holesky.ethdisco.net" : "enr:-KO4QLbrxgLUdY0NhpBPVfilpwn4d3gPFIEqoq62P1piOkVmGwh5qpbKtor5FfE4FM_eezlzMdeCM7bzau8ciKZU1GiGAY0-AhsZg2V0aMfGhJsZKtCAgmlkgnY0gmlwhEp2iPuJc2VjcDI1NmsxoQOGZRfYj6RgBYWulaw90MVPDt_9F-oM3PzevNe-RS6KyoRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "RUQLNXP5XBWPAOEKRUEBAQXXXU.all.holesky.ethdisco.net" : "enr:-KO4QPpoyIf1DfiiOW8Tt34tBuA68Qd55cyWcqGOCFJtcHKtcqYr373NJPyQVd8ktsuqZU8L_ERSRAfKesEwdBARg3OGAY45u3jEg2V0aMfGhJsZKtCAgmlkgnY0gmlwhJRxo0WJc2VjcDI1NmsxoQKhMTQ31q7EAIHkisiA02KVyFZZLq2Q9w4_jgmiYCsF_oRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "RUJF27NEYDBNQAFMI6K6SKDVRY.all.holesky.ethdisco.net" : "enrtree-branch:OOQAXEUVKR5EJ722HM2UANT3R4,HOXANHAMPVCFA2QR54VEMWCWPE,INA5QYTPU6WIOBT7IC7U3WGDIY,3PMAED3BC2HUS7AMEPGJDKENQY,VJJPHI6PWJ7NFBTW2XJH3JMMNY,5ZWIGTGKMFAFF4LAODABANSBOQ,UYESJQUB2BHP2MSJNUSDRGXQ34,CK3HQLGRQATDVF5CEGHX4DVQRE,AYB76YY6WPJVIBLRB5U7L5", + "ZM7CMNKKBVIXY7WGMB7GHYUXMA.all.holesky.ethdisco.net" : "enr:-KO4QNhl-I-sZux_gBOVLLbMdw8kMK9fSEBBNYukE2r95hDLJ9rOuhZgJO2dvNU_vCcuiqJNJHj8N3olsc7srxryuuCGAY0cB7Qsg2V0aMfGhP1PAWuAgmlkgnY0gmlwhJ7caOWJc2VjcDI1NmsxoQIyp37cpS7gvrKk0f3VxW4D9Jx7mOvSAQ6vOaQppsYp2oRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "FKSM7XWAT4KW3TDLRHWSXZPMKQ.all.holesky.ethdisco.net" : "enr:-Ke4QNDn6wmnaZU1IYGb9lX8zb2QFUpa_yen8vFTnuXpW3_iah53AKPZX1D05HE23bw-UtR6zXOpCquB9XDdxvGhZrGGAY4oYEAkg2V0aMvKhMYaYJiEZRbqwIJpZIJ2NIJpcIQlPPlxiXNlY3AyNTZrMaEDiVRaEbnUMSPCtpxluUoBgOy3Loaa6SaVW9QK8BGTFJiEc25hcMCDdGNwgnZ9g3VkcIJ2fQ", + "QXKEJG4XZEQSXNUY7JJYCATPEI.all.holesky.ethdisco.net" : "enrtree-branch:FEORTRPBZJSNRB3XCLK7KCMACQ,2M2GRZYAFKAVHHU5HTLUHPYHCM,KEC4722NVHE3KX3IYNZC34C7NY,NZCRGKUE7ZXSIS4MIQ4WUS76BA,3PYSNKXWWSRBWV377EFNYINHSA,C7SDD5OPASV7B2XUOXF5NLBBKU,QY2XP6FTX7QKFNP6TNZ2MOHZKQ,76OAILAEE52CRVMYFBIBMSEUXE,2QHFEUHLG6Q35B5LUS5BF3", + "OSHAABXYJSRWW35VOMYHZUKJXU.all.holesky.ethdisco.net" : "enrtree-branch:LHFO3FXNRHB5B3YSTKUALGMEAI,5FNWKKKVUPIHRKWZY5P33A7E74,NHLNHXPRKOALUKH4MZ7CIVDONU,BAY6SKB2RTQCM7RTSHAFQ6TTBQ,ERETBCE2BAPJRSWIEUQV3QPP7M,MFPFKTJREYMESD7STJJOFYDVV4,MOBGCDYGQA4CNBQZDPN52JC5E4,RUQLNXP5XBWPAOEKRUEBAQXXXU,NJCWGLUAGBNZQYPU752O5L", + "WAU46WR54TX2VBK4QM7NFTA73Y.all.holesky.ethdisco.net" : "enr:-KO4QE70KmVYr_jd9JOMBFTIJomf3oliyhugCm4kFnzYD7dcJk3y7dVYyakJdlWHBuk1t4hDjW05BzeVf2f-V0LQ-r6GAY0-Aab1g2V0aMfGhJsZKtCAgmlkgnY0gmlwhCUbP0KJc2VjcDI1NmsxoQMQLfyyzC-YY6A53fEu5a8tP-JWCUM3vkX-c7nRyu28d4RzbmFwwIN0Y3CCequDdWRwgnqr", + "CZ7ESLY5ZH4ULXKQ54XIFDCOUI.all.holesky.ethdisco.net" : "enr:-KO4QOQjO7c9J74CpllRngkrEXHLw-W8VqtJXxkLWPRIXC1CFL4TCjEM4ZfRW6MFlqXERaY3h9mztZXLAo1lf1DAS1qGAY2D0c0_g2V0aMfGhJsZKtCAgmlkgnY0gmlwhC06cBWJc2VjcDI1NmsxoQN8oyz6RCujPq6Hj9N8dBn3EeJ4A69HYeYnyLRiXLZ1UIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "5HSHHSS4QV3FKCNDETO7CEXMZM.all.holesky.ethdisco.net" : "enr:-KO4QAOJNWWAbN0bM51WFaFZimloFw1eBc7Pi3x7uMejmIToDZxBoAVtvdwTg3p6T0Mwmvuot6uT7PG2OjGxkk3P-iGGAY5cIO3Hg2V0aMfGhJsZKtCAgmlkgnY0gmlwhLAJA5uJc2VjcDI1NmsxoQPdRE5vPW9Wj-HRwzubnKAA-1n0p6CAOGLP-E-GzE9EnIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "DAVKEW6RQ5YTYHKCJ2A2J5GVCI.all.holesky.ethdisco.net" : "enrtree-branch:6WAXAZL7FYKEJBZOPWIHCI4F6E,OL6KYVYI7SGS7U34FW3RFBA76A,FKSM7XWAT4KW3TDLRHWSXZPMKQ,5HSHHSS4QV3FKCNDETO7CEXMZM,CZ7ESLY5ZH4ULXKQ54XIFDCOUI,ZRVWX74UFHUWOPCC7LOPLYGIZA,FFM67SMD4N3SK4ZQTY2HOMU4F4,IPSUCB6CICZIW6SERKZL7FFTIM,7XE2DGFKCGOST6BJ46JPNK", + "ELYMU6HPEMGLIYO2UO4YNUI7CQ.all.holesky.ethdisco.net" : "enr:-KO4QOWLzzuDHlwrEZhdOmeHEuFi87mX6iwJ_V820RsBL0mCLngiBaLbhumS1Q8zIc6YPzCYN07nigSMr-OXf19z3WSGAYra1TQYg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKFGJc2VjcDI1NmsxoQO4QASxyNUTDVIRkvEDQejetqJ4roUtGDD6U8CoI9wm-YRzbmFwwIN0Y3CCdnSDdWRwgnZ0", + "VNVQZHCW3CS7ELWR3ANLO7RFBA.all.holesky.ethdisco.net" : "enr:-Ji4QBY7W0c9-rsM9r3yeBngIOe0LFJx8wew3ZatidckbRSzAbXbvc5ahmadpUcrPG2oDm9ziwxw7maQtzEs4J2AnWeBr4NldGjHxoSbGSrQgIJpZIJ2NIJpcISU--s8iXNlY3AyNTZrMaECwwCgmDrePUxVSsOZqgS0USzkXwzkqF0-QK7a59EsnrCDdGNwgnX7g3VkcIJ1-w", + "MFPFKTJREYMESD7STJJOFYDVV4.all.holesky.ethdisco.net" : "enr:-KO4QJfXFSQOpwMtEgz0BSB0gJ0zXQZ6yMzoBfXYCK3ATxulM_mkkQhMWUHsrNyNH9cQYfxRbN_hEGfP3id3IfLiv7KGAY5iEk-hg2V0aMfGhJsZKtCAgmlkgnY0gmlwhGQmekqJc2VjcDI1NmsxoQOoFPqpQmRhcIfVINZ0knq8hxe2tUYnTSLEC-6Xoly7jIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "HGROZTZI7YPDW5F37QVUPQEBG4.all.holesky.ethdisco.net" : "enr:-KO4QI3-xQxY2u-misXaxFtpfezZr0Fk0jiL6U7ZAbwV4yCRcWxgNVOxLifoUOm9uMUqH4wlGxIYL7onmzlavqRIjDGGAYs5av4dg2V0aMfGhJsZKtCAgmlkgnY0gmlwhJRxqGeJc2VjcDI1NmsxoQPc4dhahamqQVxv9D89fNMO9DOP_YaPJRQ3EmT2XantU4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "VJJPHI6PWJ7NFBTW2XJH3JMMNY.all.holesky.ethdisco.net" : "enr:-KO4QHCu9ZPe68fKUXeUzje0Jwv0D8UCrAQ_K5W9KHrIpTdUYWIGwbzyl8heZ1cxijlyUhN1WB0HZpEBThUmrdm-uLiGAYra3Fk3g2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKJOJc2VjcDI1NmsxoQP0AAgBs1kDG4XBe55HY0J4F7GjHiwQVUY-xFKYXOB594RzbmFwwIN0Y3CCdnSDdWRwgnZ0", + "2M2GRZYAFKAVHHU5HTLUHPYHCM.all.holesky.ethdisco.net" : "enr:-KO4QIPWnAyt-tyaS1cnMwEJaFdvDd-MpwEcVv26cfaZ3Ffkc4WCpHqzPmd_SifEsxQf7ontOz9a1EPjbxlsu_V1XZqGAY1UHtm_g2V0aMfGhJsZKtCAgmlkgnY0gmlwhCU85MWJc2VjcDI1NmsxoQNyzc5NiamRt8y5TQ9Qj-EZAYeCb7ZaclF5sOdPrErpbIRzbmFwwIN0Y3CCdl-DdWRwgnZf", + "OOWRWZXNDJVJUCDDOJFOY4YB2Y.all.holesky.ethdisco.net" : "enr:-KO4QBKCkXrhG-hN-IY-O03b5A4JHaweb5xuuSZP4OdJ4uSSZ7E1-yioWl_0WSF8ShOfNU_7wgSCIwBPg0d4RD4w4sOGAY4oBl8og2V0aMfGhJsZKtCAgmlkgnY0gmlwhFJB7YiJc2VjcDI1NmsxoQL-RfOTNeu0SmlCfWAVQaQBUXF0WDEUCyGXv1LWC2_xqoRzbmFwwIN0Y3CCequDdWRwgnqr", + "E4GGBOZ5L2UFPAKJIPLNBA2MKA.all.holesky.ethdisco.net" : "enr:-Ke4QD_Gz-YGWvzpAe-a1l2KHz2pxG_nPUYTcHQDN1Wuvkk7TrEDq-HKIXtA_mbPukz9qLLW5sfkJH5mYda9eDssvkSGAY1Mq2nIg2V0aMvKhMYaYJiEZRbqwIJpZIJ2NIJpcIQf3GvbiXNlY3AyNTZrMaECyosSeovqxsDXTua8c47z7EK--WogcD_FCwDX6tHvVQSEc25hcMCDdGNwgnZfg3VkcIJ2Xw", + "KYTZHQX2PSOGY6RQTCVTUKTS7E.all.holesky.ethdisco.net" : "enr:-KO4QJn2ahKcTeE2karHSHOiJgE9b2BJWo54NS3nzjjCDnsvZ1JjDl8yulvzn8qQA48zCtHkiVMEVNHtdf_LM_N0Cs6GAYxElMbzg2V0aMfGhJsZKtCAgmlkgnY0gmlwhJ3m3GOJc2VjcDI1NmsxoQJzs6KencrR0_ylBVNGuZaknO_zQUYOrq4rjj_FmTlHN4RzbmFwwIN0Y3CCdl-DdWRwgnZf", + "O25DXMPE4UEZ6SFMQRBGL2E2I4.all.holesky.ethdisco.net" : "enr:-KO4QLC4qJt9OIKLkxROeQMNcj4ZuH_QZsVcS1v-NhzBGAf8B-5xF3GYqtMp40n6nwDg8o1yUs7xEx0kgf6wBJF-AuqGAYrbCvwJg2V0aMfGhJsZKtCAgmlkgnY0gmlwhMIhKGuJc2VjcDI1NmsxoQPogWsyNFpt9VYFYrsdUS4dxK2BMeL4FY41ZzgBjeEGRoRzbmFwwIN0Y3CCdmCDdWRwgnZg", + "RWRV55FT3DKDVGZK7AEU2DR77Y.all.holesky.ethdisco.net" : "enrtree-branch:ZV5CYUMJPF4XSTFHOG65622KEE,QDCV4SQTQAGHHA3DRA2TR4LNMY,MZGQKIQKIOFO3W2GJURJUXVYMQ,V5LTO36DCXU2JCCSSJ76E35OFU,NQHD4WNRRGE5JHHX6IDKGIF7KU,ELYMU6HPEMGLIYO2UO4YNUI7CQ,VN7EWW4RMUZM6KUOQ43GJ33DWM,J7ZIDKH7CKVIYY244QVU6RMPDM,QSK67XVHDPEQH7Q54HACQS", + "TMY2W2YBNCXUUNA3Y7QXWVQLRE.all.holesky.ethdisco.net" : "enr:-Ke4QEsOrFCJqnbVXiuSh3DKjvS3RlUoOrrLRlKp2mAqmCuJQBVLFREqABNWRvZfLOxDPEtvcRzDtDW2juSa1vd2xj6GAY025-JNg2V0aMvKhP1PAWuEZcNqwIJpZIJ2NIJpcIRU961viXNlY3AyNTZrMaECoqR94LV1BQMpEDbmfJdd8adEPWHV7qP09nePPVm9nLqEc25hcMCDdGNwgnZfg3VkcIJ2Xw", + "XTJ3PFTPBB3ATDDWAA6W7RRKMY.all.holesky.ethdisco.net" : "enrtree-branch:5AHKPN5NN5IHEH365X6OYZDHDE,AUQGHXRAP7J3AGI6TUOQVYTYLY,IDXHFSATDDENJYOYJC2TUSUYOY,GZVG4EONSAY6M7SMLJXDCFUF5Q,LHFTDS37XFOEXQKTWJGKWRLFWM,HTMBFBAIZBACDG3EZZ4JVANCAY,ZM7CMNKKBVIXY7WGMB7GHYUXMA,VNVQZHCW3CS7ELWR3ANLO7RFBA,PA4IN34FHBJOUK2MS7YRA3", + "V4A7I7I2SFVUDFFH7AGPFXACBA.all.holesky.ethdisco.net" : "enr:-KO4QMIHR0XgkMyX4E9Xh8Fw3rFr-QWyH49lpFmrEhx1Cc_WMxm6atHPm0g-bXmzradBORfb0S9_6dyi-GnQbtlm7GOGAYr8tSZLg2V0aMfGhJsZKtCAgmlkgnY0gmlwhA_MQUKJc2VjcDI1NmsxoQMrgP3au96duBa9PQzAFPhlQ7ikkA96YWAkrItcm5zCxIRzbmFwwIN0Y3CCdl-DdWRwgnZf" +} \ No newline at end of file diff --git a/gradle/versions.gradle b/gradle/versions.gradle index 4fa7f871320..4dd279d7e5f 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -108,7 +108,6 @@ dependencyManagement { entry 'tuweni-concurrent' entry 'tuweni-crypto' entry 'tuweni-devp2p' - entry 'tuweni-dns-discovery' entry 'tuweni-io' entry 'tuweni-net' entry 'tuweni-rlp' From 31dff4410a81c0704042b511f8b312258c433b92 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 5 Jun 2024 11:56:59 +0100 Subject: [PATCH 20/42] Use github arm64 runners (#7173) Now that the arm64 runners are re-created with the ubuntu 22.04 image, docker and other tools are available. See #7053 and #7171 fixes #7026 Signed-off-by: Sean Young Co-authored-by: Simon Dudley --- .github/workflows/develop.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index a5447473147..66537919f9c 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -36,7 +36,7 @@ jobs: matrix: platform: - ubuntu-22.04 - - [self-hosted, ARM64] + - besu-arm64 runs-on: ${{ matrix.platform }} steps: - name: Prepare diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e703623ebf..dd34bb12396 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -151,7 +151,7 @@ jobs: matrix: platform: - ubuntu-22.04 - - [self-hosted, ARM64] + - besu-arm64 runs-on: ${{ matrix.platform }} steps: - name: Prepare From 777479699f3692717d500b0ce1a2e817775ca397 Mon Sep 17 00:00:00 2001 From: Chaminda Divitotawela Date: Wed, 5 Jun 2024 23:48:32 +1000 Subject: [PATCH 21/42] DCO Check GitHub workflow (#7179) DCO App not working and needed to be disabled the check. Introducing DCO GitHub action workflow to validate the commit signatures. Closes #7175 Signed-off-by: Chaminda Divitotawela Signed-off-by: Ry Jones --- .github/workflows/dco.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/dco.yml diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml new file mode 100644 index 00000000000..da0d2115acf --- /dev/null +++ b/.github/workflows/dco.yml @@ -0,0 +1,19 @@ +name: DCO + +on: [pull_request] + +jobs: + dco_check: + runs-on: ubuntu-latest + name: DCO + if: ${{ github.actor != 'dependabot[bot]' }} + steps: + - name: Get PR Commits + id: 'get-pr-commits' + uses: tim-actions/get-pr-commits@198af03565609bb4ed924d1260247b4881f09e7d + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: DCO Check + uses: tim-actions/dco@f2279e6e62d5a7d9115b0cb8e837b777b1b02e21 + with: + commits: ${{ steps.get-pr-commits.outputs.commits }} From 4fa2592b97386405a96a9aef3dc93ceb2ab4f3a7 Mon Sep 17 00:00:00 2001 From: ahamlat Date: Wed, 5 Jun 2024 18:27:19 +0200 Subject: [PATCH 22/42] Remove sorting updated storage entries in commit phase (#7167) Signed-off-by: Ameziane H --- .../DiffBasedWorldStateUpdateAccumulator.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java index 6c44f185fb9..149cefbe540 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java @@ -45,7 +45,6 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @@ -364,27 +363,28 @@ public void commit() { return; } - final TreeSet> entries = - new TreeSet<>(Map.Entry.comparingByKey()); - entries.addAll(updatedAccount.getUpdatedStorage().entrySet()); - // parallel stream here may cause database corruption - entries.forEach( - storageUpdate -> { - final UInt256 keyUInt = storageUpdate.getKey(); - final StorageSlotKey slotKey = - new StorageSlotKey(hashAndSaveSlotPreImage(keyUInt), Optional.of(keyUInt)); - final UInt256 value = storageUpdate.getValue(); - final DiffBasedValue pendingValue = pendingStorageUpdates.get(slotKey); - if (pendingValue == null) { - pendingStorageUpdates.put( - slotKey, - new DiffBasedValue<>( - updatedAccount.getOriginalStorageValue(keyUInt), value)); - } else { - pendingValue.setUpdated(value); - } - }); + updatedAccount + .getUpdatedStorage() + .entrySet() + .forEach( + storageUpdate -> { + final UInt256 keyUInt = storageUpdate.getKey(); + final StorageSlotKey slotKey = + new StorageSlotKey( + hashAndSaveSlotPreImage(keyUInt), Optional.of(keyUInt)); + final UInt256 value = storageUpdate.getValue(); + final DiffBasedValue pendingValue = + pendingStorageUpdates.get(slotKey); + if (pendingValue == null) { + pendingStorageUpdates.put( + slotKey, + new DiffBasedValue<>( + updatedAccount.getOriginalStorageValue(keyUInt), value)); + } else { + pendingValue.setUpdated(value); + } + }); updatedAccount.getUpdatedStorage().clear(); From 2d59f4dd7eefb05f7b3b42c77177bd96c89a4369 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Thu, 6 Jun 2024 15:29:18 +1000 Subject: [PATCH 23/42] feat!: Java 21 for build and runtime (#7177) * build: Update jacoco version to 0.8.11 * build: Enforce Java 21 and above check for build * CI: Use Java 21 in Github CI workflows * CI: Use Java 21 in circleci workflows * build: Update gradle verification metadata for jacoco 0.8.11 * refactor: Fix javadoc related warnings which are applicable to Java 21 * fix(test): BackwardSyncAlgSpec slightly increase timeout to pass it in CI --------- Signed-off-by: Usman Saleem --- .circleci/config.yml | 4 +- .github/workflows/acceptance-tests.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/develop.yml | 6 +- .github/workflows/integration-tests.yml | 2 +- .github/workflows/pre-review.yml | 6 +- .github/workflows/reference-tests.yml | 4 +- .github/workflows/release.yml | 26 ++++---- .github/workflows/sonarcloud.yml | 6 +- CHANGELOG.md | 1 + .../besu/services/BlockchainServiceImpl.java | 3 + build.gradle | 10 +-- .../backwardsync/BackwardSyncAlgSpec.java | 2 +- .../besu/ethereum/rlp/RLPInput.java | 3 +- .../besu/evm/frame/MessageFrame.java | 3 + gradle/verification-metadata.xml | 62 ++++++++++++------- .../services/tasks/InMemoryTaskQueue.java | 3 + .../hyperledger/besu/util/EndianUtils.java | 1 + .../hyperledger/besu/util/FutureUtils.java | 2 + .../hyperledger/besu/util/log/LogUtil.java | 2 + .../besu/util/platform/PlatformDetector.java | 2 + 21 files changed, 92 insertions(+), 60 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a964f4d3be8..45aa3beb287 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ orbs: executors: besu_executor_med: # 2cpu, 4G ram docker: - - image: cimg/openjdk:17.0 + - image: cimg/openjdk:21.0 resource_class: medium working_directory: ~/project environment: @@ -24,7 +24,7 @@ executors: besu_executor_xl: # 8cpu, 16G ram docker: - - image: cimg/openjdk:17.0 + - image: cimg/openjdk:21.0 resource_class: xlarge working_directory: ~/project environment: diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index 38a4272bdc4..161d5d6da2b 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -34,7 +34,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: Install required packages run: sudo apt-get install -y xmlstarlet - name: setup gradle diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0a50ec57c2d..e7a13e92d40 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -33,7 +33,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: 'temurin' - java-version: 17 + java-version: 21 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@2f93e4319b2f04a2efc38fa7f78bd681bc3f7b2f diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 66537919f9c..b9bb3d95973 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -17,7 +17,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -67,7 +67,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -106,7 +106,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 8a60d09017d..171ddeb85ec 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -29,7 +29,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: diff --git a/.github/workflows/pre-review.yml b/.github/workflows/pre-review.yml index ce7d0e7c137..0a5b3edf918 100644 --- a/.github/workflows/pre-review.yml +++ b/.github/workflows/pre-review.yml @@ -45,7 +45,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: Setup Gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -65,7 +65,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: Setup Gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -93,7 +93,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: Install required packages run: sudo apt-get install -y xmlstarlet - name: Setup Gradle diff --git a/.github/workflows/reference-tests.yml b/.github/workflows/reference-tests.yml index 84123b226d1..4e458e057e3 100644 --- a/.github/workflows/reference-tests.yml +++ b/.github/workflows/reference-tests.yml @@ -34,8 +34,8 @@ jobs: - name: Set up Java uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: - distribution: adopt-openj9 - java-version: 17 + distribution: semeru # IBM Semeru with OpenJ9 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dd34bb12396..496691293dc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,11 +19,11 @@ jobs: steps: - name: checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Set up JDK 17 + - name: Set up Java uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: - distribution: 'temurin' - java-version: '17' + distribution: temurin + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -60,8 +60,8 @@ jobs: - name: Set up Java uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: - distribution: adopt - java-version: 17 + distribution: temurin + java-version: 21 - name: Download zip uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe with: @@ -108,11 +108,11 @@ jobs: steps: - name: checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Set up JDK 17 + - name: Set up Java uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: - distribution: 'temurin' - java-version: '17' + distribution: temurin + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -132,7 +132,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -174,7 +174,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -214,7 +214,7 @@ jobs: uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: distribution: temurin - java-version: 17 + java-version: 21 - name: setup gradle uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1 with: @@ -248,8 +248,8 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: - distribution: 'temurin' # See 'Supported distributions' for available options - java-version: '17' + distribution: temurin + java-version: 21 cache: gradle - name: login to ${{ env.registry }} uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 9f70e699178..7549656d223 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -17,11 +17,11 @@ jobs: steps: - name: checkout uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - name: Set up JDK 17 + - name: Set up Java uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 with: - distribution: 'temurin' - java-version: '17' + distribution: temurin + java-version: 21 - name: Cache SonarCloud packages uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d43191302..666712e4509 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Next Release ### Breaking Changes +- Java 21 has been enforced as minimum version to build and run Besu. ### Additions and Improvements - Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) diff --git a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java index 5005e5f7ccd..d9e5dbb9ef7 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java @@ -42,6 +42,9 @@ public class BlockchainServiceImpl implements BlockchainService { private ProtocolSchedule protocolSchedule; private MutableBlockchain blockchain; + /** Instantiates a new Blockchain service implementation. */ + public BlockchainServiceImpl() {} + /** * Instantiates a new Blockchain service. * diff --git a/build.gradle b/build.gradle index 74c06e8fe3f..905e8b2c8af 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ sonarqube { project.tasks["sonarqube"].dependsOn "jacocoRootReport" -if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { - throw new GradleException("Java 17 or later is required to build Besu.\n" + +if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) { + throw new GradleException("Java 21 or later is required to build Besu.\n" + " Detected version ${JavaVersion.current()}") } @@ -125,7 +125,7 @@ allprojects { version = calculateVersion() jacoco { - toolVersion = '0.8.8' + toolVersion = '0.8.11' if (project.tasks.findByName('referenceTests')) { applyTo referenceTests } @@ -144,8 +144,8 @@ allprojects { tasks.build { dependsOn 'javadoc' } - sourceCompatibility = 17 - targetCompatibility = 17 + sourceCompatibility = 21 + targetCompatibility = 21 repositories { maven { diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgSpec.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgSpec.java index 56e3324b7f6..bd5a9e7ec9c 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgSpec.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgSpec.java @@ -189,7 +189,7 @@ public void shouldAwokeWhenConditionReachedAndReady() throws Exception { completionCaptor.getValue().onInitialSyncCompleted(); - voidCompletableFuture.get(500, TimeUnit.MILLISECONDS); + voidCompletableFuture.get(800, TimeUnit.MILLISECONDS); assertThat(voidCompletableFuture).isCompleted(); verify(context.getSyncState()).unsubscribeTTDReached(88L); diff --git a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java index fba43e2a1c6..b31184ab5ef 100644 --- a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java +++ b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java @@ -50,8 +50,7 @@ * word, a method like {@link #readLongScalar()} does not expect an encoded value of exactly 8 bytes * (by opposition to {@link #readLong}), but rather one that is "up to" 8 bytes. * - * @see BytesValueRLPInput for a {@link RLPInput} that decode an RLP encoded value stored in a - * {@link Bytes}. + * @see BytesValueRLPInput */ public interface RLPInput { diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java index 9b6f4884c6e..7ac0b4aaf40 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java @@ -1427,6 +1427,9 @@ public static class Builder { private Optional> versionedHashes = Optional.empty(); + /** Instantiates a new Builder. */ + public Builder() {} + /** * The "parent" message frame. When present some fields will be populated from the parent and * ignored if passed in via builder diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 55df9903318..253868aa367 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -4746,41 +4746,41 @@ - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + @@ -5637,6 +5637,14 @@ + + + + + + + + @@ -5645,6 +5653,14 @@ + + + + + + + + diff --git a/services/tasks/src/main/java/org/hyperledger/besu/services/tasks/InMemoryTaskQueue.java b/services/tasks/src/main/java/org/hyperledger/besu/services/tasks/InMemoryTaskQueue.java index 0d743cac24e..fa125be7387 100644 --- a/services/tasks/src/main/java/org/hyperledger/besu/services/tasks/InMemoryTaskQueue.java +++ b/services/tasks/src/main/java/org/hyperledger/besu/services/tasks/InMemoryTaskQueue.java @@ -32,6 +32,9 @@ public class InMemoryTaskQueue implements TaskCollection { private final Set> unfinishedOutstandingTasks = new HashSet<>(); private final AtomicBoolean closed = new AtomicBoolean(false); + /** Default constructor. */ + public InMemoryTaskQueue() {} + @Override public synchronized void add(final T taskData) { assertNotClosed(); diff --git a/util/src/main/java/org/hyperledger/besu/util/EndianUtils.java b/util/src/main/java/org/hyperledger/besu/util/EndianUtils.java index 025eeea7ab2..b80d27216ab 100644 --- a/util/src/main/java/org/hyperledger/besu/util/EndianUtils.java +++ b/util/src/main/java/org/hyperledger/besu/util/EndianUtils.java @@ -18,6 +18,7 @@ public class EndianUtils { // next two methods adopted from: // https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/util/Pack.java + private EndianUtils() {} /** * Long to big endian. diff --git a/util/src/main/java/org/hyperledger/besu/util/FutureUtils.java b/util/src/main/java/org/hyperledger/besu/util/FutureUtils.java index c75d97ee311..ea82306528a 100644 --- a/util/src/main/java/org/hyperledger/besu/util/FutureUtils.java +++ b/util/src/main/java/org/hyperledger/besu/util/FutureUtils.java @@ -25,6 +25,8 @@ /** The Future utils. */ public class FutureUtils { + private FutureUtils() {} + /** * Returns a new CompletionStage that, when the provided stage completes exceptionally, is * executed with the provided stage's exception as the argument to the supplied function. diff --git a/util/src/main/java/org/hyperledger/besu/util/log/LogUtil.java b/util/src/main/java/org/hyperledger/besu/util/log/LogUtil.java index 794acaea641..9c570613f67 100644 --- a/util/src/main/java/org/hyperledger/besu/util/log/LogUtil.java +++ b/util/src/main/java/org/hyperledger/besu/util/log/LogUtil.java @@ -28,6 +28,8 @@ public class LogUtil { static final String BESU_NAMESPACE = "org.hyperledger.besu"; static final int MAX_SUMMARY_DEPTH = 20; + private LogUtil() {} + /** * Throttles logging to a given logger. * diff --git a/util/src/main/java/org/hyperledger/besu/util/platform/PlatformDetector.java b/util/src/main/java/org/hyperledger/besu/util/platform/PlatformDetector.java index 1367c721062..ece589bb1a5 100644 --- a/util/src/main/java/org/hyperledger/besu/util/platform/PlatformDetector.java +++ b/util/src/main/java/org/hyperledger/besu/util/platform/PlatformDetector.java @@ -43,6 +43,8 @@ public class PlatformDetector { private static String _glibc; private static String _jemalloc; + private PlatformDetector() {} + /** * Gets OS type. * From af663b064bf3bc857a0a8608e34bab1cbb29ce00 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Thu, 6 Jun 2024 23:55:01 +1000 Subject: [PATCH 24/42] In enterprise profile use sync-mode=FULL and data-storage-format=FOREST (#7186) Also remove lower casing of profile names to keep CLI values consistent Signed-off-by: Simon Dudley --- CHANGELOG.md | 2 ++ .../java/org/hyperledger/besu/cli/config/ProfileName.java | 4 +--- config/src/main/resources/profiles/enterprise-private.toml | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 666712e4509..9b5f6eac341 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Breaking Changes - Java 21 has been enforced as minimum version to build and run Besu. +- In profile=ENTERPRISE, use sync-mode=FULL (instead of FAST) and data-storage-format=FOREST (instead of BONSAI) [#7186](https://github.com/hyperledger/besu/pull/7186) + - If this breaks your node, you can reset sync-mode=FAST and data-storage-format=BONSAI ### Additions and Improvements - Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/ProfileName.java b/besu/src/main/java/org/hyperledger/besu/cli/config/ProfileName.java index 37e96bca78b..8c17dfb4f2c 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/ProfileName.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/ProfileName.java @@ -14,8 +14,6 @@ */ package org.hyperledger.besu.cli.config; -import java.util.Locale; - import org.apache.commons.lang3.StringUtils; /** Enum for profile names. Each profile corresponds to a configuration file. */ @@ -53,6 +51,6 @@ public String getConfigFile() { @Override public String toString() { - return StringUtils.capitalize(name().replaceAll("_", " ").toLowerCase(Locale.ROOT)); + return StringUtils.capitalize(name().replaceAll("_", " ")); } } diff --git a/config/src/main/resources/profiles/enterprise-private.toml b/config/src/main/resources/profiles/enterprise-private.toml index 03650e39789..9ae88a55f27 100644 --- a/config/src/main/resources/profiles/enterprise-private.toml +++ b/config/src/main/resources/profiles/enterprise-private.toml @@ -1,4 +1,5 @@ -sync-mode="FAST" +sync-mode="FULL" +data-storage-format="FOREST" sync-min-peers=1 remote-connections-limit-enabled=false tx-pool="SEQUENCED" From bf67c6a23ccd8ec8282decf7f1ca6c28e89f00f8 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Thu, 6 Jun 2024 17:37:52 +0200 Subject: [PATCH 25/42] Fix: always use miningParametersSupplier (#7187) Signed-off-by: Fabio Di Fabio --- besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index bd47630fad6..c0fd9b0bff8 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -1876,7 +1876,7 @@ public BesuController buildController() { public BesuControllerBuilder getControllerBuilder() { pluginCommonConfiguration .init(dataDir(), dataDir().resolve(DATABASE_PATH), getDataStorageConfiguration()) - .withMiningParameters(getMiningParameters()) + .withMiningParameters(miningParametersSupplier.get()) .withJsonRpcHttpOptions(jsonRpcHttpOptions); final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); return controllerBuilderFactory From 7c21eed59d0a02eb340757aaffe066c9d9ea8e2d Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Fri, 7 Jun 2024 07:53:56 +1000 Subject: [PATCH 26/42] Enable --Xbonsai-limit-trie-logs-enabled by default (#7181) * Enable --Xbonsai-limit-trie-logs-enabled by default Signed-off-by: Simon Dudley --- CHANGELOG.md | 2 + .../org/hyperledger/besu/cli/BesuCommand.java | 5 ++- .../options/stable/DataStorageOptions.java | 15 ++++++- .../hyperledger/besu/cli/BesuCommandTest.java | 39 ++++++++++++++++--- .../stable/DataStorageOptionsTest.java | 9 +++++ .../profiles/enterprise-private.toml | 3 +- .../resources/profiles/minimalist-staker.toml | 2 +- .../worldstate/DataStorageConfiguration.java | 2 +- 8 files changed, 65 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b5f6eac341..e75845362c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,13 @@ ### Breaking Changes - Java 21 has been enforced as minimum version to build and run Besu. +- With --Xbonsai-limit-trie-logs-enabled by default in this release, historic trie log data will be removed from the database unless sync-mode=FULL. It respects the --bonsai-historical-block-limit setting so shouldn't break any RPCs, but may be breaking if you are accessing this data from the database directly. Can be disabled with --Xbonsai-limit-trie-logs-enabled=false - In profile=ENTERPRISE, use sync-mode=FULL (instead of FAST) and data-storage-format=FOREST (instead of BONSAI) [#7186](https://github.com/hyperledger/besu/pull/7186) - If this breaks your node, you can reset sync-mode=FAST and data-storage-format=BONSAI ### Additions and Improvements - Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) +- Enable --Xbonsai-limit-trie-logs-enabled by default, unless sync-mode=FULL [#7181](https://github.com/hyperledger/besu/pull/7181) - `admin_nodeInfo` JSON/RPC call returns the currently active EVM version [#7127](https://github.com/hyperledger/besu/pull/7127) ### Bug fixes diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index c0fd9b0bff8..0eeaf644da6 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -1564,7 +1564,7 @@ private void validateTransactionPoolOptions() { } private void validateDataStorageOptions() { - dataStorageOptions.validate(commandLine); + dataStorageOptions.validate(commandLine, syncMode); } private void validateRequiredOptions() { @@ -2791,7 +2791,8 @@ private String generateConfigurationOverview() { builder.setHighSpecEnabled(); } - if (getDataStorageConfiguration().getUnstable().getBonsaiLimitTrieLogsEnabled()) { + if (DataStorageFormat.BONSAI.equals(getDataStorageConfiguration().getDataStorageFormat()) + && getDataStorageConfiguration().getUnstable().getBonsaiLimitTrieLogsEnabled()) { builder.setLimitTrieLogsEnabled(); builder.setTrieLogRetentionLimit(getDataStorageConfiguration().getBonsaiMaxLayersToLoad()); builder.setTrieLogsPruningWindowSize( diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java index 51fb4d3ade1..12fccf313f3 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.cli.options.CLIOptions; import org.hyperledger.besu.cli.util.CommandLineUtils; +import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; @@ -86,6 +87,7 @@ public static class Unstable { @CommandLine.Option( hidden = true, names = {BONSAI_LIMIT_TRIE_LOGS_ENABLED, "--Xbonsai-trie-log-pruning-enabled"}, + fallbackValue = "true", description = "Limit the number of trie logs that are retained. (default: ${DEFAULT-VALUE})") private boolean bonsaiLimitTrieLogsEnabled = DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; @@ -134,9 +136,18 @@ public static DataStorageOptions create() { * Validates the data storage options * * @param commandLine the full commandLine to check all the options specified by the user + * @param syncMode the sync mode */ - public void validate(final CommandLine commandLine) { - if (unstableOptions.bonsaiLimitTrieLogsEnabled) { + public void validate(final CommandLine commandLine, final SyncMode syncMode) { + if (DataStorageFormat.BONSAI == dataStorageFormat + && unstableOptions.bonsaiLimitTrieLogsEnabled) { + if (SyncMode.FULL == syncMode) { + throw new CommandLine.ParameterException( + commandLine, + String.format( + "Cannot enable " + Unstable.BONSAI_LIMIT_TRIE_LOGS_ENABLED + " with sync-mode %s", + syncMode)); + } if (bonsaiMaxLayersToLoad < MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT) { throw new CommandLine.ParameterException( commandLine, diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 74579a975d2..1fc512344c8 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -1087,8 +1087,8 @@ public void syncMode_fast() { } @Test - public void syncMode_full() { - parseCommand("--sync-mode", "FULL"); + public void syncMode_full_requires_bonsaiLimitTrieLogsToBeDisabled() { + parseCommand("--sync-mode", "FULL", "--Xbonsai-limit-trie-logs-enabled=false"); verify(mockControllerBuilder).synchronizerConfiguration(syncConfigurationCaptor.capture()); final SynchronizerConfiguration syncConfig = syncConfigurationCaptor.getValue(); @@ -1244,8 +1244,37 @@ public void ethStatsContactOptionCannotBeUsedWithoutEthStatsServerProvided() { } @Test - public void parsesValidBonsaiTrieLimitBackLayersOption() { - parseCommand("--data-storage-format", "BONSAI", "--bonsai-historical-block-limit", "11"); + public void bonsaiLimitTrieLogsEnabledByDefault() { + parseCommand(); + verify(mockControllerBuilder) + .dataStorageConfiguration(dataStorageConfigurationArgumentCaptor.capture()); + + final DataStorageConfiguration dataStorageConfiguration = + dataStorageConfigurationArgumentCaptor.getValue(); + assertThat(dataStorageConfiguration.getDataStorageFormat()).isEqualTo(BONSAI); + assertThat(dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled()).isTrue(); + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void parsesInvalidDefaultBonsaiLimitTrieLogsWhenFullSyncEnabled() { + parseCommand("--sync-mode=FULL"); + + Mockito.verifyNoInteractions(mockRunnerBuilder); + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)) + .contains("Cannot enable --Xbonsai-limit-trie-logs-enabled with sync-mode FULL"); + } + + @Test + public void parsesValidBonsaiHistoricalBlockLimitOption() { + parseCommand( + "--Xbonsai-limit-trie-logs-enabled=false", + "--data-storage-format", + "BONSAI", + "--bonsai-historical-block-limit", + "11"); verify(mockControllerBuilder) .dataStorageConfiguration(dataStorageConfigurationArgumentCaptor.capture()); @@ -1258,7 +1287,7 @@ public void parsesValidBonsaiTrieLimitBackLayersOption() { } @Test - public void parsesInvalidBonsaiTrieLimitBackLayersOption() { + public void parsesInvalidBonsaiHistoricalBlockLimitOption() { parseCommand("--data-storage-format", "BONSAI", "--bonsai-maximum-back-layers-to-load", "ten"); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java index 4508f6c4e59..b2ec0efe9be 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java @@ -38,6 +38,15 @@ public void bonsaiTrieLogPruningLimitOption() { "600"); } + @Test + public void bonsaiTrieLogsEnabled_explicitlySetToFalse() { + internalTestSuccess( + dataStorageConfiguration -> + assertThat(dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled()) + .isEqualTo(false), + "--Xbonsai-limit-trie-logs-enabled=false"); + } + @Test public void bonsaiTrieLogPruningWindowSizeShouldBePositive() { internalTestFailure( diff --git a/config/src/main/resources/profiles/enterprise-private.toml b/config/src/main/resources/profiles/enterprise-private.toml index 9ae88a55f27..c78d54ada9b 100644 --- a/config/src/main/resources/profiles/enterprise-private.toml +++ b/config/src/main/resources/profiles/enterprise-private.toml @@ -6,4 +6,5 @@ tx-pool="SEQUENCED" tx-pool-no-local-priority=true tx-pool-limit-by-account-percentage=0.15 rpc-http-max-active-connections=300 -min-gas-price=0 \ No newline at end of file +min-gas-price=0 +Xbonsai-limit-trie-logs-enabled=false \ No newline at end of file diff --git a/config/src/main/resources/profiles/minimalist-staker.toml b/config/src/main/resources/profiles/minimalist-staker.toml index fcdbf64363f..5efba0f6fb4 100644 --- a/config/src/main/resources/profiles/minimalist-staker.toml +++ b/config/src/main/resources/profiles/minimalist-staker.toml @@ -1,4 +1,4 @@ sync-mode="CHECKPOINT" data-storage-format="BONSAI" -bonsai-historical-block-limit=128 +bonsai-historical-block-limit=512 max-peers=25 \ No newline at end of file diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java index a14f86bbb5f..97dd1691a45 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java @@ -69,7 +69,7 @@ default Unstable getUnstable() { @Value.Immutable interface Unstable { - boolean DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED = false; + boolean DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED = true; long MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; int DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = 30_000; boolean DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED = true; From bfada7d0b934cd4af331c13d17fe777f8b62dd4f Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Fri, 7 Jun 2024 23:23:58 +1000 Subject: [PATCH 27/42] Promote bonsai-limit-trie-logs-enabled and bonsai-trie-logs-pruning-window-size options (#7192) Promote option: create --bonsai-limit-trie-logs-enabled as alias of --Xbonsai-limit-trie-logs-enabled and unhide. Also bonsai-trie-logs-pruning-window-size. Remove --bonsai-historical-block-limit=512 from minimalist_staker profile so it inherits the default which is the same value Signed-off-by: Simon Dudley --- CHANGELOG.md | 10 +++++- .../options/stable/DataStorageOptions.java | 21 +++++++------ .../hyperledger/besu/cli/BesuCommandTest.java | 6 ++-- .../stable/DataStorageOptionsTest.java | 31 +++++++++++++------ .../storage/TrieLogHelperTest.java | 4 +-- .../src/test/resources/everything_config.toml | 2 ++ .../profiles/enterprise-private.toml | 2 +- .../resources/profiles/minimalist-staker.toml | 1 - 8 files changed, 50 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e75845362c0..b8593d6a19e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,21 @@ ### Breaking Changes - Java 21 has been enforced as minimum version to build and run Besu. -- With --Xbonsai-limit-trie-logs-enabled by default in this release, historic trie log data will be removed from the database unless sync-mode=FULL. It respects the --bonsai-historical-block-limit setting so shouldn't break any RPCs, but may be breaking if you are accessing this data from the database directly. Can be disabled with --Xbonsai-limit-trie-logs-enabled=false +- With --Xbonsai-limit-trie-logs-enabled by default in this release, historic trie log data will be removed from the database unless sync-mode=FULL. It respects the --bonsai-historical-block-limit setting so shouldn't break any RPCs, but may be breaking if you are accessing this data from the database directly. Can be disabled with --bonsai-limit-trie-logs-enabled=false - In profile=ENTERPRISE, use sync-mode=FULL (instead of FAST) and data-storage-format=FOREST (instead of BONSAI) [#7186](https://github.com/hyperledger/besu/pull/7186) - If this breaks your node, you can reset sync-mode=FAST and data-storage-format=BONSAI +### Upcoming Breaking Changes +- Receipt compaction will be enabled by default in a future version of Besu. After this change it will not be possible to downgrade to the previous Besu version. +- PKI-backed QBFT will be removed in a future version of Besu. Other forms of QBFT will remain unchanged. +- --Xbonsai-limit-trie-logs-enabled is deprecated, use --bonsai-limit-trie-logs-enabled instead +- --Xbonsai-trie-logs-pruning-window-size is deprecated, use --bonsai-trie-logs-pruning-window-size instead + ### Additions and Improvements - Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) - Enable --Xbonsai-limit-trie-logs-enabled by default, unless sync-mode=FULL [#7181](https://github.com/hyperledger/besu/pull/7181) +- Promote experimental --Xbonsai-limit-trie-logs-enabled to production-ready, --bonsai-limit-trie-logs-enabled [#7192](https://github.com/hyperledger/besu/pull/7192) +- Promote experimental --Xbonsai-trie-logs-pruning-window-size to production-ready, --bonsai-trie-logs-pruning-window-size [#7192](https://github.com/hyperledger/besu/pull/7192) - `admin_nodeInfo` JSON/RPC call returns the currently active EVM version [#7127](https://github.com/hyperledger/besu/pull/7127) ### Bug fixes diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java index 12fccf313f3..995a28b8abe 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java @@ -77,27 +77,30 @@ public class DataStorageOptions implements CLIOptions /** The unstable options for data storage. */ public static class Unstable { - private static final String BONSAI_LIMIT_TRIE_LOGS_ENABLED = - "--Xbonsai-limit-trie-logs-enabled"; + private static final String BONSAI_LIMIT_TRIE_LOGS_ENABLED = "--bonsai-limit-trie-logs-enabled"; /** The bonsai trie logs pruning window size. */ public static final String BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = - "--Xbonsai-trie-logs-pruning-window-size"; + "--bonsai-trie-logs-pruning-window-size"; + @SuppressWarnings("ExperimentalCliOptionMustBeCorrectlyDisplayed") @CommandLine.Option( - hidden = true, - names = {BONSAI_LIMIT_TRIE_LOGS_ENABLED, "--Xbonsai-trie-log-pruning-enabled"}, + names = { + BONSAI_LIMIT_TRIE_LOGS_ENABLED, + "--Xbonsai-limit-trie-logs-enabled", + "--Xbonsai-trie-log-pruning-enabled" + }, fallbackValue = "true", description = "Limit the number of trie logs that are retained. (default: ${DEFAULT-VALUE})") - private boolean bonsaiLimitTrieLogsEnabled = DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; + private Boolean bonsaiLimitTrieLogsEnabled = DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; + @SuppressWarnings("ExperimentalCliOptionMustBeCorrectlyDisplayed") @CommandLine.Option( - hidden = true, - names = {BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE}, + names = {BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE, "--Xbonsai-trie-logs-pruning-window-size"}, description = "The max number of blocks to load and prune trie logs for at startup. (default: ${DEFAULT-VALUE})") - private int bonsaiTrieLogPruningWindowSize = DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; + private Integer bonsaiTrieLogPruningWindowSize = DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; // TODO: --Xsnapsync-synchronizer-flat-db-healing-enabled is deprecated, remove it in a future // release diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 1fc512344c8..8c7a974daf0 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -1088,7 +1088,7 @@ public void syncMode_fast() { @Test public void syncMode_full_requires_bonsaiLimitTrieLogsToBeDisabled() { - parseCommand("--sync-mode", "FULL", "--Xbonsai-limit-trie-logs-enabled=false"); + parseCommand("--sync-mode", "FULL", "--bonsai-limit-trie-logs-enabled=false"); verify(mockControllerBuilder).synchronizerConfiguration(syncConfigurationCaptor.capture()); final SynchronizerConfiguration syncConfig = syncConfigurationCaptor.getValue(); @@ -1264,13 +1264,13 @@ public void parsesInvalidDefaultBonsaiLimitTrieLogsWhenFullSyncEnabled() { Mockito.verifyNoInteractions(mockRunnerBuilder); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) - .contains("Cannot enable --Xbonsai-limit-trie-logs-enabled with sync-mode FULL"); + .contains("Cannot enable --bonsai-limit-trie-logs-enabled with sync-mode FULL"); } @Test public void parsesValidBonsaiHistoricalBlockLimitOption() { parseCommand( - "--Xbonsai-limit-trie-logs-enabled=false", + "--bonsai-limit-trie-logs-enabled=false", "--data-storage-format", "BONSAI", "--bonsai-historical-block-limit", diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java index b2ec0efe9be..548a382731c 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java @@ -29,6 +29,17 @@ public class DataStorageOptionsTest @Test public void bonsaiTrieLogPruningLimitOption() { + internalTestSuccess( + dataStorageConfiguration -> + assertThat(dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningWindowSize()) + .isEqualTo(600), + "--bonsai-limit-trie-logs-enabled", + "--bonsai-trie-logs-pruning-window-size", + "600"); + } + + @Test + public void bonsaiTrieLogPruningLimitLegacyOption() { internalTestSuccess( dataStorageConfiguration -> assertThat(dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningWindowSize()) @@ -44,24 +55,24 @@ public void bonsaiTrieLogsEnabled_explicitlySetToFalse() { dataStorageConfiguration -> assertThat(dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled()) .isEqualTo(false), - "--Xbonsai-limit-trie-logs-enabled=false"); + "--bonsai-limit-trie-logs-enabled=false"); } @Test public void bonsaiTrieLogPruningWindowSizeShouldBePositive() { internalTestFailure( - "--Xbonsai-trie-logs-pruning-window-size=0 must be greater than 0", - "--Xbonsai-limit-trie-logs-enabled", - "--Xbonsai-trie-logs-pruning-window-size", + "--bonsai-trie-logs-pruning-window-size=0 must be greater than 0", + "--bonsai-limit-trie-logs-enabled", + "--bonsai-trie-logs-pruning-window-size", "0"); } @Test public void bonsaiTrieLogPruningWindowSizeShouldBeAboveRetentionLimit() { internalTestFailure( - "--Xbonsai-trie-logs-pruning-window-size=512 must be greater than --bonsai-historical-block-limit=512", - "--Xbonsai-limit-trie-logs-enabled", - "--Xbonsai-trie-logs-pruning-window-size", + "--bonsai-trie-logs-pruning-window-size=512 must be greater than --bonsai-historical-block-limit=512", + "--bonsai-limit-trie-logs-enabled", + "--bonsai-trie-logs-pruning-window-size", "512"); } @@ -71,7 +82,7 @@ public void bonsaiTrieLogRetentionLimitOption() { dataStorageConfiguration -> assertThat(dataStorageConfiguration.getBonsaiMaxLayersToLoad()) .isEqualTo(MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT + 1), - "--Xbonsai-limit-trie-logs-enabled", + "--bonsai-limit-trie-logs-enabled", "--bonsai-historical-block-limit", "513"); } @@ -82,7 +93,7 @@ public void bonsaiTrieLogRetentionLimitOption_boundaryTest() { dataStorageConfiguration -> assertThat(dataStorageConfiguration.getBonsaiMaxLayersToLoad()) .isEqualTo(MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT), - "--Xbonsai-limit-trie-logs-enabled", + "--bonsai-limit-trie-logs-enabled", "--bonsai-historical-block-limit", "512"); } @@ -91,7 +102,7 @@ public void bonsaiTrieLogRetentionLimitOption_boundaryTest() { public void bonsaiTrieLogRetentionLimitShouldBeAboveMinimum() { internalTestFailure( "--bonsai-historical-block-limit minimum value is 512", - "--Xbonsai-limit-trie-logs-enabled", + "--bonsai-limit-trie-logs-enabled", "--bonsai-historical-block-limit", "511"); } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java index f8fba8d7002..f8225ce42f3 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java @@ -336,7 +336,7 @@ public void trieLogPruningWindowSizeShouldBePositive() { () -> helper.prune(dataStorageConfiguration, inMemoryWorldState, blockchain, Path.of(""))) .isInstanceOf(RuntimeException.class) - .hasMessage("--Xbonsai-trie-logs-pruning-window-size=0 must be greater than 0"); + .hasMessage("--bonsai-trie-logs-pruning-window-size=0 must be greater than 0"); } @Test @@ -358,7 +358,7 @@ public void trieLogPruningWindowSizeShouldBeAboveRetentionLimit() { helper.prune(dataStorageConfiguration, inMemoryWorldState, blockchain, Path.of(""))) .isInstanceOf(RuntimeException.class) .hasMessage( - "--Xbonsai-trie-logs-pruning-window-size=512 must be greater than --bonsai-historical-block-limit=512"); + "--bonsai-trie-logs-pruning-window-size=512 must be greater than --bonsai-historical-block-limit=512"); } @Test diff --git a/besu/src/test/resources/everything_config.toml b/besu/src/test/resources/everything_config.toml index d1cdaa32463..6c98e2ebaf7 100644 --- a/besu/src/test/resources/everything_config.toml +++ b/besu/src/test/resources/everything_config.toml @@ -213,6 +213,8 @@ ethstats-cacert-file="./root.cert" # Data storage data-storage-format="BONSAI" bonsai-historical-block-limit=512 +bonsai-limit-trie-logs-enabled=true +bonsai-trie-logs-pruning-window-size=100_000 receipt-compaction-enabled=true # feature flags diff --git a/config/src/main/resources/profiles/enterprise-private.toml b/config/src/main/resources/profiles/enterprise-private.toml index c78d54ada9b..ea87d5cfc18 100644 --- a/config/src/main/resources/profiles/enterprise-private.toml +++ b/config/src/main/resources/profiles/enterprise-private.toml @@ -7,4 +7,4 @@ tx-pool-no-local-priority=true tx-pool-limit-by-account-percentage=0.15 rpc-http-max-active-connections=300 min-gas-price=0 -Xbonsai-limit-trie-logs-enabled=false \ No newline at end of file +bonsai-limit-trie-logs-enabled=false \ No newline at end of file diff --git a/config/src/main/resources/profiles/minimalist-staker.toml b/config/src/main/resources/profiles/minimalist-staker.toml index 5efba0f6fb4..cfda132e374 100644 --- a/config/src/main/resources/profiles/minimalist-staker.toml +++ b/config/src/main/resources/profiles/minimalist-staker.toml @@ -1,4 +1,3 @@ sync-mode="CHECKPOINT" data-storage-format="BONSAI" -bonsai-historical-block-limit=512 max-peers=25 \ No newline at end of file From df2ce0e43745fe468775d3edc5e0169d7270d104 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Sat, 8 Jun 2024 00:06:25 +1000 Subject: [PATCH 28/42] Promote --bonsai-limit-trie-logs-enabled to stable (#7193) Also --bonsai-trie-logs-pruning-window-size Signed-off-by: Simon Dudley --- .../org/hyperledger/besu/cli/BesuCommand.java | 4 +- .../options/stable/DataStorageOptions.java | 84 +++++++++---------- .../subcommands/storage/TrieLogHelper.java | 20 ++--- .../controller/BesuControllerBuilder.java | 4 +- .../hyperledger/besu/cli/BesuCommandTest.java | 2 +- .../stable/DataStorageOptionsTest.java | 18 ++-- .../storage/TrieLogHelperTest.java | 56 +++---------- .../worldstate/DataStorageConfiguration.java | 26 +++--- 8 files changed, 87 insertions(+), 127 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 0eeaf644da6..535dcc69364 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -2792,11 +2792,11 @@ private String generateConfigurationOverview() { } if (DataStorageFormat.BONSAI.equals(getDataStorageConfiguration().getDataStorageFormat()) - && getDataStorageConfiguration().getUnstable().getBonsaiLimitTrieLogsEnabled()) { + && getDataStorageConfiguration().getBonsaiLimitTrieLogsEnabled()) { builder.setLimitTrieLogsEnabled(); builder.setTrieLogRetentionLimit(getDataStorageConfiguration().getBonsaiMaxLayersToLoad()); builder.setTrieLogsPruningWindowSize( - getDataStorageConfiguration().getUnstable().getBonsaiTrieLogPruningWindowSize()); + getDataStorageConfiguration().getBonsaiTrieLogPruningWindowSize()); } builder.setSnapServerEnabled(this.unstableSynchronizerOptions.isSnapsyncServerEnabled()); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java index 995a28b8abe..d1cb4f721b2 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/stable/DataStorageOptions.java @@ -14,13 +14,13 @@ */ package org.hyperledger.besu.cli.options.stable; +import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; +import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_RECEIPT_COMPACTION_ENABLED; +import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED; import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED; -import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; -import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; -import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT; import org.hyperledger.besu.cli.options.CLIOptions; import org.hyperledger.besu.cli.util.CommandLineUtils; @@ -58,11 +58,35 @@ public class DataStorageOptions implements CLIOptions paramLabel = "", description = "Limit of historical layers that can be loaded with BONSAI (default: ${DEFAULT-VALUE}). When using " - + Unstable.BONSAI_LIMIT_TRIE_LOGS_ENABLED + + BONSAI_LIMIT_TRIE_LOGS_ENABLED + " it will also be used as the number of layers of trie logs to retain.", arity = "1") private Long bonsaiMaxLayersToLoad = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; + private static final String BONSAI_LIMIT_TRIE_LOGS_ENABLED = "--bonsai-limit-trie-logs-enabled"; + + /** The bonsai trie logs pruning window size. */ + public static final String BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = + "--bonsai-trie-logs-pruning-window-size"; + + @SuppressWarnings("ExperimentalCliOptionMustBeCorrectlyDisplayed") + @CommandLine.Option( + names = { + BONSAI_LIMIT_TRIE_LOGS_ENABLED, + "--Xbonsai-limit-trie-logs-enabled", + "--Xbonsai-trie-log-pruning-enabled" + }, + fallbackValue = "true", + description = "Limit the number of trie logs that are retained. (default: ${DEFAULT-VALUE})") + private Boolean bonsaiLimitTrieLogsEnabled = DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; + + @SuppressWarnings("ExperimentalCliOptionMustBeCorrectlyDisplayed") + @CommandLine.Option( + names = {BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE, "--Xbonsai-trie-logs-pruning-window-size"}, + description = + "The max number of blocks to load and prune trie logs for at startup. (default: ${DEFAULT-VALUE})") + private Integer bonsaiTrieLogPruningWindowSize = DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; + @Option( names = "--receipt-compaction-enabled", description = "Enables compact storing of receipts (default: ${DEFAULT-VALUE}).", @@ -77,30 +101,6 @@ public class DataStorageOptions implements CLIOptions /** The unstable options for data storage. */ public static class Unstable { - private static final String BONSAI_LIMIT_TRIE_LOGS_ENABLED = "--bonsai-limit-trie-logs-enabled"; - - /** The bonsai trie logs pruning window size. */ - public static final String BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = - "--bonsai-trie-logs-pruning-window-size"; - - @SuppressWarnings("ExperimentalCliOptionMustBeCorrectlyDisplayed") - @CommandLine.Option( - names = { - BONSAI_LIMIT_TRIE_LOGS_ENABLED, - "--Xbonsai-limit-trie-logs-enabled", - "--Xbonsai-trie-log-pruning-enabled" - }, - fallbackValue = "true", - description = - "Limit the number of trie logs that are retained. (default: ${DEFAULT-VALUE})") - private Boolean bonsaiLimitTrieLogsEnabled = DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; - - @SuppressWarnings("ExperimentalCliOptionMustBeCorrectlyDisplayed") - @CommandLine.Option( - names = {BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE, "--Xbonsai-trie-logs-pruning-window-size"}, - description = - "The max number of blocks to load and prune trie logs for at startup. (default: ${DEFAULT-VALUE})") - private Integer bonsaiTrieLogPruningWindowSize = DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; // TODO: --Xsnapsync-synchronizer-flat-db-healing-enabled is deprecated, remove it in a future // release @@ -142,13 +142,12 @@ public static DataStorageOptions create() { * @param syncMode the sync mode */ public void validate(final CommandLine commandLine, final SyncMode syncMode) { - if (DataStorageFormat.BONSAI == dataStorageFormat - && unstableOptions.bonsaiLimitTrieLogsEnabled) { + if (DataStorageFormat.BONSAI == dataStorageFormat && bonsaiLimitTrieLogsEnabled) { if (SyncMode.FULL == syncMode) { throw new CommandLine.ParameterException( commandLine, String.format( - "Cannot enable " + Unstable.BONSAI_LIMIT_TRIE_LOGS_ENABLED + " with sync-mode %s", + "Cannot enable " + BONSAI_LIMIT_TRIE_LOGS_ENABLED + " with sync-mode %s", syncMode)); } if (bonsaiMaxLayersToLoad < MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT) { @@ -158,22 +157,22 @@ public void validate(final CommandLine commandLine, final SyncMode syncMode) { BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD + " minimum value is %d", MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT)); } - if (unstableOptions.bonsaiTrieLogPruningWindowSize <= 0) { + if (bonsaiTrieLogPruningWindowSize <= 0) { throw new CommandLine.ParameterException( commandLine, String.format( - Unstable.BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE + "=%d must be greater than 0", - unstableOptions.bonsaiTrieLogPruningWindowSize)); + BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE + "=%d must be greater than 0", + bonsaiTrieLogPruningWindowSize)); } - if (unstableOptions.bonsaiTrieLogPruningWindowSize <= bonsaiMaxLayersToLoad) { + if (bonsaiTrieLogPruningWindowSize <= bonsaiMaxLayersToLoad) { throw new CommandLine.ParameterException( commandLine, String.format( - Unstable.BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE + BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE + "=%d must be greater than " + BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD + "=%d", - unstableOptions.bonsaiTrieLogPruningWindowSize, + bonsaiTrieLogPruningWindowSize, bonsaiMaxLayersToLoad)); } } @@ -190,10 +189,9 @@ public static DataStorageOptions fromConfig(final DataStorageConfiguration domai dataStorageOptions.dataStorageFormat = domainObject.getDataStorageFormat(); dataStorageOptions.bonsaiMaxLayersToLoad = domainObject.getBonsaiMaxLayersToLoad(); dataStorageOptions.receiptCompactionEnabled = domainObject.getReceiptCompactionEnabled(); - dataStorageOptions.unstableOptions.bonsaiLimitTrieLogsEnabled = - domainObject.getUnstable().getBonsaiLimitTrieLogsEnabled(); - dataStorageOptions.unstableOptions.bonsaiTrieLogPruningWindowSize = - domainObject.getUnstable().getBonsaiTrieLogPruningWindowSize(); + dataStorageOptions.bonsaiLimitTrieLogsEnabled = domainObject.getBonsaiLimitTrieLogsEnabled(); + dataStorageOptions.bonsaiTrieLogPruningWindowSize = + domainObject.getBonsaiTrieLogPruningWindowSize(); dataStorageOptions.unstableOptions.bonsaiFullFlatDbEnabled = domainObject.getUnstable().getBonsaiFullFlatDbEnabled(); dataStorageOptions.unstableOptions.bonsaiCodeUsingCodeHashEnabled = @@ -208,10 +206,10 @@ public DataStorageConfiguration toDomainObject() { .dataStorageFormat(dataStorageFormat) .bonsaiMaxLayersToLoad(bonsaiMaxLayersToLoad) .receiptCompactionEnabled(receiptCompactionEnabled) + .bonsaiLimitTrieLogsEnabled(bonsaiLimitTrieLogsEnabled) + .bonsaiTrieLogPruningWindowSize(bonsaiTrieLogPruningWindowSize) .unstable( ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(unstableOptions.bonsaiLimitTrieLogsEnabled) - .bonsaiTrieLogPruningWindowSize(unstableOptions.bonsaiTrieLogPruningWindowSize) .bonsaiFullFlatDbEnabled(unstableOptions.bonsaiFullFlatDbEnabled) .bonsaiCodeStoredByCodeHashEnabled(unstableOptions.bonsaiCodeUsingCodeHashEnabled) .build()) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelper.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelper.java index 62d316366f8..6bcfe4d3531 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelper.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelper.java @@ -17,7 +17,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static org.hyperledger.besu.cli.options.stable.DataStorageOptions.BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD; import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; -import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; +import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; import org.hyperledger.besu.cli.options.stable.DataStorageOptions; import org.hyperledger.besu.datatypes.Hash; @@ -296,25 +296,23 @@ private void processTransactionChunk( void validatePruneConfiguration(final DataStorageConfiguration config) { checkArgument( config.getBonsaiMaxLayersToLoad() - >= DataStorageConfiguration.Unstable.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT, + >= DataStorageConfiguration.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT, String.format( BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD + " minimum value is %d", - DataStorageConfiguration.Unstable.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT)); + DataStorageConfiguration.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT)); checkArgument( - config.getUnstable().getBonsaiTrieLogPruningWindowSize() > 0, + config.getBonsaiTrieLogPruningWindowSize() > 0, String.format( - DataStorageOptions.Unstable.BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE - + "=%d must be greater than 0", - config.getUnstable().getBonsaiTrieLogPruningWindowSize())); + DataStorageOptions.BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE + "=%d must be greater than 0", + config.getBonsaiTrieLogPruningWindowSize())); checkArgument( - config.getUnstable().getBonsaiTrieLogPruningWindowSize() - > config.getBonsaiMaxLayersToLoad(), + config.getBonsaiTrieLogPruningWindowSize() > config.getBonsaiMaxLayersToLoad(), String.format( - DataStorageOptions.Unstable.BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE + DataStorageOptions.BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE + "=%d must be greater than " + BONSAI_STORAGE_FORMAT_MAX_LAYERS_TO_LOAD + "=%d", - config.getUnstable().getBonsaiTrieLogPruningWindowSize(), + config.getBonsaiTrieLogPruningWindowSize(), config.getBonsaiMaxLayersToLoad())); } diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 322f596e160..4e3929e8ae5 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -733,7 +733,7 @@ public BesuController build() { final JsonRpcMethods additionalJsonRpcMethodFactory = createAdditionalJsonRpcMethodFactory(protocolContext, protocolSchedule, miningParameters); - if (dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled() + if (dataStorageConfiguration.getBonsaiLimitTrieLogsEnabled() && DataStorageFormat.BONSAI.equals(dataStorageConfiguration.getDataStorageFormat())) { final TrieLogManager trieLogManager = ((BonsaiWorldStateProvider) worldStateArchive).getTrieLogManager(); @@ -784,7 +784,7 @@ private TrieLogPruner createTrieLogPruner( blockchain, scheduler::executeServiceTask, dataStorageConfiguration.getBonsaiMaxLayersToLoad(), - dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningWindowSize(), + dataStorageConfiguration.getBonsaiTrieLogPruningWindowSize(), isProofOfStake); trieLogPruner.initialize(); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 8c7a974daf0..e86e500a7d0 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -1252,7 +1252,7 @@ public void bonsaiLimitTrieLogsEnabledByDefault() { final DataStorageConfiguration dataStorageConfiguration = dataStorageConfigurationArgumentCaptor.getValue(); assertThat(dataStorageConfiguration.getDataStorageFormat()).isEqualTo(BONSAI); - assertThat(dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled()).isTrue(); + assertThat(dataStorageConfiguration.getBonsaiLimitTrieLogsEnabled()).isTrue(); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java index 548a382731c..2086381825f 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/stable/DataStorageOptionsTest.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.cli.options.stable; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT; +import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT; import org.hyperledger.besu.cli.options.AbstractCLIOptionsTest; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; @@ -31,8 +31,7 @@ public class DataStorageOptionsTest public void bonsaiTrieLogPruningLimitOption() { internalTestSuccess( dataStorageConfiguration -> - assertThat(dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningWindowSize()) - .isEqualTo(600), + assertThat(dataStorageConfiguration.getBonsaiTrieLogPruningWindowSize()).isEqualTo(600), "--bonsai-limit-trie-logs-enabled", "--bonsai-trie-logs-pruning-window-size", "600"); @@ -42,8 +41,7 @@ public void bonsaiTrieLogPruningLimitOption() { public void bonsaiTrieLogPruningLimitLegacyOption() { internalTestSuccess( dataStorageConfiguration -> - assertThat(dataStorageConfiguration.getUnstable().getBonsaiTrieLogPruningWindowSize()) - .isEqualTo(600), + assertThat(dataStorageConfiguration.getBonsaiTrieLogPruningWindowSize()).isEqualTo(600), "--Xbonsai-limit-trie-logs-enabled", "--Xbonsai-trie-logs-pruning-window-size", "600"); @@ -53,8 +51,7 @@ public void bonsaiTrieLogPruningLimitLegacyOption() { public void bonsaiTrieLogsEnabled_explicitlySetToFalse() { internalTestSuccess( dataStorageConfiguration -> - assertThat(dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled()) - .isEqualTo(false), + assertThat(dataStorageConfiguration.getBonsaiLimitTrieLogsEnabled()).isEqualTo(false), "--bonsai-limit-trie-logs-enabled=false"); } @@ -157,11 +154,8 @@ protected DataStorageConfiguration createCustomizedDomainObject() { return ImmutableDataStorageConfiguration.builder() .dataStorageFormat(DataStorageFormat.BONSAI) .bonsaiMaxLayersToLoad(513L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .bonsaiTrieLogPruningWindowSize(514) - .build()) + .bonsaiLimitTrieLogsEnabled(true) + .bonsaiTrieLogPruningWindowSize(514) .build(); } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java index f8225ce42f3..2f3a693f3de 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/subcommands/storage/TrieLogHelperTest.java @@ -17,7 +17,7 @@ import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.Unstable.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; +import static org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration.DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; import static org.hyperledger.besu.plugin.services.storage.DataStorageFormat.BONSAI; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; @@ -135,10 +135,7 @@ public void prune(final @TempDir Path dataDir) throws IOException { ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(3L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); mockBlockchainBase(); @@ -176,10 +173,7 @@ public void cannotPruneIfNoFinalizedIsFound() { ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(2L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); when(blockchain.getChainHeadBlockNumber()).thenReturn(5L); @@ -199,10 +193,7 @@ public void cannotPruneIfUserRetainsMoreLayersThanExistingChainLength() { ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(10L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); when(blockchain.getChainHeadBlockNumber()).thenReturn(5L); @@ -222,10 +213,7 @@ public void cannotPruneIfUserRequiredFurtherThanFinalized(final @TempDir Path da ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(2L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); mockBlockchainBase(); @@ -246,10 +234,7 @@ public void skipPruningIfTrieLogCountIsLessThanMaxLayersToLoad() { ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(6L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); when(blockchain.getChainHeadBlockNumber()).thenReturn(5L); @@ -271,10 +256,7 @@ public void mismatchInPrunedTrieLogCountShouldNotDeleteFiles(final @TempDir Path ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(3L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); mockBlockchainBase(); @@ -303,10 +285,7 @@ public void trieLogRetentionLimitShouldBeAboveMinimum() { ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(511L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); TrieLogHelper helper = new TrieLogHelper(); @@ -324,11 +303,8 @@ public void trieLogPruningWindowSizeShouldBePositive() { ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(512L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .bonsaiTrieLogPruningWindowSize(0) - .build()) + .bonsaiLimitTrieLogsEnabled(true) + .bonsaiTrieLogPruningWindowSize(0) .build(); TrieLogHelper helper = new TrieLogHelper(); @@ -345,11 +321,8 @@ public void trieLogPruningWindowSizeShouldBeAboveRetentionLimit() { ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(512L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .bonsaiTrieLogPruningWindowSize(512) - .build()) + .bonsaiLimitTrieLogsEnabled(true) + .bonsaiTrieLogPruningWindowSize(512) .build(); TrieLogHelper helper = new TrieLogHelper(); @@ -368,10 +341,7 @@ public void exceptionWhileSavingFileStopsPruneProcess(final @TempDir Path dataDi ImmutableDataStorageConfiguration.builder() .dataStorageFormat(BONSAI) .bonsaiMaxLayersToLoad(3L) - .unstable( - ImmutableDataStorageConfiguration.Unstable.builder() - .bonsaiLimitTrieLogsEnabled(true) - .build()) + .bonsaiLimitTrieLogsEnabled(true) .build(); mockBlockchainBase(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java index 97dd1691a45..646e67d2da5 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/worldstate/DataStorageConfiguration.java @@ -23,6 +23,9 @@ public interface DataStorageConfiguration { long DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD = 512; + boolean DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED = true; + long MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; + int DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = 30_000; boolean DEFAULT_RECEIPT_COMPACTION_ENABLED = false; DataStorageConfiguration DEFAULT_CONFIG = @@ -56,6 +59,16 @@ public interface DataStorageConfiguration { Long getBonsaiMaxLayersToLoad(); + @Value.Default + default boolean getBonsaiLimitTrieLogsEnabled() { + return DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; + } + + @Value.Default + default int getBonsaiTrieLogPruningWindowSize() { + return DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; + } + @Value.Default default boolean getReceiptCompactionEnabled() { return DEFAULT_RECEIPT_COMPACTION_ENABLED; @@ -69,9 +82,6 @@ default Unstable getUnstable() { @Value.Immutable interface Unstable { - boolean DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED = true; - long MINIMUM_BONSAI_TRIE_LOG_RETENTION_LIMIT = DEFAULT_BONSAI_MAX_LAYERS_TO_LOAD; - int DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE = 30_000; boolean DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED = true; boolean DEFAULT_BONSAI_CODE_USING_CODE_HASH_ENABLED = true; @@ -81,16 +91,6 @@ interface Unstable { DataStorageConfiguration.Unstable DEFAULT_PARTIAL = ImmutableDataStorageConfiguration.Unstable.builder().bonsaiFullFlatDbEnabled(false).build(); - @Value.Default - default boolean getBonsaiLimitTrieLogsEnabled() { - return DEFAULT_BONSAI_LIMIT_TRIE_LOGS_ENABLED; - } - - @Value.Default - default int getBonsaiTrieLogPruningWindowSize() { - return DEFAULT_BONSAI_TRIE_LOG_PRUNING_WINDOW_SIZE; - } - @Value.Default default boolean getBonsaiFullFlatDbEnabled() { return DEFAULT_BONSAI_FULL_FLAT_DB_ENABLED; From 40d6b2691f60c35891cc1f4ac9649cba1eb9ee17 Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Fri, 7 Jun 2024 16:30:43 +0200 Subject: [PATCH 29/42] Improve the selection of the most profitable built block (#7174) * Improve the selection of the most profitable built block Signed-off-by: Fabio Di Fabio * Update CHANGELOG Signed-off-by: Fabio Di Fabio * Update consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PayloadWrapper.java Co-authored-by: Justin Florentine Signed-off-by: Fabio Di Fabio --------- Signed-off-by: Fabio Di Fabio Co-authored-by: Justin Florentine --- CHANGELOG.md | 1 + .../besu/consensus/merge/MergeContext.java | 3 +- .../besu/consensus/merge/PayloadWrapper.java | 56 ++++++++++++-- .../consensus/merge/PostMergeContext.java | 77 ++++++++----------- .../consensus/merge/TransitionContext.java | 5 +- .../consensus/merge/PostMergeContextTest.java | 55 +++++++++---- .../engine/AbstractEngineGetPayload.java | 31 ++++---- .../methods/engine/EngineGetPayloadV1.java | 13 +--- .../methods/engine/EngineGetPayloadV2.java | 13 +--- .../methods/engine/EngineGetPayloadV3.java | 10 +-- .../methods/engine/EngineGetPayloadV4.java | 10 +-- .../internal/results/BlockResultFactory.java | 27 +++---- .../engine/AbstractEngineGetPayloadTest.java | 9 ++- .../engine/EngineGetPayloadV2Test.java | 8 +- .../engine/EngineGetPayloadV3Test.java | 9 ++- .../engine/EngineGetPayloadV4Test.java | 8 +- .../ethereum/core/BlockValueCalculator.java | 2 +- .../core/BlockValueCalculatorTest.java | 12 ++- 18 files changed, 190 insertions(+), 159 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8593d6a19e..421d856430e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Promote experimental --Xbonsai-limit-trie-logs-enabled to production-ready, --bonsai-limit-trie-logs-enabled [#7192](https://github.com/hyperledger/besu/pull/7192) - Promote experimental --Xbonsai-trie-logs-pruning-window-size to production-ready, --bonsai-trie-logs-pruning-window-size [#7192](https://github.com/hyperledger/besu/pull/7192) - `admin_nodeInfo` JSON/RPC call returns the currently active EVM version [#7127](https://github.com/hyperledger/besu/pull/7127) +- Improve the selection of the most profitable built block [#7174](https://github.com/hyperledger/besu/pull/7174) ### Bug fixes - Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeContext.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeContext.java index 64560df05c6..2554a4537fa 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeContext.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/MergeContext.java @@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.ConsensusContext; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; @@ -167,7 +166,7 @@ void fireNewUnverifiedForkchoiceEvent( * @param payloadId the payload identifier * @return the optional block with receipts */ - Optional retrieveBlockById(final PayloadIdentifier payloadId); + Optional retrievePayloadById(final PayloadIdentifier payloadId); /** * Is configured for a post-merge from genesis. diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PayloadWrapper.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PayloadWrapper.java index 35df16c8073..4a8588f84ef 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PayloadWrapper.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PayloadWrapper.java @@ -15,13 +15,53 @@ package org.hyperledger.besu.consensus.merge; import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.BlockValueCalculator; import org.hyperledger.besu.ethereum.core.BlockWithReceipts; -/** - * Wrapper for payload plus extra info. - * - * @param payloadIdentifier Payload identifier - * @param blockWithReceipts Block With Receipts - */ -public record PayloadWrapper( - PayloadIdentifier payloadIdentifier, BlockWithReceipts blockWithReceipts) {} +/** Wrapper for payload plus extra info. */ +public class PayloadWrapper { + private final PayloadIdentifier payloadIdentifier; + private final BlockWithReceipts blockWithReceipts; + private final Wei blockValue; + + /** + * Construct a wrapper with the following fields. + * + * @param payloadIdentifier Payload identifier + * @param blockWithReceipts Block with receipts + */ + public PayloadWrapper( + final PayloadIdentifier payloadIdentifier, final BlockWithReceipts blockWithReceipts) { + this.blockWithReceipts = blockWithReceipts; + this.payloadIdentifier = payloadIdentifier; + this.blockValue = BlockValueCalculator.calculateBlockValue(blockWithReceipts); + } + + /** + * Get the block value + * + * @return block value in Wei + */ + public Wei blockValue() { + return blockValue; + } + + /** + * Get this payload identifier + * + * @return payload identifier + */ + public PayloadIdentifier payloadIdentifier() { + return payloadIdentifier; + } + + /** + * Get the block with receipts + * + * @return block with receipts + */ + public BlockWithReceipts blockWithReceipts() { + return blockWithReceipts; + } +} diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PostMergeContext.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PostMergeContext.java index d296d8cdf3b..1d7e4b76c62 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PostMergeContext.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/PostMergeContext.java @@ -16,12 +16,9 @@ import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ConsensusContext; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockValueCalculator; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.util.Subscribers; @@ -29,7 +26,6 @@ import java.util.Comparator; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import java.util.stream.Stream; import com.google.common.annotations.VisibleForTesting; @@ -45,13 +41,6 @@ public class PostMergeContext implements MergeContext { static final int MAX_BLOCKS_IN_PROGRESS = 12; private static final AtomicReference singleton = new AtomicReference<>(); - - private static final Comparator compareByGasUsedDesc = - Comparator.comparingLong( - (BlockWithReceipts blockWithReceipts) -> - blockWithReceipts.getBlock().getHeader().getGasUsed()) - .reversed(); - private final AtomicReference syncState; private final AtomicReference terminalTotalDifficulty; // initial postMerge state is indeterminate until it is set: @@ -70,7 +59,6 @@ public class PostMergeContext implements MergeContext { private final AtomicReference lastSafeBlock = new AtomicReference<>(); private final AtomicReference> terminalPoWBlock = new AtomicReference<>(Optional.empty()); - private final BlockValueCalculator blockValueCalculator = new BlockValueCalculator(); private boolean isPostMergeAtGenesis; /** Instantiates a new Post merge context. */ @@ -227,66 +215,65 @@ public boolean validateCandidateHead(final BlockHeader candidateHeader) { } @Override - public void putPayloadById(final PayloadWrapper payloadWrapper) { + public void putPayloadById(final PayloadWrapper newPayload) { + final var newBlockWithReceipts = newPayload.blockWithReceipts(); + final var newBlockValue = newPayload.blockValue(); + synchronized (blocksInProgress) { - final Optional maybeCurrBestBlock = - retrieveBlockById(payloadWrapper.payloadIdentifier()); + final Optional maybeCurrBestPayload = + retrievePayloadById(newPayload.payloadIdentifier()); - maybeCurrBestBlock.ifPresentOrElse( - currBestBlock -> { - if (compareByGasUsedDesc.compare(payloadWrapper.blockWithReceipts(), currBestBlock) - < 0) { + maybeCurrBestPayload.ifPresent( + currBestPayload -> { + if (newBlockValue.greaterThan(currBestPayload.blockValue())) { LOG.atDebug() - .setMessage("New proposal for payloadId {} {} is better than the previous one {}") - .addArgument(payloadWrapper.payloadIdentifier()) + .setMessage( + "New proposal for payloadId {} {} is better than the previous one {} by {}") + .addArgument(newPayload.payloadIdentifier()) + .addArgument(() -> logBlockProposal(newBlockWithReceipts.getBlock())) .addArgument( - () -> logBlockProposal(payloadWrapper.blockWithReceipts().getBlock())) - .addArgument(() -> logBlockProposal(currBestBlock.getBlock())) + () -> logBlockProposal(currBestPayload.blockWithReceipts().getBlock())) + .addArgument( + () -> + newBlockValue + .subtract(currBestPayload.blockValue()) + .toHumanReadableString()) .log(); + blocksInProgress.removeAll( - retrievePayloadsById(payloadWrapper.payloadIdentifier()) - .collect(Collectors.toUnmodifiableList())); - blocksInProgress.add( - new PayloadWrapper( - payloadWrapper.payloadIdentifier(), payloadWrapper.blockWithReceipts())); - logCurrentBestBlock(payloadWrapper.blockWithReceipts()); + streamPayloadsById(newPayload.payloadIdentifier()).toList()); + + logCurrentBestBlock(newPayload); } - }, - () -> - blocksInProgress.add( - new PayloadWrapper( - payloadWrapper.payloadIdentifier(), payloadWrapper.blockWithReceipts()))); + }); + blocksInProgress.add(newPayload); } } - private void logCurrentBestBlock(final BlockWithReceipts blockWithReceipts) { + private void logCurrentBestBlock(final PayloadWrapper payloadWrapper) { if (LOG.isDebugEnabled()) { - final Block block = blockWithReceipts.getBlock(); + final Block block = payloadWrapper.blockWithReceipts().getBlock(); final float gasUsedPerc = 100.0f * block.getHeader().getGasUsed() / block.getHeader().getGasLimit(); final int txsNum = block.getBody().getTransactions().size(); - final Wei reward = blockValueCalculator.calculateBlockValue(blockWithReceipts); LOG.debug( "Current best proposal for block {}: txs {}, gas used {}%, reward {}", - blockWithReceipts.getNumber(), + block.getHeader().getNumber(), txsNum, String.format("%1.2f", gasUsedPerc), - reward.toHumanReadableString()); + payloadWrapper.blockValue().toHumanReadableString()); } } @Override - public Optional retrieveBlockById(final PayloadIdentifier payloadId) { + public Optional retrievePayloadById(final PayloadIdentifier payloadId) { synchronized (blocksInProgress) { - return retrievePayloadsById(payloadId) - .map(payloadWrapper -> payloadWrapper.blockWithReceipts()) - .sorted(compareByGasUsedDesc) - .findFirst(); + return streamPayloadsById(payloadId).max(Comparator.comparing(PayloadWrapper::blockValue)); } } - private Stream retrievePayloadsById(final PayloadIdentifier payloadId) { + private Stream streamPayloadsById(final PayloadIdentifier payloadId) { return blocksInProgress.stream().filter(z -> z.payloadIdentifier().equals(payloadId)); } diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionContext.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionContext.java index ea003c7090a..9d8c927e1ee 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionContext.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionContext.java @@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.ConsensusContext; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; @@ -146,8 +145,8 @@ public void putPayloadById(final PayloadWrapper payloadWrapper) { } @Override - public Optional retrieveBlockById(final PayloadIdentifier payloadId) { - return postMergeContext.retrieveBlockById(payloadId); + public Optional retrievePayloadById(final PayloadIdentifier payloadId) { + return postMergeContext.retrievePayloadById(payloadId); } @Override diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/PostMergeContextTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/PostMergeContextTest.java index 91086a8d7c4..6abf09bde0f 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/PostMergeContextTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/PostMergeContextTest.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockWithReceipts; @@ -138,9 +139,12 @@ public void putAndRetrieveFirstPayload() { BlockWithReceipts mockBlockWithReceipts = createBlockWithReceipts(1, 21000, 1); PayloadIdentifier firstPayloadId = new PayloadIdentifier(1L); - postMergeContext.putPayloadById(new PayloadWrapper(firstPayloadId, mockBlockWithReceipts)); + final var payloadWrapper = createPayloadWrapper(firstPayloadId, mockBlockWithReceipts, Wei.ONE); + postMergeContext.putPayloadById(payloadWrapper); - assertThat(postMergeContext.retrieveBlockById(firstPayloadId)).contains(mockBlockWithReceipts); + assertThat(postMergeContext.retrievePayloadById(firstPayloadId)) + .map(PayloadWrapper::blockWithReceipts) + .contains(mockBlockWithReceipts); } @Test @@ -149,10 +153,16 @@ public void puttingTwoBlocksWithTheSamePayloadIdWeRetrieveTheBest() { BlockWithReceipts betterBlockWithReceipts = createBlockWithReceipts(2, 11, 1); PayloadIdentifier payloadId = new PayloadIdentifier(1L); - postMergeContext.putPayloadById(new PayloadWrapper(payloadId, zeroTxBlockWithReceipts)); - postMergeContext.putPayloadById(new PayloadWrapper(payloadId, betterBlockWithReceipts)); - - assertThat(postMergeContext.retrieveBlockById(payloadId)).contains(betterBlockWithReceipts); + final var zeroTxPayloadWrapper = + createPayloadWrapper(payloadId, zeroTxBlockWithReceipts, Wei.ZERO); + final var betterPayloadWrapper = + createPayloadWrapper(payloadId, betterBlockWithReceipts, Wei.ONE); + postMergeContext.putPayloadById(zeroTxPayloadWrapper); + postMergeContext.putPayloadById(betterPayloadWrapper); + + assertThat(postMergeContext.retrievePayloadById(payloadId)) + .map(PayloadWrapper::blockWithReceipts) + .contains(betterBlockWithReceipts); } @Test @@ -162,25 +172,33 @@ public void puttingABlockWithTheSamePayloadIdSmallerThanAnExistingOneWeRetrieveT BlockWithReceipts smallBlockWithReceipts = createBlockWithReceipts(3, 5, 1); PayloadIdentifier payloadId = new PayloadIdentifier(1L); - postMergeContext.putPayloadById(new PayloadWrapper(payloadId, zeroTxBlockWithReceipts)); - postMergeContext.putPayloadById(new PayloadWrapper(payloadId, betterBlockWithReceipts)); - postMergeContext.putPayloadById(new PayloadWrapper(payloadId, smallBlockWithReceipts)); - - assertThat(postMergeContext.retrieveBlockById(payloadId)).contains(betterBlockWithReceipts); + final var zeroTxPayloadWrapper = + createPayloadWrapper(payloadId, zeroTxBlockWithReceipts, Wei.ZERO); + final var betterPayloadWrapper = + createPayloadWrapper(payloadId, betterBlockWithReceipts, Wei.of(2)); + final var smallPayloadWrapper = + createPayloadWrapper(payloadId, smallBlockWithReceipts, Wei.ONE); + postMergeContext.putPayloadById(zeroTxPayloadWrapper); + postMergeContext.putPayloadById(betterPayloadWrapper); + postMergeContext.putPayloadById(smallPayloadWrapper); + + assertThat(postMergeContext.retrievePayloadById(payloadId)) + .map(PayloadWrapper::blockWithReceipts) + .contains(betterBlockWithReceipts); } @Test public void tryingToRetrieveANotYetPutPayloadIdReturnsEmpty() { PayloadIdentifier payloadId = new PayloadIdentifier(1L); - assertThat(postMergeContext.retrieveBlockById(payloadId)).isEmpty(); + assertThat(postMergeContext.retrievePayloadById(payloadId)).isEmpty(); } @Test public void tryingToRetrieveABlockPutButEvictedReturnsEmpty() { PayloadIdentifier evictedPayloadId = new PayloadIdentifier(0L); - assertThat(postMergeContext.retrieveBlockById(evictedPayloadId)).isEmpty(); + assertThat(postMergeContext.retrievePayloadById(evictedPayloadId)).isEmpty(); } @Test @@ -209,6 +227,17 @@ public void syncStateNullShouldNotThrowWhenIsSyncingIsCalled() { assertThat(postMergeContext.isSyncing()).isFalse(); } + private PayloadWrapper createPayloadWrapper( + final PayloadIdentifier firstPayloadId, + final BlockWithReceipts mockBlockWithReceipts, + final Wei blockValue) { + final var payloadWrapper = mock(PayloadWrapper.class); + when(payloadWrapper.payloadIdentifier()).thenReturn(firstPayloadId); + when(payloadWrapper.blockWithReceipts()).thenReturn(mockBlockWithReceipts); + when(payloadWrapper.blockValue()).thenReturn(blockValue); + return payloadWrapper; + } + private static BlockWithReceipts createBlockWithReceipts( final int number, final long gasUsed, final int txCount) { Block mockBlock = mock(Block.class, RETURNS_DEEP_STUBS); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayload.java index d6544b6b66c..901eda782c3 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayload.java @@ -14,9 +14,9 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; @@ -70,10 +70,9 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext request) { final PayloadIdentifier payloadId = request.getRequiredParameter(0, PayloadIdentifier.class); mergeMiningCoordinator.finalizeProposalById(payloadId); - final Optional blockWithReceipts = - mergeContext.get().retrieveBlockById(payloadId); - if (blockWithReceipts.isPresent()) { - final BlockWithReceipts proposal = blockWithReceipts.get(); + final Optional maybePayload = mergeContext.get().retrievePayloadById(payloadId); + if (maybePayload.isPresent()) { + final BlockWithReceipts proposal = maybePayload.get().blockWithReceipts(); LOG.atDebug() .setMessage("assembledBlock for payloadId {}: {}") .addArgument(() -> payloadId) @@ -85,37 +84,33 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext request) { if (!forkValidationResult.isValid()) { return new JsonRpcErrorResponse(request.getRequest().getId(), forkValidationResult); } - return createResponse(request, payloadId, proposal); + return createResponse(request, maybePayload.get()); } return new JsonRpcErrorResponse(request.getRequest().getId(), RpcErrorType.UNKNOWN_PAYLOAD); } - protected void logProposal( - final PayloadIdentifier payloadId, - final BlockWithReceipts proposal, - final Optional maybeReward) { - final BlockHeader proposalHeader = proposal.getHeader(); + protected void logProposal(final PayloadWrapper payload) { + final BlockHeader proposalHeader = payload.blockWithReceipts().getHeader(); final float gasUsedPerc = 100.0f * proposalHeader.getGasUsed() / proposalHeader.getGasLimit(); final String message = "Fetch block proposal by identifier: {}, hash: {}, " + "number: {}, coinbase: {}, transaction count: {}, gas used: {}%" - + maybeReward.map(unused -> ", reward: {}").orElse("{}"); + + " reward: {}"; LOG.atInfo() .setMessage(message) - .addArgument(payloadId::toHexString) + .addArgument(payload.payloadIdentifier()::toHexString) .addArgument(proposalHeader::getHash) .addArgument(proposalHeader::getNumber) .addArgument(proposalHeader::getCoinbase) - .addArgument(() -> proposal.getBlock().getBody().getTransactions().size()) + .addArgument( + () -> payload.blockWithReceipts().getBlock().getBody().getTransactions().size()) .addArgument(() -> String.format("%1.2f", gasUsedPerc)) - .addArgument(maybeReward.map(Wei::toHumanReadableString).orElse("")) + .addArgument(payload.blockValue()::toHumanReadableString) .log(); } protected abstract JsonRpcResponse createResponse( - final JsonRpcRequestContext request, - final PayloadIdentifier payloadId, - final BlockWithReceipts blockWithReceipts); + final JsonRpcRequestContext request, final PayloadWrapper payload); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV1.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV1.java index ba691b44a44..d9365282711 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV1.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV1.java @@ -14,17 +14,14 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; -import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; - -import java.util.Optional; import io.vertx.core.Vertx; @@ -46,12 +43,10 @@ public String getName() { @Override protected JsonRpcResponse createResponse( - final JsonRpcRequestContext request, - final PayloadIdentifier payloadId, - final BlockWithReceipts blockWithReceipts) { + final JsonRpcRequestContext request, final PayloadWrapper payload) { final var result = - blockResultFactory.payloadTransactionCompleteV1(blockWithReceipts.getBlock()); - logProposal(payloadId, blockWithReceipts, Optional.empty()); + blockResultFactory.payloadTransactionCompleteV1(payload.blockWithReceipts().getBlock()); + logProposal(payload); return new JsonRpcSuccessResponse(request.getRequest().getId(), result); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2.java index 54328f37d08..ade62077df0 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2.java @@ -14,9 +14,8 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; -import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; @@ -24,7 +23,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; @@ -61,12 +59,9 @@ public String getName() { @Override protected JsonRpcResponse createResponse( - final JsonRpcRequestContext request, - final PayloadIdentifier payloadId, - final BlockWithReceipts blockWithReceipts) { - final var result = blockResultFactory.payloadTransactionCompleteV2(blockWithReceipts); - logProposal( - payloadId, blockWithReceipts, Optional.of(Wei.fromHexString(result.getBlockValue()))); + final JsonRpcRequestContext request, final PayloadWrapper payload) { + final var result = blockResultFactory.payloadTransactionCompleteV2(payload); + logProposal(payload); return new JsonRpcSuccessResponse(request.getRequest().getId(), result); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3.java index 29dea77d90b..742a240aa02 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3.java @@ -14,8 +14,8 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; -import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; @@ -23,7 +23,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; @@ -60,13 +59,10 @@ public String getName() { @Override protected JsonRpcResponse createResponse( - final JsonRpcRequestContext request, - final PayloadIdentifier payloadId, - final BlockWithReceipts blockWithReceipts) { + final JsonRpcRequestContext request, final PayloadWrapper payload) { return new JsonRpcSuccessResponse( - request.getRequest().getId(), - blockResultFactory.payloadTransactionCompleteV3(blockWithReceipts)); + request.getRequest().getId(), blockResultFactory.payloadTransactionCompleteV3(payload)); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4.java index 860c4af96e2..c5a713beea2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4.java @@ -14,8 +14,8 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; -import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; @@ -23,7 +23,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; @@ -60,13 +59,10 @@ public String getName() { @Override protected JsonRpcResponse createResponse( - final JsonRpcRequestContext request, - final PayloadIdentifier payloadId, - final BlockWithReceipts blockWithReceipts) { + final JsonRpcRequestContext request, final PayloadWrapper payload) { return new JsonRpcSuccessResponse( - request.getRequest().getId(), - blockResultFactory.payloadTransactionCompleteV4(blockWithReceipts)); + request.getRequest().getId(), blockResultFactory.payloadTransactionCompleteV4(payload)); } @Override diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java index aff5713afc6..2f89ef12ce1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java @@ -17,16 +17,14 @@ import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getDepositRequests; import static org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil.getWithdrawalRequests; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EngineGetPayloadBodiesResultV1.PayloadBody; import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata; import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockValueCalculator; -import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.core.encoding.EncodingContext; import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder; @@ -108,8 +106,8 @@ public EngineGetPayloadResultV1 payloadTransactionCompleteV1(final Block block) return new EngineGetPayloadResultV1(block.getHeader(), txs); } - public EngineGetPayloadResultV2 payloadTransactionCompleteV2( - final BlockWithReceipts blockWithReceipts) { + public EngineGetPayloadResultV2 payloadTransactionCompleteV2(final PayloadWrapper payload) { + final var blockWithReceipts = payload.blockWithReceipts(); final List txs = blockWithReceipts.getBlock().getBody().getTransactions().stream() .map( @@ -118,12 +116,11 @@ public EngineGetPayloadResultV2 payloadTransactionCompleteV2( .map(Bytes::toHexString) .collect(Collectors.toList()); - final Wei blockValue = new BlockValueCalculator().calculateBlockValue(blockWithReceipts); return new EngineGetPayloadResultV2( blockWithReceipts.getHeader(), txs, blockWithReceipts.getBlock().getBody().getWithdrawals(), - Quantity.create(blockValue)); + Quantity.create(payload.blockValue())); } public EngineGetPayloadBodiesResultV1 payloadBodiesCompleteV1( @@ -135,8 +132,8 @@ public EngineGetPayloadBodiesResultV1 payloadBodiesCompleteV1( return new EngineGetPayloadBodiesResultV1(payloadBodies); } - public EngineGetPayloadResultV3 payloadTransactionCompleteV3( - final BlockWithReceipts blockWithReceipts) { + public EngineGetPayloadResultV3 payloadTransactionCompleteV3(final PayloadWrapper payload) { + final var blockWithReceipts = payload.blockWithReceipts(); final List txs = blockWithReceipts.getBlock().getBody().getTransactions().stream() .map( @@ -145,20 +142,18 @@ public EngineGetPayloadResultV3 payloadTransactionCompleteV3( .map(Bytes::toHexString) .collect(Collectors.toList()); - final Wei blockValue = new BlockValueCalculator().calculateBlockValue(blockWithReceipts); - final BlobsBundleV1 blobsBundleV1 = new BlobsBundleV1(blockWithReceipts.getBlock().getBody().getTransactions()); return new EngineGetPayloadResultV3( blockWithReceipts.getHeader(), txs, blockWithReceipts.getBlock().getBody().getWithdrawals(), - Quantity.create(blockValue), + Quantity.create(payload.blockValue()), blobsBundleV1); } - public EngineGetPayloadResultV4 payloadTransactionCompleteV4( - final BlockWithReceipts blockWithReceipts) { + public EngineGetPayloadResultV4 payloadTransactionCompleteV4(final PayloadWrapper payload) { + final var blockWithReceipts = payload.blockWithReceipts(); final List txs = blockWithReceipts.getBlock().getBody().getTransactions().stream() .map( @@ -167,8 +162,6 @@ public EngineGetPayloadResultV4 payloadTransactionCompleteV4( .map(Bytes::toHexString) .collect(Collectors.toList()); - final Wei blockValue = new BlockValueCalculator().calculateBlockValue(blockWithReceipts); - final BlobsBundleV1 blobsBundleV1 = new BlobsBundleV1(blockWithReceipts.getBlock().getBody().getTransactions()); return new EngineGetPayloadResultV4( @@ -177,7 +170,7 @@ public EngineGetPayloadResultV4 payloadTransactionCompleteV4( blockWithReceipts.getBlock().getBody().getWithdrawals(), getDepositRequests(blockWithReceipts.getBlock().getBody().getRequests()), getWithdrawalRequests(blockWithReceipts.getBlock().getBody().getRequests()), - Quantity.create(blockValue), + Quantity.create(payload.blockValue()), blobsBundleV1); } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java index 77952f6dc69..f18b5601cf4 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.merge.MergeContext; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.crypto.KeyPair; @@ -97,6 +98,8 @@ public AbstractEngineGetPayloadTest() { new Block(mockHeader, new BlockBody(Collections.emptyList(), Collections.emptyList())); protected static final BlockWithReceipts mockBlockWithReceipts = new BlockWithReceipts(mockBlock, Collections.emptyList()); + protected static final PayloadWrapper mockPayload = + new PayloadWrapper(mockPid, mockBlockWithReceipts); private static final Block mockBlockWithWithdrawals = new Block( mockHeader, @@ -115,9 +118,13 @@ public AbstractEngineGetPayloadTest() { Optional.of(Collections.emptyList()))); protected static final BlockWithReceipts mockBlockWithReceiptsAndWithdrawals = new BlockWithReceipts(mockBlockWithWithdrawals, Collections.emptyList()); + protected static final PayloadWrapper mockPayloadWithWithdrawals = + new PayloadWrapper(mockPid, mockBlockWithReceiptsAndWithdrawals); protected static final BlockWithReceipts mockBlockWithReceiptsAndDepositRequests = new BlockWithReceipts(mockBlockWithDepositRequests, Collections.emptyList()); + protected static final PayloadWrapper mockPayloadWithDepositRequests = + new PayloadWrapper(mockPid, mockBlockWithReceiptsAndDepositRequests); @Mock protected ProtocolContext protocolContext; @@ -130,7 +137,7 @@ public AbstractEngineGetPayloadTest() { @Override public void before() { super.before(); - when(mergeContext.retrieveBlockById(mockPid)).thenReturn(Optional.of(mockBlockWithReceipts)); + when(mergeContext.retrievePayloadById(mockPid)).thenReturn(Optional.of(mockPayload)); when(protocolContext.safeConsensusContext(Mockito.any())).thenReturn(Optional.of(mergeContext)); if (methodFactory.isPresent()) { this.method = diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java index 72f89c79c3a..5f42f02c82b 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV2Test.java @@ -48,9 +48,7 @@ public EngineGetPayloadV2Test() { @Override public void before() { super.before(); - lenient() - .when(mergeContext.retrieveBlockById(mockPid)) - .thenReturn(Optional.of(mockBlockWithReceipts)); + lenient().when(mergeContext.retrievePayloadById(mockPid)).thenReturn(Optional.of(mockPayload)); when(protocolContext.safeConsensusContext(Mockito.any())).thenReturn(Optional.of(mergeContext)); this.method = new EngineGetPayloadV2( @@ -72,8 +70,8 @@ public void shouldReturnExpectedMethodName() { @Test public void shouldReturnBlockForKnownPayloadId() { // should return withdrawals for a post-Shanghai block - when(mergeContext.retrieveBlockById(mockPid)) - .thenReturn(Optional.of(mockBlockWithReceiptsAndWithdrawals)); + when(mergeContext.retrievePayloadById(mockPid)) + .thenReturn(Optional.of(mockPayloadWithWithdrawals)); final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V2.getMethodName(), mockPid); assertThat(resp).isInstanceOf(JsonRpcSuccessResponse.class); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java index 00db0171b7d..ac589c11219 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; @@ -67,9 +68,7 @@ public EngineGetPayloadV3Test() { @Override public void before() { super.before(); - lenient() - .when(mergeContext.retrieveBlockById(mockPid)) - .thenReturn(Optional.of(mockBlockWithReceipts)); + lenient().when(mergeContext.retrievePayloadById(mockPid)).thenReturn(Optional.of(mockPayload)); when(protocolContext.safeConsensusContext(Mockito.any())).thenReturn(Optional.of(mergeContext)); this.method = new EngineGetPayloadV3( @@ -132,8 +131,10 @@ public void shouldReturnBlockForKnownPayloadId() { Optional.of(Collections.emptyList()), Optional.of(Collections.emptyList()))), List.of(blobReceipt)); + PayloadWrapper payloadPostCancun = new PayloadWrapper(postCancunPid, postCancunBlock); - when(mergeContext.retrieveBlockById(postCancunPid)).thenReturn(Optional.of(postCancunBlock)); + when(mergeContext.retrievePayloadById(postCancunPid)) + .thenReturn(Optional.of(payloadPostCancun)); final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V3.getMethodName(), postCancunPid); assertThat(resp).isInstanceOf(JsonRpcSuccessResponse.class); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java index e8e4e821a37..535b2c9983e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV4Test.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import org.hyperledger.besu.consensus.merge.PayloadWrapper; import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; @@ -70,8 +71,8 @@ public EngineGetPayloadV4Test() { public void before() { super.before(); lenient() - .when(mergeContext.retrieveBlockById(mockPid)) - .thenReturn(Optional.of(mockBlockWithReceiptsAndDepositRequests)); + .when(mergeContext.retrievePayloadById(mockPid)) + .thenReturn(Optional.of(mockPayloadWithDepositRequests)); when(protocolContext.safeConsensusContext(Mockito.any())).thenReturn(Optional.of(mergeContext)); this.method = new EngineGetPayloadV4( @@ -134,8 +135,9 @@ public void shouldReturnBlockForKnownPayloadId() { Optional.of(Collections.emptyList()), Optional.of(Collections.emptyList()))), List.of(blobReceipt)); + PayloadWrapper payload = new PayloadWrapper(payloadIdentifier, block); - when(mergeContext.retrieveBlockById(payloadIdentifier)).thenReturn(Optional.of(block)); + when(mergeContext.retrievePayloadById(payloadIdentifier)).thenReturn(Optional.of(payload)); final var resp = resp(RpcMethod.ENGINE_GET_PAYLOAD_V4.getMethodName(), payloadIdentifier); assertThat(resp).isInstanceOf(JsonRpcSuccessResponse.class); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockValueCalculator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockValueCalculator.java index c7552c227f8..a0db4717278 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockValueCalculator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockValueCalculator.java @@ -20,7 +20,7 @@ public class BlockValueCalculator { - public Wei calculateBlockValue(final BlockWithReceipts blockWithReceipts) { + public static Wei calculateBlockValue(final BlockWithReceipts blockWithReceipts) { final Block block = blockWithReceipts.getBlock(); final List txs = block.getBody().getTransactions(); final List receipts = blockWithReceipts.getReceipts(); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/BlockValueCalculatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/BlockValueCalculatorTest.java index 0db0ec4145d..32dc063f313 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/BlockValueCalculatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/BlockValueCalculatorTest.java @@ -41,8 +41,8 @@ public void shouldCalculateZeroBlockValueForEmptyTransactions() { final Block block = new Block(blockHeader, new BlockBody(Collections.emptyList(), Collections.emptyList())); Wei blockValue = - new BlockValueCalculator() - .calculateBlockValue(new BlockWithReceipts(block, Collections.emptyList())); + BlockValueCalculator.calculateBlockValue( + new BlockWithReceipts(block, Collections.emptyList())); assertThat(blockValue).isEqualTo(Wei.ZERO); } @@ -85,9 +85,8 @@ public void shouldCalculateCorrectBlockValue() { final Block block = new Block(blockHeader, new BlockBody(List.of(tx1, tx2, tx3), Collections.emptyList())); Wei blockValue = - new BlockValueCalculator() - .calculateBlockValue( - new BlockWithReceipts(block, List.of(receipt1, receipt2, receipt3))); + BlockValueCalculator.calculateBlockValue( + new BlockWithReceipts(block, List.of(receipt1, receipt2, receipt3))); // Block value = 71 * 1 + (143-71) * 2 + (214-143) * 5 = 1427 assertThat(blockValue).isEqualTo(Wei.of(570L)); } @@ -114,8 +113,7 @@ public void shouldCalculateCorrectBlockValueExceedingLong() { final Block block = new Block(blockHeader, new BlockBody(List.of(tx1), Collections.emptyList())); Wei blockValue = - new BlockValueCalculator() - .calculateBlockValue(new BlockWithReceipts(block, List.of(receipt1))); + BlockValueCalculator.calculateBlockValue(new BlockWithReceipts(block, List.of(receipt1))); // Block value =~ max_long * 2 assertThat(blockValue).isGreaterThan(Wei.of(Long.MAX_VALUE)); } From 54a3e6a2871635cf7b46b2ffd88bbfdb508cccc9 Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Sat, 8 Jun 2024 20:18:55 +1000 Subject: [PATCH 30/42] feat: Refactor Node DNS Resolver to use vertx virtual threads (#7189) Signed-off-by: Usman Saleem --- .../ethereum/p2p/discovery/dns/DNSDaemon.java | 1 - .../p2p/discovery/dns/DNSResolver.java | 84 ++++++------------- .../p2p/network/DefaultP2PNetwork.java | 16 ++-- .../p2p/discovery/dns/DNSDaemonTest.java | 12 +-- 4 files changed, 38 insertions(+), 75 deletions(-) diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java index d17c846be79..ef794ae2047 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemon.java @@ -88,7 +88,6 @@ public void start() { public void stop() { LOG.info("Stopping DNSDaemon for {}", enrLink); periodicTaskId.ifPresent(vertx::cancelTimer); - dnsResolver.close(); } /** diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java index d42304ed043..0be4ca619d1 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSResolver.java @@ -24,12 +24,9 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicReference; import com.google.common.base.Splitter; +import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.dns.DnsClient; import io.vertx.core.dns.DnsClientOptions; @@ -42,9 +39,8 @@ // Adapted from https://github.com/tmio/tuweni and licensed under Apache 2.0 /** Resolves a set of ENR nodes from a host name. */ -public class DNSResolver implements AutoCloseable { +public class DNSResolver { private static final Logger LOG = LoggerFactory.getLogger(DNSResolver.class); - private final ExecutorService rawTxtRecordsExecutor = Executors.newSingleThreadExecutor(); private final String enrLink; private long seq; private final DnsClient dnsClient; @@ -118,7 +114,7 @@ public long sequence() { private void visitTree(final ENRTreeLink link, final DNSVisitor visitor) { Optional optionalEntry = resolveRecord(link.domainName()); if (optionalEntry.isEmpty()) { - LOG.debug("No DNS record found for {}", link.domainName()); + LOG.trace("No DNS record found for {}", link.domainName()); return; } @@ -146,32 +142,30 @@ private boolean internalVisit( final String entryName, final String domainName, final DNSVisitor visitor) { final Optional optionalDNSEntry = resolveRecord(entryName + "." + domainName); if (optionalDNSEntry.isEmpty()) { - LOG.debug("No DNS record found for {}", entryName + "." + domainName); return true; } final DNSEntry entry = optionalDNSEntry.get(); - if (entry instanceof ENRNode node) { - // TODO: this always return true because the visitor is reference to list.add - return visitor.visit(node.nodeRecord()); - } else if (entry instanceof DNSEntry.ENRTree tree) { - for (String e : tree.entries()) { - // TODO: When would this ever return false? - boolean keepGoing = internalVisit(e, domainName, visitor); - if (!keepGoing) { - return false; + switch (entry) { + case ENRNode node -> { + return visitor.visit(node.nodeRecord()); + } + case DNSEntry.ENRTree tree -> { + for (String e : tree.entries()) { + boolean keepGoing = internalVisit(e, domainName, visitor); + if (!keepGoing) { + return false; + } } } - } else if (entry instanceof ENRTreeLink link) { - visitTree(link, visitor); - } else { - LOG.debug("Unsupported type of node {}", entry); + case ENRTreeLink link -> visitTree(link, visitor); + default -> LOG.debug("Unsupported type of node {}", entry); } return true; } /** - * Resolves one DNS record associated with the given domain name. + * Maps TXT DNS record to DNSEntry. * * @param domainName the domain name to query * @return the DNS entry read from the domain. Empty if no record is found. @@ -187,51 +181,21 @@ Optional resolveRecord(final String domainName) { * @return the first TXT entry of the DNS record. Empty if no record is found. */ Optional resolveRawRecord(final String domainName) { - // vertx-dns is async, kotlin coroutines allows us to await, similarly Java 21 new thread - // model would also allow us to await. For now, we will use CountDownLatch to block the - // current thread until the DNS resolution is complete. - LOG.debug("Resolving TXT records on domain: {}", domainName); - final CountDownLatch latch = new CountDownLatch(1); - final AtomicReference> record = new AtomicReference<>(Optional.empty()); - rawTxtRecordsExecutor.submit( - () -> { - dnsClient - .resolveTXT(domainName) - .onComplete( - ar -> { - if (ar.succeeded()) { - LOG.trace( - "TXT record resolved on domain {}. Result: {}", domainName, ar.result()); - record.set(ar.result().stream().findFirst()); - } else { - LOG.trace( - "TXT record not resolved on domain {}, because: {}", - domainName, - ar.cause().getMessage()); - } - latch.countDown(); - }); - }); - + LOG.trace("Resolving TXT records on domain: {}", domainName); try { - // causes the worker thread to wait. Once we move to Java 21, this can be simplified. - latch.await(); - } catch (InterruptedException e) { - LOG.debug("Interrupted while waiting for DNS resolution"); + // Future.await parks current virtual thread and waits for the result. Any failure is + // thrown as a Throwable. + return Future.await(dnsClient.resolveTXT(domainName)).stream().findFirst(); + } catch (final Throwable e) { + LOG.trace("Error while resolving TXT records on domain: {}", domainName, e); + return Optional.empty(); } - - return record.get(); } private boolean checkSignature( final ENRTreeRoot root, final SECP256K1.PublicKey pubKey, final SECP256K1.Signature sig) { - Bytes32 hash = + final Bytes32 hash = Hash.keccak256(Bytes.wrap(root.signedContent().getBytes(StandardCharsets.UTF_8))); return SECP256K1.verifyHashed(hash, sig, pubKey); } - - @Override - public void close() { - rawTxtRecordsExecutor.shutdown(); - } } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java index 573effa173a..55a536976fe 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java @@ -82,7 +82,6 @@ import io.vertx.core.Future; import io.vertx.core.ThreadingModel; import io.vertx.core.Vertx; -import org.apache.commons.lang3.tuple.Pair; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.devp2p.EthereumNodeRecord; import org.slf4j.Logger; @@ -152,7 +151,7 @@ public class DefaultP2PNetwork implements P2PNetwork { private final CountDownLatch shutdownLatch = new CountDownLatch(2); private final Duration shutdownTimeout = Duration.ofSeconds(15); private final Vertx vertx; - private final AtomicReference>> dnsDaemonRef = + private final AtomicReference> dnsDaemonRef = new AtomicReference<>(Optional.empty()); /** @@ -242,17 +241,16 @@ public void start() { 600000L, config.getDnsDiscoveryServerOverride().orElse(null)); - // TODO: Java 21, we can move to Virtual Thread model + // Use Java 21 virtual thread to deploy verticle final DeploymentOptions options = new DeploymentOptions() - .setThreadingModel(ThreadingModel.WORKER) + .setThreadingModel(ThreadingModel.VIRTUAL_THREAD) .setInstances(1) .setWorkerPoolSize(1); final Future deployId = vertx.deployVerticle(dnsDaemon, options); - final String dnsDaemonDeployId = - deployId.toCompletionStage().toCompletableFuture().join(); - dnsDaemonRef.set(Optional.of(Pair.of(dnsDaemonDeployId, dnsDaemon))); + deployId.toCompletionStage().toCompletableFuture().join(); + dnsDaemonRef.set(Optional.of(dnsDaemon)); }); final int listeningPort = rlpxAgent.start().join(); @@ -301,7 +299,7 @@ public void stop() { // since dnsDaemon is a vertx verticle, vertx.close will undeploy it. // However, we can safely call stop as well. - dnsDaemonRef.get().map(Pair::getRight).ifPresent(DNSDaemon::stop); + dnsDaemonRef.get().ifPresent(DNSDaemon::stop); peerConnectionScheduler.shutdownNow(); peerDiscoveryAgent.stop().whenComplete((res, err) -> shutdownLatch.countDown()); @@ -358,7 +356,7 @@ public boolean removeMaintainedConnectionPeer(final Peer peer) { @VisibleForTesting Optional getDnsDaemon() { - return dnsDaemonRef.get().map(Pair::getRight); + return dnsDaemonRef.get(); } @VisibleForTesting diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java index cb465093d07..93074d37104 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java @@ -16,7 +16,6 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.io.IOException; import java.security.Security; import java.util.concurrent.atomic.AtomicInteger; @@ -38,12 +37,11 @@ class DNSDaemonTest { private static final String holeskyEnr = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net"; - // private static MockDNSServer mockDNSServer; private final MockDnsServerVerticle mockDnsServerVerticle = new MockDnsServerVerticle(); private DNSDaemon dnsDaemon; @BeforeAll - static void setup() throws IOException { + static void setup() { Security.addProvider(new BouncyCastleProvider()); } @@ -68,7 +66,9 @@ void testDNSDaemon(final Vertx vertx, final VertxTestContext testContext) "localhost:" + mockDnsServerVerticle.port()); final DeploymentOptions options = - new DeploymentOptions().setThreadingModel(ThreadingModel.WORKER).setWorkerPoolSize(1); + new DeploymentOptions() + .setThreadingModel(ThreadingModel.VIRTUAL_THREAD) + .setWorkerPoolSize(1); vertx.deployVerticle(dnsDaemon, options); } @@ -109,7 +109,9 @@ void testDNSDaemonPeriodic(final Vertx vertx, final VertxTestContext testContext "localhost:" + mockDnsServerVerticle.port()); final DeploymentOptions options = - new DeploymentOptions().setThreadingModel(ThreadingModel.WORKER).setWorkerPoolSize(1); + new DeploymentOptions() + .setThreadingModel(ThreadingModel.VIRTUAL_THREAD) + .setWorkerPoolSize(1); vertx.deployVerticle(dnsDaemon, options); } From c3f7f8765d7cc5c3ce55c558e925510e04ef4935 Mon Sep 17 00:00:00 2001 From: Jason Frame Date: Tue, 11 Jun 2024 13:45:07 +1000 Subject: [PATCH 31/42] Update changelog for 24.6.0 (#7198) Signed-off-by: Jason Frame --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 421d856430e..c53b586a129 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Next Release +## 24.6.0 ### Breaking Changes - Java 21 has been enforced as minimum version to build and run Besu. @@ -13,6 +13,7 @@ - PKI-backed QBFT will be removed in a future version of Besu. Other forms of QBFT will remain unchanged. - --Xbonsai-limit-trie-logs-enabled is deprecated, use --bonsai-limit-trie-logs-enabled instead - --Xbonsai-trie-logs-pruning-window-size is deprecated, use --bonsai-trie-logs-pruning-window-size instead +- Receipt compaction will be enabled by default in a future version of Besu. After this change it will not be possible to downgrade to the previous Besu version. ### Additions and Improvements - Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) From 7ef6f0dbf37878d5589975999076763dc6a85949 Mon Sep 17 00:00:00 2001 From: Jason Frame Date: Tue, 11 Jun 2024 16:33:42 +1000 Subject: [PATCH 32/42] Update gradle to 8.8 (#7199) Signed-off-by: Jason Frame --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a4f0..a4413138c96 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 186b4c5d21a41edcd2ddaf166b37f14d41bab41e Mon Sep 17 00:00:00 2001 From: Sally MacFarlane Date: Tue, 11 Jun 2024 17:37:35 +1000 Subject: [PATCH 33/42] disable flaky test (#7202) Signed-off-by: Sally MacFarlane --- .../besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java index 93074d37104..08539d47bf8 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -73,6 +74,7 @@ void testDNSDaemon(final Vertx vertx, final VertxTestContext testContext) } @Test + @Disabled("this test is flaky") @DisplayName("Test DNS Daemon with periodic lookup to a mock DNS server") void testDNSDaemonPeriodic(final Vertx vertx, final VertxTestContext testContext) throws InterruptedException { From 478b6d0184ef8154d68a45bcd3419295e35893e4 Mon Sep 17 00:00:00 2001 From: krsh24 Date: Tue, 11 Jun 2024 16:01:59 +0800 Subject: [PATCH 34/42] Support for eth_maxPriorityFeePerGasPrice (#7194) * Error out on permissions config accounts-allowlist validation errors. Signed-off-by: krishnannarayanan * Fixing compilation errors Signed-off-by: krishnannarayanan * Incorrect file check in Signed-off-by: krishnannarayanan * Support for eth_maxPriorityFeePerGas Signed-off-by: krishnannarayanan * Change log update for my PRs Signed-off-by: krishnannarayanan --------- Signed-off-by: krishnannarayanan --- CHANGELOG.md | 4 +- .../besu/ethereum/api/jsonrpc/RpcMethod.java | 1 + .../methods/EthMaxPriorityFeePerGas.java | 54 +++++++ .../jsonrpc/methods/EthJsonRpcMethods.java | 4 +- .../methods/EthMaxPriorityFeePerGasTest.java | 133 ++++++++++++++++++ 5 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java create mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c53b586a129..9b64946ae01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,10 +22,10 @@ - Promote experimental --Xbonsai-trie-logs-pruning-window-size to production-ready, --bonsai-trie-logs-pruning-window-size [#7192](https://github.com/hyperledger/besu/pull/7192) - `admin_nodeInfo` JSON/RPC call returns the currently active EVM version [#7127](https://github.com/hyperledger/besu/pull/7127) - Improve the selection of the most profitable built block [#7174](https://github.com/hyperledger/besu/pull/7174) - +- Support for eth_maxPriorityFeePerGas [#5658](https://github.com/hyperledger/besu/issues/5658) ### Bug fixes - Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) - +- Validation errors ignored in accounts-allowlist and empty list [#7138](https://github.com/hyperledger/besu/issues/7138) ## 24.5.2 ### Upcoming Breaking Changes diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java index 36e4ff8b8a5..4174fdf8313 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java @@ -109,6 +109,7 @@ public enum RpcMethod { ETH_GET_FILTER_CHANGES("eth_getFilterChanges"), ETH_GET_FILTER_LOGS("eth_getFilterLogs"), ETH_GET_LOGS("eth_getLogs"), + ETH_GET_MAX_PRIORITY_FEE_PER_GAS("eth_maxPriorityFeePerGas"), ETH_GET_MINER_DATA_BY_BLOCK_HASH("eth_getMinerDataByBlockHash"), ETH_GET_MINER_DATA_BY_BLOCK_NUMBER("eth_getMinerDataByBlockNumber"), ETH_GET_PROOF("eth_getProof"), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java new file mode 100644 index 00000000000..2828fee7aca --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java @@ -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.ethereum.api.jsonrpc.internal.methods; + +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; + +import java.util.Optional; + +public class EthMaxPriorityFeePerGas implements JsonRpcMethod { + + private final BlockchainQueries blockchainQueries; + private final MiningCoordinator miningCoordinator; + + public EthMaxPriorityFeePerGas( + final BlockchainQueries blockchainQueries, final MiningCoordinator miningCoordinator) { + this.blockchainQueries = blockchainQueries; + this.miningCoordinator = miningCoordinator; + } + + @Override + public String getName() { + return RpcMethod.ETH_GET_MAX_PRIORITY_FEE_PER_GAS.getMethodName(); + } + + @Override + public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { + return new JsonRpcSuccessResponse( + requestContext.getRequest().getId(), Quantity.create(fetchAndLimitPriorityFeePerGas())); + } + + private Wei fetchAndLimitPriorityFeePerGas() { + final Optional gasPrice = blockchainQueries.gasPriorityFee(); + return gasPrice.orElseGet(miningCoordinator::getMinPriorityFeePerGas); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java index 678df31824e..c7575a5435a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java @@ -52,6 +52,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetUncleCountByBlockNumber; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetWork; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthHashrate; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthMaxPriorityFeePerGas; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthMining; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthNewBlockFilter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthNewFilter; @@ -183,6 +184,7 @@ protected Map create() { new EthChainId(protocolSchedule.getChainId()), new EthGetMinerDataByBlockHash(blockchainQueries, protocolSchedule), new EthGetMinerDataByBlockNumber(blockchainQueries, protocolSchedule), - new EthBlobBaseFee(blockchainQueries.getBlockchain(), protocolSchedule)); + new EthBlobBaseFee(blockchainQueries.getBlockchain(), protocolSchedule), + new EthMaxPriorityFeePerGas(blockchainQueries, miningCoordinator)); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java new file mode 100644 index 00000000000..02d526107a1 --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java @@ -0,0 +1,133 @@ +/* + * 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.api.jsonrpc.internal.methods; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.internal.verification.VerificationModeFactory; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class EthMaxPriorityFeePerGasTest { + private static final String JSON_RPC_VERSION = "2.0"; + private static final String ETH_METHOD = + RpcMethod.ETH_GET_MAX_PRIORITY_FEE_PER_GAS.getMethodName(); + private EthMaxPriorityFeePerGas method; + + @Mock private BlockchainQueries blockchainQueries; + @Mock private MiningCoordinator miningCoordinator; + + @BeforeEach + public void setUp() { + method = createEthMaxPriorityFeePerGasMethod(); + } + + @Test + public void shouldReturnCorrectMethodName() { + assertThat(method.getName()).isEqualTo(ETH_METHOD); + } + + @Test + public void whenNoTransactionsExistReturnMinPriorityFeePerGasPrice() { + final JsonRpcRequestContext request = requestWithParams(); + final String expectedWei = Wei.ONE.toShortHexString(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); + when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(Wei.ONE); + + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.empty()); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(1)).getMinPriorityFeePerGas(); + } + + @ParameterizedTest + @MethodSource("minPriorityFeePerGasValues") + public void whenNoTransactionsExistReturnMinPriorityFeePerGasPriceExist( + final Wei minPriorityFeePerGasValue) { + final JsonRpcRequestContext request = requestWithParams(); + final String expectedWei = minPriorityFeePerGasValue.toShortHexString(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); + when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(minPriorityFeePerGasValue); + + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.empty()); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(1)).getMinPriorityFeePerGas(); + } + + @Test + public void whenNoTransactionsExistReturnNullMinPriorityFeePerGasPriceExist() { + final JsonRpcRequestContext request = requestWithParams(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), null); + when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(null); + + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.empty()); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(1)).getMinPriorityFeePerGas(); + } + + @Test + public void whenTransactionsExistReturnMaxPriorityFeePerGasPrice() { + final JsonRpcRequestContext request = requestWithParams(); + final String expectedWei = Wei.of(2000000000).toShortHexString(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.of(Wei.of(2000000000))); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(0)).getMinPriorityFeePerGas(); + } + + private static Stream minPriorityFeePerGasValues() { + return Stream.of(Arguments.of(Wei.ONE), Arguments.of(Wei.ZERO)); + } + + private void mockBlockchainQueriesMaxPriorityFeePerGasPrice(final Optional result) { + when(blockchainQueries.gasPriorityFee()).thenReturn(result); + } + + private JsonRpcRequestContext requestWithParams(final Object... params) { + return new JsonRpcRequestContext(new JsonRpcRequest(JSON_RPC_VERSION, ETH_METHOD, params)); + } + + private EthMaxPriorityFeePerGas createEthMaxPriorityFeePerGasMethod() { + return new EthMaxPriorityFeePerGas(blockchainQueries, miningCoordinator); + } +} From 04f304fbb51fd18a8797164f0fc314c007d69e12 Mon Sep 17 00:00:00 2001 From: daniellehrner Date: Tue, 11 Jun 2024 10:25:17 +0200 Subject: [PATCH 35/42] move traceEndTransaction after coinbase refund, add self destruct set to the method (#7188) Signed-off-by: Daniel Lehrner Co-authored-by: Sally MacFarlane --- .../besu/services/TraceServiceImplTest.java | 15 ++++++- .../mainnet/MainnetTransactionProcessor.java | 39 +++++++++++++------ .../MainnetTransactionProcessorTest.java | 2 + .../hyperledger/besu/evmtool/T8nExecutor.java | 4 ++ .../besu/evm/tracing/OperationTracer.java | 4 ++ 5 files changed, 51 insertions(+), 13 deletions(-) diff --git a/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java b/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java index f7db3639ae1..1e734f62312 100644 --- a/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java +++ b/besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java @@ -125,7 +125,7 @@ void shouldRetrieveStateUpdatePostTracingForOneBlock() { verify(opTracer).traceStartTransaction(any(), eq(tx)); verify(opTracer) .traceEndTransaction( - any(), eq(tx), anyBoolean(), any(), any(), anyLong(), anyLong()); + any(), eq(tx), anyBoolean(), any(), any(), anyLong(), any(), anyLong()); }); verify(opTracer).traceEndBlock(tracedBlock.getHeader(), tracedBlock.getBody()); @@ -173,7 +173,14 @@ void shouldRetrieveStateUpdatePostTracingForAllBlocks() { verify(opTracer).traceStartTransaction(any(), eq(tx)); verify(opTracer) .traceEndTransaction( - any(), eq(tx), anyBoolean(), any(), any(), anyLong(), anyLong()); + any(), + eq(tx), + anyBoolean(), + any(), + any(), + anyLong(), + any(), + anyLong()); }); verify(opTracer).traceEndBlock(tracedBlock.getHeader(), tracedBlock.getBody()); @@ -222,6 +229,7 @@ void shouldReturnTheCorrectWorldViewForTxStartEnd() { assertThat(txStartEndTracer.txEndStatus).isTrue(); assertThat(txStartEndTracer.txEndOutput).isEqualTo(Bytes.fromHexString("0x")); assertThat(txStartEndTracer.txEndGasUsed).isEqualTo(24303); + assertThat(txStartEndTracer.txEndSelfDestructs).isEmpty(); assertThat(txStartEndTracer.txEndTimeNs).isNotNull(); assertThat(txStartEndTracer.txEndLogs).isNotEmpty(); @@ -263,6 +271,7 @@ private static class TxStartEndTracer implements BlockAwareOperationTracer { public Bytes txEndOutput; public List txEndLogs; public long txEndGasUsed; + public Set
txEndSelfDestructs; public Long txEndTimeNs; private final Set traceStartTxCalled = new HashSet<>(); @@ -287,6 +296,7 @@ public void traceEndTransaction( final Bytes output, final List logs, final long gasUsed, + final Set
selfDestructs, final long timeNs) { if (!traceEndTxCalled.add(transaction)) { fail("traceEndTransaction already called for tx " + transaction); @@ -297,6 +307,7 @@ public void traceEndTransaction( txEndOutput = output; txEndLogs = logs; txEndGasUsed = gasUsed; + txEndSelfDestructs = selfDestructs; txEndTimeNs = timeNs; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 0027c51b79d..51d300cbc46 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -59,6 +59,8 @@ public class MainnetTransactionProcessor { private static final Logger LOG = LoggerFactory.getLogger(MainnetTransactionProcessor.class); + private static final Set
EMPTY_ADDRESS_SET = Set.of(); + protected final GasCalculator gasCalculator; protected final TransactionValidatorFactory transactionValidatorFactory; @@ -451,15 +453,6 @@ public TransactionProcessingResult processTransaction( .log(); final long gasUsedByTransaction = transaction.getGasLimit() - initialFrame.getRemainingGas(); - operationTracer.traceEndTransaction( - worldUpdater, - transaction, - initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS, - initialFrame.getOutputData(), - initialFrame.getLogs(), - gasUsedByTransaction, - 0L); - // update the coinbase final var coinbase = worldState.getOrCreate(miningBeneficiary); final long usedGas = transaction.getGasLimit() - refundedGas; @@ -485,6 +478,16 @@ public TransactionProcessingResult processTransaction( coinbase.incrementBalance(coinbaseWeiDelta); + operationTracer.traceEndTransaction( + worldUpdater, + transaction, + initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS, + initialFrame.getOutputData(), + initialFrame.getLogs(), + gasUsedByTransaction, + initialFrame.getSelfDestructs(), + 0L); + initialFrame.getSelfDestructs().forEach(worldState::deleteAccount); if (clearEmptyAccounts) { @@ -516,13 +519,27 @@ public TransactionProcessingResult processTransaction( } } catch (final MerkleTrieException re) { operationTracer.traceEndTransaction( - worldState.updater(), transaction, false, Bytes.EMPTY, List.of(), 0, 0L); + worldState.updater(), + transaction, + false, + Bytes.EMPTY, + List.of(), + 0, + EMPTY_ADDRESS_SET, + 0L); // need to throw to trigger the heal throw re; } catch (final RuntimeException re) { operationTracer.traceEndTransaction( - worldState.updater(), transaction, false, Bytes.EMPTY, List.of(), 0, 0L); + worldState.updater(), + transaction, + false, + Bytes.EMPTY, + List.of(), + 0, + EMPTY_ADDRESS_SET, + 0L); LOG.error("Critical Exception Processing Transaction", re); return TransactionProcessingResult.invalid( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java index 77466587314..d541cbd99aa 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; @@ -216,6 +217,7 @@ public void traceEndTransaction( final Bytes output, final List logs, final long gasUsed, + final Set
selfDestructs, final long timeNs) { this.traceEndTxCalled = true; } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java index 6e48aaf82ca..ccabce833a6 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java @@ -69,6 +69,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; +import java.util.Set; import java.util.Spliterator; import java.util.Spliterators; import java.util.concurrent.TimeUnit; @@ -86,6 +87,8 @@ public class T8nExecutor { + private static final Set
EMPTY_ADDRESS_SET = Set.of(); + public record RejectedTransaction(int index, String error) {} protected static List extractTransactions( @@ -349,6 +352,7 @@ static T8nResult runTest( result.getOutput(), result.getLogs(), gasUsed - intrinsicGas, + EMPTY_ADDRESS_SET, timer.elapsed(TimeUnit.NANOSECONDS)); Bytes gasUsedInTransaction = Bytes.ofUnsignedLong(transactionGasUsed); receipts.add(receipt); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java b/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java index 5bd6de591e5..34e28bbb32f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/tracing/OperationTracer.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.evm.tracing; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; import org.hyperledger.besu.evm.frame.MessageFrame; @@ -23,6 +24,7 @@ import java.util.List; import java.util.Optional; +import java.util.Set; import org.apache.tuweni.bytes.Bytes; @@ -92,6 +94,7 @@ default void traceStartTransaction(final WorldView worldView, final Transaction * @param output the bytes output from the transaction * @param logs the logs emitted by this transaction * @param gasUsed the gas used by the entire transaction + * @param selfDestructs the set of addresses that self-destructed during the transaction * @param timeNs the time in nanoseconds it took to execute the transaction */ default void traceEndTransaction( @@ -101,6 +104,7 @@ default void traceEndTransaction( final Bytes output, final List logs, final long gasUsed, + final Set
selfDestructs, final long timeNs) {} /** From b1ac5acd6067c32a85ed78c50c67da8042087c86 Mon Sep 17 00:00:00 2001 From: Matt Whitehead Date: Tue, 11 Jun 2024 11:46:36 +0100 Subject: [PATCH 36/42] Add new acceptance test to soak test BFT chains (#7023) * Add new acceptance test to soak test BFT chains Signed-off-by: Matthew Whitehead * Spotless Signed-off-by: Matthew Whitehead * Tidy up a little with re-usable start and stop functions with built in delays Signed-off-by: Matthew Whitehead * Add shanghai version of Simple Storage contract Signed-off-by: Matthew Whitehead * Put commented gradle code back in. Fix the web3j example commands in .sol files Signed-off-by: Matthew Whitehead * Spotless Signed-off-by: Matthew Whitehead * Set publication artifacts to avoid clash Signed-off-by: Matthew Whitehead * Exclude from regular acceptance tests Signed-off-by: Matthew Whitehead * Add shanghai fork to the test. Stall the chain for less time to reduce the time taken to mine new blocks Signed-off-by: Matthew Whitehead * Tidy up Signed-off-by: Matthew Whitehead * Update acceptance-tests/tests/shanghai/build.gradle Co-authored-by: Simon Dudley Signed-off-by: Matt Whitehead * Tidy up var names Signed-off-by: Matthew Whitehead * Fix ports for IBFT2 as well as QBFT Signed-off-by: Matthew Whitehead * Remove maven publish spec, disable jar building for shanghai contract project Signed-off-by: Matthew Whitehead * web3j version Signed-off-by: Matthew Whitehead * Make fixed port optional when creating a BFT node Signed-off-by: Matthew Whitehead * Only check artifact coordinates for those starting 'org.*' Signed-off-by: Matthew Whitehead --------- Signed-off-by: Matthew Whitehead Signed-off-by: Matt Whitehead Signed-off-by: Matt Whitehead Co-authored-by: Simon Dudley Co-authored-by: Sally MacFarlane --- .../node/configuration/BesuNodeFactory.java | 49 ++- acceptance-tests/tests/build.gradle | 32 ++ .../tests/contracts/CrossContractReader.sol | 2 +- .../tests/contracts/EventEmitter.sol | 2 +- .../tests/contracts/RemoteSimpleStorage.sol | 2 +- .../tests/contracts/RevertReason.sol | 2 +- .../tests/contracts/SimpleStorage.sol | 2 +- acceptance-tests/tests/shanghai/build.gradle | 21 ++ .../SimpleStorageShanghai.sol | 31 ++ .../BftAcceptanceTestParameterization.java | 15 +- .../acceptance/bftsoak/BftMiningSoakTest.java | 351 ++++++++++++++++++ build.gradle | 2 +- settings.gradle | 1 + 13 files changed, 494 insertions(+), 18 deletions(-) create mode 100644 acceptance-tests/tests/shanghai/build.gradle create mode 100644 acceptance-tests/tests/shanghai/shanghaicontracts/SimpleStorageShanghai.sol create mode 100644 acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index 6ed5ee55f33..96ab9cf6235 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -461,16 +461,30 @@ public BesuNode createIbft2Node(final String name, final String genesisFile) thr .build()); } - public BesuNode createIbft2Node(final String name) throws IOException { - return create( + public BesuNode createIbft2Node(final String name, final boolean fixedPort) throws IOException { + JsonRpcConfiguration rpcConfig = node.createJsonRpcWithIbft2EnabledConfig(false); + rpcConfig.addRpcApi("ADMIN,TXPOOL"); + if (fixedPort) { + rpcConfig.setPort( + Math.abs(name.hashCode() % 60000) + + 1024); // Generate a consistent port for p2p based on node name + } + BesuNodeConfigurationBuilder builder = new BesuNodeConfigurationBuilder() .name(name) .miningEnabled() - .jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig(false)) + .jsonRpcConfiguration(rpcConfig) .webSocketConfiguration(node.createWebSocketEnabledConfig()) .devMode(false) - .genesisConfigProvider(GenesisConfigurationFactory::createIbft2GenesisConfig) - .build()); + .genesisConfigProvider(GenesisConfigurationFactory::createIbft2GenesisConfig); + if (fixedPort) { + builder.p2pPort( + Math.abs(name.hashCode() % 60000) + + 1024 + + 500); // Generate a consistent port for p2p based on node name (+ 500 to avoid + // clashing with RPC port or other nodes with a similar name) + } + return create(builder.build()); } public BesuNode createQbftNodeWithTLS(final String name, final String type) throws IOException { @@ -498,16 +512,31 @@ public BesuNode createQbftNodeWithTLSPKCS11(final String name) throws IOExceptio return createQbftNodeWithTLS(name, KeyStoreWrapper.KEYSTORE_TYPE_PKCS11); } - public BesuNode createQbftNode(final String name) throws IOException { - return create( + public BesuNode createQbftNode(final String name, final boolean fixedPort) throws IOException { + JsonRpcConfiguration rpcConfig = node.createJsonRpcWithQbftEnabledConfig(false); + rpcConfig.addRpcApi("ADMIN,TXPOOL"); + if (fixedPort) { + rpcConfig.setPort( + Math.abs(name.hashCode() % 60000) + + 1024); // Generate a consistent port for p2p based on node name + } + + BesuNodeConfigurationBuilder builder = new BesuNodeConfigurationBuilder() .name(name) .miningEnabled() - .jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false)) + .jsonRpcConfiguration(rpcConfig) .webSocketConfiguration(node.createWebSocketEnabledConfig()) .devMode(false) - .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig) - .build()); + .genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig); + if (fixedPort) { + builder.p2pPort( + Math.abs(name.hashCode() % 60000) + + 1024 + + 500); // Generate a consistent port for p2p based on node name (+ 500 to avoid + // clashing with RPC port or other nodes with a similar name) + } + return create(builder.build()); } public BesuNode createCustomGenesisNode( diff --git a/acceptance-tests/tests/build.gradle b/acceptance-tests/tests/build.gradle index a9393b1ccf1..1bc0e55567f 100644 --- a/acceptance-tests/tests/build.gradle +++ b/acceptance-tests/tests/build.gradle @@ -24,6 +24,7 @@ solidity { resolvePackages = false // TODO: remove the forced version, when DEV network is upgraded to support latest forks version '0.8.19' + evmVersion 'london' } dependencies { @@ -79,6 +80,7 @@ dependencies { testImplementation 'org.web3j:besu' testImplementation 'org.web3j:core' testImplementation 'org.wiremock:wiremock' + testImplementation project(path: ':acceptance-tests:tests:shanghai') testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' } @@ -153,6 +155,7 @@ task acceptanceTestMainnet(type: Test) { task acceptanceTestNotPrivacy(type: Test) { inputs.property "integration.date", LocalTime.now() // so it runs at every invocation exclude '**/privacy/**' + exclude '**/bftsoak/**' useJUnitPlatform {} @@ -205,6 +208,35 @@ task acceptanceTestCliqueBft(type: Test) { doFirst { mkdir "${buildDir}/jvmErrorLogs" } } +task acceptanceTestBftSoak(type: Test) { + inputs.property "integration.date", LocalTime.now() // so it runs at every invocation + include '**/bftsoak/**' + + useJUnitPlatform {} + + dependsOn(rootProject.installDist) + setSystemProperties(test.getSystemProperties()) + systemProperty 'acctests.runBesuAsProcess', 'true' + // Set to any time > 60 minutes to run the soak test for longer + // systemProperty 'acctests.soakTimeMins', '120' + systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security" + mustRunAfter rootProject.subprojects*.test + description = 'Runs BFT soak test.' + group = 'verification' + + jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log" + + testLogging { + exceptionFormat = 'full' + showStackTraces = true + showStandardStreams = true + showExceptions = true + showCauses = true + } + + doFirst { mkdir "${buildDir}/jvmErrorLogs" } +} + task acceptanceTestPrivacy(type: Test) { inputs.property "integration.date", LocalTime.now() // so it runs at every invocation include '**/privacy/**' diff --git a/acceptance-tests/tests/contracts/CrossContractReader.sol b/acceptance-tests/tests/contracts/CrossContractReader.sol index f43ce8b621e..9524d5bde86 100644 --- a/acceptance-tests/tests/contracts/CrossContractReader.sol +++ b/acceptance-tests/tests/contracts/CrossContractReader.sol @@ -19,7 +19,7 @@ import "./EventEmitter.sol"; // compile with: // solc CrossContractReader.sol --bin --abi --optimize --overwrite -o . // then create web3j wrappers with: -// web3j solidity generate -b ./generated/CrossContractReader.bin -a ./generated/CrossContractReader.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated +// web3j generate solidity -b ./generated/CrossContractReader.bin -a ./generated/CrossContractReader.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated contract CrossContractReader { uint counter; diff --git a/acceptance-tests/tests/contracts/EventEmitter.sol b/acceptance-tests/tests/contracts/EventEmitter.sol index 2e6e29e59d6..05b8868eee9 100644 --- a/acceptance-tests/tests/contracts/EventEmitter.sol +++ b/acceptance-tests/tests/contracts/EventEmitter.sol @@ -17,7 +17,7 @@ pragma solidity >=0.7.0 <0.9.0; // compile with: // solc EventEmitter.sol --bin --abi --optimize --overwrite -o . // then create web3j wrappers with: -// web3j solidity generate -b ./generated/EventEmitter.bin -a ./generated/EventEmitter.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated +// web3j generate solidity -b ./generated/EventEmitter.bin -a ./generated/EventEmitter.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated contract EventEmitter { address owner; event stored(address _to, uint _amount); diff --git a/acceptance-tests/tests/contracts/RemoteSimpleStorage.sol b/acceptance-tests/tests/contracts/RemoteSimpleStorage.sol index 03c95dc2bd1..f399658789f 100644 --- a/acceptance-tests/tests/contracts/RemoteSimpleStorage.sol +++ b/acceptance-tests/tests/contracts/RemoteSimpleStorage.sol @@ -19,7 +19,7 @@ import "./SimpleStorage.sol"; // compile with: // solc RemoteSimpleStorage.sol --bin --abi --optimize --overwrite -o . // then create web3j wrappers with: -// web3j solidity generate -b ./generated/RemoteSimpleStorage.bin -a ./generated/RemoteSimpleStorage.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated +// web3j generate solidity -b ./generated/RemoteSimpleStorage.bin -a ./generated/RemoteSimpleStorage.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated contract RemoteSimpleStorage { SimpleStorage public simpleStorage; diff --git a/acceptance-tests/tests/contracts/RevertReason.sol b/acceptance-tests/tests/contracts/RevertReason.sol index b1270fe4ccd..2d42cafe3c2 100644 --- a/acceptance-tests/tests/contracts/RevertReason.sol +++ b/acceptance-tests/tests/contracts/RevertReason.sol @@ -17,7 +17,7 @@ pragma solidity >=0.7.0 <0.9.0; // compile with: // solc RevertReason.sol --bin --abi --optimize --overwrite -o . // then create web3j wrappers with: -// web3j solidity generate -b ./generated/RevertReason.bin -a ./generated/RevertReason.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated +// web3j generate solidity -b ./generated/RevertReason.bin -a ./generated/RevertReason.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated contract RevertReason { function revertWithRevertReason() public pure returns (bool) { diff --git a/acceptance-tests/tests/contracts/SimpleStorage.sol b/acceptance-tests/tests/contracts/SimpleStorage.sol index 9303def9e05..712e2a87456 100644 --- a/acceptance-tests/tests/contracts/SimpleStorage.sol +++ b/acceptance-tests/tests/contracts/SimpleStorage.sol @@ -17,7 +17,7 @@ pragma solidity >=0.7.0 <0.8.20; // compile with: // solc SimpleStorage.sol --bin --abi --optimize --overwrite -o . // then create web3j wrappers with: -// web3j solidity generate -b ./generated/SimpleStorage.bin -a ./generated/SimpleStorage.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated +// web3j generate solidity -b ./generated/SimpleStorage.bin -a ./generated/SimpleStorage.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated contract SimpleStorage { uint data; diff --git a/acceptance-tests/tests/shanghai/build.gradle b/acceptance-tests/tests/shanghai/build.gradle new file mode 100644 index 00000000000..c309d9e9914 --- /dev/null +++ b/acceptance-tests/tests/shanghai/build.gradle @@ -0,0 +1,21 @@ + +plugins { + id 'org.web3j' version '4.11.3' + id 'org.web3j.solidity' version '0.4.1' +} + +jar { enabled = true } + +web3j { + generatedPackageName = 'org.hyperledger.besu.tests.web3j.generated' +} + +sourceSets.main.solidity.srcDirs = [ + "$projectDir/shanghaicontracts" +] + +solidity { + resolvePackages = false + version '0.8.25' + evmVersion 'shanghai' +} diff --git a/acceptance-tests/tests/shanghai/shanghaicontracts/SimpleStorageShanghai.sol b/acceptance-tests/tests/shanghai/shanghaicontracts/SimpleStorageShanghai.sol new file mode 100644 index 00000000000..32a7d9a2a09 --- /dev/null +++ b/acceptance-tests/tests/shanghai/shanghaicontracts/SimpleStorageShanghai.sol @@ -0,0 +1,31 @@ +/* + * 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 + */ +pragma solidity >=0.8.20; + +// compile with: +// solc SimpleStorageShanghai.sol --bin --abi --optimize --overwrite -o . +// then create web3j wrappers with: +// web3j generate solidity -b ./SimpleStorageShanghai.bin -a ./SimpleStorageShanghai.abi -o ../../../../../ -p org.hyperledger.besu.tests.web3j.generated +contract SimpleStorageShanghai { + uint data; + + function set(uint value) public { + data = value; + } + + function get() public view returns (uint) { + return data; + } +} diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java index c9fcf364840..15872070d00 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bft/BftAcceptanceTestParameterization.java @@ -38,7 +38,14 @@ public static Stream getFactories() { @FunctionalInterface public interface NodeCreator { - BesuNode create(BesuNodeFactory factory, String name) throws Exception; + BesuNode create(BesuNodeFactory factory, String name, boolean fixedPort) throws Exception; + } + + @FunctionalInterface + public interface FixedPortNodeCreator { + + BesuNode createFixedPort(BesuNodeFactory factory, String name, boolean fixedPort) + throws Exception; } @FunctionalInterface @@ -57,7 +64,11 @@ public BftAcceptanceTestParameterization( } public BesuNode createNode(BesuNodeFactory factory, String name) throws Exception { - return creatorFn.create(factory, name); + return creatorFn.create(factory, name, false); + } + + public BesuNode createNodeFixedPort(BesuNodeFactory factory, String name) throws Exception { + return creatorFn.create(factory, name, true); } public BesuNode createNodeWithValidators( diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java new file mode 100644 index 00000000000..9861a7dab65 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bftsoak/BftMiningSoakTest.java @@ -0,0 +1,351 @@ +/* + * 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.tests.acceptance.bftsoak; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.config.JsonUtil; +import org.hyperledger.besu.tests.acceptance.bft.BftAcceptanceTestParameterization; +import org.hyperledger.besu.tests.acceptance.bft.ParameterizedBftTestBase; +import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode; +import org.hyperledger.besu.tests.web3j.generated.SimpleStorage; +import org.hyperledger.besu.tests.web3j.generated.SimpleStorageShanghai; + +import java.math.BigInteger; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class BftMiningSoakTest extends ParameterizedBftTestBase { + + private final int NUM_STEPS = 5; + + private final int MIN_TEST_TIME_MINS = 60; + + private static final long ONE_MINUTE = Duration.of(1, ChronoUnit.MINUTES).toMillis(); + + private static final long THREE_MINUTES = Duration.of(1, ChronoUnit.MINUTES).toMillis(); + + private static final long TEN_SECONDS = Duration.of(10, ChronoUnit.SECONDS).toMillis(); + + static int getTestDurationMins() { + // Use a default soak time of 60 mins + return Integer.getInteger("acctests.soakTimeMins", 60); + } + + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("factoryFunctions") + public void shouldBeStableDuringLongTest( + final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception { + setUp(testName, nodeFactory); + + // There is a minimum amount of time the test can be run for, due to hard coded delays + // in between certain steps. There should be no upper-limit to how long the test is run for + assertThat(getTestDurationMins()).isGreaterThanOrEqualTo(MIN_TEST_TIME_MINS); + + final BesuNode minerNode1 = nodeFactory.createNodeFixedPort(besu, "miner1"); + final BesuNode minerNode2 = nodeFactory.createNodeFixedPort(besu, "miner2"); + final BesuNode minerNode3 = nodeFactory.createNodeFixedPort(besu, "miner3"); + final BesuNode minerNode4 = nodeFactory.createNodeFixedPort(besu, "miner4"); + + // Each step should be given a minimum of 3 minutes to complete successfully. If the time + // give to run the soak test results in a time-per-step lower than this then the time + // needs to be increased. + assertThat(getTestDurationMins() / NUM_STEPS).isGreaterThanOrEqualTo(3); + + cluster.start(minerNode1, minerNode2, minerNode3, minerNode4); + + cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85)); + + // Setup + // Deploy a contract that we'll invoke periodically to ensure state + // is correct during the test, especially after stopping nodes and + // applying new forks. + SimpleStorage simpleStorageContract = + minerNode1.execute(contractTransactions.createSmartContract(SimpleStorage.class)); + + // Check the contract address is as expected for this sender & nonce + contractVerifier + .validTransactionReceipt("0x42699a7612a82f1d9c36148af9c77354759b210b") + .verify(simpleStorageContract); + + // Before upgrading to newer forks, try creating a shanghai-evm contract and check that + // the transaction fails + try { + minerNode1.execute(contractTransactions.createSmartContract(SimpleStorageShanghai.class)); + Assertions.fail("Shanghai transaction should not be executed on a pre-shanghai chain"); + } catch (RuntimeException e) { + assertThat(e.getMessage()) + .contains( + "Revert reason: 'Transaction processing could not be completed due to an exception'"); + } + + // Should initially be set to 0 + assertThat(simpleStorageContract.get().send()).isEqualTo(BigInteger.valueOf(0)); + + // Set to something new + simpleStorageContract.set(BigInteger.valueOf(101)).send(); + + // Check the state of the contract has updated correctly. We'll set & get this several times + // during the test + assertThat(simpleStorageContract.get().send()).isEqualTo(BigInteger.valueOf(101)); + + // Step 1 + // Run for the configured time period, periodically checking that + // the chain is progressing as expected + BigInteger chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + assertThat(chainHeight.compareTo(BigInteger.ZERO)).isGreaterThanOrEqualTo(1); + BigInteger lastChainHeight = chainHeight; + + Instant startTime = Instant.now(); + Instant nextStepEndTime = startTime.plus(getTestDurationMins() / NUM_STEPS, ChronoUnit.MINUTES); + + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + Thread.sleep(ONE_MINUTE); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // With 1-second block period chain height should have moved on by at least 50 blocks + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(50)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } + Instant previousStepEndTime = Instant.now(); + + // Step 2 + // Stop one of the nodes, check that the chain continues mining + // blocks + stopNode(minerNode4); + + nextStepEndTime = + previousStepEndTime.plus(getTestDurationMins() / NUM_STEPS, ChronoUnit.MINUTES); + + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + Thread.sleep(ONE_MINUTE); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should have moved on by at least 5 blocks + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(20)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } + previousStepEndTime = Instant.now(); + + // Step 3 + // Stop another one of the nodes, check that the chain now stops + // mining blocks + stopNode(minerNode3); + + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + lastChainHeight = chainHeight; + + // Leave the chain stalled for 3 minutes. Check no new blocks are mined. Then + // resume the other validators. + nextStepEndTime = previousStepEndTime.plus(3, ChronoUnit.MINUTES); + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + Thread.sleep(ONE_MINUTE); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should not have moved on + assertThat(chainHeight.equals(lastChainHeight)).isTrue(); + } + + // Step 4 + // Restart both of the stopped nodes. Check that the chain resumes + // mining blocks + startNode(minerNode3); + + startNode(minerNode4); + + previousStepEndTime = Instant.now(); + + // This step gives the stalled chain time to re-sync and agree on the next BFT round + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + nextStepEndTime = + previousStepEndTime.plus((getTestDurationMins() / NUM_STEPS), ChronoUnit.MINUTES); + lastChainHeight = chainHeight; + + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + Thread.sleep(ONE_MINUTE); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + lastChainHeight = chainHeight; + } + previousStepEndTime = Instant.now(); + + // By this loop it should be producing blocks again + nextStepEndTime = + previousStepEndTime.plus(getTestDurationMins() / NUM_STEPS, ChronoUnit.MINUTES); + + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + Thread.sleep(ONE_MINUTE); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should have moved on by at least 1 block + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(1)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } + + // Update our smart contract before upgrading from berlin to london + assertThat(simpleStorageContract.get().send()).isEqualTo(BigInteger.valueOf(101)); + simpleStorageContract.set(BigInteger.valueOf(201)).send(); + assertThat(simpleStorageContract.get().send()).isEqualTo(BigInteger.valueOf(201)); + + // Upgrade the chain from berlin to london in 120 blocks time + upgradeToLondon( + minerNode1, minerNode2, minerNode3, minerNode4, lastChainHeight.intValue() + 120); + + previousStepEndTime = Instant.now(); + + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + nextStepEndTime = + previousStepEndTime.plus(getTestDurationMins() / NUM_STEPS, ChronoUnit.MINUTES); + lastChainHeight = chainHeight; + + while (System.currentTimeMillis() < nextStepEndTime.toEpochMilli()) { + Thread.sleep(ONE_MINUTE); + chainHeight = minerNode1.execute(ethTransactions.blockNumber()); + + // Chain height should have moved on by at least 50 blocks + assertThat(chainHeight.compareTo(lastChainHeight.add(BigInteger.valueOf(50)))) + .isGreaterThanOrEqualTo(1); + lastChainHeight = chainHeight; + } + + // Check that the state of our smart contract is still correct + assertThat(simpleStorageContract.get().send()).isEqualTo(BigInteger.valueOf(201)); + + // Update it once more to check new transactions are mined OK + simpleStorageContract.set(BigInteger.valueOf(301)).send(); + assertThat(simpleStorageContract.get().send()).isEqualTo(BigInteger.valueOf(301)); + + // Upgrade the chain to shanghai in 120 seconds. Then try to deploy a shanghai contract + upgradeToShanghai( + minerNode1, minerNode2, minerNode3, minerNode4, Instant.now().getEpochSecond() + 120); + + Thread.sleep(THREE_MINUTES); + + SimpleStorageShanghai simpleStorageContractShanghai = + minerNode1.execute(contractTransactions.createSmartContract(SimpleStorageShanghai.class)); + + // Check the contract address is as expected for this sender & nonce + contractVerifier + .validTransactionReceipt("0x05d91b9031a655d08e654177336d08543ac4b711") + .verify(simpleStorageContractShanghai); + } + + private static void updateGenesisConfigToLondon( + final BesuNode minerNode, final boolean zeroBaseFeeEnabled, final int blockNumber) { + + if (minerNode.getGenesisConfig().isPresent()) { + final ObjectNode genesisConfigNode = + JsonUtil.objectNodeFromString(minerNode.getGenesisConfig().get()); + final ObjectNode config = (ObjectNode) genesisConfigNode.get("config"); + config.put("londonBlock", blockNumber); + config.put("zeroBaseFee", zeroBaseFeeEnabled); + minerNode.setGenesisConfig(genesisConfigNode.toString()); + } + } + + private static void updateGenesisConfigToShanghai( + final BesuNode minerNode, final long blockTimestamp) { + + if (minerNode.getGenesisConfig().isPresent()) { + final ObjectNode genesisConfigNode = + JsonUtil.objectNodeFromString(minerNode.getGenesisConfig().get()); + final ObjectNode config = (ObjectNode) genesisConfigNode.get("config"); + config.put("shanghaiTime", blockTimestamp); + minerNode.setGenesisConfig(genesisConfigNode.toString()); + } + } + + private void upgradeToLondon( + final BesuNode minerNode1, + final BesuNode minerNode2, + final BesuNode minerNode3, + final BesuNode minerNode4, + final int londonBlockNumber) + throws InterruptedException { + // Node 1 + stopNode(minerNode1); + updateGenesisConfigToLondon(minerNode1, true, londonBlockNumber); + startNode(minerNode1); + + // Node 2 + stopNode(minerNode2); + updateGenesisConfigToLondon(minerNode2, true, londonBlockNumber); + startNode(minerNode2); + + // Node 3 + stopNode(minerNode3); + updateGenesisConfigToLondon(minerNode3, true, londonBlockNumber); + startNode(minerNode3); + + // Node 4 + stopNode(minerNode4); + updateGenesisConfigToLondon(minerNode4, true, londonBlockNumber); + startNode(minerNode4); + } + + private void upgradeToShanghai( + final BesuNode minerNode1, + final BesuNode minerNode2, + final BesuNode minerNode3, + final BesuNode minerNode4, + final long shanghaiTime) + throws InterruptedException { + // Node 1 + stopNode(minerNode1); + updateGenesisConfigToShanghai(minerNode1, shanghaiTime); + startNode(minerNode1); + + // Node 2 + stopNode(minerNode2); + updateGenesisConfigToShanghai(minerNode2, shanghaiTime); + startNode(minerNode2); + + // Node 3 + stopNode(minerNode3); + updateGenesisConfigToShanghai(minerNode3, shanghaiTime); + startNode(minerNode3); + + // Node 4 + stopNode(minerNode4); + updateGenesisConfigToShanghai(minerNode4, shanghaiTime); + startNode(minerNode4); + } + + // Start a node with a delay before returning to give it time to start + private void startNode(final BesuNode node) throws InterruptedException { + cluster.startNode(node); + Thread.sleep(TEN_SECONDS); + } + + // Stop a node with a delay before returning to give it time to stop + private void stopNode(final BesuNode node) throws InterruptedException { + cluster.stopNode(node); + Thread.sleep(TEN_SECONDS); + } + + @Override + public void tearDownAcceptanceTestBase() { + cluster.stop(); + super.tearDownAcceptanceTestBase(); + } +} diff --git a/build.gradle b/build.gradle index 905e8b2c8af..4f34e67985d 100644 --- a/build.gradle +++ b/build.gradle @@ -386,7 +386,7 @@ task checkMavenCoordinateCollisions { getAllprojects().forEach { if (it.properties.containsKey('publishing') && it.jar?.enabled) { def coordinate = it.publishing?.publications[0].coordinates - if (coordinates.containsKey(coordinate)) { + if (coordinate.toString().startsWith("org") && coordinates.containsKey(coordinate)) { throw new GradleException("Duplicate maven coordinates detected, ${coordinate} is used by " + "both ${coordinates[coordinate]} and ${it.path}.\n" + "Please add a `publishing` script block to one or both subprojects.") diff --git a/settings.gradle b/settings.gradle index 81f4cb8736b..09a8d20d4c6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,6 +28,7 @@ rootProject.name='besu' include 'acceptance-tests:test-plugins' include 'acceptance-tests:dsl' include 'acceptance-tests:tests' +include 'acceptance-tests:tests:shanghai' include 'besu' include 'config' include 'consensus:clique' From c62f192459626a602b90a4959eab047b326c1b4a Mon Sep 17 00:00:00 2001 From: Fabio Di Fabio Date: Tue, 11 Jun 2024 15:28:30 +0200 Subject: [PATCH 37/42] Improve genesis state performance at startup (#6977) * Refactor genesis options file management Signed-off-by: Fabio Di Fabio * Make loading allocation from genesis lazy Signed-off-by: Fabio Di Fabio * Update tests Signed-off-by: Fabio Di Fabio * Memory optimization with streaming Signed-off-by: Fabio Di Fabio * Improve loading and storgin genesis state at startup Signed-off-by: Fabio Di Fabio * Remove comments Signed-off-by: Fabio Di Fabio * Avoid parsing genesis file allocations twice Signed-off-by: Fabio Di Fabio * Update javadoc Signed-off-by: Fabio Di Fabio * Fix Signed-off-by: Fabio Di Fabio * Fix Signed-off-by: Fabio Di Fabio * Ignore unknown objects in allocations Signed-off-by: Fabio Di Fabio * avoid keeping genesis allocation data in memory Signed-off-by: Fabio Di Fabio * Update CHANGELOG Signed-off-by: Fabio Di Fabio --------- Signed-off-by: Fabio Di Fabio Signed-off-by: ahamlat Co-authored-by: ahamlat --- CHANGELOG.md | 1 + .../controller/BesuControllerBuilder.java | 50 ++-- .../besu/ForkIdsNetworkConfigTest.java | 3 +- .../besu/config/GenesisAccount.java | 42 +++ .../besu/config/GenesisAllocation.java | 109 -------- .../besu/config/GenesisConfigFile.java | 51 ++-- .../besu/config/GenesisReader.java | 242 ++++++++++++++++++ .../org/hyperledger/besu/config/JsonUtil.java | 148 ++++++++++- .../besu/config/GenesisConfigFileTest.java | 59 +++-- .../besu/config/GenesisReaderTest.java | 98 +++++++ .../hyperledger/besu/config/JsonUtilTest.java | 23 +- .../MergeGenesisConfigHelper.java | 7 +- .../besu/ethereum/chain/GenesisState.java | 156 +++-------- .../besu/ethereum/chain/GenesisStateTest.java | 64 ++--- .../bonsai/AbstractIsolationTests.java | 15 +- .../bonsai/BonsaiSnapshotIsolationTests.java | 2 +- 16 files changed, 713 insertions(+), 357 deletions(-) create mode 100644 config/src/main/java/org/hyperledger/besu/config/GenesisAccount.java delete mode 100644 config/src/main/java/org/hyperledger/besu/config/GenesisAllocation.java create mode 100644 config/src/main/java/org/hyperledger/besu/config/GenesisReader.java create mode 100644 config/src/test/java/org/hyperledger/besu/config/GenesisReaderTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b64946ae01..435ecea9e35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### Additions and Improvements - Add two counters to DefaultBlockchain in order to be able to calculate TPS and Mgas/s [#7105](https://github.com/hyperledger/besu/pull/7105) +- Improve genesis state performance at startup [#6977](https://github.com/hyperledger/besu/pull/6977) - Enable --Xbonsai-limit-trie-logs-enabled by default, unless sync-mode=FULL [#7181](https://github.com/hyperledger/besu/pull/7181) - Promote experimental --Xbonsai-limit-trie-logs-enabled to production-ready, --bonsai-limit-trie-logs-enabled [#7192](https://github.com/hyperledger/besu/pull/7192) - Promote experimental --Xbonsai-trie-logs-pruning-window-size to production-ready, --bonsai-trie-logs-pruning-window-size [#7192](https://github.com/hyperledger/besu/pull/7192) diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 4e3929e8ae5..aab0000592f 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -41,6 +41,7 @@ import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.VariablesStorage; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters; @@ -552,30 +553,9 @@ public BesuController build() { prepForBuild(); final ProtocolSchedule protocolSchedule = createProtocolSchedule(); - final GenesisState genesisState; final VariablesStorage variablesStorage = storageProvider.createVariablesStorage(); - Optional genesisStateHash = Optional.empty(); - if (variablesStorage != null && this.genesisStateHashCacheEnabled) { - genesisStateHash = variablesStorage.getGenesisStateHash(); - } - - if (genesisStateHash.isPresent()) { - genesisState = - GenesisState.fromConfig(genesisStateHash.get(), genesisConfigFile, protocolSchedule); - } else { - genesisState = - GenesisState.fromConfig(dataStorageConfiguration, genesisConfigFile, protocolSchedule); - if (variablesStorage != null) { - VariablesStorage.Updater updater = variablesStorage.updater(); - if (updater != null) { - updater.setGenesisStateHash(genesisState.getBlock().getHeader().getStateRoot()); - updater.commit(); - } - } - } - final WorldStateStorageCoordinator worldStateStorageCoordinator = storageProvider.createWorldStateStorageCoordinator(dataStorageConfiguration); @@ -583,6 +563,13 @@ public BesuController build() { storageProvider.createBlockchainStorage( protocolSchedule, variablesStorage, dataStorageConfiguration); + final var maybeStoredGenesisBlockHash = blockchainStorage.getBlockHash(0L); + + final var genesisState = + getGenesisState( + maybeStoredGenesisBlockHash.flatMap(blockchainStorage::getBlockHeader), + protocolSchedule); + final MutableBlockchain blockchain = DefaultBlockchain.createMutable( genesisState.getBlock(), @@ -591,7 +578,6 @@ public BesuController build() { reorgLoggingThreshold, dataDirectory.toString(), numberOfBlocksToCache); - final BonsaiCachedMerkleTrieLoader bonsaiCachedMerkleTrieLoader = besuComponent .map(BesuComponent::getCachedMerkleTrieLoader) @@ -601,7 +587,7 @@ public BesuController build() { createWorldStateArchive( worldStateStorageCoordinator, blockchain, bonsaiCachedMerkleTrieLoader); - if (blockchain.getChainHeadBlockNumber() < 1) { + if (maybeStoredGenesisBlockHash.isEmpty()) { genesisState.writeStateTo(worldStateArchive.getMutable()); } @@ -772,6 +758,24 @@ public BesuController build() { dataStorageConfiguration); } + private GenesisState getGenesisState( + final Optional maybeGenesisBlockHeader, + final ProtocolSchedule protocolSchedule) { + final Optional maybeGenesisStateRoot = + genesisStateHashCacheEnabled + ? maybeGenesisBlockHeader.map(BlockHeader::getStateRoot) + : Optional.empty(); + + return maybeGenesisStateRoot + .map( + genesisStateRoot -> + GenesisState.fromStorage(genesisStateRoot, genesisConfigFile, protocolSchedule)) + .orElseGet( + () -> + GenesisState.fromConfig( + dataStorageConfiguration, genesisConfigFile, protocolSchedule)); + } + private TrieLogPruner createTrieLogPruner( final WorldStateKeyValueStorage worldStateStorage, final Blockchain blockchain, diff --git a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java index 7d7c6391ff8..ae338f27cac 100644 --- a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java +++ b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java @@ -18,7 +18,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; @@ -138,7 +137,7 @@ public static Collection parameters() { @MethodSource("parameters") public void testForkId(final NetworkName chainName, final List expectedForkIds) { final GenesisConfigFile genesisConfigFile = - GenesisConfigFile.fromConfig(EthNetworkConfig.jsonConfig(chainName)); + GenesisConfigFile.fromResource(chainName.getGenesisFile()); final MilestoneStreamingTransitionProtocolSchedule schedule = createSchedule(genesisConfigFile); final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, schedule); final Blockchain mockBlockchain = mock(Blockchain.class); diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisAccount.java b/config/src/main/java/org/hyperledger/besu/config/GenesisAccount.java new file mode 100644 index 00000000000..70bb80e0422 --- /dev/null +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisAccount.java @@ -0,0 +1,42 @@ +/* + * 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.config; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; + +import java.util.Map; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt256; + +/** + * Genesis account + * + * @param address of the account + * @param nonce nonce of the account at genesis + * @param balance balance of the account at genesis + * @param code code of the account at genesis, can be null + * @param storage storage of the account at genesis + * @param privateKey of the account, only use for testing + */ +public record GenesisAccount( + Address address, + long nonce, + Wei balance, + Bytes code, + Map storage, + Bytes32 privateKey) {} diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisAllocation.java b/config/src/main/java/org/hyperledger/besu/config/GenesisAllocation.java deleted file mode 100644 index c53ded9e865..00000000000 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisAllocation.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.config; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import com.fasterxml.jackson.databind.node.ObjectNode; - -/** The Genesis allocation configuration. */ -public class GenesisAllocation { - private final String address; - private final ObjectNode data; - - /** - * Instantiates a new Genesis allocation. - * - * @param address the address - * @param data the data - */ - GenesisAllocation(final String address, final ObjectNode data) { - this.address = address; - this.data = data; - } - - /** - * Gets address. - * - * @return the address - */ - public String getAddress() { - return address; - } - - /** - * Gets private key. - * - * @return the private key - */ - public Optional getPrivateKey() { - return Optional.ofNullable(JsonUtil.getString(data, "privatekey", null)); - } - - /** - * Gets balance. - * - * @return the balance - */ - public String getBalance() { - return JsonUtil.getValueAsString(data, "balance", "0"); - } - - /** - * Gets code. - * - * @return the code - */ - public String getCode() { - return JsonUtil.getString(data, "code", null); - } - - /** - * Gets nonce. - * - * @return the nonce - */ - public String getNonce() { - return JsonUtil.getValueAsString(data, "nonce", "0"); - } - - /** - * Gets version. - * - * @return the version - */ - public String getVersion() { - return JsonUtil.getValueAsString(data, "version", null); - } - - /** - * Gets storage map. - * - * @return fields under storage as a map - */ - public Map getStorage() { - final Map map = new HashMap<>(); - JsonUtil.getObjectNode(data, "storage") - .orElse(JsonUtil.createEmptyObjectNode()) - .fields() - .forEachRemaining( - (entry) -> { - map.put(entry.getKey(), entry.getValue().asText()); - }); - return map; - } -} diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java index cf5a13d8558..bd1e117773b 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java @@ -14,8 +14,6 @@ */ package org.hyperledger.besu.config; -import static org.hyperledger.besu.config.JsonUtil.normalizeKeys; - import org.hyperledger.besu.datatypes.Wei; import java.net.URL; @@ -30,22 +28,23 @@ import java.util.stream.Stream; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.collect.Streams; /** The Genesis config file. */ public class GenesisConfigFile { /** The constant DEFAULT. */ public static final GenesisConfigFile DEFAULT = - new GenesisConfigFile(JsonUtil.createEmptyObjectNode()); + new GenesisConfigFile(new GenesisReader.FromObjectNode(JsonUtil.createEmptyObjectNode())); /** The constant BASEFEE_AT_GENESIS_DEFAULT_VALUE. */ public static final Wei BASEFEE_AT_GENESIS_DEFAULT_VALUE = Wei.of(1_000_000_000L); + private final GenesisReader loader; private final ObjectNode genesisRoot; - private GenesisConfigFile(final ObjectNode config) { - this.genesisRoot = config; + private GenesisConfigFile(final GenesisReader loader) { + this.loader = loader; + this.genesisRoot = loader.getRoot(); } /** @@ -70,21 +69,31 @@ public static GenesisConfigFile fromSource(final URL jsonSource) { /** * Genesis file from resource. * - * @param jsonResource the resource name + * @param resourceName the resource name + * @return the genesis config file + */ + public static GenesisConfigFile fromResource(final String resourceName) { + return fromConfig(GenesisConfigFile.class.getResource(resourceName)); + } + + /** + * From config genesis config file. + * + * @param jsonSource the json string * @return the genesis config file */ - public static GenesisConfigFile fromResource(final String jsonResource) { - return fromSource(GenesisConfigFile.class.getResource(jsonResource)); + public static GenesisConfigFile fromConfig(final URL jsonSource) { + return new GenesisConfigFile(new GenesisReader.FromURL(jsonSource)); } /** * From config genesis config file. * - * @param jsonString the json string + * @param json the json string * @return the genesis config file */ - public static GenesisConfigFile fromConfig(final String jsonString) { - return fromConfig(JsonUtil.objectNodeFromString(jsonString, false)); + public static GenesisConfigFile fromConfig(final String json) { + return fromConfig(JsonUtil.objectNodeFromString(json, false)); } /** @@ -94,7 +103,7 @@ public static GenesisConfigFile fromConfig(final String jsonString) { * @return the genesis config file */ public static GenesisConfigFile fromConfig(final ObjectNode config) { - return new GenesisConfigFile(normalizeKeys(config)); + return new GenesisConfigFile(new GenesisReader.FromObjectNode(config)); } /** @@ -113,8 +122,7 @@ public GenesisConfigOptions getConfigOptions() { * @return the config options */ public GenesisConfigOptions getConfigOptions(final Map overrides) { - final ObjectNode config = - JsonUtil.getObjectNode(genesisRoot, "config").orElse(JsonUtil.createEmptyObjectNode()); + final ObjectNode config = loader.getConfig(); Map overridesRef = overrides; @@ -134,15 +142,8 @@ public GenesisConfigOptions getConfigOptions(final Map overrides * * @return the stream */ - public Stream streamAllocations() { - return JsonUtil.getObjectNode(genesisRoot, "alloc").stream() - .flatMap( - allocations -> - Streams.stream(allocations.fieldNames()) - .map( - key -> - new GenesisAllocation( - key, JsonUtil.getObjectNode(allocations, key).get()))); + public Stream streamAllocations() { + return loader.streamAllocations(); } /** @@ -344,7 +345,7 @@ public String toString() { + "genesisRoot=" + genesisRoot + ", allocations=" - + streamAllocations().map(GenesisAllocation::toString).collect(Collectors.joining(",")) + + loader.streamAllocations().map(GenesisAccount::toString).collect(Collectors.joining(",")) + '}'; } } diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisReader.java b/config/src/main/java/org/hyperledger/besu/config/GenesisReader.java new file mode 100644 index 00000000000..316aa73d043 --- /dev/null +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisReader.java @@ -0,0 +1,242 @@ +/* + * 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.config; + +import static org.hyperledger.besu.config.JsonUtil.normalizeKey; +import static org.hyperledger.besu.config.JsonUtil.normalizeKeys; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; + +import java.io.IOException; +import java.math.BigInteger; +import java.net.URL; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.Streams; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.apache.tuweni.units.bigints.UInt256; + +interface GenesisReader { + String CONFIG_FIELD = "config"; + String ALLOCATION_FIELD = "alloc"; + + ObjectNode getRoot(); + + ObjectNode getConfig(); + + Stream streamAllocations(); + + class FromObjectNode implements GenesisReader { + private final ObjectNode allocations; + private final ObjectNode rootWithoutAllocations; + + public FromObjectNode(final ObjectNode root) { + final var removedAllocations = root.remove(ALLOCATION_FIELD); + this.allocations = + removedAllocations != null + ? (ObjectNode) removedAllocations + : JsonUtil.createEmptyObjectNode(); + this.rootWithoutAllocations = normalizeKeys(root); + } + + @Override + public ObjectNode getRoot() { + return rootWithoutAllocations; + } + + @Override + public ObjectNode getConfig() { + return JsonUtil.getObjectNode(rootWithoutAllocations, CONFIG_FIELD) + .orElse(JsonUtil.createEmptyObjectNode()); + } + + @Override + public Stream streamAllocations() { + return Streams.stream(allocations.fields()) + .map( + entry -> { + final var on = normalizeKeys((ObjectNode) entry.getValue()); + return new GenesisAccount( + Address.fromHexString(entry.getKey()), + JsonUtil.getString(on, "nonce").map(ParserUtils::parseUnsignedLong).orElse(0L), + JsonUtil.getString(on, "balance") + .map(ParserUtils::parseBalance) + .orElse(Wei.ZERO), + JsonUtil.getBytes(on, "code", null), + ParserUtils.getStorageMap(on, "storage"), + JsonUtil.getBytes(on, "privatekey").map(Bytes32::wrap).orElse(null)); + }); + } + } + + class FromURL implements GenesisReader { + private final URL url; + private final ObjectNode rootWithoutAllocations; + + public FromURL(final URL url) { + this.url = url; + this.rootWithoutAllocations = + normalizeKeys(JsonUtil.objectNodeFromURL(url, false, ALLOCATION_FIELD)); + } + + @Override + public ObjectNode getRoot() { + return rootWithoutAllocations; + } + + @Override + public ObjectNode getConfig() { + return JsonUtil.getObjectNode(rootWithoutAllocations, CONFIG_FIELD) + .orElse(JsonUtil.createEmptyObjectNode()); + } + + @Override + public Stream streamAllocations() { + final var parser = JsonUtil.jsonParserFromURL(url, false); + + try { + parser.nextToken(); + while (parser.nextToken() != JsonToken.END_OBJECT) { + if (ALLOCATION_FIELD.equals(parser.getCurrentName())) { + parser.nextToken(); + parser.nextToken(); + break; + } else { + parser.skipChildren(); + } + } + } catch (final IOException e) { + throw new RuntimeException(e); + } + + return Streams.stream(new AllocationIterator(parser)); + } + + private static class AllocationIterator implements Iterator { + final JsonParser parser; + + public AllocationIterator(final JsonParser parser) { + this.parser = parser; + } + + @Override + public boolean hasNext() { + final var end = parser.currentToken() == JsonToken.END_OBJECT; + if (end) { + try { + parser.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return !end; + } + + @Override + public GenesisAccount next() { + try { + final Address address = Address.fromHexString(parser.currentName()); + long nonce = 0; + Wei balance = Wei.ZERO; + Bytes code = null; + Map storage = Map.of(); + Bytes32 privateKey = null; + parser.nextToken(); // consume start object + while (parser.nextToken() != JsonToken.END_OBJECT) { + switch (normalizeKey(parser.currentName())) { + case "nonce": + parser.nextToken(); + nonce = ParserUtils.parseUnsignedLong(parser.getText()); + break; + case "balance": + parser.nextToken(); + balance = ParserUtils.parseBalance(parser.getText()); + break; + case "code": + parser.nextToken(); + code = Bytes.fromHexStringLenient(parser.getText()); + break; + case "privatekey": + parser.nextToken(); + privateKey = Bytes32.fromHexStringLenient(parser.getText()); + break; + case "storage": + parser.nextToken(); + storage = new HashMap<>(); + while (parser.nextToken() != JsonToken.END_OBJECT) { + final var key = UInt256.fromHexString(parser.currentName()); + parser.nextToken(); + final var value = UInt256.fromHexString(parser.getText()); + storage.put(key, value); + } + break; + } + if (parser.currentToken() == JsonToken.START_OBJECT) { + // ignore any unknown nested object + parser.skipChildren(); + } + } + parser.nextToken(); + return new GenesisAccount(address, nonce, balance, code, storage, privateKey); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + + class ParserUtils { + static long parseUnsignedLong(final String value) { + String v = value.toLowerCase(Locale.US); + if (v.startsWith("0x")) { + v = v.substring(2); + } + return Long.parseUnsignedLong(v, 16); + } + + static Wei parseBalance(final String balance) { + final BigInteger val; + if (balance.startsWith("0x")) { + val = new BigInteger(1, Bytes.fromHexStringLenient(balance).toArrayUnsafe()); + } else { + val = new BigInteger(balance); + } + + return Wei.of(val); + } + + static Map getStorageMap(final ObjectNode json, final String key) { + return JsonUtil.getObjectNode(json, key) + .map( + storageMap -> + Streams.stream(storageMap.fields()) + .collect( + Collectors.toMap( + e -> UInt256.fromHexString(e.getKey()), + e -> UInt256.fromHexString(e.getValue().asText())))) + .orElse(Map.of()); + } + } +} diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonUtil.java b/config/src/main/java/org/hyperledger/besu/config/JsonUtil.java index fba62dd9060..bcb89c64edb 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonUtil.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonUtil.java @@ -23,17 +23,30 @@ import java.util.Optional; import java.util.OptionalInt; import java.util.OptionalLong; +import java.util.Set; +import java.util.function.Function; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser.Feature; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.filter.FilteringParserDelegate; +import com.fasterxml.jackson.core.filter.TokenFilter; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeType; import com.fasterxml.jackson.databind.node.ObjectNode; +import org.apache.tuweni.bytes.Bytes; /** The Json util class. */ public class JsonUtil { + private static final JsonFactory JSON_FACTORY = + JsonFactory.builder() + .disable(JsonFactory.Feature.INTERN_FIELD_NAMES) + .disable(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES) + .build(); + /** Default constructor. */ private JsonUtil() {} @@ -53,7 +66,7 @@ public static ObjectNode normalizeKeys(final ObjectNode objectNode) { entry -> { final String key = entry.getKey(); final JsonNode value = entry.getValue(); - final String normalizedKey = key.toLowerCase(Locale.US); + final String normalizedKey = normalizeKey(key); if (value instanceof ObjectNode) { normalized.set(normalizedKey, normalizeKeys((ObjectNode) value)); } else if (value instanceof ArrayNode) { @@ -65,6 +78,17 @@ public static ObjectNode normalizeKeys(final ObjectNode objectNode) { return normalized; } + /** + * Converts the key to lowercase for easier lookup. This is useful in cases such as the + * 'genesis.json' file where all keys are assumed to be case insensitive. + * + * @param key the key to be normalized + * @return key in lower case. + */ + public static String normalizeKey(final String key) { + return key.toLowerCase(Locale.US); + } + private static ArrayNode normalizeKeysInArray(final ArrayNode arrayNode) { final ArrayNode normalizedArray = JsonUtil.createEmptyArrayNode(); arrayNode.forEach( @@ -263,6 +287,35 @@ public static boolean getBoolean( return getBoolean(node, key).orElse(defaultValue); } + /** + * Gets Bytes. + * + * @param json the json + * @param key the key + * @return the Bytes + */ + public static Optional getBytes(final ObjectNode json, final String key) { + return getParsedValue(json, key, Bytes::fromHexString); + } + + /** + * Gets Wei. + * + * @param json the json + * @param key the key + * @param defaultValue the default value + * @return the Wei + */ + public static Bytes getBytes(final ObjectNode json, final String key, final Bytes defaultValue) { + return getBytes(json, key).orElse(defaultValue); + } + + private static Optional getParsedValue( + final ObjectNode json, final String name, final Function parser) { + + return getValue(json, name).map(JsonNode::asText).map(parser); + } + /** * Create empty object node object node. * @@ -308,18 +361,75 @@ public static ObjectNode objectNodeFromString(final String jsonData) { * * @param jsonData the json data * @param allowComments true to allow comments + * @param excludeFields names of the fields to not read * @return the object node */ public static ObjectNode objectNodeFromString( - final String jsonData, final boolean allowComments) { - final ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(Feature.ALLOW_COMMENTS, allowComments); + final String jsonData, final boolean allowComments, final String... excludeFields) { try { - final JsonNode jsonNode = objectMapper.readTree(jsonData); + return objectNodeFromParser( + JSON_FACTORY.createParser(jsonData), allowComments, excludeFields); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Object node from string object node. + * + * @param jsonSource the json data + * @param allowComments true to allow comments + * @param excludeFields names of the fields to not read + * @return the object node + */ + public static ObjectNode objectNodeFromURL( + final URL jsonSource, final boolean allowComments, final String... excludeFields) { + try { + return objectNodeFromParser( + JSON_FACTORY.createParser(jsonSource).enable(Feature.AUTO_CLOSE_SOURCE), + allowComments, + excludeFields); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Get a JsonParser to parse JSON from URL. + * + * @param jsonSource the json source + * @param allowComments true to allow comments + * @return the json parser + */ + public static JsonParser jsonParserFromURL(final URL jsonSource, final boolean allowComments) { + try { + return JSON_FACTORY + .createParser(jsonSource) + .enable(Feature.AUTO_CLOSE_SOURCE) + .configure(Feature.ALLOW_COMMENTS, allowComments); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static ObjectNode objectNodeFromParser( + final JsonParser baseParser, final boolean allowComments, final String... excludeFields) { + try { + final var parser = + excludeFields.length > 0 + ? new FilteringParserDelegate( + baseParser, + new NameExcludeFilter(excludeFields), + TokenFilter.Inclusion.INCLUDE_ALL_AND_PATH, + true) + : baseParser; + parser.configure(Feature.ALLOW_COMMENTS, allowComments); + + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonNode = objectMapper.readTree(parser); validateType(jsonNode, JsonNodeType.OBJECT); return (ObjectNode) jsonNode; } catch (final IOException e) { - // Reading directly from a string should not raise an IOException, just catch and rethrow throw new RuntimeException(e); } } @@ -490,4 +600,30 @@ private static boolean validateInt(final JsonNode node) { } return true; } + + private static class NameExcludeFilter extends TokenFilter { + private final Set names; + + public NameExcludeFilter(final String... names) { + this.names = Set.of(names); + } + + @Override + public TokenFilter includeProperty(final String name) { + if (names.contains(name)) { + return null; + } + return this; + } + + @Override + public boolean includeEmptyObject(final boolean contentsFiltered) { + return !contentsFiltered; + } + + @Override + public boolean includeEmptyArray(final boolean contentsFiltered) { + return !contentsFiltered; + } + } } diff --git a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java index 2605f0d5e89..9f014b7d4d2 100644 --- a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java @@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hyperledger.besu.config.GenesisConfigFile.fromConfig; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import java.io.IOException; @@ -50,7 +51,11 @@ void shouldLoadMainnetConfigFile() { // Sanity check some basic properties to confirm this is the mainnet file. assertThat(config.getConfigOptions().isEthHash()).isTrue(); assertThat(config.getConfigOptions().getChainId()).hasValue(MAINNET_CHAIN_ID); - assertThat(config.streamAllocations().map(GenesisAllocation::getAddress)) + assertThat( + config + .streamAllocations() + .map(GenesisAccount::address) + .map(Address::toUnprefixedHexString)) .contains( "000d836201318ec6899a67540690382780743280", "001762430ea9c3a26e5749afdb70da5f78ddbb8c", @@ -63,7 +68,11 @@ void shouldLoadDevelopmentConfigFile() { // Sanity check some basic properties to confirm this is the dev file. assertThat(config.getConfigOptions().isEthHash()).isTrue(); assertThat(config.getConfigOptions().getChainId()).hasValue(DEVELOPMENT_CHAIN_ID); - assertThat(config.streamAllocations().map(GenesisAllocation::getAddress)) + assertThat( + config + .streamAllocations() + .map(GenesisAccount::address) + .map(Address::toUnprefixedHexString)) .contains( "fe3b557e8fb62b89f4916b721be55ceb828dbd73", "627306090abab3a6e1400e9345bc60c78a8bef57", @@ -271,31 +280,41 @@ void shouldGetAllocations() { + " }" + "}"); - final Map allocations = + final Map allocations = config .streamAllocations() - .collect(Collectors.toMap(GenesisAllocation::getAddress, Function.identity())); - assertThat(allocations) - .containsOnlyKeys( + .collect(Collectors.toMap(GenesisAccount::address, Function.identity())); + assertThat(allocations.keySet()) + .map(Address::toUnprefixedHexString) + .containsOnly( "fe3b557e8fb62b89f4916b721be55ceb828dbd73", "627306090abab3a6e1400e9345bc60c78a8bef57", "f17f52151ebef6c7334fad080c5704d77216b732"); - final GenesisAllocation alloc1 = allocations.get("fe3b557e8fb62b89f4916b721be55ceb828dbd73"); - final GenesisAllocation alloc2 = allocations.get("627306090abab3a6e1400e9345bc60c78a8bef57"); - final GenesisAllocation alloc3 = allocations.get("f17f52151ebef6c7334fad080c5704d77216b732"); - - assertThat(alloc1.getBalance()).isEqualTo("0xad78ebc5ac6200000"); - assertThat(alloc2.getBalance()).isEqualTo("1000"); - assertThat(alloc3.getBalance()).isEqualTo("90000000000000000000000"); - assertThat(alloc3.getStorage()).hasSize(2); - assertThat(alloc3.getStorage()) + final GenesisAccount alloc1 = + allocations.get(Address.fromHexString("fe3b557e8fb62b89f4916b721be55ceb828dbd73")); + final GenesisAccount alloc2 = + allocations.get(Address.fromHexString("627306090abab3a6e1400e9345bc60c78a8bef57")); + final GenesisAccount alloc3 = + allocations.get(Address.fromHexString("f17f52151ebef6c7334fad080c5704d77216b732")); + + assertThat(alloc1.balance()) + .isEqualTo(GenesisReader.ParserUtils.parseBalance("0xad78ebc5ac6200000")); + assertThat(alloc2.balance()).isEqualTo(GenesisReader.ParserUtils.parseBalance("1000")); + assertThat(alloc3.balance()) + .isEqualTo(GenesisReader.ParserUtils.parseBalance("90000000000000000000000")); + assertThat(alloc3.storage()).hasSize(2); + assertThat(alloc3.storage()) .containsEntry( - "0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a4", - "0x937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"); - assertThat(alloc3.getStorage()) + UInt256.fromHexString( + "0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a4"), + UInt256.fromHexString( + "0x937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0")); + assertThat(alloc3.storage()) .containsEntry( - "0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a3", - "0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012"); + UInt256.fromHexString( + "0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a3"), + UInt256.fromHexString( + "0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012")); } @Test diff --git a/config/src/test/java/org/hyperledger/besu/config/GenesisReaderTest.java b/config/src/test/java/org/hyperledger/besu/config/GenesisReaderTest.java new file mode 100644 index 00000000000..5d73a2829f5 --- /dev/null +++ b/config/src/test/java/org/hyperledger/besu/config/GenesisReaderTest.java @@ -0,0 +1,98 @@ +/* + * 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.config; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.config.GenesisReader.ALLOCATION_FIELD; +import static org.hyperledger.besu.config.GenesisReader.CONFIG_FIELD; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Wei; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class GenesisReaderTest { + private final ObjectMapper mapper = new ObjectMapper(); + + @Test + public void readGenesisFromObjectNode() { + final var configNode = mapper.createObjectNode(); + configNode.put("londonBlock", 1); + final var allocNode = mapper.createObjectNode(); + allocNode.put(Address.BLS12_G2MUL.toUnprefixedHexString(), generateAllocation(Wei.ONE)); + final var rootNode = mapper.createObjectNode(); + rootNode.put("chainId", 12); + rootNode.put(CONFIG_FIELD, configNode); + rootNode.put(ALLOCATION_FIELD, allocNode); + final var genesisReader = new GenesisReader.FromObjectNode(rootNode); + + assertThat(genesisReader.getRoot().get("chainid").asInt()).isEqualTo(12); + assertThat(genesisReader.getRoot().has(ALLOCATION_FIELD)).isFalse(); + assertThat(genesisReader.getConfig().get("londonblock").asInt()).isEqualTo(1); + assertThat(genesisReader.streamAllocations()) + .containsExactly(new GenesisAccount(Address.BLS12_G2MUL, 0, Wei.ONE, null, Map.of(), null)); + } + + @Test + public void readGenesisFromURL(@TempDir final Path folder) throws IOException { + final String jsonStr = + """ + { + "chainId":11, + "config": { + "londonBlock":1 + }, + "alloc": { + "000d836201318ec6899a67540690382780743280": { + "balance": "0xad78ebc5ac6200000" + } + }, + "gasLimit": "0x1" + } + """; + + final var genesisFile = Files.writeString(folder.resolve("genesis.json"), jsonStr); + + final var genesisReader = new GenesisReader.FromURL(genesisFile.toUri().toURL()); + + assertThat(genesisReader.getRoot().get("chainid").asInt()).isEqualTo(11); + assertThat(genesisReader.getRoot().get("gaslimit").asText()).isEqualTo("0x1"); + assertThat(genesisReader.getRoot().has(ALLOCATION_FIELD)).isFalse(); + assertThat(genesisReader.getConfig().get("londonblock").asInt()).isEqualTo(1); + assertThat(genesisReader.streamAllocations()) + .containsExactly( + new GenesisAccount( + Address.fromHexString("000d836201318ec6899a67540690382780743280"), + 0, + Wei.fromHexString("0xad78ebc5ac6200000"), + null, + Map.of(), + null)); + } + + private ObjectNode generateAllocation(final Wei balance) { + final ObjectNode entry = mapper.createObjectNode(); + entry.put("balance", balance.toShortHexString()); + return entry; + } +} diff --git a/config/src/test/java/org/hyperledger/besu/config/JsonUtilTest.java b/config/src/test/java/org/hyperledger/besu/config/JsonUtilTest.java index 1b251d5cd1d..1e1df382e71 100644 --- a/config/src/test/java/org/hyperledger/besu/config/JsonUtilTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/JsonUtilTest.java @@ -659,7 +659,24 @@ public void objectNodeFromString_withComments_commentsEnabled() { } @Test - public void objectNodeFromURL(@TempDir final Path folder) throws IOException { + public void objectNodeFromString_excludingField() { + final String jsonStr = + """ + { + "a":1, + "b":2, + "c":3 + } + """; + + final ObjectNode result = JsonUtil.objectNodeFromString(jsonStr, false, "b"); + assertThat(result.get("a").asInt()).isEqualTo(1); + assertThat(result.has("b")).isFalse(); + assertThat(result.get("c").asInt()).isEqualTo(3); + } + + @Test + public void objectNodeFromURL_excludingField(@TempDir final Path folder) throws IOException { final String jsonStr = """ { @@ -670,9 +687,9 @@ public void objectNodeFromURL(@TempDir final Path folder) throws IOException { """; final var genesisFile = Files.writeString(folder.resolve("genesis.json"), jsonStr); - final ObjectNode result = JsonUtil.objectNodeFromURL(genesisFile.toUri().toURL(), false); + final ObjectNode result = JsonUtil.objectNodeFromURL(genesisFile.toUri().toURL(), false, "b"); assertThat(result.get("a").asInt()).isEqualTo(1); - assertThat(result.get("b").asInt()).isEqualTo(2); + assertThat(result.has("b")).isFalse(); assertThat(result.get("c").asInt()).isEqualTo(3); } diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java index 4f510ec7e30..54099f868cb 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.consensus.merge.blockcreation; -import org.hyperledger.besu.config.GenesisAllocation; +import org.hyperledger.besu.config.GenesisAccount; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.consensus.merge.MergeProtocolSchedule; import org.hyperledger.besu.datatypes.Address; @@ -48,10 +48,7 @@ default GenesisConfigFile getPowGenesisConfigFile() { } default Stream
genesisAllocations(final GenesisConfigFile configFile) { - return configFile - .streamAllocations() - .map(GenesisAllocation::getAddress) - .map(Address::fromHexString); + return configFile.streamAllocations().map(GenesisAccount::address); } default ProtocolSchedule getMergeProtocolSchedule() { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java index ae9acc89a69..d42f2d39a3f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java @@ -17,12 +17,11 @@ import static java.util.Collections.emptyList; import static org.hyperledger.besu.ethereum.trie.common.GenesisWorldStateProvider.createGenesisWorldState; -import org.hyperledger.besu.config.GenesisAllocation; +import org.hyperledger.besu.config.GenesisAccount; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -38,29 +37,27 @@ import org.hyperledger.besu.evm.log.LogsBloomFilter; import org.hyperledger.besu.evm.worldstate.WorldUpdater; -import java.math.BigInteger; -import java.util.HashMap; +import java.net.URL; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Optional; import java.util.OptionalLong; import java.util.function.Function; import java.util.stream.Stream; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; -import org.apache.tuweni.units.bigints.UInt256; public final class GenesisState { private final Block block; - private final List genesisAccounts; + private final GenesisConfigFile genesisConfigFile; - private GenesisState(final Block block, final List genesisAccounts) { + private GenesisState(final Block block, final GenesisConfigFile genesisConfigFile) { this.block = block; - this.genesisAccounts = genesisAccounts; + this.genesisConfigFile = genesisConfigFile; } /** @@ -75,24 +72,25 @@ public static GenesisState fromJson(final String json, final ProtocolSchedule pr } /** - * Construct a {@link GenesisState} from a JSON string. + * Construct a {@link GenesisState} from a URL * * @param dataStorageConfiguration A {@link DataStorageConfiguration} describing the storage * configuration - * @param json A JSON string describing the genesis block + * @param jsonSource A URL pointing to JSON genesis file * @param protocolSchedule A protocol Schedule associated with * @return A new {@link GenesisState}. */ - public static GenesisState fromJson( + @VisibleForTesting + static GenesisState fromJsonSource( final DataStorageConfiguration dataStorageConfiguration, - final String json, + final URL jsonSource, final ProtocolSchedule protocolSchedule) { return fromConfig( - dataStorageConfiguration, GenesisConfigFile.fromConfig(json), protocolSchedule); + dataStorageConfiguration, GenesisConfigFile.fromConfig(jsonSource), protocolSchedule); } /** - * Construct a {@link GenesisState} from a JSON object. + * Construct a {@link GenesisState} from a genesis file object. * * @param config A {@link GenesisConfigFile} describing the genesis block. * @param protocolSchedule A protocol Schedule associated with @@ -108,41 +106,40 @@ public static GenesisState fromConfig( * * @param dataStorageConfiguration A {@link DataStorageConfiguration} describing the storage * configuration - * @param config A {@link GenesisConfigFile} describing the genesis block. + * @param genesisConfigFile A {@link GenesisConfigFile} describing the genesis block. * @param protocolSchedule A protocol Schedule associated with * @return A new {@link GenesisState}. */ public static GenesisState fromConfig( final DataStorageConfiguration dataStorageConfiguration, - final GenesisConfigFile config, + final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule) { - final List genesisAccounts = parseAllocations(config).toList(); + final var genesisStateRoot = + calculateGenesisStateRoot(dataStorageConfiguration, genesisConfigFile); final Block block = new Block( - buildHeader( - config, - calculateGenesisStateHash(dataStorageConfiguration, genesisAccounts), - protocolSchedule), - buildBody(config)); - return new GenesisState(block, genesisAccounts); + buildHeader(genesisConfigFile, genesisStateRoot, protocolSchedule), + buildBody(genesisConfigFile)); + return new GenesisState(block, genesisConfigFile); } /** * Construct a {@link GenesisState} from a JSON object. * - * @param genesisStateHash The hash of the genesis state. - * @param config A {@link GenesisConfigFile} describing the genesis block. + * @param genesisStateRoot The root of the genesis state. + * @param genesisConfigFile A {@link GenesisConfigFile} describing the genesis block. * @param protocolSchedule A protocol Schedule associated with * @return A new {@link GenesisState}. */ - public static GenesisState fromConfig( - final Hash genesisStateHash, - final GenesisConfigFile config, + public static GenesisState fromStorage( + final Hash genesisStateRoot, + final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule) { - final List genesisAccounts = parseAllocations(config).toList(); final Block block = - new Block(buildHeader(config, genesisStateHash, protocolSchedule), buildBody(config)); - return new GenesisState(block, genesisAccounts); + new Block( + buildHeader(genesisConfigFile, genesisStateRoot, protocolSchedule), + buildBody(genesisConfigFile)); + return new GenesisState(block, genesisConfigFile); } private static BlockBody buildBody(final GenesisConfigFile config) { @@ -164,31 +161,31 @@ public Block getBlock() { * @param target WorldView to write genesis state to */ public void writeStateTo(final MutableWorldState target) { - writeAccountsTo(target, genesisAccounts, block.getHeader()); + writeAccountsTo(target, genesisConfigFile.streamAllocations(), block.getHeader()); } private static void writeAccountsTo( final MutableWorldState target, - final List genesisAccounts, + final Stream genesisAccounts, final BlockHeader rootHeader) { final WorldUpdater updater = target.updater(); genesisAccounts.forEach( genesisAccount -> { - final MutableAccount account = updater.getOrCreate(genesisAccount.address); - account.setNonce(genesisAccount.nonce); - account.setBalance(genesisAccount.balance); - account.setCode(genesisAccount.code); - genesisAccount.storage.forEach(account::setStorageValue); + final MutableAccount account = updater.createAccount(genesisAccount.address()); + account.setNonce(genesisAccount.nonce()); + account.setBalance(genesisAccount.balance()); + account.setCode(genesisAccount.code()); + genesisAccount.storage().forEach(account::setStorageValue); }); updater.commit(); target.persist(rootHeader); } - private static Hash calculateGenesisStateHash( + private static Hash calculateGenesisStateRoot( final DataStorageConfiguration dataStorageConfiguration, - final List genesisAccounts) { + final GenesisConfigFile genesisConfigFile) { try (var worldState = createGenesisWorldState(dataStorageConfiguration)) { - writeAccountsTo(worldState, genesisAccounts, null); + writeAccountsTo(worldState, genesisConfigFile.streamAllocations(), null); return worldState.rootHash(); } catch (Exception e) { throw new RuntimeException(e); @@ -265,10 +262,6 @@ private static Hash parseMixHash(final GenesisConfigFile genesis) { return withNiceErrorMessage("mixHash", genesis.getMixHash(), Hash::fromHexStringLenient); } - private static Stream parseAllocations(final GenesisConfigFile genesis) { - return genesis.streamAllocations().map(GenesisAccount::fromAllocation); - } - private static long parseNonce(final GenesisConfigFile genesis) { return withNiceErrorMessage("nonce", genesis.getNonce(), GenesisState::parseUnsignedLong); } @@ -340,75 +333,6 @@ private static boolean isExperimentalEipsTimeAtGenesis(final GenesisConfigFile g @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("block", block) - .add("genesisAccounts", genesisAccounts) - .toString(); - } - - private static final class GenesisAccount { - - final long nonce; - final Address address; - final Wei balance; - final Map storage; - final Bytes code; - - static GenesisAccount fromAllocation(final GenesisAllocation allocation) { - return new GenesisAccount( - allocation.getNonce(), - allocation.getAddress(), - allocation.getBalance(), - allocation.getStorage(), - allocation.getCode()); - } - - private GenesisAccount( - final String hexNonce, - final String hexAddress, - final String balance, - final Map storage, - final String hexCode) { - this.nonce = withNiceErrorMessage("nonce", hexNonce, GenesisState::parseUnsignedLong); - this.address = withNiceErrorMessage("address", hexAddress, Address::fromHexString); - this.balance = withNiceErrorMessage("balance", balance, this::parseBalance); - this.code = hexCode != null ? Bytes.fromHexString(hexCode) : null; - this.storage = parseStorage(storage); - } - - private Wei parseBalance(final String balance) { - final BigInteger val; - if (balance.startsWith("0x")) { - val = new BigInteger(1, Bytes.fromHexStringLenient(balance).toArrayUnsafe()); - } else { - val = new BigInteger(balance); - } - - return Wei.of(val); - } - - private Map parseStorage(final Map storage) { - final Map parsedStorage = new HashMap<>(); - storage.forEach( - (key1, value1) -> { - final UInt256 key = withNiceErrorMessage("storage key", key1, UInt256::fromHexString); - final UInt256 value = - withNiceErrorMessage("storage value", value1, UInt256::fromHexString); - parsedStorage.put(key, value); - }); - - return parsedStorage; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("address", address) - .add("nonce", nonce) - .add("balance", balance) - .add("storage", storage) - .add("code", code) - .toString(); - } + return MoreObjects.toStringHelper(this).add("block", block).toString(); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java index 6e6217e08bc..ea1eb044149 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java @@ -29,8 +29,6 @@ import java.util.stream.Stream; -import com.google.common.base.Charsets; -import com.google.common.io.Resources; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; import org.bouncycastle.util.encoders.Hex; @@ -64,12 +62,11 @@ public Stream provideArguments(final ExtensionContext conte @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - public void createFromJsonWithAllocs(final DataStorageConfiguration dataStorageConfiguration) - throws Exception { + public void createFromJsonWithAllocs(final DataStorageConfiguration dataStorageConfiguration) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString(GenesisStateTest.class.getResource("genesis1.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesis1.json"), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getStateRoot()) @@ -95,12 +92,11 @@ public void createFromJsonWithAllocs(final DataStorageConfiguration dataStorageC @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - void createFromJsonNoAllocs(final DataStorageConfiguration dataStorageConfiguration) - throws Exception { + void createFromJsonNoAllocs(final DataStorageConfiguration dataStorageConfiguration) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString(GenesisStateTest.class.getResource("genesis2.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesis2.json"), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getStateRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); @@ -114,12 +110,11 @@ void createFromJsonNoAllocs(final DataStorageConfiguration dataStorageConfigurat private void assertContractInvariants( final DataStorageConfiguration dataStorageConfiguration, final String sourceFile, - final String blockHash) - throws Exception { + final String blockHash) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString(GenesisStateTest.class.getResource(sourceFile), Charsets.UTF_8), + GenesisStateTest.class.getResource(sourceFile), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getHash()).isEqualTo(Hash.fromHexString(blockHash)); @@ -141,8 +136,7 @@ private void assertContractInvariants( @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - void createFromJsonWithContract(final DataStorageConfiguration dataStorageConfiguration) - throws Exception { + void createFromJsonWithContract(final DataStorageConfiguration dataStorageConfiguration) { assertContractInvariants( dataStorageConfiguration, "genesis3.json", @@ -151,13 +145,11 @@ void createFromJsonWithContract(final DataStorageConfiguration dataStorageConfig @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - void createFromJsonWithNonce(final DataStorageConfiguration dataStorageConfiguration) - throws Exception { + void createFromJsonWithNonce(final DataStorageConfiguration dataStorageConfiguration) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString( - GenesisStateTest.class.getResource("genesisNonce.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesisNonce.json"), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getHash()) @@ -168,13 +160,11 @@ void createFromJsonWithNonce(final DataStorageConfiguration dataStorageConfigura @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - void encodeOlympicBlock(final DataStorageConfiguration dataStorageConfiguration) - throws Exception { + void encodeOlympicBlock(final DataStorageConfiguration dataStorageConfiguration) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString( - GenesisStateTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesis-olympic.json"), ProtocolScheduleFixture.MAINNET); final BytesValueRLPOutput tmp = new BytesValueRLPOutput(); genesisState.getBlock().writeTo(tmp); @@ -190,13 +180,11 @@ private void assertStorageValue(final Account contract, final String key, final @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - void genesisFromShanghai(final DataStorageConfiguration dataStorageConfiguration) - throws Exception { + void genesisFromShanghai(final DataStorageConfiguration dataStorageConfiguration) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString( - GenesisStateTest.class.getResource("genesis_shanghai.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesis_shanghai.json"), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getHash()) @@ -241,12 +229,11 @@ void genesisFromShanghai(final DataStorageConfiguration dataStorageConfiguration @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - void genesisFromCancun(final DataStorageConfiguration dataStorageConfiguration) throws Exception { + void genesisFromCancun(final DataStorageConfiguration dataStorageConfiguration) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString( - GenesisStateTest.class.getResource("genesis_cancun.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesis_cancun.json"), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getHash()) @@ -292,12 +279,11 @@ void genesisFromCancun(final DataStorageConfiguration dataStorageConfiguration) @ParameterizedTest @ArgumentsSource(GenesisStateTestArguments.class) - void genesisFromPrague(final DataStorageConfiguration dataStorageConfiguration) throws Exception { + void genesisFromPrague(final DataStorageConfiguration dataStorageConfiguration) { final GenesisState genesisState = - GenesisState.fromJson( + GenesisState.fromJsonSource( dataStorageConfiguration, - Resources.toString( - GenesisStateTest.class.getResource("genesis_prague.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesis_prague.json"), ProtocolScheduleFixture.MAINNET); final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getHash()) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java index d9b9d5d1955..62adf26eccb 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisAllocation; +import org.hyperledger.besu.config.GenesisAccount; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SECPPrivateKey; @@ -85,7 +85,6 @@ import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Function; -import java.util.stream.Collectors; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -98,10 +97,10 @@ public abstract class AbstractIsolationTests { protected ProtocolContext protocolContext; protected EthContext ethContext; protected EthScheduler ethScheduler = new DeterministicEthScheduler(); - final Function asKeyPair = + final Function asKeyPair = key -> SignatureAlgorithmFactory.getInstance() - .createKeyPair(SECPPrivateKey.create(Bytes32.fromHexString(key), "ECDSA")); + .createKeyPair(SECPPrivateKey.create(key, "ECDSA")); protected final ProtocolSchedule protocolSchedule = MainnetProtocolSchedule.fromConfig( GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), @@ -139,13 +138,13 @@ public abstract class AbstractIsolationTests { new BlobCache(), MiningParameters.newDefault())); - protected final List accounts = + protected final List accounts = GenesisConfigFile.fromResource("/dev.json") .streamAllocations() - .filter(ga -> ga.getPrivateKey().isPresent()) - .collect(Collectors.toList()); + .filter(ga -> ga.privateKey() != null) + .toList(); - KeyPair sender1 = asKeyPair.apply(accounts.get(0).getPrivateKey().get()); + KeyPair sender1 = Optional.ofNullable(accounts.get(0).privateKey()).map(asKeyPair).orElseThrow(); TransactionPool transactionPool; @TempDir private Path tempData; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java index ffdc3fa897f..322aacb7eb7 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiSnapshotIsolationTests.java @@ -39,7 +39,7 @@ public void ensureTruncateDoesNotCauseSegfault() { var postTruncatedWorldState = archive.getMutable(genesisState.getBlock().getHeader(), false); assertThat(postTruncatedWorldState).isEmpty(); // assert that trying to access pre-worldstate does not segfault after truncating - preTruncatedWorldState.get().get(Address.fromHexString(accounts.get(0).getAddress())); + preTruncatedWorldState.get().get(accounts.get(0).address()); assertThat(true).isTrue(); } From a8621f4962fb28f9067093a69b926f793b5dbecb Mon Sep 17 00:00:00 2001 From: ahamlat Date: Tue, 11 Jun 2024 16:57:26 +0200 Subject: [PATCH 38/42] Enable JFR continuous profiling with default setting (#7006) Enable JFR continuous profiling with default setting Signed-off-by: Ameziane H --- CHANGELOG.md | 2 ++ build.gradle | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 435ecea9e35..c3efddef70d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ - `admin_nodeInfo` JSON/RPC call returns the currently active EVM version [#7127](https://github.com/hyperledger/besu/pull/7127) - Improve the selection of the most profitable built block [#7174](https://github.com/hyperledger/besu/pull/7174) - Support for eth_maxPriorityFeePerGas [#5658](https://github.com/hyperledger/besu/issues/5658) +- Enable continuous profiling with default setting [#7006](https://github.com/hyperledger/besu/pull/7006) + ### Bug fixes - Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) - Validation errors ignored in accounts-allowlist and empty list [#7138](https://github.com/hyperledger/besu/issues/7138) diff --git a/build.gradle b/build.gradle index 4f34e67985d..b26f36b5194 100644 --- a/build.gradle +++ b/build.gradle @@ -634,7 +634,9 @@ startScripts { defaultJvmOpts = applicationDefaultJvmArgs + [ "-XX:G1ConcRefinementThreads=2", "-XX:G1HeapWastePercent=15", - "-XX:MaxGCPauseMillis=100" + "-XX:MaxGCPauseMillis=100", + "-XX:StartFlightRecording,dumponexit=true,settings=default.jfc", + "-Xlog:jfr*=off" ] unixStartScriptGenerator.template = resources.text.fromFile("${projectDir}/besu/src/main/scripts/unixStartScript.txt") windowsStartScriptGenerator.template = resources.text.fromFile("${projectDir}/besu/src/main/scripts/windowsStartScript.txt") From c7e2e4dbbf1a3348992d2701465fa0b3521ad96a Mon Sep 17 00:00:00 2001 From: Usman Saleem Date: Wed, 12 Jun 2024 10:40:32 +1000 Subject: [PATCH 39/42] fix(test): Fix dns daemon periodic test (#7200) * fix(test): Fix dns daemon periodic test Increase second run to 3 seconds Signed-off-by: Usman Saleem * fix(test): Fix dns daemon periodic test change vertx testContext verify to failNow Signed-off-by: Usman Saleem * fix(test): Fix dns daemon periodic test Remove Disabled Signed-off-by: Usman Saleem * fix(test): Code formatting Signed-off-by: Usman Saleem --------- Signed-off-by: Usman Saleem --- .../p2p/discovery/dns/DNSDaemonTest.java | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java index 08539d47bf8..fd8ba1382d8 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/discovery/dns/DNSDaemonTest.java @@ -29,13 +29,13 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(VertxExtension.class) class DNSDaemonTest { + private static final int EXPECTED_SEQ = 932; private static final String holeskyEnr = "enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.holesky.ethdisco.net"; private final MockDnsServerVerticle mockDnsServerVerticle = new MockDnsServerVerticle(); @@ -54,13 +54,24 @@ void prepare(final Vertx vertx, final VertxTestContext vertxTestContext) { @Test @DisplayName("Test DNS Daemon with a mock DNS server") - void testDNSDaemon(final Vertx vertx, final VertxTestContext testContext) - throws InterruptedException { + void testDNSDaemon(final Vertx vertx, final VertxTestContext testContext) { final Checkpoint checkpoint = testContext.checkpoint(); dnsDaemon = new DNSDaemon( holeskyEnr, - (seq, records) -> checkpoint.flag(), + (seq, records) -> { + if (seq != EXPECTED_SEQ) { + testContext.failNow( + String.format( + "Expecting sequence to be %d in first pass but got: %d", + EXPECTED_SEQ, seq)); + } + if (records.size() != 115) { + testContext.failNow( + "Expecting 115 records in first pass but got: " + records.size()); + } + checkpoint.flag(); + }, 0, 0, 0, @@ -74,7 +85,6 @@ void testDNSDaemon(final Vertx vertx, final VertxTestContext testContext) } @Test - @Disabled("this test is flaky") @DisplayName("Test DNS Daemon with periodic lookup to a mock DNS server") void testDNSDaemonPeriodic(final Vertx vertx, final VertxTestContext testContext) throws InterruptedException { @@ -87,18 +97,28 @@ void testDNSDaemonPeriodic(final Vertx vertx, final VertxTestContext testContext (seq, records) -> { switch (pass.incrementAndGet()) { case 1: - testContext.verify( - () -> { - assertThat(seq).isEqualTo(932); - assertThat(records).hasSize(115); - }); + if (seq != EXPECTED_SEQ) { + testContext.failNow( + String.format( + "Expecting sequence to be %d in first pass but got: %d", + EXPECTED_SEQ, seq)); + } + if (records.size() != 115) { + testContext.failNow( + "Expecting 115 records in first pass but got: " + records.size()); + } break; case 2: - testContext.verify( - () -> { - assertThat(seq).isEqualTo(932); - assertThat(records).isEmpty(); - }); + if (seq != EXPECTED_SEQ) { + testContext.failNow( + String.format( + "Expecting sequence to be %d in second pass but got: %d", + EXPECTED_SEQ, seq)); + } + if (!records.isEmpty()) { + testContext.failNow( + "Expecting 0 records in second pass but got: " + records.size()); + } break; default: testContext.failNow("Third pass is not expected"); @@ -107,7 +127,7 @@ void testDNSDaemonPeriodic(final Vertx vertx, final VertxTestContext testContext }, 0, 1, // initial delay - 300, // second lookup after 300 ms (due to Mock DNS server, we are very quick). + 3000, // second lookup after 3 seconds (the thread scheduling can be slower in CI) "localhost:" + mockDnsServerVerticle.port()); final DeploymentOptions options = From d9ab92e8870b36409e55b745548b495be1c80c33 Mon Sep 17 00:00:00 2001 From: Lucas Saldanha Date: Wed, 12 Jun 2024 17:45:20 +1200 Subject: [PATCH 40/42] Updated EIP-7002 WithdrawalRequestV1 field (validatorPublicKey -> validatorPubkey) (#7209) Signed-off-by: Lucas Saldanha --- .../test-cases/06_prague_getPayloadV4.json | 2 +- .../test-cases/09_prague_newPayloadV4.json | 2 +- .../test-cases/15_prague_getPayloadV4.json | 2 +- .../WithdrawalRequestParameter.java | 20 +++++++++---------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json index b0bc6ffeeb5..6ff3614cdf7 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/06_prague_getPayloadV4.json @@ -30,7 +30,7 @@ "withdrawalRequests": [ { "sourceAddress": "0xa4664c40aacebd82a2db79f0ea36c06bc6a19adb", - "validatorPublicKey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e", + "validatorPubkey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e", "amount": "0x0" } ], diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json index 27885c1c81b..a5ff6fa7ec8 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/09_prague_newPayloadV4.json @@ -32,7 +32,7 @@ { "sourceAddress": "0xa4664c40aacebd82a2db79f0ea36c06bc6a19adb", "amount": "0x0", - "validatorPublicKey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e" + "validatorPubkey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e" } ], "blockNumber": "0x2", diff --git a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json index 1450ac4bba9..c287cfaed8a 100644 --- a/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json +++ b/acceptance-tests/tests/src/test/resources/jsonrpc/engine/prague/test-cases/15_prague_getPayloadV4.json @@ -33,7 +33,7 @@ { "sourceAddress": "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", "amount": "0x0", - "validatorPublicKey": "0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243" + "validatorPubkey": "0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243" } ], "blockNumber": "0x4", diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java index 79c0251e838..67fa13f3f89 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/WithdrawalRequestParameter.java @@ -28,16 +28,16 @@ public class WithdrawalRequestParameter { private final String sourceAddress; - private final String validatorPublicKey; + private final String validatorPubkey; private final String amount; @JsonCreator public WithdrawalRequestParameter( @JsonProperty("sourceAddress") final String sourceAddress, - @JsonProperty("validatorPublicKey") final String validatorPublicKey, + @JsonProperty("validatorPubkey") final String validatorPubkey, @JsonProperty("amount") final String amount) { this.sourceAddress = sourceAddress; - this.validatorPublicKey = validatorPublicKey; + this.validatorPubkey = validatorPubkey; this.amount = amount; } @@ -52,7 +52,7 @@ public static WithdrawalRequestParameter fromWithdrawalRequest( public WithdrawalRequest toWithdrawalRequest() { return new WithdrawalRequest( Address.fromHexString(sourceAddress), - BLSPublicKey.fromHexString(validatorPublicKey), + BLSPublicKey.fromHexString(validatorPubkey), GWei.fromHexString(amount)); } @@ -62,8 +62,8 @@ public String getSourceAddress() { } @JsonGetter - public String getValidatorPublicKey() { - return validatorPublicKey; + public String getValidatorPubkey() { + return validatorPubkey; } @JsonGetter @@ -77,13 +77,13 @@ public boolean equals(final Object o) { if (o == null || getClass() != o.getClass()) return false; final WithdrawalRequestParameter that = (WithdrawalRequestParameter) o; return Objects.equals(sourceAddress, that.sourceAddress) - && Objects.equals(validatorPublicKey, that.validatorPublicKey) + && Objects.equals(validatorPubkey, that.validatorPubkey) && Objects.equals(amount, that.amount); } @Override public int hashCode() { - return Objects.hash(sourceAddress, validatorPublicKey, amount); + return Objects.hash(sourceAddress, validatorPubkey, amount); } @Override @@ -92,8 +92,8 @@ public String toString() { + "sourceAddress='" + sourceAddress + '\'' - + ", validatorPublicKey='" - + validatorPublicKey + + ", validatorPubkey='" + + validatorPubkey + '\'' + ", amount='" + amount From e2f541a44700aabe59c527bd5e19580e3bb0f672 Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Wed, 12 Jun 2024 10:44:11 +0200 Subject: [PATCH 41/42] fix unit tests Signed-off-by: Karim Taam --- .../besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java | 1 + .../internal/methods/engine/AbstractEngineNewPayload.java | 2 +- .../internal/parameters/ExecutionWitnessParameter.java | 2 +- .../api/jsonrpc/internal/parameters/IPAProofParameter.java | 4 ++-- .../api/jsonrpc/internal/parameters/StateDiffParameter.java | 2 +- .../jsonrpc/internal/parameters/StemStateDiffParameter.java | 2 +- .../jsonrpc/internal/parameters/SuffixStateDiffParameter.java | 2 +- .../api/jsonrpc/internal/parameters/VerkleProofParameter.java | 4 ++-- .../java/org/hyperledger/besu/ethereum/core/BlockHeader.java | 2 +- .../hyperledger/besu/ethereum/core/BlockHeaderBuilder.java | 2 +- .../hyperledger/besu/ethereum/core/SealableBlockHeader.java | 2 +- .../besu/ethereum/core/witness}/ExecutionWitness.java | 2 +- .../org/hyperledger/besu/ethereum/core/witness}/IPAProof.java | 2 +- .../hyperledger/besu/ethereum/core/witness}/StateDiff.java | 2 +- .../besu/ethereum/core/witness}/StemStateDiff.java | 2 +- .../besu/ethereum/core/witness}/SuffixStateDiff.java | 2 +- .../hyperledger/besu/ethereum/core/witness}/VerkleProof.java | 2 +- .../besu/ethereum/mainnet/ExecutionWitnessValidator.java | 2 +- .../besu/ethereum/mainnet/MainnetTransactionProcessor.java | 2 +- plugin-api/build.gradle | 2 +- .../besu/plugin/services/storage/rocksdb/Utils.java | 1 + 21 files changed, 23 insertions(+), 21 deletions(-) rename ethereum/{trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle => core/src/main/java/org/hyperledger/besu/ethereum/core/witness}/ExecutionWitness.java (97%) rename ethereum/{trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle => core/src/main/java/org/hyperledger/besu/ethereum/core/witness}/IPAProof.java (96%) rename ethereum/{trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle => core/src/main/java/org/hyperledger/besu/ethereum/core/witness}/StateDiff.java (94%) rename ethereum/{trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle => core/src/main/java/org/hyperledger/besu/ethereum/core/witness}/StemStateDiff.java (94%) rename ethereum/{trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle => core/src/main/java/org/hyperledger/besu/ethereum/core/witness}/SuffixStateDiff.java (94%) rename ethereum/{trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle => core/src/main/java/org/hyperledger/besu/ethereum/core/witness}/VerkleProof.java (96%) diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java index 4e067e6ec8a..09235fbdb20 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java @@ -131,6 +131,7 @@ public JsonRpcResponse response( null, // ToDo 4844: set with the value of excess_blob_gas field null, // TODO 4788: set with the value of the parent beacon block root field requestsRoot, + null, blockHeaderFunctions); return new JsonRpcSuccessResponse( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index c4471ea9877..6ff4a78c1e4 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -67,7 +67,7 @@ import org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil; import org.hyperledger.besu.ethereum.rlp.RLPException; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; -import org.hyperledger.besu.ethereum.trie.verkle.ExecutionWitness; +import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import org.hyperledger.besu.plugin.services.exception.StorageException; import java.security.InvalidParameterException; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/ExecutionWitnessParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/ExecutionWitnessParameter.java index 6382abbf597..9c6337b0c48 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/ExecutionWitnessParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/ExecutionWitnessParameter.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; -import org.hyperledger.besu.ethereum.trie.verkle.ExecutionWitness; +import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonGetter; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/IPAProofParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/IPAProofParameter.java index fa502144252..d42189296ac 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/IPAProofParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/IPAProofParameter.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; import org.hyperledger.besu.ethereum.core.json.HexStringDeserializer; -import org.hyperledger.besu.ethereum.trie.verkle.IPAProof; +import org.hyperledger.besu.ethereum.core.witness.IPAProof; import java.util.List; @@ -52,7 +52,7 @@ public static IPAProofParameter fromIPAProof(final IPAProof ipaProof) { } public static IPAProof toIPAProof(final IPAProofParameter ipaProofParameter) { - return new org.hyperledger.besu.ethereum.trie.verkle.IPAProof( + return new IPAProof( ipaProofParameter.getCl().stream().map(Bytes32::fromHexString).toList(), ipaProofParameter.getCr().stream().map(Bytes32::fromHexString).toList(), ipaProofParameter.getFinalEvaluation()); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StateDiffParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StateDiffParameter.java index f671023b398..9331b3e9d22 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StateDiffParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StateDiffParameter.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; -import org.hyperledger.besu.ethereum.trie.verkle.StateDiff; +import org.hyperledger.besu.ethereum.core.witness.StateDiff; import java.util.List; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StemStateDiffParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StemStateDiffParameter.java index 360823b398f..8a4903bc863 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StemStateDiffParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/StemStateDiffParameter.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; import org.hyperledger.besu.ethereum.core.json.HexStringDeserializer; -import org.hyperledger.besu.ethereum.trie.verkle.StemStateDiff; +import org.hyperledger.besu.ethereum.core.witness.StemStateDiff; import java.util.ArrayList; import java.util.List; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/SuffixStateDiffParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/SuffixStateDiffParameter.java index b932bc7ede6..0282e68afbe 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/SuffixStateDiffParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/SuffixStateDiffParameter.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; import org.hyperledger.besu.ethereum.core.json.HexStringDeserializer; -import org.hyperledger.besu.ethereum.trie.verkle.SuffixStateDiff; +import org.hyperledger.besu.ethereum.core.witness.SuffixStateDiff; import java.util.ArrayList; import java.util.List; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java index 2373e939457..b3d15e06e87 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; import org.hyperledger.besu.ethereum.core.json.HexStringDeserializer; -import org.hyperledger.besu.ethereum.trie.verkle.VerkleProof; +import org.hyperledger.besu.ethereum.core.witness.VerkleProof; import java.util.List; @@ -51,7 +51,7 @@ public VerkleProofParameter( } public static VerkleProofParameter fromVerkleProof( - final org.hyperledger.besu.ethereum.trie.verkle.VerkleProof verkleProof) { + final VerkleProof verkleProof) { return new VerkleProofParameter( verkleProof.otherStems().stream().map(Bytes::toHexString).toList(), verkleProof.depthExtensionPresent(), diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java index 6c262d23558..d381e982937 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java @@ -18,9 +18,9 @@ import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; -import org.hyperledger.besu.ethereum.trie.verkle.ExecutionWitness; import org.hyperledger.besu.evm.log.LogsBloomFilter; import java.util.Objects; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java index 2dcde436259..8ea903786e2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java @@ -23,7 +23,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; -import org.hyperledger.besu.ethereum.trie.verkle.ExecutionWitness; +import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import org.hyperledger.besu.evm.log.LogsBloomFilter; import java.time.Instant; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java index f645d1a0855..1b3d2dc6465 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java @@ -18,7 +18,7 @@ import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.ethereum.trie.verkle.ExecutionWitness; +import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import org.hyperledger.besu.evm.log.LogsBloomFilter; import java.util.Optional; diff --git a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/ExecutionWitness.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/ExecutionWitness.java similarity index 97% rename from ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/ExecutionWitness.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/ExecutionWitness.java index b803697a25b..977a78997dc 100644 --- a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/ExecutionWitness.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/ExecutionWitness.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.trie.verkle; +package org.hyperledger.besu.ethereum.core.witness; import org.hyperledger.besu.ethereum.rlp.RLPInput; diff --git a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/IPAProof.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/IPAProof.java similarity index 96% rename from ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/IPAProof.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/IPAProof.java index faa757200fc..a6fde167d85 100644 --- a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/IPAProof.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/IPAProof.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.trie.verkle; +package org.hyperledger.besu.ethereum.core.witness; import java.util.List; diff --git a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/StateDiff.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/StateDiff.java similarity index 94% rename from ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/StateDiff.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/StateDiff.java index a4667b7ce48..895b02467fb 100644 --- a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/StateDiff.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/StateDiff.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.trie.verkle; +package org.hyperledger.besu.ethereum.core.witness; import java.util.List; diff --git a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/StemStateDiff.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/StemStateDiff.java similarity index 94% rename from ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/StemStateDiff.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/StemStateDiff.java index abfee93377e..0e1e7d43036 100644 --- a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/StemStateDiff.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/StemStateDiff.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.trie.verkle; +package org.hyperledger.besu.ethereum.core.witness; import java.util.List; diff --git a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/SuffixStateDiff.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/SuffixStateDiff.java similarity index 94% rename from ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/SuffixStateDiff.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/SuffixStateDiff.java index 156d35cd728..410e924ac4f 100644 --- a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/SuffixStateDiff.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/SuffixStateDiff.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.trie.verkle; +package org.hyperledger.besu.ethereum.core.witness; import org.apache.tuweni.bytes.Bytes32; diff --git a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/VerkleProof.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/VerkleProof.java similarity index 96% rename from ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/VerkleProof.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/VerkleProof.java index 54dc11e6237..c2603b04a1b 100644 --- a/ethereum/trie/src/main/java/org/hyperledger/besu/ethereum/trie/verkle/VerkleProof.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/witness/VerkleProof.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.trie.verkle; +package org.hyperledger.besu.ethereum.core.witness; import java.util.List; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ExecutionWitnessValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ExecutionWitnessValidator.java index 99fe97b3b49..f72dbecd70d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ExecutionWitnessValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ExecutionWitnessValidator.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet; -import org.hyperledger.besu.ethereum.trie.verkle.ExecutionWitness; +import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import java.util.Optional; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 881202dd94f..9b99f866d09 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -502,7 +502,7 @@ public TransactionProcessingResult processTransaction( initialFrame.getSelfDestructs().forEach(worldState::deleteAccount); - clearEmptyAccountStrategy.process(worldUpdater); + clearEmptyAccountStrategy.process(worldState); if (initialFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) { return TransactionProcessingResult.successful( diff --git a/plugin-api/build.gradle b/plugin-api/build.gradle index f61fe316bf3..66801e3c2ed 100644 --- a/plugin-api/build.gradle +++ b/plugin-api/build.gradle @@ -70,7 +70,7 @@ Calculated : ${currentHash} tasks.register('checkAPIChanges', FileStateChecker) { description = "Checks that the API for the Plugin-API project does not change without deliberate thought" files = sourceSets.main.allJava.files - knownHash = 'xU0LMvStiFihBKBxkfNHB7oIg0PUHWkPuv2yt1GVC94=' + knownHash = 'pXUnzOxMq+cCmmaS39fa2nHlZWQm2wqYxU2nNSDdNfs=' } check.dependsOn('checkAPIChanges') diff --git a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/Utils.java b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/Utils.java index a5d4f1ba913..c79e25a277b 100644 --- a/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/Utils.java +++ b/plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/Utils.java @@ -86,6 +86,7 @@ private static int dataStorageFormatToV1(final DataStorageFormat dataStorageForm return switch (dataStorageFormat) { case FOREST -> 1; case BONSAI -> 2; + case VERKLE -> 3; }; } } From 9d88191ec859f0a13d78d2ca6cd0304c4b58483c Mon Sep 17 00:00:00 2001 From: Karim Taam Date: Wed, 12 Jun 2024 17:04:12 +0200 Subject: [PATCH 42/42] fix build Signed-off-by: Karim Taam --- .../engine/AbstractEngineNewPayload.java | 2 +- .../parameters/VerkleProofParameter.java | 3 +- .../internal/methods/EthGasPriceTest.java | 1 + .../methods/EthGetTransactionReceiptTest.java | 7 +++-- .../engine/AbstractEngineNewPayloadTest.java | 4 +-- ...neExchangeTransitionConfigurationTest.java | 1 + .../engine/EngineNewPayloadV2Test.java | 16 +++++++--- .../engine/EngineNewPayloadV3Test.java | 6 ++-- .../engine/EngineNewPayloadV4Test.java | 16 +++++++--- .../query/BlockchainQueriesLogCacheTest.java | 1 + .../cache/TransactionLogBloomCacherTest.java | 2 ++ .../ethereum/core/BlockHeaderBuilder.java | 2 +- .../common/GenesisWorldStateProvider.java | 5 +-- .../bonsai/BonsaiWorldStateProvider.java | 5 --- .../common/DiffBasedWorldStateProvider.java | 4 +++ .../common/trielog/TrieLogManager.java | 9 +++--- .../verkle/VerkleWorldStateProvider.java | 11 +++++-- .../VerkleCachedWorldStorageManager.java | 11 +++++-- .../VerkleNoOpCachedWorldStorageManager.java | 3 +- .../verkle/worldview/VerkleWorldState.java | 18 ++++++++--- .../diffbased/verkle/LogRollingTests.java | 31 +++++++++++++------ .../besu/evm/frame/MessageFrame.java | 1 + .../operation/AbstractCreateOperation.java | 3 +- 23 files changed, 108 insertions(+), 54 deletions(-) diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index 86743149676..f2004f6e4f7 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -57,6 +57,7 @@ import org.hyperledger.besu.ethereum.core.Withdrawal; import org.hyperledger.besu.ethereum.core.encoding.EncodingContext; import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder; +import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; @@ -67,7 +68,6 @@ import org.hyperledger.besu.ethereum.mainnet.requests.RequestUtil; import org.hyperledger.besu.ethereum.rlp.RLPException; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; -import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; import org.hyperledger.besu.plugin.services.exception.StorageException; import java.security.InvalidParameterException; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java index b3d15e06e87..1b302ecd79d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/VerkleProofParameter.java @@ -50,8 +50,7 @@ public VerkleProofParameter( this.ipaProof = ipaProof; } - public static VerkleProofParameter fromVerkleProof( - final VerkleProof verkleProof) { + public static VerkleProofParameter fromVerkleProof(final VerkleProof verkleProof) { return new VerkleProofParameter( verkleProof.otherStems().stream().map(Bytes::toHexString).toList(), verkleProof.depthExtensionPresent(), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java index 54e17cb21cb..4992c09986c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java @@ -371,6 +371,7 @@ private Block createFakeBlock( null, null, null, + null, null), new BlockBody( IntStream.range(0, txsNum) diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java index 884cc504d8e..c747ffb5d0c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java @@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.ethereum.mainnet.ExecutionWitnessValidator; import org.hyperledger.besu.ethereum.mainnet.PoWHasher; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; @@ -151,7 +152,8 @@ public class EthGetTransactionReceiptTest { Optional.empty(), new FrontierBlockHashProcessor(), true, - true); + true, + new ExecutionWitnessValidator.ProhibitedExecutionWitness()); private final ProtocolSpec statusTransactionTypeSpec = new ProtocolSpec( "status", @@ -182,7 +184,8 @@ public class EthGetTransactionReceiptTest { Optional.empty(), new FrontierBlockHashProcessor(), true, - true); + true, + new ExecutionWitnessValidator.ProhibitedExecutionWitness()); @SuppressWarnings("unchecked") private final ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java index 5025c8e747b..38aa5bd3add 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java @@ -411,9 +411,9 @@ protected EnginePayloadParameter mockEnginePayload( final BlockHeader header, final List txs, final List withdrawals, - final List depositRequests, + final List depositRequests, final List withdrawalRequests, - final ExecutionWitnessParameter executionWitness) { + final ExecutionWitnessParameter executionWitness) { return new EnginePayloadParameter( header.getHash(), header.getParentHash(), diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java index d3104670de8..f5928091c16 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java @@ -254,6 +254,7 @@ private BlockHeader createBlockHeader(final Hash blockHash, final long blockNumb null, null, null, + null, new BlockHeaderFunctions() { @Override public Hash hash(final BlockHeader header) { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java index 6421d7eeb2a..412dc6f8927 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV2Test.java @@ -87,7 +87,9 @@ public void shouldReturnValidIfWithdrawalsIsNotNull_WhenWithdrawalsAllowed() { .when(blockchain.getBlockHeader(mockHeader.getParentHash())) .thenReturn(Optional.of(mock(BlockHeader.class))); var resp = - resp(mockEnginePayload(mockHeader, Collections.emptyList(), withdrawalsParam, null, null, null)); + resp( + mockEnginePayload( + mockHeader, Collections.emptyList(), withdrawalsParam, null, null, null)); assertValidResponse(mockHeader, resp); } @@ -127,7 +129,8 @@ public void shouldReturnInvalidIfWithdrawalsIsNotNull_WhenWithdrawalsProhibited( Collections.emptyList(), withdrawals, null, - null, null)); + null, + null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -143,7 +146,8 @@ public void shouldValidateBlobGasUsedCorrectly() { .blobGasUsed(100L) .buildHeader(); - var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); + var resp = + resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); assertThat(jsonRpcError.getData()).isEqualTo("non-null BlobGasUsed pre-cancun"); @@ -159,7 +163,8 @@ public void shouldValidateExcessBlobGasCorrectly() { .excessBlobGas(BlobGas.MAX_BLOB_GAS) .buildHeader(); - var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); + var resp = + resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -180,7 +185,8 @@ public void shouldReturnInvalidIfWithdrawalsIsNull_WhenWithdrawalsAllowed() { Collections.emptyList(), withdrawals, null, - null, null)); + null, + null)); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); verify(engineCallListener, times(1)).executionEngineCalled(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java index eae3223fd4c..c19bb8fbcbd 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java @@ -193,7 +193,8 @@ public void shouldValidateBlobGasUsedCorrectly() { .blobGasUsed(null) .buildHeader(); - var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); + var resp = + resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -212,7 +213,8 @@ public void shouldValidateExcessBlobGasCorrectly() { .blobGasUsed(100L) .buildHeader(); - var resp = resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); + var resp = + resp(mockEnginePayload(blockHeader, Collections.emptyList(), List.of(), null, null, null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java index 28efa560d52..9ea17213059 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV4Test.java @@ -109,7 +109,9 @@ public void shouldReturnValidIfDepositRequestsIsNull_WhenDepositRequestsProhibit .thenReturn(Optional.of(mockHeader.getHash())); var resp = - resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, depositRequests, null, null)); + resp( + mockEnginePayload( + mockHeader, Collections.emptyList(), null, depositRequests, null, null)); assertValidResponse(mockHeader, resp); } @@ -125,7 +127,8 @@ public void shouldReturnInvalidIfDepositRequestsIsNull_WhenDepositRequestsAllowe Collections.emptyList(), null, depositRequests, - null, null)); + null, + null)); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); verify(engineCallListener, times(1)).executionEngineCalled(); @@ -172,7 +175,8 @@ public void shouldReturnInvalidIfDepositRequestsIsNotNull_WhenDepositRequestsPro Collections.emptyList(), null, depositRequests, - null, null)); + null, + null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); @@ -211,7 +215,8 @@ public void shouldReturnInvalidIfWithdrawalRequestsIsNull_WhenWithdrawalRequests Collections.emptyList(), null, null, - null, null)); + null, + null)); assertThat(fromErrorResp(resp).getCode()).isEqualTo(INVALID_PARAMS.getCode()); verify(engineCallListener, times(1)).executionEngineCalled(); @@ -258,7 +263,8 @@ public void shouldReturnValidIfWithdrawalRequestsIsNotNull_WhenWithdrawalRequest Collections.emptyList(), null, null, - withdrawalRequests, null)); + withdrawalRequests, + null)); final JsonRpcError jsonRpcError = fromErrorResp(resp); assertThat(jsonRpcError.getCode()).isEqualTo(INVALID_PARAMS.getCode()); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java index c0420163de8..4b963173290 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java @@ -120,6 +120,7 @@ public void setup() { null, null, null, + null, new MainnetBlockHeaderFunctions()); testHash = fakeHeader.getHash(); final BlockBody fakeBody = new BlockBody(Collections.emptyList(), Collections.emptyList()); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java index 5772a04a49d..293c0b176ea 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java @@ -108,6 +108,7 @@ public void setup() throws IOException { null, null, null, + null, new MainnetBlockHeaderFunctions()); testHash = fakeHeader.getHash(); when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(fakeHeader)); @@ -283,6 +284,7 @@ private BlockHeader createBlock(final long number, final Optional messag null, null, null, + null, new MainnetBlockHeaderFunctions()); testHash = fakeHeader.getHash(); when(blockchain.getBlockHeader(number)).thenReturn(Optional.of(fakeHeader)); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java index 8ea903786e2..d65b99f0b11 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java @@ -22,8 +22,8 @@ import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; -import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; +import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.evm.log.LogsBloomFilter; import java.time.Instant; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java index 1298db16633..6282fb4e226 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/common/GenesisWorldStateProvider.java @@ -22,10 +22,10 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.NoOpTrieLogManager; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.cache.VerkleNoOpCachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.storage.VerkleWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.worldview.VerkleWorldState; -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.worldview.ForestMutableWorldState; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; @@ -95,7 +95,8 @@ private static MutableWorldState createGenesisVerkleWorldState() { verkleWorldStateKeyValueStorage, new VerkleNoOpCachedWorldStorageManager(verkleWorldStateKeyValueStorage), new NoOpTrieLogManager(), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); } /** diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java index 4d91341c88a..15513f987fa 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/BonsaiWorldStateProvider.java @@ -24,7 +24,6 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; -import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.patricia.StoredMerklePatriciaTrie; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.evm.internal.EvmConfiguration; @@ -153,8 +152,4 @@ public void prepareStateHealing(final Address address, final Bytes location) { getBonsaiWorldStateKeyValueStorage().downgradeToPartialFlatDbMode(); } - - private DiffBasedWorldStateConfig cloneBonsaiWorldStateConfig() { - return new DiffBasedWorldStateConfig(defaultWorldStateConfig); - } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java index 5cb06a1c311..53e9e56860a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/DiffBasedWorldStateProvider.java @@ -336,4 +336,8 @@ public void close() { // no op } } + + protected DiffBasedWorldStateConfig cloneBonsaiWorldStateConfig() { + return new DiffBasedWorldStateConfig(defaultWorldStateConfig); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java index d61b3c458e4..91338d13ca9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/trielog/TrieLogManager.java @@ -135,11 +135,12 @@ public synchronized void unsubscribe(final long id) { trieLogObservers.unsubscribe(id); } - private TrieLogFactory setupTrieLogFactory(final DataStorageFormat dataStorageFormat,final BesuContext pluginContext) { + private TrieLogFactory setupTrieLogFactory( + final DataStorageFormat dataStorageFormat, final BesuContext pluginContext) { // if we have a TrieLogService from pluginContext, use it. var trieLogServicez = - Optional.ofNullable(pluginContext) - .flatMap(context -> context.getService(TrieLogService.class)); + Optional.ofNullable(pluginContext) + .flatMap(context -> context.getService(TrieLogService.class)); if (trieLogServicez.isPresent()) { var trieLogService = trieLogServicez.get(); @@ -158,7 +159,7 @@ private TrieLogFactory setupTrieLogFactory(final DataStorageFormat dataStorageFo if (dataStorageFormat.equals(DataStorageFormat.VERKLE)) { return new TrieLogFactoryImpl(); } - //or default to BONSAI TrieLogFactoryImpl + // or default to BONSAI TrieLogFactoryImpl return new org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactoryImpl(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleWorldStateProvider.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleWorldStateProvider.java index 59c914653c1..12fd5fe51ca 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleWorldStateProvider.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/VerkleWorldStateProvider.java @@ -43,8 +43,11 @@ public VerkleWorldStateProvider( maxLayersToLoad, pluginContext); provideCachedWorldStorageManager( - new VerkleCachedWorldStorageManager(this, worldStateKeyValueStorage)); - loadPersistedState(new VerkleWorldState(this, worldStateKeyValueStorage, evmConfiguration)); + new VerkleCachedWorldStorageManager( + this, worldStateKeyValueStorage, this::cloneBonsaiWorldStateConfig)); + loadPersistedState( + new VerkleWorldState( + this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig)); } @VisibleForTesting @@ -56,6 +59,8 @@ public VerkleWorldStateProvider( final EvmConfiguration evmConfiguration) { super(worldStateKeyValueStorage, blockchain, trieLogManager); provideCachedWorldStorageManager(cachedWorldStorageManager); - loadPersistedState(new VerkleWorldState(this, worldStateKeyValueStorage, evmConfiguration)); + loadPersistedState( + new VerkleWorldState( + this, worldStateKeyValueStorage, evmConfiguration, defaultWorldStateConfig)); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleCachedWorldStorageManager.java index d180b7b7e2b..8d123a4aee4 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleCachedWorldStorageManager.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCachedWorldStorageManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.VerkleWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.storage.VerkleLayeredWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.storage.VerkleSnapshotWorldStateKeyValueStorage; @@ -25,12 +26,15 @@ import org.hyperledger.besu.ethereum.trie.diffbased.verkle.worldview.VerkleWorldState; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import java.util.function.Supplier; + public class VerkleCachedWorldStorageManager extends DiffBasedCachedWorldStorageManager { public VerkleCachedWorldStorageManager( final DiffBasedWorldStateProvider archive, - final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage) { - super(archive, worldStateKeyValueStorage); + final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage, + final Supplier defaultBonsaiWorldStateConfigSupplier) { + super(archive, worldStateKeyValueStorage, defaultBonsaiWorldStateConfigSupplier); } @Override @@ -41,7 +45,8 @@ public DiffBasedWorldState createWorldState( return new VerkleWorldState( (VerkleWorldStateProvider) archive, (VerkleWorldStateKeyValueStorage) worldStateKeyValueStorage, - evmConfiguration); + evmConfiguration, + defaultBonsaiWorldStateConfigSupplier.get()); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleNoOpCachedWorldStorageManager.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleNoOpCachedWorldStorageManager.java index 67810ce0a46..be8085af7d0 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleNoOpCachedWorldStorageManager.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/cache/VerkleNoOpCachedWorldStorageManager.java @@ -17,6 +17,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; 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.verkle.storage.VerkleWorldStateKeyValueStorage; import java.util.Optional; @@ -26,7 +27,7 @@ public class VerkleNoOpCachedWorldStorageManager extends VerkleCachedWorldStorag public VerkleNoOpCachedWorldStorageManager( final VerkleWorldStateKeyValueStorage verkleWorldStateKeyValueStorage) { - super(null, verkleWorldStateKeyValueStorage); + super(null, verkleWorldStateKeyValueStorage, DiffBasedWorldStateConfig::new); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java index b095b86b9f1..3e3bf89bd1c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/worldview/VerkleWorldState.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.common.trielog.TrieLogManager; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; +import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; 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.verkle.VerkleAccount; @@ -67,20 +68,27 @@ public class VerkleWorldState extends DiffBasedWorldState { public VerkleWorldState( final VerkleWorldStateProvider archive, final VerkleWorldStateKeyValueStorage worldStateKeyValueStorage, - final EvmConfiguration evmConfiguration) { + final EvmConfiguration evmConfiguration, + final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { this( worldStateKeyValueStorage, archive.getCachedWorldStorageManager(), archive.getTrieLogManager(), - evmConfiguration); + evmConfiguration, + diffBasedWorldStateConfig); } public VerkleWorldState( final VerkleWorldStateKeyValueStorage worldStateKeyValueStorage, final DiffBasedCachedWorldStorageManager cachedWorldStorageManager, final TrieLogManager trieLogManager, - final EvmConfiguration evmConfiguration) { - super(worldStateKeyValueStorage, cachedWorldStorageManager, trieLogManager); + final EvmConfiguration evmConfiguration, + final DiffBasedWorldStateConfig diffBasedWorldStateConfig) { + super( + worldStateKeyValueStorage, + cachedWorldStorageManager, + trieLogManager, + diffBasedWorldStateConfig); this.trieKeyPreloader = new TrieKeyPreloader(); this.setAccumulator( new VerkleWorldStateUpdateAccumulator( @@ -360,7 +368,7 @@ private void updateAccountStorageState( @Override public MutableWorldState freeze() { - this.isFrozen = true; + this.worldStateConfig.setFrozen(true); this.worldStateKeyValueStorage = new VerkleLayeredWorldStateKeyValueStorage(getWorldStateStorage()); return this; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/LogRollingTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/LogRollingTests.java index 9db0811f70c..a474fe412ff 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/LogRollingTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/verkle/LogRollingTests.java @@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; 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.trie.diffbased.verkle.storage.VerkleWorldStateKeyValueStorage; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.trielog.TrieLogFactoryImpl; import org.hyperledger.besu.ethereum.trie.diffbased.verkle.worldview.VerkleWorldState; @@ -217,7 +218,8 @@ void rollForwardComparedWithTestnet() { // TODO change the name new VerkleWorldState( archive, new VerkleWorldStateKeyValueStorage(provider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount contract = @@ -243,7 +245,8 @@ void simpleRollForwardTest() { new VerkleWorldState( archive, new VerkleWorldStateKeyValueStorage(provider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -256,7 +259,8 @@ void simpleRollForwardTest() { new VerkleWorldState( secondArchive, new VerkleWorldStateKeyValueStorage(secondProvider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final VerkleWorldStateUpdateAccumulator secondUpdater = (VerkleWorldStateUpdateAccumulator) secondWorldState.updater(); @@ -287,7 +291,8 @@ void rollForwardTwice() { new VerkleWorldState( archive, new VerkleWorldStateKeyValueStorage(provider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -308,7 +313,8 @@ void rollForwardTwice() { new VerkleWorldState( secondArchive, new VerkleWorldStateKeyValueStorage(secondProvider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final VerkleWorldStateUpdateAccumulator secondUpdater = (VerkleWorldStateUpdateAccumulator) secondWorldState.updater(); @@ -340,7 +346,8 @@ void rollBackOnce() { new VerkleWorldState( archive, new VerkleWorldStateKeyValueStorage(provider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -368,7 +375,8 @@ void rollBackOnce() { new VerkleWorldState( secondArchive, new VerkleWorldStateKeyValueStorage(secondProvider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater secondUpdater = secondWorldState.updater(); final MutableAccount secondMutableAccount = @@ -397,7 +405,8 @@ void rollBackTwice() { new VerkleWorldState( archive, new VerkleWorldStateKeyValueStorage(provider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -437,7 +446,8 @@ void rollBackFourTimes() { new VerkleWorldState( archive, new VerkleWorldStateKeyValueStorage(provider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); @@ -507,7 +517,8 @@ void rollingWithRemovedStorageValue() { new VerkleWorldState( archive, new VerkleWorldStateKeyValueStorage(provider, new NoOpMetricsSystem()), - EvmConfiguration.DEFAULT); + EvmConfiguration.DEFAULT, + new DiffBasedWorldStateConfig()); final WorldUpdater updater = worldState.updater(); final MutableAccount mutableAccount = updater.createAccount(addressOne, 1, Wei.of(1L)); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java index 270ab86109a..7d93b4c108e 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java @@ -1442,6 +1442,7 @@ public static class Builder { private Optional> versionedHashes = Optional.empty(); private AccessWitness accessWitness = null; + /** Instantiates a new Builder. */ public Builder() {} diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java index e6e58ae27a6..c3d13d6abf8 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java @@ -100,15 +100,16 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { } else { account.incrementNonce(); + System.out.println("aalloo"); final Bytes inputData = frame.readMemory(inputOffset, inputSize); // Never cache CREATEx initcode. The amount of reuse is very low, and caching mostly // addresses disk loading delay, and we already have the code. Code code = evm.getCodeUncached(inputData); - final Address contractAddress = targetContractAddress(frame, code); final Wei contractValue = Wei.wrap(frame.getStackItem(0)); if (code.isValid() && frame.getCode().getEofVersion() <= code.getEofVersion()) { + final Address contractAddress = targetContractAddress(frame, code); frame.decrementRemainingGas(statelessCost(frame, contractAddress, contractValue)); frame.decrementRemainingGas(cost); spawnChildMessage(frame, contractAddress, contractValue, code, evm);