Merge branch 'main' into zkbesu

# Conflicts:
#	.github/workflows/acceptance-tests.yml
#	.github/workflows/artifacts.yml
#	besu/src/main/java/org/hyperledger/besu/controller/BesuController.java
#	build.gradle
#	ethereum/evmtool/build.gradle
This commit is contained in:
Fabio Di Fabio
2024-05-03 14:50:21 +02:00
1362 changed files with 7204 additions and 6046 deletions

121
.github/workflows/develop.yml vendored Normal file
View File

@@ -0,0 +1,121 @@
name: docker develop
on:
push:
branches:
- main
env:
registry: docker.io
jobs:
hadolint:
runs-on: ubuntu-22.04
steps:
- name: Checkout Repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up Java
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93
with:
distribution: temurin
java-version: 17
- name: setup gradle
uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1
with:
cache-disabled: true
- name: hadoLint
run: docker run --rm -i hadolint/hadolint < docker/Dockerfile
buildDocker:
needs: hadolint
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
platform:
- ubuntu-22.04
- [self-hosted, ARM64]
runs-on: ${{ matrix.platform }}
steps:
- name: Prepare
id: prep
run: |
platform=${{ matrix.platform }}
if [ "$platform" = 'ubuntu-22.04' ]; then
echo "PLATFORM_PAIR=linux-amd64" >> $GITHUB_OUTPUT
echo "ARCH=amd64" >> $GITHUB_OUTPUT
else
echo "PLATFORM_PAIR=linux-arm64" >> $GITHUB_OUTPUT
echo "ARCH=arm64" >> $GITHUB_OUTPUT
fi
# Get the current date and time in the format YY.MM
DATE_TIME=$(date +"%y.%-m")
# Get the short SHA of the merge commit
SHORT_SHA=${GITHUB_SHA::7}
# Construct the build target name
BUILD_TARGET_NAME="${DATE_TIME}-develop-${SHORT_SHA}"
echo "Build Target Name: $BUILD_TARGET_NAME"
# Set the build target name as an environment variable
echo "BUILD_TARGET_NAME=${BUILD_TARGET_NAME}" >> $GITHUB_ENV
- name: Checkout Repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up Java
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93
with:
distribution: temurin
java-version: 17
- name: setup gradle
uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1
with:
cache-disabled: true
- name: install goss
run: |
mkdir -p docker/reports
curl -L https://github.com/aelsabbahy/goss/releases/download/v0.4.4/goss-${{ steps.prep.outputs.PLATFORM_PAIR }} -o ./docker/tests/goss-${{ steps.prep.outputs.PLATFORM_PAIR }}
- name: login to ${{ env.registry }}
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d
with:
registry: ${{ env.registry }}
username: ${{ secrets.DOCKER_USER_RW }}
password: ${{ secrets.DOCKER_PASSWORD_RW }}
- name: build and test docker
uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1
env:
architecture: ${{ steps.prep.outputs.ARCH }}
with:
cache-disabled: true
arguments: testDocker -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{ env.BUILD_TARGET_NAME}} -Prelease.releaseVersion=develop
- name: publish
env:
architecture: ${{ steps.prep.outputs.ARCH }}
run: ./gradlew --no-daemon dockerUpload -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{ env.BUILD_TARGET_NAME }} -Prelease.releaseVersion=develop
multiArch:
needs: buildDocker
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout Repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up Java
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93
with:
distribution: temurin
java-version: 17
- name: setup gradle
uses: gradle/actions/setup-gradle@9e899d11ad247ec76be7a60bc1cf9d3abbb9e7f1
with:
cache-disabled: true
- name: login to ${{ env.registry }}
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d
with:
registry: ${{ env.registry }}
username: ${{ secrets.DOCKER_USER_RW }}
password: ${{ secrets.DOCKER_PASSWORD_RW }}
- name: multi-arch docker
run: ./gradlew manifestDocker -PdockerOrgName=${{ env.registry }}/${{ secrets.DOCKER_ORG }} -Pversion=${{ env.BUILD_TARGET_NAME }} -Prelease.releaseVersion=develop

69
.github/workflows/splitTestsByTime.sh vendored Executable file
View File

@@ -0,0 +1,69 @@
#!/bin/bash
REPORTS_DIR="$1"
SPLIT_COUNT=$2
SPLIT_INDEX=$3
# extract tests time from Junit XML reports
find "$REPORTS_DIR" -type f -name TEST-*.xml | xargs -I{} bash -c "xmlstarlet sel -t -v 'sum(//testcase/@time)' '{}'; echo '{}' | sed 's/.*TEST\-\(.*\)\.xml/ \1/'" > tmp/timing.tsv
# Sort times in descending order
IFS=$'\n' sorted=($(sort -nr tmp/timing.tsv))
unset IFS
sums=()
tests=()
# Initialize sums
for ((i=0; i<SPLIT_COUNT; i++))
do
sums[$i]=0
done
# add tests to groups trying to balance the sum of execution time of each group
for line in "${sorted[@]}"; do
line_parts=( $line )
test_time=${line_parts[0]//./} # convert to millis
test_time=${test_time##0} # remove leading zeros
test_name=${line_parts[1]}
# Does the test still exists?
if grep -F -q --line-regexp "$test_name" tmp/currentTests.list
then
# Find index of min sum
idx_min_sum=0
min_sum=${sums[0]}
for ((i=0; i<SPLIT_COUNT; i++))
do
if [[ ${sums[$i]} -lt $min_sum ]]
then
idx_min_sum=$i
min_sum=${sums[$i]}
fi
done
# Add the test to the min sum list
min_sum_tests=${tests[$idx_min_sum]}
tests[$idx_min_sum]="${min_sum_tests}${test_name},"
# Update the sums
((sums[idx_min_sum]+=test_time))
echo "$test_name" >> tmp/processedTests.list
fi
done
# Any new test?
grep -F --line-regexp -v -f tmp/processedTests.list tmp/currentTests.list > tmp/newTests.list
idx_new_test=0
while read -r new_test_name
do
idx_group=$(( idx_new_test % SPLIT_COUNT ))
group=${tests[$idx_group]}
tests[$idx_group]="${group}${new_test_name},"
idx_new_test=$(( idx_new_test + 1 ))
done < tmp/newTests.list
# return the requests index, without quotes to drop the last trailing space
echo ${tests[$SPLIT_INDEX]//,/ }

View File

@@ -9,6 +9,7 @@
### Upcoming Breaking Changes
- Receipt compaction will be enabled by default in a future version of Besu. After this change it will not be possible to downgrade to the previous Besu version.
- PKI-backed QBFT will be removed in a future version of Besu. Other forms of QBFT will remain unchanged.
### Deprecations
@@ -40,6 +41,10 @@
- Expose transaction count by type metrics for the layered txpool [#6903](https://github.com/hyperledger/besu/pull/6903)
- Expose bad block events via the BesuEvents plugin API [#6848](https://github.com/hyperledger/besu/pull/6848)
- Add RPC errors metric [#6919](https://github.com/hyperledger/besu/pull/6919/)
- Add `rlp decode` subcommand to decode IBFT/QBFT extraData to validator list [#6895](https://github.com/hyperledger/besu/pull/6895)
- Allow users to specify which plugins are registered [#6700](https://github.com/hyperledger/besu/pull/6700)
- Layered txpool tuning for blob transactions [#6940](https://github.com/hyperledger/besu/pull/6940)
- Update Gradle to 7.6.4 [#7030](https://github.com/hyperledger/besu/pull/7030)
### Bug fixes
- Fix txpool dump/restore race condition [#6665](https://github.com/hyperledger/besu/pull/6665)
@@ -50,6 +55,8 @@
- Fix to avoid broadcasting full blob txs, instead of only the tx announcement, to a subset of nodes [#6835](https://github.com/hyperledger/besu/pull/6835)
- Snap client fixes discovered during snap server testing [#6847](https://github.com/hyperledger/besu/pull/6847)
- Correctly initialize the txpool as disabled on creation [#6890](https://github.com/hyperledger/besu/pull/6890)
- Fix worldstate download halt when using snap sync during initial sync [#6981](https://github.com/hyperledger/besu/pull/6981)
- Fix chain halt due to peers only partially responding with headers. And worldstate halts caused by a halt in the chain sync [#7027](https://github.com/hyperledger/besu/pull/7027)
### Download Links

View File

@@ -56,12 +56,15 @@ import java.math.BigInteger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.jupiter.api.AfterEach;
import org.junit.After;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Superclass for acceptance tests. */
/**
* Superclass for acceptance tests. For now (transition to junit5 is ongoing) this class supports
* junit4 format.
*/
@ExtendWith(AcceptanceTestBaseTestWatcher.class)
public class AcceptanceTestBase {
@@ -128,7 +131,7 @@ public class AcceptanceTestBase {
exitedSuccessfully = new ExitedWithCode(0);
}
@AfterEach
@After
public void tearDownAcceptanceTestBase() {
reportMemory();
cluster.close();

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl;
import static java.nio.charset.StandardCharsets.UTF_8;

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl;
import java.io.File;

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.condition.admin;
import static org.assertj.core.api.Assertions.assertThat;

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.condition.admin;
import static org.assertj.core.api.Assertions.assertThat;

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -35,7 +35,6 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
@@ -132,7 +131,6 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
private final List<String> staticNodes;
private boolean isDnsEnabled = false;
private Optional<Integer> exitCode = Optional.empty();
private Optional<PkiKeyStoreConfiguration> pkiKeyStoreConfiguration = Optional.empty();
private final boolean isStrictTxReplayProtectionEnabled;
private final Map<String, String> environment;
@@ -169,7 +167,6 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
final Optional<PrivacyParameters> privacyParameters,
final List<String> runCommand,
final Optional<KeyPair> keyPair,
final Optional<PkiKeyStoreConfiguration> pkiKeyStoreConfiguration,
final boolean isStrictTxReplayProtectionEnabled,
final Map<String, String> environment)
throws IOException {
@@ -230,7 +227,6 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
this.staticNodes = staticNodes;
this.isDnsEnabled = isDnsEnabled;
privacyParameters.ifPresent(this::setPrivacyParameters);
this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration;
this.environment = environment;
LOG.info("Created BesuNode {}", this);
}
@@ -763,10 +759,6 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
return runCommand;
}
public Optional<PkiKeyStoreConfiguration> getPkiKeyStoreConfiguration() {
return pkiKeyStoreConfiguration;
}
public boolean isStrictTxReplayProtectionEnabled() {
return isStrictTxReplayProtectionEnabled;
}
@@ -789,21 +781,6 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
nodeRequests.shutdown();
nodeRequests = null;
}
deleteRuntimeFiles();
}
private void deleteRuntimeFiles() {
try {
Files.deleteIfExists(homeDirectory.resolve("besu.networks"));
} catch (IOException e) {
LOG.error("Failed to clean up besu.networks file in {}", homeDirectory, e);
}
try {
Files.deleteIfExists(homeDirectory.resolve("besu.ports"));
} catch (IOException e) {
LOG.error("Failed to clean up besu.ports file in {}", homeDirectory, e);
}
}
@Override

View File

@@ -52,7 +52,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
@@ -78,15 +77,8 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
final Path dataDir = node.homeDirectory();
final var workingDir =
new File(System.getProperty("user.dir")).getParentFile().getParentFile().toPath();
final List<String> params = new ArrayList<>();
if (SystemUtils.IS_OS_WINDOWS) {
params.add(workingDir.resolve("build\\install\\besu\\bin\\besu.bat").toString());
} else {
params.add("build/install/besu/bin/besu");
}
params.add("build/install/besu/bin/besu");
params.add("--data-path");
params.add(dataDir.toAbsolutePath().toString());
@@ -385,33 +377,6 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
permissioningConfiguration.getNodeSmartContractInterfaceVersion()));
});
node.getPkiKeyStoreConfiguration()
.ifPresent(
pkiConfig -> {
params.add("--Xpki-block-creation-enabled");
params.add("--Xpki-block-creation-keystore-certificate-alias");
params.add(pkiConfig.getCertificateAlias());
params.add("--Xpki-block-creation-keystore-type");
params.add(pkiConfig.getKeyStoreType());
params.add("--Xpki-block-creation-keystore-file");
params.add(pkiConfig.getKeyStorePath().toAbsolutePath().toString());
params.add("--Xpki-block-creation-keystore-password-file");
params.add(pkiConfig.getKeyStorePasswordPath().toAbsolutePath().toString());
params.add("--Xpki-block-creation-truststore-type");
params.add(pkiConfig.getTrustStoreType());
params.add("--Xpki-block-creation-truststore-file");
params.add(pkiConfig.getTrustStorePath().toAbsolutePath().toString());
params.add("--Xpki-block-creation-truststore-password-file");
params.add(pkiConfig.getTrustStorePasswordPath().toAbsolutePath().toString());
});
params.addAll(node.getExtraCLIOptions());
params.add("--key-value-storage");
@@ -430,13 +395,15 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
LOG.info("Creating besu process with params {}", params);
final ProcessBuilder processBuilder =
new ProcessBuilder(params)
.directory(workingDir.toFile())
.directory(new File(System.getProperty("user.dir")).getParentFile().getParentFile())
.redirectErrorStream(true)
.redirectInput(Redirect.INHERIT);
if (!node.getPlugins().isEmpty()) {
processBuilder
.environment()
.put("BESU_OPTS", "-Dbesu.plugins.dir=" + dataDir.resolve("plugins").toAbsolutePath());
.put(
"BESU_OPTS",
"-Dbesu.plugins.dir=" + dataDir.resolve("plugins").toAbsolutePath().toString());
}
// Use non-blocking randomness for acceptance tests
processBuilder
@@ -578,7 +545,7 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
LOG.info("Killing {} process, pid {}", name, process.pid());
process.descendants().forEach(ProcessHandle::destroy);
process.destroy();
try {
process.waitFor(30, TimeUnit.SECONDS);
} catch (final InterruptedException e) {

View File

@@ -21,7 +21,6 @@ import org.hyperledger.besu.RunnerBuilder;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.controller.BesuControllerBuilder;
import org.hyperledger.besu.crypto.KeyPairUtil;
@@ -31,6 +30,7 @@ import org.hyperledger.besu.ethereum.GasLimitCalculator;
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters;
import org.hyperledger.besu.ethereum.core.plugins.PluginConfiguration;
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
@@ -74,7 +74,6 @@ import org.hyperledger.besu.services.TransactionSimulationServiceImpl;
import java.io.File;
import java.nio.file.Path;
import java.time.Clock;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -141,7 +140,8 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
besuPluginContext.addService(PermissioningService.class, permissioningService);
besuPluginContext.addService(PrivacyPluginService.class, new PrivacyPluginServiceImpl());
besuPluginContext.registerPlugins(pluginsPath);
besuPluginContext.registerPlugins(new PluginConfiguration(pluginsPath));
commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0]));
// register built-in plugins
@@ -212,14 +212,16 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
final EthNetworkConfig.Builder networkConfigBuilder =
new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(network))
.setBootNodes(bootnodes);
node.getConfiguration().getGenesisConfig().ifPresent(networkConfigBuilder::setGenesisConfig);
node.getConfiguration()
.getGenesisConfig()
.map(GenesisConfigFile::fromConfig)
.ifPresent(networkConfigBuilder::setGenesisConfigFile);
final EthNetworkConfig ethNetworkConfig = networkConfigBuilder.build();
final SynchronizerConfiguration synchronizerConfiguration =
new SynchronizerConfiguration.Builder().build();
final BesuControllerBuilder builder =
new BesuController.Builder()
.fromEthNetworkConfig(
ethNetworkConfig, Collections.emptyMap(), synchronizerConfiguration.getSyncMode());
.fromEthNetworkConfig(ethNetworkConfig, synchronizerConfiguration.getSyncMode());
final KeyValueStorageProvider storageProvider =
new KeyValueStorageProviderBuilder()
@@ -251,9 +253,6 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.isRevertReasonEnabled(node.isRevertReasonEnabled())
.storageProvider(storageProvider)
.gasLimitCalculator(GasLimitCalculator.constant())
.pkiBlockCreationConfiguration(
node.getPkiKeyStoreConfiguration()
.map(pkiConfig -> new PkiBlockCreationConfigurationProvider().load(pkiConfig)))
.evmConfiguration(EvmConfiguration.DEFAULT)
.maxPeers(maxPeers)
.maxRemotelyInitiatedPeers(15)

View File

@@ -1,16 +1,13 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with
* 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
* 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
@@ -39,7 +36,6 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory.CliqueOptions;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki.PkiKeystoreConfigurationFactory;
import java.io.File;
import java.io.IOException;
@@ -57,8 +53,6 @@ import io.vertx.core.Vertx;
public class BesuNodeFactory {
private final NodeConfigurationFactory node = new NodeConfigurationFactory();
private final PkiKeystoreConfigurationFactory pkiKeystoreConfigurationFactory =
new PkiKeystoreConfigurationFactory();
public BesuNode create(final BesuNodeConfiguration config) throws IOException {
return new BesuNode(
@@ -94,7 +88,6 @@ public class BesuNodeFactory {
config.getPrivacyParameters(),
config.getRunCommand(),
config.getKeyPair(),
config.getPkiKeyStoreConfiguration(),
config.isStrictTxReplayProtectionEnabled(),
config.getEnvironment());
}
@@ -517,31 +510,6 @@ public class BesuNodeFactory {
.build());
}
public BesuNode createPkiQbftJKSNode(final String name) throws IOException {
return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_JKS, name);
}
public BesuNode createPkiQbftPKCS11Node(final String name) throws IOException {
return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, name);
}
public BesuNode createPkiQbftPKCS12Node(final String name) throws IOException {
return createPkiQbftNode(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, name);
}
public BesuNode createPkiQbftNode(final String type, final String name) throws IOException {
return create(
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false))
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.genesisConfigProvider(GenesisConfigurationFactory::createQbftGenesisConfig)
.pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig(type, name))
.build());
}
public BesuNode createCustomGenesisNode(
final String name, final String genesisPath, final boolean canBeBootnode) throws IOException {
return createCustomGenesisNode(name, genesisPath, canBeBootnode, false);
@@ -699,41 +667,6 @@ public class BesuNodeFactory {
.build());
}
public BesuNode createPkiQbftJKSNodeWithValidators(final String name, final String... validators)
throws IOException {
return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_JKS, name, validators);
}
public BesuNode createPkiQbftPKCS11NodeWithValidators(
final String name, final String... validators) throws IOException {
return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11, name, validators);
}
public BesuNode createPkiQbftPKCS12NodeWithValidators(
final String name, final String... validators) throws IOException {
return createPkiQbftNodeWithValidators(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12, name, validators);
}
public BesuNode createPkiQbftNodeWithValidators(
final String type, final String name, final String... validators) throws IOException {
return create(
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false))
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig(type, name))
.genesisConfigProvider(
nodes ->
node.createGenesisConfigForValidators(
asList(validators),
nodes,
GenesisConfigurationFactory::createQbftGenesisConfig))
.build());
}
public BesuNode createNodeWithStaticNodes(final String name, final List<Node> staticNodes)
throws IOException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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
@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki;
import java.io.File;

