Merge branch 'main' into zkbesu

# Conflicts:
#	.github/workflows/acceptance-tests.yml
#	.github/workflows/pre-review.yml
#	.github/workflows/splitTestsByTime.sh
#	build.gradle
#	gradle/verification-metadata.xml
This commit is contained in:
Fabio Di Fabio
2024-05-29 10:01:00 +02:00
120 changed files with 2686 additions and 1499 deletions

View File

@@ -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 --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
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-*.xml'

View File

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

View File

@@ -180,11 +180,10 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.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,

View File

@@ -274,7 +274,9 @@ public class PrivacyNode implements AutoCloseable {
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(

View File

@@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.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 @@ public class Runner implements AutoCloseable {
return networkRunner.getNetwork().getLocalEnode();
}
/**
* get P2PNetwork service.
*
* @return p2p network service.
*/
public P2PNetwork getP2PNetwork() {
return networkRunner.getNetwork();
}
@FunctionalInterface
private interface SynchronousShutdown {
/**

View File

@@ -172,21 +172,29 @@ import org.hyperledger.besu.plugin.services.TransactionSimulationService;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.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 class BesuCommand implements DefaultCommandValues, Runnable {
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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
pidPath);
}
private void startPlugins() {
private void startPlugins(final Runner runner) {
blockchainServiceImpl.init(
besuController.getProtocolContext(), besuController.getProtocolSchedule());
transactionSimulationServiceImpl.init(
@@ -1348,6 +1359,26 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
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 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
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 class BesuCommand implements DefaultCommandValues, Runnable {
* @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())

View File

@@ -475,6 +475,15 @@ public class JsonRpcHttpOptions {
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.
*

View File

@@ -28,10 +28,17 @@ public class ChainPruningOptions implements CLIOptions<ChainPrunerConfiguration>
private static final String CHAIN_PRUNING_ENABLED_FLAG = "--Xchain-pruning-enabled";
private static final String CHAIN_PRUNING_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<ChainPrunerConfiguration>
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 =
DEFAULT_CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED;
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 chainDataPruningBlocksRetainedLimit =
CHAIN_DATA_PRUNING_MIN_BLOCKS_RETAINED_LIMIT;
@CommandLine.Option(
hidden = true,
@@ -91,11 +108,21 @@ public class ChainPruningOptions implements CLIOptions<ChainPrunerConfiguration>
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 class ChainPruningOptions implements CLIOptions<ChainPrunerConfiguration>
chainDataPruningEnabled.toString(),
CHAIN_PRUNING_BLOCKS_RETAINED_FLAG,
chainDataPruningBlocksRetained.toString(),
CHAIN_PRUNING_BLOCKS_RETAINED_LIMIT_FLAG,
chainDataPruningBlocksRetainedLimit.toString(),
CHAIN_PRUNING_FREQUENCY_FLAG,
chainDataPruningBlocksFrequency.toString());
}

View File

@@ -610,16 +610,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
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 abstract class BesuControllerBuilder implements MiningParameterOverrides
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,

View File

@@ -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.BesuConfiguration;
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<String> rpcHttpHost = Optional.of("http://localhost");
private Optional<Integer> rpcHttpPort = Optional.of(8545);
/** Default Constructor. */
public BesuConfigurationImpl() {}
@@ -38,17 +44,49 @@ public class BesuConfigurationImpl implements BesuConfiguration {
* @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<String> getRpcHttpHost() {
return rpcHttpHost;
}
@Override
public Optional<Integer> getRpcHttpPort() {
return rpcHttpPort;
}
@Override

View File

@@ -114,6 +114,11 @@ public class BesuEventsImpl implements BesuEvents {
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);

View File

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

View File

@@ -17,17 +17,22 @@ package org.hyperledger.besu.services;
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 class BlockchainServiceImpl implements BlockchainService {
public void init(final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule) {
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
this.blockchain = protocolContext.getBlockchain();
}
/**
@@ -91,6 +95,43 @@ public class BlockchainServiceImpl implements BlockchainService {
feeMarket.targetGasUsed(chainHeadHeader)));
}
@Override
public Optional<List<TransactionReceipt>> getReceiptsByBlockHash(final Hash blockHash) {
return blockchain
.getTxReceipts(blockHash)
.map(
list -> list.stream().map(TransactionReceipt.class::cast).collect(Collectors.toList()));
}
@Override
public void storeBlock(
final BlockHeader blockHeader,
final BlockBody blockBody,
final List<TransactionReceipt> receipts) {
final org.hyperledger.besu.ethereum.core.BlockHeader coreHeader =
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader;
final org.hyperledger.besu.ethereum.core.BlockBody coreBody =
(org.hyperledger.besu.ethereum.core.BlockBody) blockBody;
final List<org.hyperledger.besu.ethereum.core.TransactionReceipt> coreReceipts =
receipts.stream()
.map(org.hyperledger.besu.ethereum.core.TransactionReceipt.class::cast)
.toList();
blockchain.unsafeImportBlock(
new Block(coreHeader, coreBody),
coreReceipts,
Optional.ofNullable(blockchain.calculateTotalDifficulty(coreHeader)));
}
@Override
public Optional<Hash> getSafeBlock() {
return blockchain.getSafeBlock();
}
@Override
public Optional<Hash> getFinalizedBlock() {
return blockchain.getFinalized();
}
private static BlockContext blockContext(
final Supplier<BlockHeader> blockHeaderSupplier,
final Supplier<BlockBody> blockBodySupplier) {

View File

@@ -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();
}
}

View File

@@ -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));
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.services;
import org.hyperledger.besu.consensus.merge.MergeContext;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.data.BlockBody;
import org.hyperledger.besu.plugin.data.BlockHeader;
import org.hyperledger.besu.plugin.services.sync.SynchronizationService;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Synchronization service. */
public class SynchronizationServiceImpl implements SynchronizationService {
private static final Logger LOG = LoggerFactory.getLogger(SynchronizationServiceImpl.class);
private final ProtocolContext protocolContext;
private final ProtocolSchedule protocolSchedule;
private final SyncState syncState;
private final Optional<DiffBasedWorldStateProvider> worldStateArchive;
/**
* Constructor for SynchronizationServiceImpl.
*
* @param protocolContext protocol context
* @param protocolSchedule protocol schedule
* @param syncState sync state
* @param worldStateArchive world state archive
*/
public SynchronizationServiceImpl(
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final SyncState syncState,
final WorldStateArchive worldStateArchive) {
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
this.syncState = syncState;
this.worldStateArchive =
Optional.ofNullable(worldStateArchive)
.filter(z -> z instanceof DiffBasedWorldStateProvider)
.map(DiffBasedWorldStateProvider.class::cast);
}
@Override
public void fireNewUnverifiedForkchoiceEvent(
final Hash head, final Hash safeBlock, final Hash finalizedBlock) {
final MergeContext mergeContext = protocolContext.getConsensusContext(MergeContext.class);
if (mergeContext != null) {
mergeContext.fireNewUnverifiedForkchoiceEvent(head, safeBlock, finalizedBlock);
protocolContext.getBlockchain().setFinalized(finalizedBlock);
protocolContext.getBlockchain().setSafeBlock(safeBlock);
} else {
LOG.atWarn()
.setMessage(
"The merge context is unavailable, hence the fork choice event cannot be triggered")
.log();
}
}
@Override
public boolean setHead(final BlockHeader blockHeader, final BlockBody blockBody) {
final BlockImporter blockImporter =
protocolSchedule
.getByBlockHeader((org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader)
.getBlockImporter();
return blockImporter
.importBlock(
protocolContext,
new Block(
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader,
(org.hyperledger.besu.ethereum.core.BlockBody) blockBody),
HeaderValidationMode.SKIP_DETACHED)
.isImported();
}
@Override
public boolean setHeadUnsafe(final BlockHeader blockHeader, final BlockBody blockBody) {
final org.hyperledger.besu.ethereum.core.BlockHeader coreHeader =
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader;
final MutableBlockchain blockchain = protocolContext.getBlockchain();
if (worldStateArchive.flatMap(archive -> archive.getMutable(coreHeader, true)).isPresent()) {
if (coreHeader.getParentHash().equals(blockchain.getChainHeadHash())) {
LOG.atDebug()
.setMessage(
"Forwarding chain head to the block {} saved from a previous newPayload invocation")
.addArgument(coreHeader::toLogString)
.log();
return blockchain.forwardToBlock(coreHeader);
} else {
LOG.atDebug()
.setMessage("New head {} is a chain reorg, rewind chain head to it")
.addArgument(coreHeader::toLogString)
.log();
return blockchain.rewindToBlock(coreHeader.getBlockHash());
}
} else {
LOG.atWarn()
.setMessage("The world state is unavailable, setting of head cannot be performed.")
.log();
}
return false;
}
@Override
public boolean isInitialSyncPhaseDone() {
return syncState.isInitialSyncPhaseDone();
}
@Override
public void disableWorldStateTrie() {
// TODO maybe find a best way in the future to delete and disable trie
worldStateArchive.ifPresent(
archive -> {
archive.getDefaultWorldStateConfig().setTrieDisabled(true);
final DiffBasedWorldStateKeyValueStorage worldStateStorage =
archive.getWorldStateKeyValueStorage();
final Optional<Hash> worldStateBlockHash = worldStateStorage.getWorldStateBlockHash();
final Optional<Bytes> worldStateRootHash = worldStateStorage.getWorldStateRootHash();
if (worldStateRootHash.isPresent() && worldStateBlockHash.isPresent()) {
worldStateStorage.clearTrie();
// keep root and block hash in the trie branch
final DiffBasedWorldStateKeyValueStorage.Updater updater = worldStateStorage.updater();
updater.saveWorldState(
worldStateBlockHash.get(), Bytes32.wrap(worldStateRootHash.get()), Bytes.EMPTY);
updater.commit();
// currently only bonsai needs an explicit upgrade to full flat db
if (worldStateStorage instanceof BonsaiWorldStateKeyValueStorage bonsaiStorage) {
bonsaiStorage.upgradeToFullFlatDbMode();
}
}
});
}
}

View File

@@ -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();
}
}

View File

@@ -137,7 +137,9 @@ public class PrivacyTest {
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(

View File

@@ -391,7 +391,9 @@ public final class RunnerTest {
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(

View File

@@ -127,6 +127,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
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;

View File

@@ -30,7 +30,6 @@ import org.hyperledger.besu.consensus.common.bft.blockcreation.BftMiningCoordina
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

View File

@@ -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());
}
}

View File

@@ -23,10 +23,10 @@ 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 '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 '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'

View File

@@ -30,7 +30,6 @@ import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreatorFa
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftMiningCoordinator;
import org.hyperledger.besu.consensus.common.bft.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 class MigratingMiningCoordinatorTest {
@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);

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.datatypes;
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 final class BlobGas extends BaseUInt64Value<BlobGas> implements Quantity
return toBigInteger();
}
@JsonValue
@Override
public String toHexString() {
return super.toHexString();
@@ -140,6 +142,6 @@ public final class BlobGas extends BaseUInt64Value<BlobGas> implements Quantity
* @return the blob gas
*/
public static BlobGas fromQuantity(final Quantity quantity) {
return BlobGas.wrap((Bytes) quantity);
return BlobGas.of(quantity.getAsBigInteger());
}
}

View File

@@ -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 enum RequestType {
* 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));
};
}
}

