mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-09 13:58:02 -05:00
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:
51
.github/workflows/update-test-reports.yml
vendored
Normal file
51
.github/workflows/update-test-reports.yml
vendored
Normal 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'
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -4,17 +4,36 @@
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
### Additions and Improvements
|
||||
|
||||
### Bug fixes
|
||||
- Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102)
|
||||
|
||||
## 24.5.2
|
||||
|
||||
### Upcoming Breaking Changes
|
||||
- Version 24.5.x will be the last series to support Java 17. Next release after versions 24.5.x will require Java 21 to build and run.
|
||||
- Receipt compaction will be enabled by default in a future version of Besu. After this change it will not be possible to downgrade to the previous Besu version.
|
||||
- PKI-backed QBFT will be removed in a future version of Besu. Other forms of QBFT will remain unchanged.
|
||||
|
||||
### Additions and Improvements
|
||||
- Remove deprecated Goerli testnet [#7049](https://github.com/hyperledger/besu/pull/7049)
|
||||
- Default bonsai to use full-flat db and code-storage-by-code-hash [#6984](https://github.com/hyperledger/besu/pull/6894)
|
||||
- New RPC methods miner_setExtraData and miner_getExtraData [#7078](https://github.com/hyperledger/besu/pull/7078)
|
||||
- Disconnect peers that have multiple discovery ports since they give us bad neighbours [#7089](https://github.com/hyperledger/besu/pull/7089)
|
||||
|
||||
### Known Issues
|
||||
- [Frequency: occasional < 10%] Chain download halt. Only affects new syncs (new nodes syncing from scratch). Symptom: Block import halts, despite having a full set of peers and world state downloading finishing. Generally restarting besu will resolve the issue. We are tracking this in [#6884](https://github.com/hyperledger/besu/pull/6884)
|
||||
|
||||
### Bug fixes
|
||||
- Fix parsing `gasLimit` parameter when its value is > `Long.MAX_VALUE` [#7116](https://github.com/hyperledger/besu/pull/7116)
|
||||
- Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102)
|
||||
- Skip validation of withdrawals when importing BFT blocks since withdrawals don't apply to BFT chains [#7115](https://github.com/hyperledger/besu/pull/7115)
|
||||
|
||||
### Download Links
|
||||
https://github.com/hyperledger/besu/releases/tag/24.5.2
|
||||
https://github.com/hyperledger/besu/releases/download/24.5.2/besu-24.5.2.tar.gz / sha256 4049bf48022ae073065b46e27088399dfb22035e9134ed4ac2c86dd8c5b5fbe9
|
||||
https://github.com/hyperledger/besu/releases/download/24.5.2/besu-24.5.2.zip / sha256 23966b501a69e320e8f8f46a3d103ccca45b53f8fee35a6543bd9a260b5784ee
|
||||
|
||||
## 24.5.1
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.services;
|
||||
|
||||
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
|
||||
import org.hyperledger.besu.plugin.services.p2p.P2PService;
|
||||
|
||||
/** Service to enable and disable P2P discovery. */
|
||||
public class P2PServiceImpl implements P2PService {
|
||||
|
||||
private final P2PNetwork p2PNetwork;
|
||||
|
||||
/**
|
||||
* Creates a new P2PServiceImpl.
|
||||
*
|
||||
* @param p2PNetwork the P2P network to enable and disable.
|
||||
*/
|
||||
public P2PServiceImpl(final P2PNetwork p2PNetwork) {
|
||||
this.p2PNetwork = p2PNetwork;
|
||||
}
|
||||
|
||||
/** Enables P2P discovery. */
|
||||
@Override
|
||||
public void enableDiscovery() {
|
||||
p2PNetwork.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableDiscovery() {
|
||||
p2PNetwork.stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.services;
|
||||
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.rlp.RLP;
|
||||
import org.hyperledger.besu.plugin.data.BlockBody;
|
||||
import org.hyperledger.besu.plugin.data.BlockHeader;
|
||||
import org.hyperledger.besu.plugin.data.TransactionReceipt;
|
||||
import org.hyperledger.besu.plugin.services.rlp.RlpConverterService;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/** RLP Serialiaztion/Deserialization service. */
|
||||
public class RlpConverterServiceImpl implements RlpConverterService {
|
||||
|
||||
private final BlockHeaderFunctions blockHeaderFunctions;
|
||||
|
||||
/**
|
||||
* Constructor for RlpConverterServiceImpl.
|
||||
*
|
||||
* @param protocolSchedule the protocol schedule.
|
||||
*/
|
||||
public RlpConverterServiceImpl(final ProtocolSchedule protocolSchedule) {
|
||||
this.blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockHeader buildHeaderFromRlp(final Bytes rlp) {
|
||||
return org.hyperledger.besu.ethereum.core.BlockHeader.readFrom(
|
||||
RLP.input(rlp), blockHeaderFunctions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBody buildBodyFromRlp(final Bytes rlp) {
|
||||
return org.hyperledger.besu.ethereum.core.BlockBody.readWrappedBodyFrom(
|
||||
RLP.input(rlp), blockHeaderFunctions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionReceipt buildReceiptFromRlp(final Bytes rlp) {
|
||||
return org.hyperledger.besu.ethereum.core.TransactionReceipt.readFrom(RLP.input(rlp));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bytes buildRlpFromHeader(final BlockHeader blockHeader) {
|
||||
return RLP.encode(
|
||||
org.hyperledger.besu.ethereum.core.BlockHeader.convertPluginBlockHeader(
|
||||
blockHeader, blockHeaderFunctions)
|
||||
::writeTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bytes buildRlpFromBody(final BlockBody blockBody) {
|
||||
return RLP.encode(
|
||||
rlpOutput ->
|
||||
((org.hyperledger.besu.ethereum.core.BlockBody) blockBody)
|
||||
.writeWrappedBodyTo(rlpOutput));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bytes buildRlpFromReceipt(final TransactionReceipt receipt) {
|
||||
return RLP.encode(
|
||||
rlpOutput ->
|
||||
((org.hyperledger.besu.ethereum.core.TransactionReceipt) receipt)
|
||||
.writeToForNetwork(rlpOutput));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.services;
|
||||
|
||||
import org.hyperledger.besu.consensus.merge.MergeContext;
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.Block;
|
||||
import org.hyperledger.besu.ethereum.core.BlockImporter;
|
||||
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
|
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
|
||||
import org.hyperledger.besu.plugin.data.BlockBody;
|
||||
import org.hyperledger.besu.plugin.data.BlockHeader;
|
||||
import org.hyperledger.besu.plugin.services.sync.SynchronizationService;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** Synchronization service. */
|
||||
public class SynchronizationServiceImpl implements SynchronizationService {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SynchronizationServiceImpl.class);
|
||||
|
||||
private final ProtocolContext protocolContext;
|
||||
private final ProtocolSchedule protocolSchedule;
|
||||
|
||||
private final SyncState syncState;
|
||||
private final Optional<DiffBasedWorldStateProvider> worldStateArchive;
|
||||
|
||||
/**
|
||||
* Constructor for SynchronizationServiceImpl.
|
||||
*
|
||||
* @param protocolContext protocol context
|
||||
* @param protocolSchedule protocol schedule
|
||||
* @param syncState sync state
|
||||
* @param worldStateArchive world state archive
|
||||
*/
|
||||
public SynchronizationServiceImpl(
|
||||
final ProtocolContext protocolContext,
|
||||
final ProtocolSchedule protocolSchedule,
|
||||
final SyncState syncState,
|
||||
final WorldStateArchive worldStateArchive) {
|
||||
this.protocolContext = protocolContext;
|
||||
this.protocolSchedule = protocolSchedule;
|
||||
this.syncState = syncState;
|
||||
this.worldStateArchive =
|
||||
Optional.ofNullable(worldStateArchive)
|
||||
.filter(z -> z instanceof DiffBasedWorldStateProvider)
|
||||
.map(DiffBasedWorldStateProvider.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireNewUnverifiedForkchoiceEvent(
|
||||
final Hash head, final Hash safeBlock, final Hash finalizedBlock) {
|
||||
final MergeContext mergeContext = protocolContext.getConsensusContext(MergeContext.class);
|
||||
if (mergeContext != null) {
|
||||
mergeContext.fireNewUnverifiedForkchoiceEvent(head, safeBlock, finalizedBlock);
|
||||
protocolContext.getBlockchain().setFinalized(finalizedBlock);
|
||||
protocolContext.getBlockchain().setSafeBlock(safeBlock);
|
||||
} else {
|
||||
LOG.atWarn()
|
||||
.setMessage(
|
||||
"The merge context is unavailable, hence the fork choice event cannot be triggered")
|
||||
.log();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setHead(final BlockHeader blockHeader, final BlockBody blockBody) {
|
||||
final BlockImporter blockImporter =
|
||||
protocolSchedule
|
||||
.getByBlockHeader((org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader)
|
||||
.getBlockImporter();
|
||||
return blockImporter
|
||||
.importBlock(
|
||||
protocolContext,
|
||||
new Block(
|
||||
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader,
|
||||
(org.hyperledger.besu.ethereum.core.BlockBody) blockBody),
|
||||
HeaderValidationMode.SKIP_DETACHED)
|
||||
.isImported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setHeadUnsafe(final BlockHeader blockHeader, final BlockBody blockBody) {
|
||||
final org.hyperledger.besu.ethereum.core.BlockHeader coreHeader =
|
||||
(org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader;
|
||||
|
||||
final MutableBlockchain blockchain = protocolContext.getBlockchain();
|
||||
|
||||
if (worldStateArchive.flatMap(archive -> archive.getMutable(coreHeader, true)).isPresent()) {
|
||||
if (coreHeader.getParentHash().equals(blockchain.getChainHeadHash())) {
|
||||
LOG.atDebug()
|
||||
.setMessage(
|
||||
"Forwarding chain head to the block {} saved from a previous newPayload invocation")
|
||||
.addArgument(coreHeader::toLogString)
|
||||
.log();
|
||||
return blockchain.forwardToBlock(coreHeader);
|
||||
} else {
|
||||
LOG.atDebug()
|
||||
.setMessage("New head {} is a chain reorg, rewind chain head to it")
|
||||
.addArgument(coreHeader::toLogString)
|
||||
.log();
|
||||
return blockchain.rewindToBlock(coreHeader.getBlockHash());
|
||||
}
|
||||
} else {
|
||||
LOG.atWarn()
|
||||
.setMessage("The world state is unavailable, setting of head cannot be performed.")
|
||||
.log();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInitialSyncPhaseDone() {
|
||||
return syncState.isInitialSyncPhaseDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableWorldStateTrie() {
|
||||
// TODO maybe find a best way in the future to delete and disable trie
|
||||
worldStateArchive.ifPresent(
|
||||
archive -> {
|
||||
archive.getDefaultWorldStateConfig().setTrieDisabled(true);
|
||||
final DiffBasedWorldStateKeyValueStorage worldStateStorage =
|
||||
archive.getWorldStateKeyValueStorage();
|
||||
final Optional<Hash> worldStateBlockHash = worldStateStorage.getWorldStateBlockHash();
|
||||
final Optional<Bytes> worldStateRootHash = worldStateStorage.getWorldStateRootHash();
|
||||
if (worldStateRootHash.isPresent() && worldStateBlockHash.isPresent()) {
|
||||
worldStateStorage.clearTrie();
|
||||
// keep root and block hash in the trie branch
|
||||
final DiffBasedWorldStateKeyValueStorage.Updater updater = worldStateStorage.updater();
|
||||
updater.saveWorldState(
|
||||
worldStateBlockHash.get(), Bytes32.wrap(worldStateRootHash.get()), Bytes.EMPTY);
|
||||
updater.commit();
|
||||
|
||||
// currently only bonsai needs an explicit upgrade to full flat db
|
||||
if (worldStateStorage instanceof BonsaiWorldStateKeyValueStorage bonsaiStorage) {
|
||||
bonsaiStorage.upgradeToFullFlatDbMode();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.services;
|
||||
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
|
||||
import org.hyperledger.besu.plugin.services.transactionpool.TransactionPoolService;
|
||||
|
||||
/** Service to enable and disable the transaction pool. */
|
||||
public class TransactionPoolServiceImpl implements TransactionPoolService {
|
||||
|
||||
private final TransactionPool transactionPool;
|
||||
|
||||
/**
|
||||
* Creates a new TransactionPoolServiceImpl.
|
||||
*
|
||||
* @param transactionPool the transaction pool to control
|
||||
*/
|
||||
public TransactionPoolServiceImpl(final TransactionPool transactionPool) {
|
||||
this.transactionPool = transactionPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableTransactionPool() {
|
||||
transactionPool.setDisabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableTransactionPool() {
|
||||
transactionPool.setEnabled();
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,9 @@ public class PrivacyTest {
|
||||
final DataStorageConfiguration dataStorageConfiguration,
|
||||
final 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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
+ '\''
|
||||
@@ -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() {
|
||||
|
||||
@@ -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='"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -38,7 +38,7 @@ public class RequestEncoder {
|
||||
RequestType.WITHDRAWAL,
|
||||
WithdrawalRequestEncoder::encode,
|
||||
RequestType.DEPOSIT,
|
||||
DepositEncoder::encode);
|
||||
DepositRequestEncoder::encode);
|
||||
|
||||
/**
|
||||
* Encodes a Request into the provided RLPOutput.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -21,5 +21,7 @@ public interface StorageSubscriber {
|
||||
|
||||
default void onClearTrieLog() {}
|
||||
|
||||
default void onClearTrie() {}
|
||||
|
||||
default void onCloseStorage() {}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.StorageSubscriber;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.DiffBasedLayeredWorldStateKeyValueStorage;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.common.storage.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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright contributors to Hyperledger Besu.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
|
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.ethereum.trie.diffbased.common.worldview;
|
||||
|
||||
public class DiffBasedWorldStateConfig {
|
||||
|
||||
private boolean isFrozen;
|
||||
|
||||
private boolean isTrieDisabled;
|
||||
|
||||
public DiffBasedWorldStateConfig() {
|
||||
this(false, false);
|
||||
}
|
||||
|
||||
public DiffBasedWorldStateConfig(final boolean isTrieDisabled) {
|
||||
this(false, isTrieDisabled);
|
||||
}
|
||||
|
||||
public DiffBasedWorldStateConfig(final DiffBasedWorldStateConfig config) {
|
||||
this(config.isFrozen(), config.isTrieDisabled());
|
||||
}
|
||||
|
||||
public DiffBasedWorldStateConfig(final boolean isFrozen, final boolean isTrieDisabled) {
|
||||
this.isFrozen = isFrozen;
|
||||
this.isTrieDisabled = isTrieDisabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the world state is frozen. When the world state is frozen, it cannot mutate.
|
||||
*
|
||||
* @return true if the world state is frozen, false otherwise.
|
||||
*/
|
||||
public boolean isFrozen() {
|
||||
return isFrozen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the frozen status of the world state. When the world state is frozen, it cannot mutate.
|
||||
*
|
||||
* @param frozen the new frozen status to set.
|
||||
*/
|
||||
public void setFrozen(final boolean frozen) {
|
||||
isFrozen = frozen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the trie is disabled for the world state. When the trie is disabled, the world state
|
||||
* will only work with the flat database and not the trie. In this mode, it's impossible to verify
|
||||
* the state root.
|
||||
*
|
||||
* @return true if the trie is disabled, false otherwise.
|
||||
*/
|
||||
public boolean isTrieDisabled() {
|
||||
return isTrieDisabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the disabled status of the trie for the world state. When the trie is disabled, the world
|
||||
* state will only work with the flat database and not the trie. In this mode, it's impossible to
|
||||
* verify the state root.
|
||||
*
|
||||
* @param trieDisabled the new disabled status to set for the trie.
|
||||
*/
|
||||
public void setTrieDisabled(final boolean trieDisabled) {
|
||||
isTrieDisabled = trieDisabled;
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import org.hyperledger.besu.ethereum.storage.StorageProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider;
|
||||
import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.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(
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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"))));
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ public class PipelineChainDownloader implements ChainDownloader {
|
||||
@Override
|
||||
public synchronized void cancel() {
|
||||
cancelled.set(true);
|
||||
syncTargetManager.cancel();
|
||||
if (currentDownloadPipeline != null) {
|
||||
currentDownloadPipeline.abort();
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user