View File

@@ -1,196 +0,0 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.createKeyPair;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.createSelfSignedCertificate;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.issueCertificate;
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration;
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper;
import org.hyperledger.besu.pki.util.TestCertificateUtils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.UUID;
public class PkiKeystoreConfigurationFactory {
/*
PKCS11 config files
*/
final String NSSCONFIG_PATH_STRING = "/pki-certs/%s/nss.cfg";
final String NSSPIN_PATH_STRING = "/pki-certs/%s/nsspin.txt";
final String TRUSTSTORE_PATH_STRING = "/pki-certs/%s/truststore.p12";
final String CRL_PATH_STRING = "/pki-certs/crl/crl.pem";
/*
Software keystore config
*/
public static final String KEYSTORE_DEFAULT_PASSWORD = "password";
private KeyPair caKeyPair;
private X509Certificate caCertificate;
private Path trustStoreFile;
private Path passwordFile;
public PkiKeyStoreConfiguration createPkiConfig(final String type, final String name) {
if (KeyStoreWrapper.KEYSTORE_TYPE_PKCS11.equals(type)) {
return createPKCS11PkiConfig(name);
} else {
return createSoftwareKeyStorePkiConfig(type, name);
}
}
private PkiKeyStoreConfiguration createPKCS11PkiConfig(final String name) {
final PkiKeyStoreConfiguration.Builder pkiKeyStoreConfigBuilder =
new PkiKeyStoreConfiguration.Builder();
try {
pkiKeyStoreConfigBuilder
.withKeyStoreType(KeyStoreWrapper.KEYSTORE_TYPE_PKCS11)
.withKeyStorePath(
PKCS11Utils.initNSSConfigFile(
readResourceAsPath(String.format(NSSCONFIG_PATH_STRING, name))))
.withKeyStorePasswordPath(readResourceAsPath(String.format(NSSPIN_PATH_STRING, name)))
.withTrustStoreType(KeyStoreWrapper.KEYSTORE_TYPE_PKCS12)
.withTrustStorePath(readResourceAsPath(String.format(TRUSTSTORE_PATH_STRING, name)))
.withTrustStorePasswordPath(readResourceAsPath(String.format(NSSPIN_PATH_STRING, name)))
.withCrlFilePath(readResourceAsPath(CRL_PATH_STRING))
.withCertificateAlias(name);
} catch (Exception e) {
throw new RuntimeException(e);
}
return pkiKeyStoreConfigBuilder.build();
}
private PkiKeyStoreConfiguration createSoftwareKeyStorePkiConfig(
final String type, final String name) {
PkiKeyStoreConfiguration.Builder pkiKeyStoreConfigBuilder =
new PkiKeyStoreConfiguration.Builder();
pkiKeyStoreConfigBuilder.withTrustStoreType(type);
pkiKeyStoreConfigBuilder.withTrustStorePath(createTrustStore(type));
pkiKeyStoreConfigBuilder.withTrustStorePasswordPath(passwordFile);
pkiKeyStoreConfigBuilder.withKeyStoreType(type);
pkiKeyStoreConfigBuilder.withKeyStorePath(createKeyStore(type, name));
pkiKeyStoreConfigBuilder.withKeyStorePasswordPath(passwordFile);
pkiKeyStoreConfigBuilder.withCertificateAlias(name);
return pkiKeyStoreConfigBuilder.build();
}
private Path createTrustStore(final String type) {
// Only create the truststore if this is the first time this method is being called
if (caKeyPair == null) {
try {
caKeyPair = createKeyPair(TestCertificateUtils.Algorithm.RSA);
caCertificate = createSelfSignedCertificate("ca", notBefore(), notAfter(), caKeyPair);
final KeyStore truststore = KeyStore.getInstance(type);
truststore.load(null, null);
truststore.setCertificateEntry("ca", caCertificate);
final String uniqueId = UUID.randomUUID().toString();
trustStoreFile = writeKeyStoreFile(truststore, "truststore", uniqueId);
passwordFile = writePasswordFile(KEYSTORE_DEFAULT_PASSWORD, "password", uniqueId);
} catch (final Exception e) {
throw new RuntimeException("Error creating truststore for Acceptance Test", e);
}
}
return trustStoreFile;
}
private Path createKeyStore(final String type, final String alias) {
if (caKeyPair == null) {
createTrustStore(type);
}
final KeyPair kp = createKeyPair(TestCertificateUtils.Algorithm.RSA);
final X509Certificate certificate =
issueCertificate(caCertificate, caKeyPair, "validator", notBefore(), notAfter(), kp, false);
try {
final KeyStore keyStore = KeyStore.getInstance(type);
keyStore.load(null, null);
keyStore.setKeyEntry(
alias,
kp.getPrivate(),
KEYSTORE_DEFAULT_PASSWORD.toCharArray(),
new Certificate[] {certificate, caCertificate});
final String id = UUID.randomUUID().toString();
return writeKeyStoreFile(keyStore, "keystore", id);
} catch (final Exception e) {
throw new RuntimeException("Error creating keystore for Acceptance Test", e);
}
}
private Path writeKeyStoreFile(
final KeyStore keyStore, final String prefix, final String suffix) {
try {
final Path file = Files.createTempFile(prefix, suffix != null ? suffix : "");
file.toFile().deleteOnExit();
final FileOutputStream keyStoreFOS = new FileOutputStream(file.toFile());
keyStore.store(keyStoreFOS, KEYSTORE_DEFAULT_PASSWORD.toCharArray());
return file;
} catch (final Exception e) {
throw new RuntimeException("Error creating keystore file", e);
}
}
private Path writePasswordFile(final String password, final String prefix, final String suffix) {
try {
final Path file = Files.createTempFile(prefix, suffix);
file.toFile().deleteOnExit();
Files.write(file, password.getBytes(StandardCharsets.UTF_8));
return file;
} catch (final IOException e) {
throw new RuntimeException("Error creating password file", e);
}
}
private Instant notBefore() {
return Instant.now().minus(1, ChronoUnit.DAYS);
}
private Instant notAfter() {
return Instant.now().plus(10, ChronoUnit.DAYS);
}
private Path readResourceAsPath(final String path) throws Exception {
return Path.of(Objects.requireNonNull(this.getClass().getResource(path)).toURI());
}
}

View File

@@ -130,7 +130,6 @@ public class PrivacyNode implements AutoCloseable {
besuConfig.getPrivacyParameters(),
List.of(),
Optional.empty(),
Optional.empty(),
besuConfig.isStrictTxReplayProtectionEnabled(),
besuConfig.getEnvironment());
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.transaction.admin;
import static org.assertj.core.api.Assertions.assertThat;

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -11,7 +11,6 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.tests.acceptance.plugins;

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.plugins;
import org.hyperledger.besu.plugin.BesuContext;

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -11,7 +11,6 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.tests.acceptance.plugins.privacy;

View File

@@ -11,7 +11,6 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.tests.acceptance.plugins.privacy;

View File