View File

@@ -35,7 +35,7 @@ import org.hyperledger.besu.ethereum.BlockProcessingResult;
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 abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
reqId, new JsonRpcError(INVALID_PARAMS, "Invalid withdrawals"));
}
final Optional<List<Request>> maybeDeposits =
Optional.ofNullable(blockParam.getDeposits())
.map(ds -> ds.stream().map(DepositParameter::toDeposit).collect(toList()));
final Optional<List<Request>> 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 abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
}
Optional<List<Request>> maybeRequests =
RequestUtil.combine(maybeDeposits, maybeWithdrawalRequests);
RequestUtil.combine(maybeDepositRequests, maybeWithdrawalRequests);
if (mergeContext.get().isSyncing()) {
LOG.debug("We are syncing");

View File

@@ -63,7 +63,7 @@ public class EngineNewPayloadV4 extends AbstractEngineNewPayload {
} 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();

View File

@@ -66,6 +66,6 @@ public class RequestValidatorProvider {
final ProtocolSpec protocolSchedule) {
return Optional.ofNullable(protocolSchedule)
.map(ProtocolSpec::getRequestsValidatorCoordinator)
.orElseGet(() -> new RequestsValidatorCoordinator.Builder().build());
.orElseGet(RequestsValidatorCoordinator::empty);
}
}

View File