@@ -16,24 +16,31 @@ package org.hyperledger.besu.services;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.hyperledger.besu.ethereum.core.plugins.PluginConfiguration;
import org.hyperledger.besu.ethereum.core.plugins.PluginInfo;
import org.hyperledger.besu.plugin.BesuPlugin;
import org.hyperledger.besu.tests.acceptance.plugins.TestBesuEventsPlugin;
import org.hyperledger.besu.tests.acceptance.plugins.TestPicoCLIPlugin;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.ThrowableAssert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class BesuPluginContextImplTest {
private static final Path DEFAULT_PLUGIN_DIRECTORY = Paths.get(".");
private BesuPluginContextImpl contextImpl;
@BeforeAll
public static void createFakePluginDir() throws IOException {
@@ -49,16 +56,20 @@ public class BesuPluginContextImplTest {
System.clearProperty("testPicoCLIPlugin.testOption");
}
@BeforeEach
void setup() {
contextImpl = new BesuPluginContextImpl();
}
@Test
public void verifyEverythingGoesSmoothly() {
final BesuPluginContextImpl contextImpl = new BesuPluginContextImpl();
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
contextImpl.registerPlugins(new PluginConfiguration(DEFAULT_PLUGIN_DIRECTORY));
assertThat(contextImpl.getRegisteredPlugins()).isNotEmpty();
assertThat(contextImpl.getPlugins()).isEmpty();
contextImpl.registerPlugins(new File(".").toPath());
assertThat(contextImpl.getPlugins()).isNotEmpty();
final Optional<TestPicoCLIPlugin> testPluginOptional = findTestPlugin(contextImpl.getPlugins());
Assertions.assertThat(testPluginOptional).isPresent();
final Optional<TestPicoCLIPlugin> testPluginOptional =
findTestPlugin(contextImpl.getRegisteredPlugins(), TestPicoCLIPlugin.class);
assertThat(testPluginOptional).isPresent();
final TestPicoCLIPlugin testPicoCLIPlugin = testPluginOptional.get();
assertThat(testPicoCLIPlugin.getState()).isEqualTo("registered");
@@ -72,33 +83,34 @@ public class BesuPluginContextImplTest {
@Test
public void registrationErrorsHandledSmoothly() {
final BesuPluginContextImpl contextImpl = new BesuPluginContextImpl();
System.setProperty("testPicoCLIPlugin.testOption", "FAILREGISTER");
assertThat(contextImpl.getPlugins()).isEmpty();
contextImpl.registerPlugins(new File(".").toPath());
assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
contextImpl.registerPlugins(new PluginConfiguration(DEFAULT_PLUGIN_DIRECTORY));
assertThat(contextImpl.getRegisteredPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
contextImpl.beforeExternalServices();
assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
contextImpl.startPlugins();
assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
contextImpl.stopPlugins();
assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
}
@Test
public void startErrorsHandledSmoothly() {
final BesuPluginContextImpl contextImpl = new BesuPluginContextImpl();
System.setProperty("testPicoCLIPlugin.testOption", "FAILSTART");
assertThat(contextImpl.getPlugins()).isEmpty();
contextImpl.registerPlugins(new File(".").toPath());
assertThat(contextImpl.getPlugins()).extracting("class").contains(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
contextImpl.registerPlugins(new PluginConfiguration(DEFAULT_PLUGIN_DIRECTORY));
assertThat(contextImpl.getRegisteredPlugins())
.extracting("class")
.contains(TestPicoCLIPlugin.class);
final Optional<TestPicoCLIPlugin> testPluginOptional = findTestPlugin(contextImpl.getPlugins());
final Optional<TestPicoCLIPlugin> testPluginOptional =
findTestPlugin(contextImpl.getRegisteredPlugins(), TestPicoCLIPlugin.class);
assertThat(testPluginOptional).isPresent();
final TestPicoCLIPlugin testPicoCLIPlugin = testPluginOptional.get();
assertThat(testPicoCLIPlugin.getState()).isEqualTo("registered");
@@ -106,22 +118,24 @@ public class BesuPluginContextImplTest {
contextImpl.beforeExternalServices();
contextImpl.startPlugins();
assertThat(testPicoCLIPlugin.getState()).isEqualTo("failstart");
assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
contextImpl.stopPlugins();
assertThat(contextImpl.getPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isNotInstanceOfAny(TestPicoCLIPlugin.class);
}
@Test
public void stopErrorsHandledSmoothly() {
final BesuPluginContextImpl contextImpl = new BesuPluginContextImpl();
System.setProperty("testPicoCLIPlugin.testOption", "FAILSTOP");
assertThat(contextImpl.getPlugins()).isEmpty();
contextImpl.registerPlugins(new File(".").toPath());
assertThat(contextImpl.getPlugins()).extracting("class").contains(TestPicoCLIPlugin.class);
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
contextImpl.registerPlugins(new PluginConfiguration(DEFAULT_PLUGIN_DIRECTORY));
assertThat(contextImpl.getRegisteredPlugins())
.extracting("class")
.contains(TestPicoCLIPlugin.class);
final Optional<TestPicoCLIPlugin> testPluginOptional = findTestPlugin(contextImpl.getPlugins());
final Optional<TestPicoCLIPlugin> testPluginOptional =
findTestPlugin(contextImpl.getRegisteredPlugins(), TestPicoCLIPlugin.class);
assertThat(testPluginOptional).isPresent();
final TestPicoCLIPlugin testPicoCLIPlugin = testPluginOptional.get();
assertThat(testPicoCLIPlugin.getState()).isEqualTo("registered");
@@ -136,9 +150,8 @@ public class BesuPluginContextImplTest {
@Test
public void lifecycleExceptions() throws Throwable {
final BesuPluginContextImpl contextImpl = new BesuPluginContextImpl();
final ThrowableAssert.ThrowingCallable registerPlugins =
() -> contextImpl.registerPlugins(new File(".").toPath());
() -> contextImpl.registerPlugins(new PluginConfiguration(DEFAULT_PLUGIN_DIRECTORY));
assertThatExceptionOfType(IllegalStateException.class).isThrownBy(contextImpl::startPlugins);
assertThatExceptionOfType(IllegalStateException.class).isThrownBy(contextImpl::stopPlugins);
@@ -158,9 +171,74 @@ public class BesuPluginContextImplTest {
assertThatExceptionOfType(IllegalStateException.class).isThrownBy(contextImpl::stopPlugins);
}
private Optional<TestPicoCLIPlugin> findTestPlugin(final List<BesuPlugin> plugins) {
@Test
public void shouldRegisterAllPluginsWhenNoPluginsOption() {
final PluginConfiguration config = createConfigurationForAllPlugins();
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
contextImpl.registerPlugins(config);
final Optional<TestPicoCLIPlugin> testPluginOptional =
findTestPlugin(contextImpl.getRegisteredPlugins(), TestPicoCLIPlugin.class);
assertThat(testPluginOptional).isPresent();
final TestPicoCLIPlugin testPicoCLIPlugin = testPluginOptional.get();
assertThat(testPicoCLIPlugin.getState()).isEqualTo("registered");
}
@Test
public void shouldRegisterOnlySpecifiedPluginWhenPluginsOptionIsSet() {
final PluginConfiguration config = createConfigurationForSpecificPlugin("TestPicoCLIPlugin");
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
contextImpl.registerPlugins(config);
final Optional<TestPicoCLIPlugin> requestedPlugin =
findTestPlugin(contextImpl.getRegisteredPlugins(), TestPicoCLIPlugin.class);
assertThat(requestedPlugin).isPresent();
assertThat(requestedPlugin.get().getState()).isEqualTo("registered");
final Optional<TestPicoCLIPlugin> nonRequestedPlugin =
findTestPlugin(contextImpl.getRegisteredPlugins(), TestBesuEventsPlugin.class);
assertThat(nonRequestedPlugin).isEmpty();
}
@Test
public void shouldNotRegisterUnspecifiedPluginsWhenPluginsOptionIsSet() {
final PluginConfiguration config = createConfigurationForSpecificPlugin("TestPicoCLIPlugin");
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
contextImpl.registerPlugins(config);
final Optional<TestPicoCLIPlugin> nonRequestedPlugin =
findTestPlugin(contextImpl.getRegisteredPlugins(), TestBesuEventsPlugin.class);
assertThat(nonRequestedPlugin).isEmpty();
}
@Test
void shouldThrowExceptionIfExplicitlySpecifiedPluginNotFound() {
PluginConfiguration config = createConfigurationForSpecificPlugin("NonExistentPlugin");
String exceptionMessage =
assertThrows(NoSuchElementException.class, () -> contextImpl.registerPlugins(config))
.getMessage();
final String expectedMessage =
"The following requested plugins were not found: NonExistentPlugin";
assertThat(exceptionMessage).isEqualTo(expectedMessage);
assertThat(contextImpl.getRegisteredPlugins()).isEmpty();
}
private PluginConfiguration createConfigurationForAllPlugins() {
return new PluginConfiguration(null, DEFAULT_PLUGIN_DIRECTORY);
}
private PluginConfiguration createConfigurationForSpecificPlugin(final String pluginName) {
return new PluginConfiguration(List.of(new PluginInfo(pluginName)), DEFAULT_PLUGIN_DIRECTORY);
}
private Optional<TestPicoCLIPlugin> findTestPlugin(
final List<BesuPlugin> plugins, final Class<?> type) {
return plugins.stream()
.filter(p -> p instanceof TestPicoCLIPlugin)
.filter(p -> type.equals(p.getClass()))
.map(p -> (TestPicoCLIPlugin) p)
.findFirst();
}

View File

@@ -13,7 +13,7 @@
plugins {
id 'org.web3j' version '4.11.1'
id 'org.web3j.solidity' version '0.4.0'
id 'org.web3j.solidity' version '0.4.1'
}
web3j { generatedPackageName = 'org.hyperledger.besu.tests.web3j.generated' }
@@ -258,3 +258,32 @@ task acceptanceTestPermissioning(type: Test) {
doFirst { mkdir "${buildDir}/jvmErrorLogs" }
}
// temporary solution to get a list of tests
// Gradle >8.3 has a supported test dry-run option to achieve the same result
task listAcceptanceTestNotPrivacy {
doLast {
def testExecutionSpec = tasks.getByName("acceptanceTestNotPrivacy") as Test
def processor = new org.gradle.api.internal.tasks.testing.TestClassProcessor() {
void startProcessing(org.gradle.api.internal.tasks.testing.TestResultProcessor processor) {}
void stop() {}
void stopNow() {}
void processTestClass(org.gradle.api.internal.tasks.testing.TestClassRunInfo info) {
def splitName = info.getTestClassName().split("\\.");
def testClassName = splitName[splitName.length-1];
if(testClassName.endsWith("Test") && !testClassName.startsWith("Abstract")) {
println(info.getTestClassName())
}
}
}
def detector = new org.gradle.api.internal.tasks.testing.detection.DefaultTestClassScanner(testExecutionSpec.getCandidateClassFiles(), testExecutionSpec.getTestFramework().getDetector()?.tap {
setTestClasses(testExecutionSpec.getTestClassesDirs().getFiles())
setTestClasspath(Collections.unmodifiableSet(testExecutionSpec.getClasspath().getFiles()))
}, processor)
detector.run()
}
}

View File

@@ -59,4 +59,4 @@ contract CrossContractReader {
CrossContractReader cross = CrossContractReader(crossAddress);
cross.destroy();
}
}
}

View File

@@ -41,4 +41,4 @@ contract EventEmitter {
function sender() view public returns (address) {
return _sender;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu
* 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
@@ -34,4 +34,4 @@ contract RemoteSimpleStorage {
function get() public view returns (uint) {
return simpleStorage.get();
}
}
}

View File

@@ -27,4 +27,4 @@ contract RevertReason {
function revertWithoutRevertReason() public pure returns (bool) {
revert();
}
}
}

View File

@@ -28,4 +28,4 @@ contract SimpleStorage {
function get() public view returns (uint) {
return data;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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
@@ -29,4 +29,4 @@ contract TestDepth {
x = gasleft();
}
}
}
}

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
pragma solidity ^0.5.0;
contract Migrations {

View File

@@ -1,3 +1,17 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
pragma solidity >=0.4.0 <0.6.0;
// THIS CONTRACT IS FOR TESTING PURPOSES ONLY
// DO NOT USE THIS CONTRACT IN PRODUCTION APPLICATIONS
@@ -43,4 +57,4 @@ contract SimpleAccountPermissioning {
function getSize() public view returns(uint256) {
return size;
}
}
}

View File

@@ -1,3 +1,17 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
pragma solidity >=0.4.0 <0.6.0;
// THIS CONTRACT IS FOR TESTING PURPOSES ONLY
// DO NOT USE THIS CONTRACT IN PRODUCTION APPLICATIONS

View File

@@ -1,3 +1,17 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
pragma solidity >=0.4.0 <0.6.0;
// THIS CONTRACT IS FOR TESTING PURPOSES ONLY
// DO NOT USE THIS CONTRACT IN PRODUCTION APPLICATIONS

View File

@@ -11,9 +11,7 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.tests.acceptance;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

View File

@@ -1,5 +1,5 @@
/*
* Copyright contributors to Hyperledger Besu
* 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

View File

@@ -11,9 +11,7 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.tests.acceptance.backup;
import static java.util.Collections.singletonList;

View File

@@ -1,130 +0,0 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.bft.pki;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
public class PkiQbftAcceptanceTest extends ParameterizedPkiQbftTestBase {
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("factoryFunctions")
public void shouldMineOnSingleNode(
final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory)
throws Exception {
final BesuNode minerNode = nodeFactory.createNode(besu, "miner1");
cluster.start(minerNode);
cluster.verify(blockchain.reachesHeight(minerNode, 1));
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode.execute(accountTransactions.createTransfer(sender, 50));
cluster.verify(sender.balanceEquals(50));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1));
cluster.verify(receiver.balanceEquals(1));
minerNode.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2));
cluster.verify(receiver.balanceEquals(3));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("factoryFunctions")
public void shouldMineOnMultipleNodes(
final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory)
throws Exception {
final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1");
final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2");
final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3");
final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4");
cluster.start(minerNode1, minerNode2, minerNode3, minerNode4);
cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85));
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode1.execute(accountTransactions.createTransfer(sender, 50));
cluster.verify(sender.balanceEquals(50));
minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1));
cluster.verify(receiver.balanceEquals(1));
minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2));
cluster.verify(receiver.balanceEquals(3));
minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3));
cluster.verify(receiver.balanceEquals(6));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("factoryFunctions")
public void shouldMineWithIgnoringANodeInCRL(
final String testName, final PkiQbftAcceptanceTestParameterization nodeFactory)
throws Exception {
final BesuNode minerNode1 = nodeFactory.createNode(besu, "miner1");
final BesuNode minerNode2 = nodeFactory.createNode(besu, "miner2");
final BesuNode minerNode3 = nodeFactory.createNode(besu, "miner3");
final BesuNode minerNode4 = nodeFactory.createNode(besu, "miner4");
final BesuNode minerNode5 = nodeFactory.createNode(besu, "miner5");
final BesuNode minerNode6 = nodeFactory.createNode(besu, "miner6");
try {
cluster.start(minerNode1, minerNode2, minerNode3, minerNode4);
cluster.startNode(minerNode5);
cluster.startNode(minerNode6);
cluster.verify(blockchain.reachesHeight(minerNode1, 1, 85));
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode1.execute(accountTransactions.createTransfer(sender, 50));
cluster.verify(sender.balanceEquals(50));
minerNode2.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 1));
cluster.verify(receiver.balanceEquals(1));
minerNode3.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 2));
cluster.verify(receiver.balanceEquals(3));
minerNode4.execute(accountTransactions.createIncrementalTransfers(sender, receiver, 3));
cluster.verify(receiver.balanceEquals(6));
if (minerNode1.getTLSConfiguration().isEmpty()) {
minerNode1.verify(net.awaitPeerCount(5));
minerNode5.verify(net.awaitPeerCount(5));
minerNode6.verify(net.awaitPeerCount(5));
} else {
minerNode1.verify(net.awaitPeerCount(3));
minerNode5.verify(net.awaitPeerCount(0));
minerNode6.verify(net.awaitPeerCount(0));
}
} finally {
cluster.stopNode(minerNode5);
cluster.stopNode(minerNode6);
minerNode5.close();
minerNode6.close();
}
}
}

View File

@@ -1,120 +0,0 @@
/*
* Copyright 2020 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.bft.pki;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.params.provider.Arguments;
public class PkiQbftAcceptanceTestParameterization {
public static Stream<Arguments> getFactories() {
List<Arguments> args = new ArrayList<>();
/*
BLOCK CREATION
*/
args.add(
Arguments.of(
"qbft-pki-jks",
new PkiQbftAcceptanceTestParameterization(
BesuNodeFactory::createPkiQbftJKSNode,
BesuNodeFactory::createPkiQbftJKSNodeWithValidators)));
args.add(
Arguments.of(
"qbft-pki-pkcs12",
new PkiQbftAcceptanceTestParameterization(
BesuNodeFactory::createPkiQbftPKCS12Node,
BesuNodeFactory::createPkiQbftPKCS12NodeWithValidators)));
if (Boolean.getBoolean("acctests.runBesuAsProcess")) {
args.add(
Arguments.of(
"qbft-pki-pkcs11",
new PkiQbftAcceptanceTestParameterization(
BesuNodeFactory::createPkiQbftPKCS11Node,
BesuNodeFactory::createPkiQbftPKCS11NodeWithValidators)));
}
/*
TLS
*/
args.add(
Arguments.of(
"qbft-tls-jks",
new PkiQbftAcceptanceTestParameterization(
BesuNodeFactory::createQbftNodeWithTLSJKS,
BesuNodeFactory::createQbftTLSJKSNodeWithValidators)));
args.add(
Arguments.of(
"qbft-tls-pkcs12",
new PkiQbftAcceptanceTestParameterization(
BesuNodeFactory::createQbftNodeWithTLSPKCS12,
BesuNodeFactory::createQbftTLSPKCS12NodeWithValidators)));
if (Boolean.getBoolean("acctests.runBesuAsProcess")) {
args.add(
Arguments.of(
"qbft-tls-pkcs11",
new PkiQbftAcceptanceTestParameterization(
BesuNodeFactory::createQbftNodeWithTLSPKCS11,
BesuNodeFactory::createQbftTLSPKCS11NodeWithValidators)));
}
return args.stream();
}
@FunctionalInterface
public interface NodeCreator {
BesuNode create(BesuNodeFactory factory, String name) throws Exception;
}
@FunctionalInterface
public interface NodeWithValidatorsCreator {
BesuNode create(BesuNodeFactory factory, String name, String[] validators) throws Exception;
}
private final NodeCreator creatorFn;
private final NodeWithValidatorsCreator createorWithValidatorFn;
public PkiQbftAcceptanceTestParameterization(
final NodeCreator creatorFn, final NodeWithValidatorsCreator createorWithValidatorFn) {
this.creatorFn = creatorFn;
this.createorWithValidatorFn = createorWithValidatorFn;
}
public BesuNode createNode(BesuNodeFactory factory, String name) throws Exception {
return creatorFn.create(factory, name);
}
public BesuNode createNodeWithValidators(
BesuNodeFactory factory, String name, String[] validators) throws Exception {
return createorWithValidatorFn.create(factory, name, validators);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -86,7 +86,7 @@ public class CliqueMiningAcceptanceTest extends AcceptanceTestBaseJunit5 {
final BesuNode minerNode1 = besu.createCliqueNode("miner1");
final BesuNode minerNode2 = besu.createCliqueNode("miner2");
final BesuNode minerNode3 = besu.createCliqueNode("miner3");
cluster.start(minerNode1, minerNode2, minerNode3);
startClusterAndVerifyProducingBlocks(minerNode1, minerNode2, minerNode3);
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
@@ -106,7 +106,7 @@ public class CliqueMiningAcceptanceTest extends AcceptanceTestBaseJunit5 {
final BesuNode minerNode1 = besu.createCliqueNode("miner1");
final BesuNode minerNode2 = besu.createCliqueNode("miner2");
final BesuNode minerNode3 = besu.createCliqueNode("miner3");
cluster.start(minerNode1, minerNode2, minerNode3);
startClusterAndVerifyProducingBlocks(minerNode1, minerNode2, minerNode3);
cluster.stopNode(minerNode2);
cluster.stopNode(minerNode3);
@@ -116,12 +116,23 @@ public class CliqueMiningAcceptanceTest extends AcceptanceTestBaseJunit5 {
minerNode1.verify(clique.noNewBlockCreated(minerNode1));
}
private void startClusterAndVerifyProducingBlocks(
final BesuNode minerNode1, final BesuNode minerNode2, final BesuNode minerNode3) {
cluster.start(minerNode1, minerNode2, minerNode3);
// verify that we have started producing blocks
waitForBlockHeight(minerNode1, 1);
final var minerChainHead = minerNode1.execute(ethTransactions.block());
minerNode2.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
minerNode3.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
}
@Test
public void shouldStillMineWhenANodeFailsAndHasSufficientValidators() throws IOException {
final BesuNode minerNode1 = besu.createCliqueNode("miner1");
final BesuNode minerNode2 = besu.createCliqueNode("miner2");
final BesuNode minerNode3 = besu.createCliqueNode("miner3");
cluster.start(minerNode1, minerNode2, minerNode3);
startClusterAndVerifyProducingBlocks(minerNode1, minerNode2, minerNode3);
cluster.verifyOnActiveNodes(blockchain.reachesHeight(minerNode1, 1, 85));

View File

@@ -11,7 +11,6 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.tests.acceptance.crypto;

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.database;
import static java.util.Collections.singletonList;

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -21,15 +21,15 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTra
import java.math.BigInteger;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class AccountLocalAndOnchainPermissioningAcceptanceTest
extends AccountSmartContractPermissioningAcceptanceTestBase {
private Account senderC;
@Before
@BeforeEach
public void setUp() {
senderC = accounts.createAccount("Account-C");
}

View File

@@ -22,8 +22,8 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTra
import java.math.BigInteger;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class AccountLocalConfigPermissioningAcceptanceTest extends AcceptanceTestBase {
@@ -31,7 +31,7 @@ public class AccountLocalConfigPermissioningAcceptanceTest extends AcceptanceTes
private Account senderA;
private Account senderB;
@Before
@BeforeEach
public void setUp() throws Exception {
senderA = accounts.getPrimaryBenefactor();
senderB = accounts.getSecondaryBenefactor();

View File

@@ -21,20 +21,19 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
public class AccountLocalConfigPermissioningImportAcceptanceTest extends AcceptanceTestBase {
@Rule public TemporaryFolder folder = new TemporaryFolder();
@TempDir Path folder;
private static final String GENESIS_FILE = "/ibft/ibft.json";
@@ -45,20 +44,20 @@ public class AccountLocalConfigPermissioningImportAcceptanceTest extends Accepta
private BesuNode nodeB;
private Cluster permissionedCluster;
@Before
@BeforeEach
public void setUp() throws IOException {
sender = accounts.getPrimaryBenefactor();
beneficiary = accounts.createAccount("beneficiary");
final List<String> allowList = List.of(sender.getAddress(), beneficiary.getAddress());
final File sharedFile = folder.newFile();
persistAllowList(allowList, sharedFile.toPath());
final Path sharedFile = Files.createFile(folder.resolve("sharedFile"));
persistAllowList(allowList, sharedFile);
bootnode = besu.createIbft2NonValidatorBootnode("bootnode", GENESIS_FILE);
nodeA =
besu.createIbft2NodeWithLocalAccountPermissioning(
"nodeA", GENESIS_FILE, allowList, sharedFile);
"nodeA", GENESIS_FILE, allowList, sharedFile.toFile());
nodeB =
besu.createIbft2NodeWithLocalAccountPermissioning(
"nodeB", GENESIS_FILE, allowList, sharedFile);
"nodeB", GENESIS_FILE, allowList, sharedFile.toFile());
permissionedCluster =
new Cluster(new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build(), net);
@@ -67,12 +66,12 @@ public class AccountLocalConfigPermissioningImportAcceptanceTest extends Accepta
@Test
public void transactionFromDeniedAccountShouldNotBreakBlockImport() throws IOException {
final File newPermissionsFile = folder.newFile();
final Path newPermissionsFile = Files.createFile(folder.resolve("newPermissionsFile"));
final List<String> allowList = List.of(beneficiary.getAddress());
persistAllowList(allowList, newPermissionsFile.toPath());
persistAllowList(allowList, newPermissionsFile);
final BesuNode nodeC =
besu.createIbft2NodeWithLocalAccountPermissioning(
"nodeC", GENESIS_FILE, allowList, newPermissionsFile);
"nodeC", GENESIS_FILE, allowList, newPermissionsFile.toFile());
waitForBlockHeight(bootnode, 2);
@@ -91,7 +90,7 @@ public class AccountLocalConfigPermissioningImportAcceptanceTest extends Accepta
AllowlistPersistor.ALLOWLIST_TYPE.ACCOUNTS, allowList, path);
}
@After
@AfterEach
public void tearDown() {
permissionedCluster.stop();
}

View File

@@ -21,8 +21,8 @@ import org.hyperledger.besu.tests.acceptance.dsl.transaction.account.TransferTra
import java.math.BigInteger;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class AccountSmartContractPermissioningAcceptanceTest
extends AccountSmartContractPermissioningAcceptanceTestBase {
@@ -31,7 +31,7 @@ public class AccountSmartContractPermissioningAcceptanceTest
private Account allowedSender;
private Account otherAccount;
@Before
@BeforeEach
public void setUp() {
node = permissionedNode("node1", Collections.emptyList());
permissionedCluster.start(node);

View File

@@ -26,8 +26,8 @@ import java.util.ArrayList;
import java.util.Collections;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class AllowlistPersistorAcceptanceTest extends AcceptanceTestBase {
@@ -45,7 +45,7 @@ public class AllowlistPersistorAcceptanceTest extends AcceptanceTestBase {
private Account senderB;
private Path tempFile;
@Before
@BeforeEach
public void setUp() throws Exception {
senderA = accounts.getPrimaryBenefactor();
senderB = accounts.getSecondaryBenefactor();

View File

@@ -31,8 +31,8 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class AllowlistWithDnsPersistorAcceptanceTest extends AcceptanceTestBase {
@@ -48,7 +48,7 @@ public class AllowlistWithDnsPersistorAcceptanceTest extends AcceptanceTestBase
private Account senderA;
private Path tempFile;
@Before
@BeforeEach
public void setUp() throws Exception {
ENODE_LOCALHOST_DNS = ENODE_PREFIX + InetAddress.getLocalHost().getHostName() + PORT_SUFFIX;
ENODE_LOCALHOST_IP = ENODE_PREFIX + "127.0.0.1" + PORT_SUFFIX;

View File

@@ -16,8 +16,8 @@ package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodeLocalAndOnchainPermissioningAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
@@ -27,7 +27,7 @@ public class NodeLocalAndOnchainPermissioningAcceptanceTest
private Node allowedNode;
private Node forbiddenNode;
@Before
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");

View File

@@ -20,8 +20,8 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.Cluster;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.cluster.ClusterConfigurationBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodeLocalConfigPermissioningAcceptanceTest extends AcceptanceTestBase {
@@ -31,7 +31,7 @@ public class NodeLocalConfigPermissioningAcceptanceTest extends AcceptanceTestBa
private Node allowedNode;
private Node permissionedNode;
@Before
@BeforeEach
public void setUp() throws Exception {
final ClusterConfiguration clusterConfiguration =
new ClusterConfigurationBuilder().awaitPeerDiscovery(false).build();

View File

@@ -16,8 +16,8 @@ package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
@@ -27,7 +27,7 @@ public class NodeSmartContractPermissioningAcceptanceTest
private Node allowedNode;
private Node forbiddenNode;
@Before
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");

View File

@@ -22,7 +22,7 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import java.io.IOException;
import java.util.Optional;
import org.junit.Test;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningIbft2StallAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {

View File

@@ -16,8 +16,8 @@ package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningOutOfSyncAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
@@ -25,7 +25,7 @@ public class NodeSmartContractPermissioningOutOfSyncAcceptanceTest
private Node permissionedNodeA;
private Node permissionedNodeB;
@Before
@BeforeEach
public void setUp() throws InterruptedException {
bootnode = bootnode("bootnode");
permissionedNodeA = permissionedNode("permissioned-node-A");
@@ -46,14 +46,18 @@ public class NodeSmartContractPermissioningOutOfSyncAcceptanceTest
final long blockchainHeight = 25L;
waitForBlockHeight(permissionedNodeA, blockchainHeight);
// Add Node B
// verify Node A is in sync with bootnode
final var minerChainHead = bootnode.execute(ethTransactions.block());
permissionedNodeA.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
// check that connection is forbidden (before node b is permitted)
permissionedCluster.addNode(permissionedNodeB);
permissionedNodeB.verify(connectionIsForbidden(permissionedNodeA, permissionedNodeB));
// Permit Node B
permissionedNodeA.execute(allowNode(permissionedNodeB));
permissionedNodeA.verify(admin.addPeer(permissionedNodeB));
// check that connection is forbidden (while node b is syncing)
permissionedNodeB.verify(connectionIsForbidden(permissionedNodeA, permissionedNodeB));
// connection should be allowed after node B syncs
waitForBlockHeight(permissionedNodeB, blockchainHeight);
permissionedNodeB.verify(connectionIsAllowed(permissionedNodeA, permissionedNodeB));

View File

@@ -16,8 +16,8 @@ package org.hyperledger.besu.tests.acceptance.permissioning;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningV2AcceptanceTest
extends NodeSmartContractPermissioningV2AcceptanceTestBase {
@@ -27,7 +27,7 @@ public class NodeSmartContractPermissioningV2AcceptanceTest
private Node allowedNode;
private Node forbiddenNode;
@Before
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");
@@ -116,6 +116,8 @@ public class NodeSmartContractPermissioningV2AcceptanceTest
permissionedCluster.stop();
permissionedCluster.start(bootnode, forbiddenNode, allowedNode, permissionedNode);
verifyAllNodesAreInSyncWithMiner();
permissionedNode.verify(connectionIsAllowed(allowedNode));
permissionedNode.verify(connectionIsAllowed(bootnode));
permissionedNode.verify(connectionIsAllowed(permissionedNode));

View File

@@ -24,8 +24,8 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodeSmartContractPermissioningV2DNSAcceptanceTest
extends NodeSmartContractPermissioningV2AcceptanceTestBase {
@@ -38,7 +38,7 @@ public class NodeSmartContractPermissioningV2DNSAcceptanceTest
final ImmutableEnodeDnsConfiguration enodeDnsConfiguration =
ImmutableEnodeDnsConfiguration.builder().dnsEnabled(true).updateEnabled(true).build();
@Before
@BeforeEach
public void setUp() {
bootnode = bootnode("bootnode");
forbiddenNode = node("forbidden-node");

View File

@@ -24,8 +24,8 @@ import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class NodesSmartContractPermissioningStaticNodesAcceptanceTest
extends NodeSmartContractPermissioningAcceptanceTestBase {
@@ -33,7 +33,7 @@ public class NodesSmartContractPermissioningStaticNodesAcceptanceTest
private Node miner;
private Node permissionedNode;
@Before
@BeforeEach
public void setUp() {
miner = miner("miner");
permissionedCluster.start(miner);

View File

@@ -11,7 +11,6 @@
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.tests.acceptance.plugins;

View File

@@ -12,7 +12,6 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.plugins;
import org.hyperledger.besu.datatypes.Hash;

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,8 @@
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0x78a301e0d846bd169889c9755c9aa4ce2972dfc4bd63de61f3303887d3e81f98",
"safeBlockHash": "0x78a301e0d846bd169889c9755c9aa4ce2972dfc4bd63de61f3303887d3e81f98",
"headBlockHash": "0x292042b10484fc182be8aba2a4c1863f6712cc7f0c74489c226792138134248f",
"safeBlockHash": "0x292042b10484fc182be8aba2a4c1863f6712cc7f0c74489c226792138134248f",
"finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
@@ -24,10 +24,10 @@
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0x78a301e0d846bd169889c9755c9aa4ce2972dfc4bd63de61f3303887d3e81f98",
"latestValidHash": "0x292042b10484fc182be8aba2a4c1863f6712cc7f0c74489c226792138134248f",
"validationError": null
},
"payloadId": "0x282643d459a6f711"
"payloadId": "0x282643efdc841a11"
}
},
"statusCode": 200

View File

@@ -3,7 +3,7 @@
"jsonrpc": "2.0",
"method": "engine_getPayloadV3",
"params": [
"0x282643d459a6f711"
"0x282643efdc841a11"
],
"id": 67
},
@@ -12,9 +12,9 @@
"id": 67,
"result": {
"executionPayload": {
"parentHash": "0x78a301e0d846bd169889c9755c9aa4ce2972dfc4bd63de61f3303887d3e81f98",
"parentHash": "0x292042b10484fc182be8aba2a4c1863f6712cc7f0c74489c226792138134248f",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x9b8c4a9a86cb49252075c0db2f0e72fb1e49350a0f70ea36f26f700201961e62",
"stateRoot": "0xf4e9cba3bdb0cf3aa214612d87f2a1ab18cdc604a0af18f71110754a85de5d15",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@@ -29,7 +29,7 @@
"blockNumber": "0x1",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"blobGasUsed": "0x0",
"blockHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315"
"blockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a"
},
"blockValue": "0x0",
"blobsBundle": {

View File

@@ -4,9 +4,9 @@
"method": "engine_newPayloadV3",
"params": [
{
"parentHash": "0x78a301e0d846bd169889c9755c9aa4ce2972dfc4bd63de61f3303887d3e81f98",
"parentHash": "0x292042b10484fc182be8aba2a4c1863f6712cc7f0c74489c226792138134248f",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x9b8c4a9a86cb49252075c0db2f0e72fb1e49350a0f70ea36f26f700201961e62",
"stateRoot": "0xf4e9cba3bdb0cf3aa214612d87f2a1ab18cdc604a0af18f71110754a85de5d15",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@@ -17,7 +17,7 @@
"transactions": [],
"withdrawals": [],
"blockNumber": "0x1",
"blockHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"blockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"excessBlobGas": "0x0",
"blobGasUsed": "0x0"
@@ -32,7 +32,7 @@
"id": 67,
"result": {
"status": "VALID",
"latestValidHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"latestValidHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"validationError": null
}
},

View File

@@ -4,9 +4,9 @@
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"safeBlockHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"finalizedBlockHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315"
"headBlockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"safeBlockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"finalizedBlockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a"
},
null
],
@@ -18,7 +18,7 @@
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"latestValidHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"validationError": null
},
"payloadId": null

View File

@@ -4,9 +4,9 @@
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"safeBlockHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
"headBlockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"safeBlockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"finalizedBlockHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a"
},
{
"timestamp": "0x20",
@@ -24,10 +24,10 @@
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"latestValidHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"validationError": null
},
"payloadId": "0x282643b909febddf"
"payloadId": "0x282643882dfdc121"
}
},
"statusCode": 200

View File

@@ -3,7 +3,7 @@
"jsonrpc": "2.0",
"method": "engine_getPayloadV4",
"params": [
"0x282643b909febddf"
"0x282643882dfdc121"
],
"id": 67
},
@@ -12,9 +12,9 @@
"id": 67,
"result": {
"executionPayload": {
"parentHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"parentHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x9b8c4a9a86cb49252075c0db2f0e72fb1e49350a0f70ea36f26f700201961e62",
"stateRoot": "0x9d7467981e875b5b81ec6b9ab44300fa390d253b5d83da24fe58700f66a3925e",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@@ -27,9 +27,15 @@
"transactions": [],
"withdrawals": [],
"depositReceipts": [],
"exits": [],
"withdrawalRequests": [
{
"sourceAddress": "0xa4664c40aacebd82a2db79f0ea36c06bc6a19adb",
"amount" : "0x0",
"validatorPubKey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"
}
],
"blockNumber": "0x2",
"blockHash": "0x194d190af2a85c418947fecca405eb168c832481f33f618b0c36326ba65d4767",
"blockHash": "0xb4be7cd1193f86d725c93275f9f9fe902c5fc34e1758b9ebcac371de370a1bdd",
"blobGasUsed": "0x0",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
},

View File

@@ -4,9 +4,9 @@
"method": "engine_newPayloadV4",
"params": [
{
"parentHash": "0x1dd4f141551d53ce393845e2873754e43396101a8ebc0fd0eeb2e6798a591315",
"parentHash": "0x2b0ef8ec0a5f8b3bd5e64cde3f1ed7f61c472b79bea9e44598921c3c37890a6a",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x14208ac0e218167936e220b72d5d5887a963cb858ea2f2d268518f014a3da3fa",
"stateRoot": "0xdcd8284a4904f95448a522e4c47d9c2f1b4541c5f6f711b42692fb26e1e0d986",
"logsBloom": "0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@@ -19,12 +19,24 @@
"0x02f9021c8217de808459682f008459682f0e830271009442424242424242424242424242424242424242428901bc16d674ec800000b901a422895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120749715de5d1226545c6b3790f515d551a5cc5bf1d49c87a696860554d2fc4f14000000000000000000000000000000000000000000000000000000000000003096a96086cff07df17668f35f7418ef8798079167e3f4f9b72ecde17b28226137cf454ab1dd20ef5d924786ab3483c2f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020003f5102dabe0a27b1746098d1dc17a5d3fbd478759fea9287e4e419b3c3cef20000000000000000000000000000000000000000000000000000000000000060b1acdb2c4d3df3f1b8d3bfd33421660df358d84d78d16c4603551935f4b67643373e7eb63dcb16ec359be0ec41fee33b03a16e80745f2374ff1d3c352508ac5d857c6476d3c3bcf7e6ca37427c9209f17be3af5264c0e2132b3dd1156c28b4e9c080a09f597089338d7f44f5c59f8230bb38f243849228a8d4e9d2e2956e6050f5b2c7a076486996c7e62802b8f95eee114783e4b403fd11093ba96286ff42c595f24452"
],
"withdrawals": [],
"depositReceipts" : [
{"amount":"0x773594000","index":"0x0","pubkey":"0x96a96086cff07df17668f35f7418ef8798079167e3f4f9b72ecde17b28226137cf454ab1dd20ef5d924786ab3483c2f9","signature":"0xb1acdb2c4d3df3f1b8d3bfd33421660df358d84d78d16c4603551935f4b67643373e7eb63dcb16ec359be0ec41fee33b03a16e80745f2374ff1d3c352508ac5d857c6476d3c3bcf7e6ca37427c9209f17be3af5264c0e2132b3dd1156c28b4e9","withdrawalCredentials":"0x003f5102dabe0a27b1746098d1dc17a5d3fbd478759fea9287e4e419b3c3cef2"}
"depositReceipts": [
{
"amount": "0x773594000",
"index": "0x0",
"pubkey": "0x96a96086cff07df17668f35f7418ef8798079167e3f4f9b72ecde17b28226137cf454ab1dd20ef5d924786ab3483c2f9",
"signature": "0xb1acdb2c4d3df3f1b8d3bfd33421660df358d84d78d16c4603551935f4b67643373e7eb63dcb16ec359be0ec41fee33b03a16e80745f2374ff1d3c352508ac5d857c6476d3c3bcf7e6ca37427c9209f17be3af5264c0e2132b3dd1156c28b4e9",
"withdrawalCredentials": "0x003f5102dabe0a27b1746098d1dc17a5d3fbd478759fea9287e4e419b3c3cef2"
}
],
"withdrawalRequests": [
{
"sourceAddress": "0xa4664c40aacebd82a2db79f0ea36c06bc6a19adb",
"amount" : "0x0",
"validatorPubKey": "0xb10a4a15bf67b328c9b101d09e5c6ee6672978fdad9ef0d9e2ceffaee99223555d8601f0cb3bcc4ce1af9864779a416e"
}
],
"exits": [],
"blockNumber": "0x2",
"blockHash": "0x84e13dc50074ba4be5841bd7e453a87b6f77261a8907518a78f3de8c9d877ee7",
"blockHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c",
"receiptsRoot": "0x79ee3424eb720a3ad4b1c5a372bb8160580cbe4d893778660f34213c685627a9",
"blobGasUsed": "0x0"
},
@@ -38,7 +50,7 @@
"id": 67,
"result": {
"status": "VALID",
"latestValidHash": "0x84e13dc50074ba4be5841bd7e453a87b6f77261a8907518a78f3de8c9d877ee7",
"latestValidHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c",
"validationError": null
}
},

View File

@@ -4,9 +4,9 @@
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0x84e13dc50074ba4be5841bd7e453a87b6f77261a8907518a78f3de8c9d877ee7",
"safeBlockHash": "0x84e13dc50074ba4be5841bd7e453a87b6f77261a8907518a78f3de8c9d877ee7",
"finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
"headBlockHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c",
"safeBlockHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c",
"finalizedBlockHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c"
},
{
"timestamp": "0x30",
@@ -24,10 +24,10 @@
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0x84e13dc50074ba4be5841bd7e453a87b6f77261a8907518a78f3de8c9d877ee7",
"latestValidHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c",
"validationError": null
},
"payloadId": "0x282643f559414ecf"
"payloadId": "0x282643832633dccf"
}
},
"statusCode" : 200

View File

@@ -3,7 +3,7 @@
"jsonrpc": "2.0",
"method": "engine_getPayloadV4",
"params": [
"0x282643f559414ecf"
"0x282643832633dccf"
],
"id": 67
},
@@ -12,9 +12,9 @@
"id": 67,
"result": {
"executionPayload": {
"parentHash": "0x84e13dc50074ba4be5841bd7e453a87b6f77261a8907518a78f3de8c9d877ee7",
"parentHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x14208ac0e218167936e220b72d5d5887a963cb858ea2f2d268518f014a3da3fa",
"stateRoot": "0xdcd8284a4904f95448a522e4c47d9c2f1b4541c5f6f711b42692fb26e1e0d986",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
@@ -27,9 +27,9 @@
"transactions": [],
"withdrawals": [],
"depositReceipts": [],
"exits": [],
"withdrawalRequests": [],
"blockNumber": "0x3",
"blockHash": "0xec4741580be2d83cde0dcd6346a67a71636d915f5da592f39d4470aecef72020",
"blockHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"blobGasUsed": "0x0"
},

View File

@@ -0,0 +1,42 @@
{
"request": {
"jsonrpc": "2.0",
"method": "engine_newPayloadV3",
"params": [
{
"parentHash": "0x57291a8c6fd912648046cae66dcae8b3f3d00b49e679c69566cd11286490458c",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0xdcd8284a4904f95448a522e4c47d9c2f1b4541c5f6f711b42692fb26e1e0d986",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
"gasUsed": "0x0",
"timestamp": "0x30",
"extraData": "0x",
"baseFeePerGas": "0x7",
"transactions": [],
"withdrawals": [],
"depositReceipts": [],
"withdrawalRequests": [],
"blockNumber": "0x3",
"blockHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"excessBlobGas": "0x0",
"blobGasUsed": "0x0"
},
[],
"0x0000000000000000000000000000000000000000000000000000000000000000"
],
"id": 67
},
"response": {
"jsonrpc": "2.0",
"id": 67,
"result": {
"status": "VALID",
"latestValidHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b",
"validationError": null
}
},
"statusCode": 200
}

View File

@@ -0,0 +1,14 @@
{
"request": {
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": ["0xf8a08085e8d4a51000832dc6c094ed8ea01d70cb49726175bcf2778b9c982912e01702b8388706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf2430000000000000000822fe0a008135b1be1734b1b446de871eba10dbc317437eff377a7444f2ff6c06b5e5345a01bc61e0d4dd6d8e0b1f41d843fd9e07260c8be8c664ec2fa8c364477fa021176"],
"id": 67
},
"response": {
"jsonrpc": "2.0",
"id": 67,
"result": "0x764bfa879d0df4ff3962e32dfd45dc39ea18a35ccbd0dadf0bb58672537b1db2"
},
"statusCode": 200
}

View File

@@ -0,0 +1,34 @@
{
"request": {
"jsonrpc": "2.0",
"method": "engine_forkchoiceUpdatedV3",
"params": [
{
"headBlockHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b",
"safeBlockHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b",
"finalizedBlockHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b"
},
{
"timestamp": "0x40",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"withdrawals": [],
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
],
"id": 67
},
"response": {
"jsonrpc": "2.0",
"id": 67,
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b",
"validationError": null
},
"payloadId": "0x282643f22efc45bf"
}
},
"statusCode" : 200
}

View File

@@ -0,0 +1,55 @@
{
"request": {
"jsonrpc": "2.0",
"method": "engine_getPayloadV4",
"params": [
"0x282643f22efc45bf"
],
"id": 67
},
"response": {
"jsonrpc": "2.0",
"id": 67,
"result": {
"executionPayload": {
"parentHash": "0xbac2080fec3fecfb46b4fa1ce20767021f0e53e85b017d5b6a5f4ec43bdbf18b",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0x4a387af05417b5767993052457ca85b2a5a172b3f809eb5cbcf17f070f398c3f",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1c9c380",
"gasUsed": "0x145d3",
"timestamp": "0x40",
"extraData": "0x",
"baseFeePerGas": "0x7",
"excessBlobGas": "0x0",
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"transactions": [
"0xf8a08085e8d4a51000832dc6c094ed8ea01d70cb49726175bcf2778b9c982912e01702b8388706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf2430000000000000000822fe0a008135b1be1734b1b446de871eba10dbc317437eff377a7444f2ff6c06b5e5345a01bc61e0d4dd6d8e0b1f41d843fd9e07260c8be8c664ec2fa8c364477fa021176"
],
"withdrawals": [],
"depositReceipts": [],
"withdrawalRequests": [
{
"sourceAddress": "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f",
"amount": "0x0",
"validatorPubKey": "0x8706d19a62f28a6a6549f96c5adaebac9124a61d44868ec94f6d2d707c6a2f82c9162071231dfeb40e24bfde4ffdf243"
}
],
"receiptsRoot": "0x765bd9d63cc10fa47117d6cc0958f15e55a3bde540d4ed15d220f573fbb82cba",
"blobGasUsed": "0x0",
"blockHash": "0xe589c7673025f6844ffbaeddcf38d77d652669c60412e8506a2ae62ac80e9de4",
"blockNumber": "0x4"
},
"blockValue": "0x12855dcd153473b",
"blobsBundle": {
"commitments": [],
"proofs": [],
"blobs": []
},
"shouldOverrideBuilder": false
}
},
"statusCode": 200,
"waitTime": 1500
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -603,15 +603,15 @@ public class RunnerBuilder {
.setAdvertisedHost(p2pAdvertisedHost);
if (discovery) {
final List<EnodeURL> bootstrap;
if (ethNetworkConfig.getBootNodes() == null) {
bootstrap = EthNetworkConfig.getNetworkConfig(NetworkName.MAINNET).getBootNodes();
if (ethNetworkConfig.bootNodes() == null) {
bootstrap = EthNetworkConfig.getNetworkConfig(NetworkName.MAINNET).bootNodes();
} else {
bootstrap = ethNetworkConfig.getBootNodes();
bootstrap = ethNetworkConfig.bootNodes();
}
discoveryConfiguration.setBootnodes(bootstrap);
LOG.info("Resolved {} bootnodes.", bootstrap.size());
LOG.debug("Bootnodes = {}", bootstrap);
discoveryConfiguration.setDnsDiscoveryURL(ethNetworkConfig.getDnsDiscoveryUrl());
discoveryConfiguration.setDnsDiscoveryURL(ethNetworkConfig.dnsDiscoveryUrl());
discoveryConfiguration.setDiscoveryV5Enabled(
networkingConfiguration.getDiscovery().isDiscoveryV5Enabled());
discoveryConfiguration.setFilterOnEnrForkId(
@@ -1209,7 +1209,7 @@ public class RunnerBuilder {
new JsonRpcMethodsFactory()
.methods(
BesuInfo.nodeName(identityString),
ethNetworkConfig.getNetworkId(),
ethNetworkConfig.networkId(),
besuController.getGenesisConfigOptions(),
network,
blockchainQueries,

View File

@@ -16,7 +16,6 @@ package org.hyperledger.besu.cli;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.hyperledger.besu.cli.DefaultCommandValues.getDefaultBesuDataPath;
@@ -58,6 +57,7 @@ import org.hyperledger.besu.cli.options.stable.LoggingLevelOption;
import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption;
import org.hyperledger.besu.cli.options.stable.P2PTLSConfigOptions;
import org.hyperledger.besu.cli.options.stable.PermissionsOptions;
import org.hyperledger.besu.cli.options.stable.PluginsConfigurationOptions;
import org.hyperledger.besu.cli.options.stable.RpcWebsocketOptions;
import org.hyperledger.besu.cli.options.unstable.ChainPruningOptions;
import org.hyperledger.besu.cli.options.unstable.DnsOptions;
@@ -85,7 +85,7 @@ import org.hyperledger.besu.cli.subcommands.rlp.RLPSubCommand;
import org.hyperledger.besu.cli.subcommands.storage.StorageSubCommand;
import org.hyperledger.besu.cli.util.BesuCommandCustomFactory;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.cli.util.ConfigOptionSearchAndRunHandler;
import org.hyperledger.besu.cli.util.ConfigDefaultValueProviderStrategy;
import org.hyperledger.besu.cli.util.VersionProvider;
import org.hyperledger.besu.components.BesuComponent;
import org.hyperledger.besu.config.CheckpointConfigOptions;
@@ -121,6 +121,7 @@ import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.MiningParametersMetrics;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.VersionMetadata;
import org.hyperledger.besu.ethereum.core.plugins.PluginConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.SyncMode;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
@@ -205,6 +206,7 @@ import java.math.BigInteger;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.file.Path;
import java.time.Clock;
@@ -229,7 +231,6 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Resources;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.json.DecodeException;
@@ -322,7 +323,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final Set<Integer> allocatedPorts = new HashSet<>();
private final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider;
private GenesisConfigOptions genesisConfigOptions;
private final Supplier<GenesisConfigFile> genesisConfigFileSupplier =
Suppliers.memoize(this::readGenesisConfigFile);
private final Supplier<GenesisConfigOptions> genesisConfigOptionsSupplier =
Suppliers.memoize(this::readGenesisConfigOptions);
private RocksDBPlugin rocksDBPlugin;
@@ -876,6 +880,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
@Mixin private PkiBlockCreationOptions pkiBlockCreationOptions;
// Plugins Configuration Option Group
@CommandLine.ArgGroup(validate = false)
PluginsConfigurationOptions pluginsConfigurationOptions = new PluginsConfigurationOptions();
private EthNetworkConfig ethNetworkConfig;
private JsonRpcConfiguration jsonRpcConfiguration;
private JsonRpcConfiguration engineJsonRpcConfiguration;
@@ -1020,6 +1028,16 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
* @param args arguments to Besu command
* @return success or failure exit code.
*/
/**
* Parses command line arguments and configures the application accordingly.
*
* @param resultHandler The strategy to handle the execution result.
* @param parameterExceptionHandler Handler for exceptions related to command line parameters.
* @param executionExceptionHandler Handler for exceptions during command execution.
* @param in The input stream for commands.
* @param args The command line arguments.
* @return The execution result status code.
*/
public int parse(
final IExecutionStrategy resultHandler,
final BesuParameterExceptionHandler parameterExceptionHandler,
@@ -1027,9 +1045,24 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final InputStream in,
final String... args) {
toCommandLine();
initializeCommandLineSettings(in);
// use terminal width for usage message
// Create the execution strategy chain.
final IExecutionStrategy executeTask = createExecuteTask(resultHandler);
final IExecutionStrategy pluginRegistrationTask = createPluginRegistrationTask(executeTask);
final IExecutionStrategy setDefaultValueProviderTask =
createDefaultValueProviderTask(pluginRegistrationTask);
// 1- Config default value provider
// 2- Register plugins
// 3- Execute command
return executeCommandLine(
setDefaultValueProviderTask, parameterExceptionHandler, executionExceptionHandler, args);
}
private void initializeCommandLineSettings(final InputStream in) {
toCommandLine();
// Automatically adjust the width of usage messages to the terminal width.
commandLine.getCommandSpec().usageMessage().autoWidth(true);
handleStableOptions();
@@ -1037,11 +1070,51 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
registerConverters();
handleUnstableOptions();
preparePlugins();
}
final int exitCode =
parse(resultHandler, executionExceptionHandler, parameterExceptionHandler, args);
private IExecutionStrategy createExecuteTask(final IExecutionStrategy nextStep) {
return parseResult -> {
commandLine.setExecutionStrategy(nextStep);
// At this point we don't allow unmatched options since plugins were already registered
commandLine.setUnmatchedArgumentsAllowed(false);
return commandLine.execute(parseResult.originalArgs().toArray(new String[0]));
};
}
return exitCode;
private IExecutionStrategy createPluginRegistrationTask(final IExecutionStrategy nextStep) {
return parseResult -> {
PluginConfiguration configuration =
PluginsConfigurationOptions.fromCommandLine(parseResult.commandSpec().commandLine());
besuPluginContext.registerPlugins(configuration);
commandLine.setExecutionStrategy(nextStep);
return commandLine.execute(parseResult.originalArgs().toArray(new String[0]));
};
}
private IExecutionStrategy createDefaultValueProviderTask(final IExecutionStrategy nextStep) {
return new ConfigDefaultValueProviderStrategy(nextStep, environment);
}
/**
* Executes the command line with the provided execution strategy and exception handlers.
*
* @param executionStrategy The execution strategy to use.
* @param args The command line arguments.
* @return The execution result status code.
*/
private int executeCommandLine(
final IExecutionStrategy executionStrategy,
final BesuParameterExceptionHandler parameterExceptionHandler,
final BesuExecutionExceptionHandler executionExceptionHandler,
final String... args) {
return commandLine
.setExecutionStrategy(executionStrategy)
.setParameterExceptionHandler(parameterExceptionHandler)
.setExecutionExceptionHandler(executionExceptionHandler)
// As this happens before the plugins registration and plugins can add options, we must
// allow unmatched options
.setUnmatchedArgumentsAllowed(true)
.execute(args);
}
/** Used by Dagger to parse all options into a commandline instance. */
@@ -1059,10 +1132,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
try {
configureLogging(true);
if (genesisFile != null) {
genesisConfigOptions = readGenesisConfigOptions();
}
// set merge config on the basis of genesis config
setMergeConfigOptions();
@@ -1208,8 +1277,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
rocksDBPlugin.register(besuPluginContext);
new InMemoryStoragePlugin().register(besuPluginContext);
besuPluginContext.registerPlugins(pluginsDir());
metricCategoryRegistry
.getMetricCategories()
.forEach(metricCategoryConverter::addRegistryCategory);
@@ -1223,8 +1290,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return new KeyPairSecurityModule(loadKeyPair(nodePrivateKeyFileOption.getNodePrivateKeyFile()));
}
// loadKeyPair() is public because it is accessed by subcommands
/**
* Load key pair from private key. Visible to be accessed by subcommands.
*
@@ -1235,26 +1300,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return KeyPairUtil.loadKeyPair(resolveNodePrivateKeyFile(nodePrivateKeyFile));
}
private int parse(
final CommandLine.IExecutionStrategy resultHandler,
final BesuExecutionExceptionHandler besuExecutionExceptionHandler,
final BesuParameterExceptionHandler besuParameterExceptionHandler,
final String... args) {
// Create a handler that will search for a config file option and use it for
// default values
// and eventually it will run regular parsing of the remaining options.
final ConfigOptionSearchAndRunHandler configParsingHandler =
new ConfigOptionSearchAndRunHandler(
resultHandler, besuParameterExceptionHandler, environment);
return commandLine
.setExecutionStrategy(configParsingHandler)
.setParameterExceptionHandler(besuParameterExceptionHandler)
.setExecutionExceptionHandler(besuExecutionExceptionHandler)
.execute(args);
}
private void preSynchronization() {
preSynchronizationTaskRunner.runTasks(besuController);
}
@@ -1424,8 +1469,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
logger.info("Using the Java implementation of the blake2bf algorithm");
}
if (getActualGenesisConfigOptions().getCancunTime().isPresent()
|| getActualGenesisConfigOptions().getPragueTime().isPresent()) {
if (genesisConfigOptionsSupplier.get().getCancunTime().isPresent()
|| genesisConfigOptionsSupplier.get().getPragueTime().isPresent()) {
if (kzgTrustedSetupFile != null) {
KZGPointEvalPrecompiledContract.init(kzgTrustedSetupFile);
} else {
@@ -1455,16 +1500,33 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
validateDataStorageOptions();
validateGraphQlOptions();
validateApiOptions();
validateConsensusSyncCompatibilityOptions();
p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine);
pkiBlockCreationOptions.checkPkiBlockCreationOptionsDependencies(logger, commandLine);
}
private void validateConsensusSyncCompatibilityOptions() {
// snap and checkpoint can't be used with BFT but can for clique
if (genesisConfigOptionsSupplier.get().isIbftLegacy()
|| genesisConfigOptionsSupplier.get().isIbft2()
|| genesisConfigOptionsSupplier.get().isQbft()) {
final String errorSuffix = "can't be used with BFT networks";
if (SyncMode.CHECKPOINT.equals(syncMode) || SyncMode.X_CHECKPOINT.equals(syncMode)) {
throw new ParameterException(
commandLine, String.format("%s %s", "Checkpoint sync", errorSuffix));
}
if (syncMode == SyncMode.SNAP || syncMode == SyncMode.X_SNAP) {
throw new ParameterException(commandLine, String.format("%s %s", "Snap sync", errorSuffix));
}
}
}
private void validateApiOptions() {
apiConfigurationOptions.validate(commandLine, logger);
}
private void validateTransactionPoolOptions() {
transactionPoolOptions.validate(commandLine, getActualGenesisConfigOptions());
transactionPoolOptions.validate(commandLine, genesisConfigOptionsSupplier.get());
}
private void validateDataStorageOptions() {
@@ -1485,7 +1547,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
private void validateMiningParams() {
miningOptions.validate(commandLine, getActualGenesisConfigOptions(), isMergeEnabled(), logger);
miningOptions.validate(
commandLine, genesisConfigOptionsSupplier.get(), isMergeEnabled(), logger);
}
/**
@@ -1595,29 +1658,20 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
}
private GenesisConfigOptions readGenesisConfigOptions() {
private GenesisConfigFile readGenesisConfigFile() {
return genesisFile != null
? GenesisConfigFile.fromSource(genesisConfigSource(genesisFile))
: GenesisConfigFile.fromResource(
Optional.ofNullable(network).orElse(MAINNET).getGenesisFile());
}
private GenesisConfigOptions readGenesisConfigOptions() {
try {
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(genesisConfig());
genesisConfigOptions = genesisConfigFile.getConfigOptions(genesisConfigOverrides);
return genesisConfigFileSupplier.get().getConfigOptions(genesisConfigOverrides);
} catch (final Exception e) {
throw new ParameterException(
this.commandLine, "Unable to load genesis file. " + e.getCause());
}
// snap and checkpoint can't be used with BFT but can for clique
if (genesisConfigOptions.isIbftLegacy()
|| genesisConfigOptions.isIbft2()
|| genesisConfigOptions.isQbft()) {
final String errorSuffix = "can't be used with BFT networks";
if (SyncMode.CHECKPOINT.equals(syncMode) || SyncMode.X_CHECKPOINT.equals(syncMode)) {
throw new ParameterException(
commandLine, String.format("%s %s", "Checkpoint sync", errorSuffix));
}
if (syncMode == SyncMode.SNAP || syncMode == SyncMode.X_SNAP) {
throw new ParameterException(commandLine, String.format("%s %s", "Snap sync", errorSuffix));
}
}
return genesisConfigOptions;
}
private void issueOptionWarnings() {
@@ -1716,7 +1770,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
permissioningConfiguration = permissioningConfiguration();
staticNodes = loadStaticNodes();
final List<EnodeURL> enodeURIs = ethNetworkConfig.getBootNodes();
final List<EnodeURL> enodeURIs = ethNetworkConfig.bootNodes();
permissioningConfiguration
.flatMap(PermissioningConfiguration::getLocalConfig)
.ifPresent(p -> ensureAllNodesAreInAllowlist(enodeURIs, p));
@@ -1793,8 +1847,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
getMiningParameters());
final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName);
return controllerBuilderFactory
.fromEthNetworkConfig(
updateNetworkConfig(network), genesisConfigOverrides, getDefaultSyncModeIfNotSet())
.fromEthNetworkConfig(updateNetworkConfig(network), getDefaultSyncModeIfNotSet())
.synchronizerConfiguration(buildSyncConfig())
.ethProtocolConfiguration(unstableEthProtocolOptions.toDomainObject())
.networkConfiguration(unstableNetworkingOptions.toDomainObject())
@@ -1810,7 +1863,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.clock(Clock.systemUTC())
.isRevertReasonEnabled(isRevertReasonEnabled)
.storageProvider(storageProvider)
.genesisConfigOverrides(genesisConfigOverrides)
.gasLimitCalculator(
getMiningParameters().getTargetGasLimit().isPresent()
? new FrontierTargetingGasLimitCalculator()
@@ -2099,7 +2151,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.from(txPoolConf)
.saveFile((dataPath.resolve(txPoolConf.getSaveFile().getPath()).toFile()));
if (getActualGenesisConfigOptions().isZeroBaseFee()) {
if (genesisConfigOptionsSupplier.get().isZeroBaseFee()) {
logger.info(
"Forcing price bump for transaction replacement to 0, since we are on a zero basefee network");
txPoolConfBuilder.priceBump(Percentage.ZERO);
@@ -2136,7 +2188,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
if (miningParameters == null) {
miningOptions.setTransactionSelectionService(transactionSelectionServiceImpl);
miningParameters = miningOptions.toDomainObject();
getGenesisBlockPeriodSeconds(getActualGenesisConfigOptions())
getGenesisBlockPeriodSeconds(genesisConfigOptionsSupplier.get())
.ifPresent(miningParameters::setBlockPeriodSeconds);
initMiningParametersMetrics(miningParameters);
}
@@ -2288,16 +2340,14 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
+ "refer to CLI reference for more details about this constraint.");
}
builder.setGenesisConfig(genesisConfig());
if (networkId == null) {
// If no chain id is found in the genesis, use mainnet network id
try {
builder.setNetworkId(
getGenesisConfigFile()
.getConfigOptions(genesisConfigOverrides)
genesisConfigOptionsSupplier
.get()
.getChainId()
.orElse(EthNetworkConfig.getNetworkConfig(MAINNET).getNetworkId()));
.orElse(EthNetworkConfig.getNetworkConfig(MAINNET).networkId()));
} catch (final DecodeException e) {
throw new ParameterException(
this.commandLine, String.format("Unable to parse genesis file %s.", genesisFile), e);
@@ -2315,18 +2365,20 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
builder.setDnsDiscoveryUrl(null);
}
if (p2PDiscoveryOptionGroup.discoveryDnsUrl != null) {
builder.setDnsDiscoveryUrl(p2PDiscoveryOptionGroup.discoveryDnsUrl);
} else if (genesisConfigOptions != null) {
final Optional<String> discoveryDnsUrlFromGenesis =
genesisConfigOptions.getDiscoveryOptions().getDiscoveryDnsUrl();
discoveryDnsUrlFromGenesis.ifPresent(builder::setDnsDiscoveryUrl);
}
builder.setGenesisConfigFile(genesisConfigFileSupplier.get());
if (networkId != null) {
builder.setNetworkId(networkId);
}
if (p2PDiscoveryOptionGroup.discoveryDnsUrl != null) {
builder.setDnsDiscoveryUrl(p2PDiscoveryOptionGroup.discoveryDnsUrl);
} else {
final Optional<String> discoveryDnsUrlFromGenesis =
genesisConfigOptionsSupplier.get().getDiscoveryOptions().getDiscoveryDnsUrl();
discoveryDnsUrlFromGenesis.ifPresent(builder::setDnsDiscoveryUrl);
}
List<EnodeURL> listBootNodes = null;
if (p2PDiscoveryOptionGroup.bootNodes != null) {
try {
@@ -2334,9 +2386,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} catch (final IllegalArgumentException e) {
throw new ParameterException(commandLine, e.getMessage());
}
} else if (genesisConfigOptions != null) {
} else {
final Optional<List<String>> bootNodesFromGenesis =
genesisConfigOptions.getDiscoveryOptions().getBootNodes();
genesisConfigOptionsSupplier.get().getDiscoveryOptions().getBootNodes();
if (bootNodesFromGenesis.isPresent()) {
listBootNodes = buildEnodes(bootNodesFromGenesis.get(), getEnodeDnsConfiguration());
}
@@ -2351,28 +2403,15 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return builder.build();
}
private GenesisConfigFile getGenesisConfigFile() {
return GenesisConfigFile.fromConfig(genesisConfig());
}
private String genesisConfig() {
private URL genesisConfigSource(final File genesisFile) {
try {
return Resources.toString(genesisFile.toURI().toURL(), UTF_8);
return genesisFile.toURI().toURL();
} catch (final IOException e) {
throw new ParameterException(
this.commandLine, String.format("Unable to load genesis URL %s.", genesisFile), e);
}
}
private static String genesisConfig(final NetworkName networkName) {
try (final InputStream genesisFileInputStream =
EthNetworkConfig.class.getResourceAsStream(networkName.getGenesisFile())) {
return new String(genesisFileInputStream.readAllBytes(), UTF_8);
} catch (final IOException | NullPointerException e) {
throw new IllegalStateException(e);
}
}
/**
* Returns data directory used by Besu. Visible as it is accessed by other subcommands.
*
@@ -2382,15 +2421,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return dataPath.toAbsolutePath();
}
private Path pluginsDir() {
final String pluginsDir = System.getProperty("besu.plugins.dir");
if (pluginsDir == null) {
return new File(System.getProperty("besu.home", "."), "plugins").toPath();
} else {
return new File(pluginsDir).toPath();
}
}
private SecurityModule securityModule() {
return securityModuleService
.getByName(securityModuleName)
@@ -2595,26 +2625,21 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
if (genesisFile == null) {
return Optional.empty();
}
return genesisConfigOptions.getEcCurve();
return genesisConfigOptionsSupplier.get().getEcCurve();
}
/**
* Return the genesis config options after applying any specified config overrides
* Return the genesis config options
*
* @return the genesis config options after applying any specified config overrides
* @return the genesis config options
*/
protected GenesisConfigOptions getActualGenesisConfigOptions() {
return Optional.ofNullable(genesisConfigOptions)
.orElseGet(
() ->
GenesisConfigFile.fromConfig(
genesisConfig(Optional.ofNullable(network).orElse(MAINNET)))
.getConfigOptions(genesisConfigOverrides));
protected GenesisConfigOptions getGenesisConfigOptions() {
return genesisConfigOptionsSupplier.get();
}
private void setMergeConfigOptions() {
MergeConfigOptions.setMergeEnabled(
getActualGenesisConfigOptions().getTerminalTotalDifficulty().isPresent());
genesisConfigOptionsSupplier.get().getTerminalTotalDifficulty().isPresent());
}
/** Set ignorable segments in RocksDB Storage Provider plugin. */
@@ -2625,11 +2650,12 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
private void validatePostMergeCheckpointBlockRequirements() {
final GenesisConfigOptions genesisOptions = getActualGenesisConfigOptions();
final SynchronizerConfiguration synchronizerConfiguration =
unstableSynchronizerOptions.toDomainObject().build();
final Optional<UInt256> terminalTotalDifficulty = genesisOptions.getTerminalTotalDifficulty();
final CheckpointConfigOptions checkpointConfigOptions = genesisOptions.getCheckpointOptions();
final Optional<UInt256> terminalTotalDifficulty =
genesisConfigOptionsSupplier.get().getTerminalTotalDifficulty();
final CheckpointConfigOptions checkpointConfigOptions =
genesisConfigOptionsSupplier.get().getCheckpointOptions();
if (synchronizerConfiguration.isCheckpointPostMergeEnabled()) {
if (!checkpointConfigOptions.isValid()) {
throw new InvalidConfigurationException(
@@ -2637,15 +2663,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
terminalTotalDifficulty.ifPresentOrElse(
ttd -> {
if (UInt256.fromHexString(
genesisOptions.getCheckpointOptions().getTotalDifficulty().get())
if (UInt256.fromHexString(checkpointConfigOptions.getTotalDifficulty().get())
.equals(UInt256.ZERO)
&& ttd.equals(UInt256.ZERO)) {
throw new InvalidConfigurationException(
"PoS checkpoint sync can't be used with TTD = 0 and checkpoint totalDifficulty = 0");
}
if (UInt256.fromHexString(
genesisOptions.getCheckpointOptions().getTotalDifficulty().get())
if (UInt256.fromHexString(checkpointConfigOptions.getTotalDifficulty().get())
.lessThan(ttd)) {
throw new InvalidConfigurationException(
"PoS checkpoint sync requires a block with total difficulty greater or equal than the TTD");
@@ -2679,7 +2703,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private Boolean getDefaultVersionCompatibilityProtectionIfNotSet() {
// Version compatibility protection is enabled by default for non-named networks
return Optional.ofNullable(versionCompatibilityProtection)
.orElse(commandLine.getParseResult().hasMatchedOption("network") ? false : true);
// if we have a specific genesis file or custom network id, we are not using a named network
.orElse(genesisFile != null || networkId != null);
}
private String generateConfigurationOverview() {
@@ -2701,7 +2726,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
if (genesisFile != null) {
builder.setCustomGenesis(genesisFile.getAbsolutePath());
}
builder.setNetworkId(ethNetworkConfig.getNetworkId());
builder.setNetworkId(ethNetworkConfig.networkId());
builder
.setDataStorage(dataStorageOptions.normalizeDataStorageFormat())

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -125,6 +125,9 @@ public interface DefaultCommandValues {
/** The Default tls protocols. */
List<String> DEFAULT_TLS_PROTOCOLS = List.of("TLSv1.3", "TLSv1.2");
/** The constant DEFAULT_PLUGINS_OPTION_NAME. */
String DEFAULT_PLUGINS_OPTION_NAME = "--plugins";
/**
* Gets default besu data path.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -14,8 +14,6 @@
*/
package org.hyperledger.besu.cli.config;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
@@ -24,6 +22,8 @@ import org.hyperledger.besu.plugin.data.EnodeURL;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -31,102 +31,25 @@ import java.util.Optional;
import java.util.stream.Collectors;
/** The Eth network config. */
public class EthNetworkConfig {
private final String genesisConfig;
private final BigInteger networkId;
private final List<EnodeURL> bootNodes;
private final String dnsDiscoveryUrl;
public record EthNetworkConfig(
GenesisConfigFile genesisConfigFile,
BigInteger networkId,
List<EnodeURL> bootNodes,
String dnsDiscoveryUrl) {
/**
* Instantiates a new Eth network config.
* Validate parameters on new record creation
*
* @param genesisConfig the genesis config
* @param genesisConfigFile the genesis config
* @param networkId the network id
* @param bootNodes the boot nodes
* @param dnsDiscoveryUrl the dns discovery url
*/
public EthNetworkConfig(
final String genesisConfig,
final BigInteger networkId,
final List<EnodeURL> bootNodes,
final String dnsDiscoveryUrl) {
Objects.requireNonNull(genesisConfig);
@SuppressWarnings(
"MethodInputParametersMustBeFinal") // needed since record constructors are not yet supported
public EthNetworkConfig {
Objects.requireNonNull(genesisConfigFile);
Objects.requireNonNull(bootNodes);
this.genesisConfig = genesisConfig;
this.networkId = networkId;
this.bootNodes = bootNodes;
this.dnsDiscoveryUrl = dnsDiscoveryUrl;
}
/**
* Gets genesis config.
*
* @return the genesis config
*/
public String getGenesisConfig() {
return genesisConfig;
}
/**
* Gets network id.
*
* @return the network id
*/
public BigInteger getNetworkId() {
return networkId;
}
/**
* Gets boot nodes.
*
* @return the boot nodes
*/
public List<EnodeURL> getBootNodes() {
return bootNodes;
}
/**
* Gets dns discovery url.
*
* @return the dns discovery url
*/
public String getDnsDiscoveryUrl() {
return dnsDiscoveryUrl;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final EthNetworkConfig that = (EthNetworkConfig) o;
return networkId.equals(that.networkId)
&& Objects.equals(genesisConfig, that.genesisConfig)
&& Objects.equals(bootNodes, that.bootNodes)
&& Objects.equals(dnsDiscoveryUrl, that.dnsDiscoveryUrl);
}
@Override
public int hashCode() {
return Objects.hash(genesisConfig, networkId, bootNodes, dnsDiscoveryUrl);
}
@Override
public String toString() {
return "EthNetworkConfig{"
+ "genesisConfig="
+ genesisConfig
+ ", networkId="
+ networkId
+ ", bootNodes="
+ bootNodes
+ ", dnsDiscoveryUrl="
+ dnsDiscoveryUrl
+ '}';
}
/**
@@ -136,9 +59,9 @@ public class EthNetworkConfig {
* @return the network config
*/
public static EthNetworkConfig getNetworkConfig(final NetworkName networkName) {
final String genesisContent = jsonConfig(networkName.getGenesisFile());
final GenesisConfigOptions genesisConfigOptions =
GenesisConfigFile.fromConfig(genesisContent).getConfigOptions();
final URL genesisSource = jsonConfigSource(networkName.getGenesisFile());
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromSource(genesisSource);
final GenesisConfigOptions genesisConfigOptions = genesisConfigFile.getConfigOptions();
final Optional<List<String>> rawBootNodes =
genesisConfigOptions.getDiscoveryOptions().getBootNodes();
final List<EnodeURL> bootNodes =
@@ -148,36 +71,36 @@ public class EthNetworkConfig {
strings.stream().map(EnodeURLImpl::fromString).collect(Collectors.toList()))
.orElse(Collections.emptyList());
return new EthNetworkConfig(
genesisContent,
genesisConfigFile,
networkName.getNetworkId(),
bootNodes,
genesisConfigOptions.getDiscoveryOptions().getDiscoveryDnsUrl().orElse(null));
}
private static String jsonConfig(final String resourceName) {
try (final InputStream genesisFileInputStream =
EthNetworkConfig.class.getResourceAsStream(resourceName)) {
return new String(genesisFileInputStream.readAllBytes(), UTF_8);
} catch (IOException | NullPointerException e) {
throw new IllegalStateException(e);
}
private static URL jsonConfigSource(final String resourceName) {
return EthNetworkConfig.class.getResource(resourceName);
}
/**
* Json config string.
*
* @param network the network
* @return the string
* @param network the named network
* @return the json string
*/
public static String jsonConfig(final NetworkName network) {
return jsonConfig(network.getGenesisFile());
try (final InputStream genesisFileInputStream =
EthNetworkConfig.class.getResourceAsStream(network.getGenesisFile())) {
return new String(genesisFileInputStream.readAllBytes(), StandardCharsets.UTF_8);
} catch (IOException | NullPointerException e) {
throw new IllegalStateException(e);
}
}
/** The type Builder. */
public static class Builder {
private String dnsDiscoveryUrl;
private String genesisConfig;
private GenesisConfigFile genesisConfigFile;
private BigInteger networkId;
private List<EnodeURL> bootNodes;
@@ -187,20 +110,20 @@ public class EthNetworkConfig {
* @param ethNetworkConfig the eth network config
*/
public Builder(final EthNetworkConfig ethNetworkConfig) {
this.genesisConfig = ethNetworkConfig.genesisConfig;
this.genesisConfigFile = ethNetworkConfig.genesisConfigFile;
this.networkId = ethNetworkConfig.networkId;
this.bootNodes = ethNetworkConfig.bootNodes;
this.dnsDiscoveryUrl = ethNetworkConfig.dnsDiscoveryUrl;
}
/**
* Sets genesis config.
* Sets genesis config file.
*
* @param genesisConfig the genesis config
* @return the genesis config
* @param genesisConfigFile the genesis config
* @return this builder
*/
public Builder setGenesisConfig(final String genesisConfig) {
this.genesisConfig = genesisConfig;
public Builder setGenesisConfigFile(final GenesisConfigFile genesisConfigFile) {
this.genesisConfigFile = genesisConfigFile;
return this;
}
@@ -208,7 +131,7 @@ public class EthNetworkConfig {
* Sets network id.
*
* @param networkId the network id
* @return the network id
* @return this builder
*/
public Builder setNetworkId(final BigInteger networkId) {
this.networkId = networkId;
@@ -219,7 +142,7 @@ public class EthNetworkConfig {
* Sets boot nodes.
*
* @param bootNodes the boot nodes
* @return the boot nodes
* @return this builder
*/
public Builder setBootNodes(final List<EnodeURL> bootNodes) {
this.bootNodes = bootNodes;
@@ -230,7 +153,7 @@ public class EthNetworkConfig {
* Sets dns discovery url.
*
* @param dnsDiscoveryUrl the dns discovery url
* @return the dns discovery url
* @return this builder
*/
public Builder setDnsDiscoveryUrl(final String dnsDiscoveryUrl) {
this.dnsDiscoveryUrl = dnsDiscoveryUrl;
@@ -243,7 +166,7 @@ public class EthNetworkConfig {
* @return the eth network config
*/
public EthNetworkConfig build() {
return new EthNetworkConfig(genesisConfig, networkId, bootNodes, dnsDiscoveryUrl);
return new EthNetworkConfig(genesisConfigFile, networkId, bootNodes, dnsDiscoveryUrl);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -0,0 +1,53 @@
/*
* 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.cli.converter;
import org.hyperledger.besu.ethereum.core.plugins.PluginInfo;
import java.util.List;
import java.util.stream.Stream;
import picocli.CommandLine;
/**
* Converts a comma-separated string into a list of {@link PluginInfo} objects. This converter is
* intended for use with PicoCLI to process command line arguments that specify plugin information.
*/
public class PluginInfoConverter implements CommandLine.ITypeConverter<List<PluginInfo>> {
/**
* Converts a comma-separated string into a list of {@link PluginInfo}.
*
* @param value The comma-separated string representing plugin names.
* @return A list of {@link PluginInfo} objects created from the provided string.
*/
@Override
public List<PluginInfo> convert(final String value) {
if (value == null || value.isBlank()) {
return List.of();
}
return Stream.of(value.split(",")).map(String::trim).map(this::toPluginInfo).toList();
}
/**
* Creates a {@link PluginInfo} object from a plugin name.
*
* @param pluginName The name of the plugin.
* @return A {@link PluginInfo} object representing the plugin.
*/
private PluginInfo toPluginInfo(final String pluginName) {
return new PluginInfo(pluginName);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright Hyperledger Besu Contributors.
* 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

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