@@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters;
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 io.vertx.core.json.JsonObject;
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 class 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 class DepositParameter {
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 class DepositParameter {
@Override
public String toString() {
return "DepositParameter{"
return "DepositRequestParameter{"
+ "pubKey='"
+ pubkey
+ '\''

View File

@@ -43,7 +43,7 @@ public class EnginePayloadParameter {
private final List<WithdrawalParameter> withdrawals;
private final Long blobGasUsed;
private final String excessBlobGas;
private final List<DepositParameter> deposits;
private final List<DepositRequestParameter> depositRequests;
private final List<WithdrawalRequestParameter> 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 class EnginePayloadParameter {
@JsonProperty("withdrawals") final List<WithdrawalParameter> withdrawals,
@JsonProperty("blobGasUsed") final UnsignedLongParameter blobGasUsed,
@JsonProperty("excessBlobGas") final String excessBlobGas,
@JsonProperty("depositRequests") final List<DepositParameter> deposits,
@JsonProperty("depositRequests") final List<DepositRequestParameter> depositRequests,
@JsonProperty("withdrawalRequests")
final List<WithdrawalRequestParameter> withdrawalRequestParameters) {
this.blockHash = blockHash;
@@ -108,7 +108,7 @@ public class 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 class EnginePayloadParameter {
return excessBlobGas;
}
public List<DepositParameter> getDeposits() {
return deposits;
public List<DepositRequestParameter> getDepositRequests() {
return depositRequests;
}
public List<WithdrawalRequestParameter> getWithdrawalRequests() {

View File

@@ -45,7 +45,7 @@ public class WithdrawalRequestParameter {
final WithdrawalRequest withdrawalRequest) {
return new WithdrawalRequestParameter(
withdrawalRequest.getSourceAddress().toHexString(),
withdrawalRequest.getValidatorPubKey().toHexString(),
withdrawalRequest.getValidatorPublicKey().toHexString(),
withdrawalRequest.getAmount().toShortHexString());
}
@@ -92,7 +92,7 @@ public class WithdrawalRequestParameter {
+ "sourceAddress='"
+ sourceAddress
+ '\''
+ ", validatorPubKey='"
+ ", validatorPublicKey='"
+ validatorPublicKey
+ '\''
+ ", amount='"

View File

@@ -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.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.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 class BlockResultFactory {
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<List<Deposit>> getDepositRequest(final Optional<List<Request>> requests) {
return requests.map(
requestList -> RequestUtil.filterRequestsOfType(requestList, Deposit.class));
}
private Optional<List<WithdrawalRequest>> getWithdrawalRequest(
final Optional<List<Request>> requests) {
return requests.map(
requestList -> RequestUtil.filterRequestsOfType(requestList, WithdrawalRequest.class));
}
public BlockResult transactionHash(final BlockWithMetadata<Hash, Hash> blockWithMetadata) {
return transactionHash(blockWithMetadata, false);
}

View File

@@ -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 class EngineGetPayloadResultV4 {
final BlockHeader header,
final List<String> transactions,
final Optional<List<Withdrawal>> withdrawals,
final Optional<List<Deposit>> deposits,
final Optional<List<DepositRequest>> depositRequests,
final Optional<List<WithdrawalRequest>> 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 class EngineGetPayloadResultV4 {
protected final List<String> transactions;
private final List<WithdrawalParameter> withdrawals;
private final List<DepositParameter> deposits;
private final List<DepositRequestParameter> depositRequests;
private final List<WithdrawalRequestParameter> withdrawalRequests;
public PayloadResult(
final BlockHeader header,
final List<String> transactions,
final Optional<List<Withdrawal>> withdrawals,
final Optional<List<Deposit>> deposits,
final Optional<List<DepositRequest>> depositRequests,
final Optional<List<WithdrawalRequest>> withdrawalRequests) {
this.blockNumber = Quantity.create(header.getNumber());
this.blockHash = header.getHash().toString();
@@ -125,10 +125,13 @@ public class EngineGetPayloadResultV4 {
.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 class EngineGetPayloadResultV4 {
}
@JsonGetter(value = "depositRequests")
public List<DepositParameter> getDeposits() {
return deposits;
public List<DepositRequestParameter> getDepositRequests() {
return depositRequests;
}
@JsonGetter(value = "withdrawalRequests")

View File

@@ -105,7 +105,7 @@ public abstract class AbstractEngineGetPayloadTest extends AbstractScheduledApiT
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 abstract class AbstractEngineGetPayloadTest extends AbstractScheduledApiT
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;

View File

@@ -38,7 +38,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
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.Block;
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 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
final BlockHeader header,
final List<String> txs,
final List<WithdrawalParameter> withdrawals,
final List<DepositParameter> deposits,
final List<DepositRequestParameter> depositRequests,
final List<WithdrawalRequestParameter> withdrawalRequests) {
return new EnginePayloadParameter(
header.getHash(),
@@ -430,18 +430,18 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
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<List<Withdrawal>> maybeWithdrawals,
final Optional<List<Deposit>> maybeDeposits,
final Optional<List<DepositRequest>> maybeDepositRequests,
final Optional<List<WithdrawalRequest>> 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 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
protected BlockHeader createBlockHeader(
final Optional<List<Withdrawal>> maybeWithdrawals,
final Optional<List<Deposit>> maybeDeposits,
final Optional<List<DepositRequest>> maybeDepositRequests,
final Optional<List<WithdrawalRequest>> maybeWithdrawalRequests) {
return createBlockHeaderFixture(maybeWithdrawals, maybeDeposits, maybeWithdrawalRequests)
return createBlockHeaderFixture(maybeWithdrawals, maybeDepositRequests, maybeWithdrawalRequests)
.buildHeader();
}
protected BlockHeaderTestFixture createBlockHeaderFixture(
final Optional<List<Withdrawal>> maybeWithdrawals,
final Optional<List<Deposit>> maybeDeposits,
final Optional<List<DepositRequest>> maybeDepositRequests,
final Optional<List<WithdrawalRequest>> maybeWithdrawalRequests) {
Optional<List<Request>> maybeRequests;
if (maybeDeposits.isPresent() || maybeWithdrawalRequests.isPresent()) {
if (maybeDepositRequests.isPresent() || maybeWithdrawalRequests.isPresent()) {
List<Request> requests = new ArrayList<>();
maybeDeposits.ifPresent(requests::addAll);
maybeDepositRequests.ifPresent(requests::addAll);
maybeWithdrawalRequests.ifPresent(requests::addAll);
maybeRequests = Optional.of(requests);
} else {
@@ -521,7 +521,7 @@ public abstract class AbstractEngineNewPayloadTest extends AbstractScheduledApiT
}
private void mockProhibitedRequestsValidator() {
var validator = new RequestsValidatorCoordinator.Builder().build();
var validator = RequestsValidatorCoordinator.empty();
when(protocolSpec.getRequestsValidatorCoordinator()).thenReturn(validator);
}
}

View File

@@ -71,7 +71,7 @@ public class EngineGetPayloadV4Test extends AbstractEngineGetPayloadTest {
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 class EngineGetPayloadV4Test extends AbstractEngineGetPayloadTest {
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());

View File

@@ -44,7 +44,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EnginePayloadS
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 class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
@Override
protected BlockHeader createBlockHeader(
final Optional<List<Withdrawal>> maybeWithdrawals,
final Optional<List<Deposit>> maybeDeposits,
final Optional<List<DepositRequest>> maybeDepositRequests,
final Optional<List<WithdrawalRequest>> maybeWithdrawalRequests) {
BlockHeader parentBlockHeader =
new BlockHeaderTestFixture()

View File

@@ -33,19 +33,19 @@ import org.hyperledger.besu.ethereum.BlockProcessingOutputs;
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 class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
}
@Test
public void shouldReturnValidIfDepositsIsNull_WhenDepositsProhibited() {
final List<DepositParameter> deposits = null;
public void shouldReturnValidIfDepositRequestsIsNull_WhenDepositRequestsProhibited() {
final List<DepositRequestParameter> depositRequests = null;
mockProhibitedRequestsValidator();
BlockHeader mockHeader =
@@ -108,22 +108,23 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
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<DepositParameter> deposits = null;
mockAllowedDepositsRequestValidator();
public void shouldReturnInvalidIfDepositRequestsIsNull_WhenDepositRequestsAllowed() {
final List<DepositRequestParameter> 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 class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
}
@Test
public void shouldReturnValidIfDepositsIsNotNull_WhenDepositsAllowed() {
final List<DepositParameter> depositsParam = List.of(DEPOSIT_PARAM_1);
final List<Request> deposits = List.of(DEPOSIT_PARAM_1.toDeposit());
public void shouldReturnValidIfDepositRequestsIsNotNull_WhenDepositRequestsAllowed() {
final List<DepositRequestParameter> depositRequestsParam = List.of(DEPOSIT_PARAM_1);
final List<Request> 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,17 +150,19 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
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<DepositParameter> deposits = List.of();
public void shouldReturnInvalidIfDepositRequestsIsNotNull_WhenDepositRequestsProhibited() {
final List<DepositRequestParameter> depositRequests = List.of();
lenient()
.when(protocolSpec.getRequestsValidatorCoordinator())
.thenReturn(new RequestsValidatorCoordinator.Builder().build());
.thenReturn(RequestsValidatorCoordinator.empty());
var resp =
resp(
@@ -167,7 +171,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
Optional.empty(), Optional.of(Collections.emptyList()), Optional.empty()),
Collections.emptyList(),
null,
deposits,
depositRequests,
null));
final JsonRpcError jsonRpcError = fromErrorResp(resp);
@@ -264,7 +268,7 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
@Override
protected BlockHeader createBlockHeader(
final Optional<List<Withdrawal>> maybeWithdrawals,
final Optional<List<Deposit>> maybeDeposits,
final Optional<List<DepositRequest>> maybeDepositRequests,
final Optional<List<WithdrawalRequest>> maybeWithdrawalRequests) {
BlockHeader parentBlockHeader =
new BlockHeaderTestFixture()
@@ -275,9 +279,9 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
.buildHeader();
Optional<List<Request>> maybeRequests;
if (maybeDeposits.isPresent() || maybeWithdrawalRequests.isPresent()) {
if (maybeDepositRequests.isPresent() || maybeWithdrawalRequests.isPresent()) {
List<Request> requests = new ArrayList<>();
maybeDeposits.ifPresent(requests::addAll);
maybeDepositRequests.ifPresent(requests::addAll);
maybeWithdrawalRequests.ifPresent(requests::addAll);
maybeRequests = Optional.of(requests);
} else {
@@ -311,14 +315,14 @@ public class EngineNewPayloadV4Test extends EngineNewPayloadV3Test {
}
private void mockProhibitedRequestsValidator() {
var validator = new RequestsValidatorCoordinator.Builder().build();
var validator = RequestsValidatorCoordinator.empty();
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);
}

View File

@@ -16,14 +16,14 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters;
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);
}
}

View File

@@ -20,18 +20,18 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.Depo
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 class DepositParameterTest {
@Test
public void fromDeposit() {
Deposit deposit =
new Deposit(
DepositRequest depositRequest =
new DepositRequest(
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
Bytes32.fromHexString(
@@ -56,6 +56,6 @@ public class DepositParameterTest {
"0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"),
UInt64.ONE);
assertThat(DepositParameter.fromDeposit(deposit)).isEqualTo(DEPOSIT_PARAM_1);
assertThat(DepositRequestParameter.fromDeposit(depositRequest)).isEqualTo(DEPOSIT_PARAM_1);
}
}

View File

@@ -47,7 +47,7 @@ import org.hyperledger.besu.ethereum.core.BlobTestFixture;
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.ProtocolSpecAdapters;
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 @@ abstract class AbstractBlockCreatorTest {
List<TransactionReceipt> receipts =
List.of(receiptWithoutDeposit1, receiptWithDeposit, receiptWithoutDeposit2);
Deposit expectedDeposit =
new Deposit(
DepositRequest expectedDepositRequest =
new DepositRequest(
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
Bytes32.fromHexString(
@@ -132,17 +132,17 @@ abstract class AbstractBlockCreatorTest {
BLSSignature.fromHexString(
"0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"),
UInt64.valueOf(539967));
final List<Deposit> expectedDeposits = List.of(expectedDeposit);
final List<DepositRequest> expectedDepositRequests = List.of(expectedDepositRequest);
final Optional<List<Request>> 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 @@ abstract class AbstractBlockCreatorTest {
1L,
false);
List<Request> deposits = emptyList();
final Hash requestsRoot = BodyValidation.requestsRoot(deposits);
List<Request> 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 @@ abstract class AbstractBlockCreatorTest {
}
@Test
void withProhibitedDeposits_DepositsAreNotParsed() {
final AbstractBlockCreator blockCreator = blockCreatorWithProhibitedDeposits();
void withProhibitedDepositRequests_DepositRequestsAreNotParsed() {
final AbstractBlockCreator blockCreator = blockCreatorWithProhibitedDepositRequests();
final BlockCreationResult blockCreationResult =
blockCreator.createBlock(
@@ -196,7 +196,7 @@ abstract class AbstractBlockCreatorTest {
assertThat(blockCreationResult.getBlock().getBody().getRequests()).isEmpty();
}
private AbstractBlockCreator blockCreatorWithAllowedDeposits(
private AbstractBlockCreator blockCreatorWithAllowedDepositRequests(
final Address depositContractAddress) {
final ProtocolSpecAdapters protocolSpecAdapters =
ProtocolSpecAdapters.create(
@@ -207,7 +207,7 @@ abstract class AbstractBlockCreatorTest {
new RequestsValidatorCoordinator.Builder()
.addValidator(
RequestType.DEPOSIT,
new DepositsValidator((depositContractAddress)))
new DepositRequestValidator((depositContractAddress)))
.build())
.requestProcessorCoordinator(
new RequestProcessorCoordinator.Builder()
@@ -218,7 +218,7 @@ abstract class AbstractBlockCreatorTest {
return createBlockCreator(protocolSpecAdapters);
}
private AbstractBlockCreator blockCreatorWithProhibitedDeposits() {
private AbstractBlockCreator blockCreatorWithProhibitedDepositRequests() {
final ProtocolSpecAdapters protocolSpecAdapters =
ProtocolSpecAdapters.create(0, specBuilder -> specBuilder);
return createBlockCreator(protocolSpecAdapters);

View File

@@ -16,15 +16,20 @@ package org.hyperledger.besu.ethereum.chain;
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 class ChainPrunerConfiguration {
return blocksRetained;
}
public long getBlocksRetainedLimit() {
return blocksRetainedLimit;
}
public boolean getChainPruningEnabled() {
return enabled;
}

View File

@@ -469,7 +469,8 @@ public class DefaultBlockchain implements MutableBlockchain {
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();
}

View File

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

View File

@@ -147,7 +147,7 @@ public class BlockBody implements org.hyperledger.besu.plugin.data.BlockBody {
/**
* 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

View File

@@ -309,7 +309,7 @@ public class BlockHeader extends SealableBlockHeader
.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()

View File

@@ -25,7 +25,8 @@ import java.util.Objects;
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 class Deposit extends Request implements org.hyperledger.besu.plugin.data
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)

View File

@@ -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 class WithdrawalRequest extends Request
}
@Override
public PublicKey getValidatorPubKey() {
return validatorPubKey;
public PublicKey getValidatorPublicKey() {
return validatorPublicKey;
}
@Override
@@ -61,8 +61,8 @@ public class WithdrawalRequest extends Request
return "WithdrawalRequest{"
+ "sourceAddress="
+ sourceAddress
+ " validatorPubKey="
+ validatorPubKey
+ " validatorPublicKey="
+ validatorPublicKey
+ " amount="
+ amount
+ '}';
@@ -78,12 +78,12 @@ public class WithdrawalRequest extends Request
}
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);
}
}

View File

@@ -17,8 +17,8 @@ package org.hyperledger.besu.ethereum.core.encoding;
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.bytes.Bytes32;
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 class DepositDecoder {
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 class DepositDecoder {
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 class DepositDecoder {
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));
}
}

View File

@@ -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();
}

View File

@@ -41,7 +41,7 @@ public class RequestDecoder {
RequestType.WITHDRAWAL,
WithdrawalRequestDecoder::decode,
RequestType.DEPOSIT,
DepositDecoder::decode);
DepositRequestDecoder::decode);
/**
* Decodes a request from its RLP encoded bytes.

View File

@@ -38,7 +38,7 @@ public class RequestEncoder {
RequestType.WITHDRAWAL,
WithdrawalRequestEncoder::encode,
RequestType.DEPOSIT,
DepositEncoder::encode);
DepositRequestEncoder::encode);
/**
* Encodes a Request into the provided RLPOutput.

View File

@@ -48,7 +48,7 @@ public class WithdrawalRequestEncoder {
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();
}

View File

@@ -89,7 +89,7 @@ public final class BodyValidation {
}
/**
* 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

View File

@@ -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();

View File

@@ -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 class WithdrawalRequestContractHelper {
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();
}
@@ -150,7 +153,7 @@ public class WithdrawalRequestContractHelper {
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 +165,7 @@ public class WithdrawalRequestContractHelper {
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;

View File

@@ -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;
@@ -39,24 +39,25 @@ public class DepositRequestProcessor implements RequestProcessor {
}
@Override
public Optional<List<Request>> process(
public Optional<List<? extends Request>> process(
final MutableWorldState ignored, final List<TransactionReceipt> transactionReceipts) {
if (depositContractAddress.isEmpty()) {
return Optional.empty();
}
List<Deposit> deposits = findDepositsFromReceipts(transactionReceipts);
return Optional.of(deposits.stream().map(r -> (Request) r).toList());
List<DepositRequest> depositRequests = findDepositRequestsFromReceipts(transactionReceipts);
return Optional.of(depositRequests);
}
@VisibleForTesting
List<Deposit> findDepositsFromReceipts(final List<TransactionReceipt> transactionReceipts) {
List<DepositRequest> findDepositRequestsFromReceipts(
final List<TransactionReceipt> 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());
}

View File

@@ -14,59 +14,64 @@
*/
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;
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;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
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<List<Request>> deposits) {
return deposits.isPresent();
public boolean validateParameter(final Optional<List<Request>> depositRequests) {
return depositRequests.isPresent();
}
public boolean validateDeposits(
public boolean validateDepositRequests(
final Block block,
final List<Deposit> actualDeposits,
final List<DepositRequest> actualDepositRequests,
final List<TransactionReceipt> receipts) {
List<Deposit> expectedDeposits = new ArrayList<>();
List<DepositRequest> 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;
@@ -75,7 +80,7 @@ public class DepositsValidator implements RequestValidator {
@Override
public boolean validate(
final Block block, final List<Request> requests, final List<TransactionReceipt> receipts) {
var deposits = RequestUtil.filterRequestsOfType(requests, Deposit.class);
return validateDeposits(block, deposits, receipts);
var depositRequests = getDepositRequests(Optional.of(requests)).orElse(Collections.emptyList());
return validateDepositRequests(block, depositRequests, receipts);
}
}

View File

@@ -22,7 +22,7 @@ public class MainnetRequestsValidator {
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();
}

View File

@@ -22,7 +22,7 @@ import java.util.List;
import java.util.Optional;
public interface RequestProcessor {
Optional<List<Request>> process(
Optional<List<? extends Request>> process(
final MutableWorldState mutableWorldState,
final List<TransactionReceipt> transactionReceipts);
}

View File

@@ -14,7 +14,9 @@
*/
package org.hyperledger.besu.ethereum.mainnet.requests;
import org.hyperledger.besu.ethereum.core.DepositRequest;
import org.hyperledger.besu.ethereum.core.Request;
import org.hyperledger.besu.ethereum.core.WithdrawalRequest;
import java.util.ArrayList;
import java.util.Collections;
@@ -40,14 +42,32 @@ public class RequestUtil {
return requests.stream().filter(requestType::isInstance).map(requestType::cast).toList();
}
public static Optional<List<DepositRequest>> getDepositRequests(
final Optional<List<Request>> requests) {
return requests.map(r -> filterRequestsOfType(r, DepositRequest.class));
}
public static Optional<List<WithdrawalRequest>> getWithdrawalRequests(
final Optional<List<Request>> requests) {
return requests.map(r -> filterRequestsOfType(r, WithdrawalRequest.class));
}
/**
* Combines two optional lists of requests into a single optional list.
*
* @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<List<Request>> combine(
final Optional<List<Request>> maybeDeposits,
final Optional<List<Request>> maybeDepositRequests,
final Optional<List<Request>> maybeWithdrawalRequest) {
if (maybeDeposits.isEmpty() && maybeWithdrawalRequest.isEmpty()) {
if (maybeDepositRequests.isEmpty() && maybeWithdrawalRequest.isEmpty()) {
return Optional.empty();
}
List<Request> requests = new ArrayList<>();
maybeDeposits.ifPresent(requests::addAll);
maybeDepositRequests.ifPresent(requests::addAll);
maybeWithdrawalRequest.ifPresent(requests::addAll);
return Optional.of(requests);
}

View File

@@ -41,6 +41,10 @@ public class RequestsValidatorCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(RequestsValidatorCoordinator.class);
private final ImmutableSortedMap<RequestType, RequestValidator> validators;
public static RequestsValidatorCoordinator empty() {
return new Builder().build();
}
/**
* Constructs a new RequestsDelegateValidator with a mapping of request types to their respective
* validators.

View File

@@ -25,7 +25,7 @@ import java.util.Optional;
public class WithdrawalRequestProcessor implements RequestProcessor {
@Override
public Optional<List<Request>> process(
public Optional<List<? extends Request>> process(
final MutableWorldState mutableWorldState,
final List<TransactionReceipt> transactionReceipts) {
@@ -33,6 +33,6 @@ public class WithdrawalRequestProcessor implements RequestProcessor {
WithdrawalRequestContractHelper.popWithdrawalRequestsFromQueue(mutableWorldState).stream()
.toList();
return Optional.of(withdrawalRequests.stream().map(r -> (Request) r).toList());
return Optional.of(withdrawalRequests);
}
}

View File

@@ -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 @@ public class WithdrawalRequestValidator implements RequestValidator {
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 @@ public class WithdrawalRequestValidator implements RequestValidator {
@Override
public boolean validate(
final Block block, final List<Request> requests, final List<TransactionReceipt> receipts) {
var withdrawalRequests = RequestUtil.filterRequestsOfType(requests, WithdrawalRequest.class);
var withdrawalRequests =
getWithdrawalRequests(Optional.of(requests)).orElse(Collections.emptyList());
return validateWithdrawalRequestsInBlock(block, withdrawalRequests);
}

View File

@@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.NoOpBonsaiCache
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.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 @@ public class GenesisWorldStateProvider {
bonsaiCachedMerkleTrieLoader,
new NoOpBonsaiCachedWorldStorageManager(bonsaiWorldStateKeyValueStorage),
new NoOpTrieLogManager(),
EvmConfiguration.DEFAULT);
EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
}
/**

View File

@@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldSt
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.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 class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
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 class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
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 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
public void prepareStateHealing(final Address address, final Bytes location) {
final Set<Bytes> keysToDelete = new HashSet<>();
final BonsaiWorldStateKeyValueStorage.Updater updater =
getWorldStateKeyValueStorage().updater();
getBonsaiWorldStateKeyValueStorage().updater();
final Hash accountHash = address.addressHash();
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
new StoredMerklePatriciaTrie<>(
(l, h) -> {
final Optional<Bytes> node =
getWorldStateKeyValueStorage().getAccountStateTrieNode(l, h);
getBonsaiWorldStateKeyValueStorage().getAccountStateTrieNode(l, h);
if (node.isPresent()) {
keysToDelete.add(l);
}
@@ -115,7 +121,7 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
new StoredMerklePatriciaTrie<>(
(l, h) -> {
Optional<Bytes> node =
getWorldStateKeyValueStorage()
getBonsaiWorldStateKeyValueStorage()
.getAccountStorageTrieNode(accountHash, l, h);
if (node.isPresent()) {
keysToDelete.add(Bytes.concatenate(accountHash, l));
@@ -139,6 +145,10 @@ public class BonsaiWorldStateProvider extends DiffBasedWorldStateProvider {
keysToDelete.forEach(updater::removeAccountStateTrieNode);
updater.commit();
getWorldStateKeyValueStorage().downgradeToPartialFlatDbMode();
getBonsaiWorldStateKeyValueStorage().downgradeToPartialFlatDbMode();
}
private DiffBasedWorldStateConfig cloneBonsaiWorldStateConfig() {
return new DiffBasedWorldStateConfig(defaultWorldStateConfig);
}
}

View File

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

View File

@@ -18,6 +18,7 @@ import org.hyperledger.besu.datatypes.Hash;
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

View File

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

View File

@@ -23,6 +23,7 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
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.cache.DiffBasedCached
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 class BonsaiWorldState extends DiffBasedWorldState {
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<Bytes> 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 @@ public class BonsaiWorldState extends DiffBasedWorldState {
updateCode(maybeStateUpdater, worldStateUpdater);
// next walk the account trie
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
final MerkleTrie<Bytes, Bytes> accountTrie =
createTrie(
(location, hash) ->
bonsaiCachedMerkleTrieLoader.getAccountStateTrieNode(
@@ -157,7 +172,7 @@ public class BonsaiWorldState extends DiffBasedWorldState {
private void updateTheAccounts(
final Optional<BonsaiWorldStateKeyValueStorage.Updater> maybeStateUpdater,
final BonsaiWorldStateUpdateAccumulator worldStateUpdater,
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie) {
final MerkleTrie<Bytes, Bytes> accountTrie) {
for (final Map.Entry<Address, DiffBasedValue<BonsaiAccount>> accountUpdate :
worldStateUpdater.getAccountsToUpdate().entrySet()) {
final Bytes accountKey = accountUpdate.getKey();
@@ -234,7 +249,7 @@ public class BonsaiWorldState extends DiffBasedWorldState {
|| worldStateUpdater.getStorageToClear().contains(updatedAddress))
? Hash.EMPTY_TRIE_HASH
: accountOriginal.getStorageRoot();
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
final MerkleTrie<Bytes, Bytes> storageTrie =
createTrie(
(location, key) ->
bonsaiCachedMerkleTrieLoader.getAccountStorageTrieNode(
@@ -277,8 +292,11 @@ public class BonsaiWorldState extends DiffBasedWorldState {
(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 class BonsaiWorldState extends DiffBasedWorldState {
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 class BonsaiWorldState extends DiffBasedWorldState {
.orElse(null);
}
@Override
public Optional<Bytes> getCode(@Nonnull final Address address, final Hash codeHash) {
return getWorldStateStorage().getCode(codeHash, address.addressHash());
}
protected Optional<Bytes> getAccountStateTrieNode(final Bytes location, final Bytes32 nodeHash) {
return getWorldStateStorage().getAccountStateTrieNode(location, nodeHash);
}
@@ -423,16 +429,26 @@ public class BonsaiWorldState extends DiffBasedWorldState {
@Override
public Map<Bytes32, Bytes> getAllAccountStorage(final Address address, final Hash rootHash) {
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
final MerkleTrie<Bytes, Bytes> storageTrie =
createTrie(
(location, key) -> getStorageTrieNode(address.addressHash(), location, key), rootHash);
return storageTrie.entriesFrom(Bytes32.ZERO, Integer.MAX_VALUE);
}
private StoredMerklePatriciaTrie<Bytes, Bytes> 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<Bytes, Bytes> createTrie(final NodeLoader nodeLoader, final Bytes32 rootHash) {
if (worldStateConfig.isTrieDisabled()) {
return new NoOpMerkleTrie<>();
} else {
return new StoredMerklePatriciaTrie<>(
nodeLoader, rootHash, Function.identity(), Function.identity());
}
}
protected Hash hashAndSavePreImage(final Bytes value) {

View File

@@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.cache.DiffBasedCached
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.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 abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
maxLayersToLoad.orElse(DiffBasedCachedWorldStorageManager.RETAINED_LAYERS),
pluginContext);
this.blockchain = blockchain;
this.defaultWorldStateConfig = new DiffBasedWorldStateConfig();
}
public DiffBasedWorldStateProvider(
@@ -81,6 +84,7 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
// TODO: de-dup constructors
this.trieLogManager = trieLogManager;
this.blockchain = blockchain;
this.defaultWorldStateConfig = new DiffBasedWorldStateConfig();
}
protected void provideCachedWorldStorageManager(
@@ -252,6 +256,19 @@ public abstract class DiffBasedWorldStateProvider implements WorldStateArchive {
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;
}

View File

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

View File

@@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.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.Optional;
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<DiffBasedWorldStateConfig> defaultBonsaiWorldStateConfigSupplier;
private final Cache<Hash, BlockHeader> stateRootToBlockHeaderCache =
Caffeine.newBuilder()
.maximumSize(RETAINED_LAYERS)
@@ -59,18 +62,26 @@ public abstract class DiffBasedCachedWorldStorageManager implements StorageSubsc
final DiffBasedWorldStateProvider archive,
final DiffBasedWorldStateKeyValueStorage worldStateKeyValueStorage,
final Map<Bytes32, DiffBasedCachedWorldView> cachedWorldStatesByHash,
final EvmConfiguration evmConfiguration) {
final EvmConfiguration evmConfiguration,
final Supplier<DiffBasedWorldStateConfig> 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<DiffBasedWorldStateConfig> defaultBonsaiWorldStateConfigSupplier) {
this(
archive,
worldStateKeyValueStorage,
new ConcurrentHashMap<>(),
EvmConfiguration.DEFAULT,
defaultBonsaiWorldStateConfigSupplier);
}
public synchronized void addCachedLayer(
@@ -263,6 +274,11 @@ public abstract class DiffBasedCachedWorldStorageManager implements StorageSubsc
this.cachedWorldStatesByHash.clear();
}
@Override
public void onClearTrie() {
this.cachedWorldStatesByHash.clear();
}
@Override
public void onCloseStorage() {
this.cachedWorldStatesByHash.clear();

View File

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

View File

@@ -34,6 +34,7 @@ import java.util.Optional;
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 @@ public class TrieLogManager {
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<Bytes> getRawTrieLogLayer(final Hash blockHash) {
return rootWorldStateStorage.getTrieLog(blockHash).map(Bytes::wrap);
}
@Override
public Optional<Bytes> getRawTrieLogLayer(final long blockNumber) {
return TrieLogManager.this
.blockchain
.getBlockHeader(blockNumber)
.map(BlockHeader::getHash)
.flatMap(this::getRawTrieLogLayer);
}
@Override
public void saveRawTrieLogLayer(
final Hash blockHash, final long blockNumber, final Bytes trieLog) {
final DiffBasedWorldStateKeyValueStorage.Updater updater = rootWorldStateStorage.updater();
updater
.getTrieLogStorageTransaction()
.put(blockHash.toArrayUnsafe(), trieLog.toArrayUnsafe());
updater.commit();
// TODO maybe find a way to have a clean and complete trielog for observers
trieLogObservers.forEach(
o ->
o.onTrieLogAdded(
new TrieLogAddedEvent(
new TrieLogLayer().setBlockHash(blockHash).setBlockNumber(blockNumber))));
}
@Override
public Optional<TrieLog> getTrieLogLayer(final Hash blockHash) {
return TrieLogManager.this.getTrieLogLayer(blockHash);

View File

@@ -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 @@ public abstract class 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 abstract class DiffBasedWorldState
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<BlockHeader> maybeBlockHeader = Optional.ofNullable(blockHeader);
@@ -151,19 +162,32 @@ public abstract class DiffBasedWorldState
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 abstract class DiffBasedWorldState
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 abstract class DiffBasedWorldState
}
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 abstract class DiffBasedWorldState
@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 abstract class DiffBasedWorldState
try {
if (!isPersisted()) {
this.worldStateKeyValueStorage.close();
if (isFrozen) {
if (worldStateConfig.isFrozen()) {
closeFrozenStorage();
}
}

View File

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

View File

@@ -46,6 +46,7 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.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();
@@ -112,7 +114,7 @@ class BlockImportExceptionHandlingTest {
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(

View File

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

View File

@@ -1,50 +0,0 @@
/*
* 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.core.encoding;
import static org.assertj.core.api.Assertions.assertThat;
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.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 {
@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(
"0xf8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501"));
}
}

View File

@@ -20,7 +20,7 @@ import org.hyperledger.besu.datatypes.Address;
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.bytes.Bytes32;
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 @@ class DepositDecoderTest {
"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 @@ class DepositDecoderTest {
"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 @@ class DepositDecoderTest {
"0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"),
UInt64.valueOf(539967));
assertThat(deposit).isEqualTo(expectedDeposit);
assertThat(depositRequest).isEqualTo(expectedDepositRequest);
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.core.encoding;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.BLSPublicKey;
import org.hyperledger.besu.datatypes.BLSSignature;
import org.hyperledger.besu.datatypes.GWei;
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 DepositRequestRequestEncoderTest {
private final String expectedDepositEncodedBytes =
"f8bbb0b10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416ea00017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483850773594000b860a889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb501";
final DepositRequest depositRequest =
new DepositRequest(
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
Bytes32.fromHexString(
"0x0017a7fcf06faf493d30bbe2632ea7c2383cd86825e12797165de7aa35589483"),
GWei.of(32000000000L),
BLSSignature.fromHexString(
"0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"),
UInt64.ONE);
@Test
void shouldEncodeDeposit() {
final Bytes encoded = DepositRequestEncoder.encodeOpaqueBytes(depositRequest);
assertThat(encoded).isEqualTo(Bytes.fromHexString(expectedDepositEncodedBytes));
}
@Test
void shouldEncodeDepositRequest() {
final Bytes encoded = RequestEncoder.encodeOpaqueBytes(depositRequest);
// Request encoding is Request = RequestType ++ RequestData
assertThat(encoded)
.isEqualTo(
Bytes.fromHexString(
String.format(
"0x%02X%s",
depositRequest.getType().getSerializedType(), expectedDepositEncodedBytes)));
}
}

View File

@@ -25,20 +25,31 @@ import org.apache.tuweni.bytes.Bytes;
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)));
}
}

View File

@@ -70,7 +70,7 @@ abstract class AbstractBlockProcessorTest {
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());

View File

@@ -23,10 +23,10 @@ import org.hyperledger.besu.datatypes.GWei;
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.apache.tuweni.units.bigints.UInt64;
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 class DepositsValidatorTest {
"0xa889db8300194050a2636c92a95bc7160515867614b7971a9500cdb62f9c0890217d2901c3241f86fac029428fc106930606154bd9e406d7588934a5f15b837180b17194d6e44bd6de23e43b163dfe12e369dcc75a3852cd997963f158217eb5"),
UInt64.valueOf(539967));
DEPOSIT_2 =
new Deposit(
depositRequest2 =
new DepositRequest(
BLSPublicKey.fromHexString(
"0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243"),
Bytes32.fromHexString(
@@ -97,8 +97,8 @@ public class DepositsValidatorTest {
}
@Test
public void validateAllowedDeposits() {
final List<Request> request = List.of(DEPOSIT_1, DEPOSIT_2);
public void validateAllowedDepositRequests() {
final List<Request> request = List.of(depositRequest1, depositRequest2);
final BlockDataGenerator.BlockOptions blockOptions =
BlockDataGenerator.BlockOptions.create()
.setRequests(Optional.of(request))
@@ -113,9 +113,9 @@ public class DepositsValidatorTest {
}
@Test
public void validateAllowedDepositsSeparateReceipts() {
public void validateAllowedDepositRequestsSeparateReceipts() {
final List<Request> requests = List.of(DEPOSIT_1, DEPOSIT_2);
final List<Request> requests = List.of(depositRequest1, depositRequest2);
final BlockDataGenerator.BlockOptions blockOptions =
BlockDataGenerator.BlockOptions.create()
@@ -135,9 +135,9 @@ public class DepositsValidatorTest {
}
@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 class DepositsValidatorTest {
}
@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 class DepositsValidatorTest {
}
@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 class DepositsValidatorTest {
}
@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 class DepositsValidatorTest {
}
@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 class DepositsValidatorTest {
@Test
public void validateAllowedDepositParams() {
final Optional<List<Request>> deposits = Optional.of(List.of(DEPOSIT_1, DEPOSIT_2));
assertThat(depositsValidator.validateParameter(deposits)).isTrue();
final Optional<List<Request>> depositRequests =
Optional.of(List.of(depositRequest1, depositRequest2));
assertThat(depositRequestValidator.validateParameter(depositRequests)).isTrue();
final Optional<List<Request>> emptyDeposits = Optional.of(List.of());
assertThat(depositsValidator.validateParameter(emptyDeposits)).isTrue();
final Optional<List<Request>> emptyDepositRequests = Optional.of(List.of());
assertThat(depositRequestValidator.validateParameter(emptyDepositRequests)).isTrue();
}
@Test
public void invalidateAllowedDepositParams() {
final Optional<List<Request>> deposits = Optional.empty();
assertThat(depositsValidator.validateParameter(deposits)).isFalse();
final Optional<List<Request>> 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();
}
}

View File

@@ -28,7 +28,7 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
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 @@ class MainnetBlockBodyValidatorTest {
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);

View File

@@ -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());
}

View File

@@ -186,13 +186,14 @@ class WithdrawalRequestContractHelperTest {
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"))));
}

View File

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

View File

@@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactor
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.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 @@ class LogRollingTests {
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 @@ class LogRollingTests {
secondProvider,
new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT);
EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final BonsaiWorldStateUpdateAccumulator secondUpdater =
(BonsaiWorldStateUpdateAccumulator) secondWorldState.updater();
@@ -210,7 +213,8 @@ class LogRollingTests {
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 @@ class LogRollingTests {
secondProvider,
new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT);
EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final BonsaiWorldStateUpdateAccumulator secondUpdater =
(BonsaiWorldStateUpdateAccumulator) secondWorldState.updater();
@@ -267,7 +272,8 @@ class LogRollingTests {
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 @@ class LogRollingTests {
secondProvider,
new NoOpMetricsSystem(),
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT);
EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final WorldUpdater secondUpdater = secondWorldState.updater();
final MutableAccount secondMutableAccount =

View File

@@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.trielog.TrieLogFactor
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState;
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.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 class RollingImport {
archive,
new BonsaiWorldStateKeyValueStorage(
provider, new NoOpMetricsSystem(), DataStorageConfiguration.DEFAULT_BONSAI_CONFIG),
EvmConfiguration.DEFAULT);
EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
final SegmentedInMemoryKeyValueStorage worldStateKeyValueStorage =
(SegmentedInMemoryKeyValueStorage)
provider.getStorageBySegmentIdentifiers(

View File

@@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.chain.Blockchain;
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 @@ class BonsaiWorldStateTest {
new BonsaiWorldState(
InMemoryKeyValueStorageProvider.createBonsaiInMemoryWorldStateArchive(blockchain),
bonsaiWorldStateKeyValueStorage,
EvmConfiguration.DEFAULT);
EvmConfiguration.DEFAULT,
new DiffBasedWorldStateConfig());
}
@ParameterizedTest

View File

@@ -24,7 +24,6 @@ import org.hyperledger.besu.datatypes.Hash;
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 class WorldStateDownloaderBenchmark {
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(

View File

@@ -28,6 +28,7 @@ import org.hyperledger.besu.plugin.services.MetricsSystem;
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 @@ public abstract class AbstractSyncTargetManager {
}
public CompletableFuture<SyncTarget> findSyncTarget() {
if (isCancelled()) {
return completedFuture(null);
}
return selectBestAvailableSyncTarget()
.thenCompose(
maybeBestPeer -> {
@@ -99,6 +105,10 @@ public abstract class AbstractSyncTargetManager {
});
}
public synchronized void cancel() {
cancelled.set(true);
}
protected Optional<SyncTarget> finalizeSelectedSyncTarget(final SyncTarget syncTarget) {
return Optional.of(syncTarget);
}
@@ -115,5 +125,9 @@ public abstract class AbstractSyncTargetManager {
.timeout(WaitForPeerTask.create(ethContext, metricsSystem), Duration.ofSeconds(5));
}
private boolean isCancelled() {
return cancelled.get();
}
public abstract boolean shouldContinueDownloading();
}

View File

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

View File

@@ -24,7 +24,7 @@ import org.hyperledger.besu.datatypes.GWei;
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 class GetBodiesFromPeerTaskTest extends PeerMessageTaskTest<List<Block>>
}
@Test
public void assertBodyIdentifierUsesDepositsToGenerateBodyIdentifiers() {
public void assertBodyIdentifierUsesDepositRequestsToGenerateBodyIdentifiers() {
final Request deposit =
new Deposit(
new DepositRequest(
BLSPublicKey.fromHexString(
"0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"),
Bytes32.fromHexString(

View File

@@ -87,7 +87,7 @@ public class EvmToolCommandOptionsModule {
@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;
}

View File

@@ -32,13 +32,17 @@ import org.hyperledger.besu.datatypes.VersionedHash;
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.DepositRequest;
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.Comparator;
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 @@ public class T8nExecutor {
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 @@ public class T8nExecutor {
.getBlockHashProcessor()
.processBlockHashes(blockchain, worldState, referenceTestEnv);
final WorldUpdater worldStateUpdater = worldState.updater();
final WorldUpdater rootWorldStateUpdater = worldState.updater();
List<TransactionReceipt> receipts = new ArrayList<>();
List<RejectedTransaction> invalidTransactions = new ArrayList<>(rejections);
List<Transaction> 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 @@ public class T8nExecutor {
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 @@ public class T8nExecutor {
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 @@ public class T8nExecutor {
}
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 @@ public class T8nExecutor {
receiptObject.putNull("logs");
} else {
ArrayNode logsArray = receiptObject.putArray("logs");
for (Log log : result.getLogs()) {
logsArray.addPOJO(log);
List<Log> 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 @@ public class T8nExecutor {
"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 @@ public class T8nExecutor {
(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 @@ public class T8nExecutor {
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<List<Request>> 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()), DepositRequest.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 @@ public class T8nExecutor {
.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<Entry<UInt256, UInt256>> storageEntries =
account.storageEntriesFrom(Bytes32.ZERO, Integer.MAX_VALUE).values().stream()
.map(
e ->

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More