diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index 74ba75c2f91..7b212cdcad1 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -35,6 +35,8 @@ jobs: with: distribution: temurin java-version: 17 + - name: Install required packages + run: sudo apt-get install -y xmlstarlet - name: get acceptance test report uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d with: @@ -48,19 +50,16 @@ jobs: with: cache-disabled: true - name: Split tests - id: split-tests - uses: r7kamura/split-tests-by-timings@9322bd292d9423e2bc5a65bec548901801341e3f + run: .github/workflows/splitTestsByTime.sh tmp/junit-xml-reports-downloaded ${{env.total-runners}} ${{ matrix.runner_index }} > testList.txt + - name: Upload Timing + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 + if: matrix.runner_index == 0 with: - reports: tmp/junit-xml-reports-downloaded - glob: 'acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/**/*Test.java' - total: ${{env.total-runners}} - index: ${{ matrix.runner_index }} - - name: write out test list - run: echo "${{ steps.split-tests.outputs.paths }}" >> testList.txt + name: acceptance-tests-timing + path: 'tmp/timing.tsv' - name: format gradle args - #regex means: first truncate file paths to align with package name, then swap path delimiter with package delimiter, - #then drop file extension, then insert --tests option between each. - run: cat testList.txt | sed -e 's@acceptance-tests/tests/src/test/java/@--tests\ @g;s@/@.@g;s/\.java//g' > gradleArgs.txt + # insert --tests option between each. + run: cat testList.txt | sed -e 's/^\| / --tests /g' | tee gradleArgs.txt - name: run acceptance tests run: ./gradlew acceptanceTestNotPrivacy `cat gradleArgs.txt` -Dorg.gradle.parallel=true -Dorg.gradle.caching=true - name: cleanup tempfiles diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml new file mode 100644 index 00000000000..a5447473147 --- /dev/null +++ b/.github/workflows/develop.yml @@ -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 diff --git a/.github/workflows/splitTestsByTime.sh b/.github/workflows/splitTestsByTime.sh new file mode 100755 index 00000000000..3afb614d427 --- /dev/null +++ b/.github/workflows/splitTestsByTime.sh @@ -0,0 +1,52 @@ +#!/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 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()); @@ -430,13 +422,15 @@ public void startNode(final BesuNode node) { 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 +572,7 @@ private void killBesuProcess(final String name) { 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) { diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 4c504c4e33b..9648122de3b 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -2679,7 +2679,8 @@ private SyncMode getDefaultSyncModeIfNotSet() { 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() { diff --git a/build.gradle b/build.gradle index 63c2b24b882..31eec61f219 100644 --- a/build.gradle +++ b/build.gradle @@ -979,6 +979,7 @@ def getGitCommitDetails(length = 8) { def isInterimBuild(dockerBuildVersion) { return (dockerBuildVersion ==~ /.*-SNAPSHOT/) || (dockerBuildVersion ==~ /.*-alpha/) || (dockerBuildVersion ==~ /.*-beta/) || (dockerBuildVersion ==~ /.*-RC.*/) + || (dockerBuildVersion ==~ /.*develop.*/) } tasks.register("verifyDistributions") { diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java index bdeac24be10..646e6d52510 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/BlockMiner.java @@ -170,16 +170,15 @@ protected boolean mineBlock() throws InterruptedException { private void logProducedBlock(final Block block, final BlockCreationTiming blockCreationTiming) { LOG.info( String.format( - "Produced #%,d / %d tx / %d om / %,d (%01.1f%%) gas / (%s) in %01.3fs", + "Produced #%,d / %d tx / %d om / %,d (%01.1f%%) gas / (%s) in %01.3fs / Timing(%s)", block.getHeader().getNumber(), block.getBody().getTransactions().size(), block.getBody().getOmmers().size(), block.getHeader().getGasUsed(), (block.getHeader().getGasUsed() * 100.0) / block.getHeader().getGasLimit(), block.getHash(), - blockCreationTiming.end("log").toMillis() / 1000.0)); - - LOG.debug("Timing #{} / {}", block.getHeader().getNumber(), blockCreationTiming); + blockCreationTiming.end("log").toMillis() / 1000.0, + blockCreationTiming)); } public void cancel() { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/VersionMetadata.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/VersionMetadata.java index 5246cb5fae3..0346dd84018 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/VersionMetadata.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/VersionMetadata.java @@ -18,6 +18,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Path; +import javax.annotation.Nonnull; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; @@ -27,7 +28,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VersionMetadata { +public class VersionMetadata implements Comparable { private static final Logger LOG = LoggerFactory.getLogger(VersionMetadata.class); /** Represents an unknown Besu version in the version metadata file */ @@ -42,12 +43,16 @@ public class VersionMetadata { * * @return the version of Besu */ - public static String getRuntimeVersion() { + public static String getRuntimeVersionString() { return VersionMetadata.class.getPackage().getImplementationVersion() == null ? BESU_VERSION_UNKNOWN : VersionMetadata.class.getPackage().getImplementationVersion(); } + public static VersionMetadata getRuntimeVersion() { + return new VersionMetadata(getRuntimeVersionString()); + } + @JsonCreator public VersionMetadata(@JsonProperty("besuVersion") final String besuVersion) { this.besuVersion = besuVersion; @@ -103,52 +108,57 @@ private static VersionMetadata resolveVersionMetadata(final File metadataFile) */ public static void versionCompatibilityChecks( final boolean enforceCompatibilityProtection, final Path dataDir) throws IOException { - final VersionMetadata versionMetaData = VersionMetadata.lookUpFrom(dataDir); - if (versionMetaData.getBesuVersion().equals(VersionMetadata.BESU_VERSION_UNKNOWN)) { + final VersionMetadata metadataVersion = VersionMetadata.lookUpFrom(dataDir); + final VersionMetadata runtimeVersion = getRuntimeVersion(); + if (metadataVersion.getBesuVersion().equals(VersionMetadata.BESU_VERSION_UNKNOWN)) { // The version isn't known, potentially because the file doesn't exist. Write the latest // version to the metadata file. LOG.info( "No version data detected. Writing Besu version {} to metadata file", - VersionMetadata.getRuntimeVersion()); - new VersionMetadata(VersionMetadata.getRuntimeVersion()).writeToDirectory(dataDir); + runtimeVersion.getBesuVersion()); + runtimeVersion.writeToDirectory(dataDir); } else { // Check the runtime version against the most recent version as recorded in the version // metadata file - final String installedVersion = VersionMetadata.getRuntimeVersion().split("-", 2)[0]; - final String metadataVersion = versionMetaData.getBesuVersion().split("-", 2)[0]; - final int versionComparison = - new ComparableVersion(installedVersion).compareTo(new ComparableVersion(metadataVersion)); + final int versionComparison = runtimeVersion.compareTo(metadataVersion); if (versionComparison == 0) { // Versions match - no-op } else if (versionComparison < 0) { if (!enforceCompatibilityProtection) { LOG.warn( "Besu version {} is lower than version {} that last started. Allowing startup because --version-compatibility-protection has been disabled.", - installedVersion, - metadataVersion); + runtimeVersion.getBesuVersion(), + metadataVersion.getBesuVersion()); // We've allowed startup at an older version of Besu. Since the version in the metadata // file records the latest version of // Besu to write to the database we'll update the metadata version to this // downgraded-version. - new VersionMetadata(VersionMetadata.getRuntimeVersion()).writeToDirectory(dataDir); + runtimeVersion.writeToDirectory(dataDir); } else { final String message = "Besu version " - + installedVersion + + runtimeVersion.getBesuVersion() + " is lower than version " - + metadataVersion + + metadataVersion.getBesuVersion() + " that last started. Remove --version-compatibility-protection option to allow Besu to start at " + " the lower version (warning - this may have unrecoverable effects on the database)."; - LOG.error(message, installedVersion, metadataVersion); + LOG.error(message); throw new IllegalStateException(message); } } else { LOG.info( "Besu version {} is higher than version {} that last started. Updating version metadata.", - installedVersion, - metadataVersion); - new VersionMetadata(VersionMetadata.getRuntimeVersion()).writeToDirectory(dataDir); + runtimeVersion.getBesuVersion(), + metadataVersion.getBesuVersion()); + runtimeVersion.writeToDirectory(dataDir); } } } + + @Override + public int compareTo(@Nonnull final VersionMetadata versionMetadata) { + final String thisVersion = this.getBesuVersion().split("-", 2)[0]; + final String metadataVersion = versionMetadata.getBesuVersion().split("-", 2)[0]; + return new ComparableVersion(thisVersion).compareTo(new ComparableVersion(metadataVersion)); + } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/VersionMetadataTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/VersionMetadataTest.java index 0cebcd4bda8..dce027b5e5d 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/VersionMetadataTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/VersionMetadataTest.java @@ -22,10 +22,14 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.stream.Stream; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -60,6 +64,33 @@ void dataDirShouldBeCreatedIfNotPresent() throws Exception { assertThat(Files.exists(temporaryFolder)).isTrue(); } + static Stream versionTestProvider() { + return Stream.of( + Arguments.of("24.4.0", "24.3.3", 1), + Arguments.of("24.3.3", "24.3.3", 0), + Arguments.of("24.2.0", "24.3.3", -1), + Arguments.of("24.3.3", "24.3-develop-59da092", 1), + Arguments.of("24.3.0", "24.3-develop-59da092", 0), + Arguments.of("24.3.3", "24.4-develop-59da092", -1), + Arguments.of("24.2-develop-59da092", "24.3-develop-9999999", -1), + Arguments.of("24.3-develop-59da092", "24.3-develop-9999999", 0), + Arguments.of("24.4-develop-59da092", "24.3-develop-9999999", 1), + Arguments.of("24.4-develop-59da092", "24.3.0", 1), + Arguments.of("24.4-develop-59da092", "24.4.0", 0), + Arguments.of("24.4-develop-59da092", "24.4.1", -1)); + } + + @ParameterizedTest + @MethodSource("versionTestProvider") + public void assertComparableChecks( + final String runtimeVersion, + final String metadataVersion, + final int expectedComparisonResult) { + VersionMetadata runtime = new VersionMetadata(runtimeVersion); + VersionMetadata develop = new VersionMetadata(metadataVersion); + assertThat(runtime.compareTo(develop)).isEqualTo(expectedComparisonResult); + } + @Test void compatibilityCheckShouldThrowExceptionIfEnabled() throws Exception { // The version file says the last version to start was 23.10.3 @@ -69,7 +100,7 @@ void compatibilityCheckShouldThrowExceptionIfEnabled() throws Exception { // The runtime says the current version is 23.10.2 (i.e. a downgrade) try (MockedStatic mocked = Mockito.mockStatic(VersionMetadata.class, Mockito.CALLS_REAL_METHODS)) { - mocked.when(VersionMetadata::getRuntimeVersion).thenReturn("23.10.2"); + mocked.when(VersionMetadata::getRuntimeVersionString).thenReturn("23.10.2"); final VersionMetadata versionMetadata = VersionMetadata.lookUpFrom(tempDataDir); assertThat(versionMetadata).isNotNull(); @@ -96,7 +127,7 @@ void compatibilityCheckShouldNotThrowExceptionIfDisabled() throws Exception { // version-compatibility-protection = false so no exception should be thrown try (MockedStatic mocked = Mockito.mockStatic(VersionMetadata.class, Mockito.CALLS_REAL_METHODS)) { - mocked.when(VersionMetadata::getRuntimeVersion).thenReturn("23.10.2"); + mocked.when(VersionMetadata::getRuntimeVersionString).thenReturn("23.10.2"); final VersionMetadata versionMetadata = VersionMetadata.lookUpFrom(tempDataDir); assertThat(versionMetadata).isNotNull(); @@ -122,7 +153,7 @@ void compatibilityCheckShouldNotThrowExceptionIfResultIsUpgrade() throws Excepti // The runtime says the current version is 23.10.2 (i.e. a downgrade) try (MockedStatic mocked = Mockito.mockStatic(VersionMetadata.class, Mockito.CALLS_REAL_METHODS)) { - mocked.when(VersionMetadata::getRuntimeVersion).thenReturn("23.10.4"); + mocked.when(VersionMetadata::getRuntimeVersionString).thenReturn("23.10.4"); final VersionMetadata versionMetadata = VersionMetadata.lookUpFrom(tempDataDir); assertThat(versionMetadata).isNotNull(); diff --git a/ethereum/evmtool/build.gradle b/ethereum/evmtool/build.gradle index db582bcb02f..0d1700082fa 100644 --- a/ethereum/evmtool/build.gradle +++ b/ethereum/evmtool/build.gradle @@ -139,7 +139,7 @@ tasks.register('dockerUpload', Exec) { additionalTags.add('develop') } - if (!(dockerBuildVersion ==~ /.*-SNAPSHOT/)) { + if (!(dockerBuildVersion ==~ /.*-SNAPSHOT/ || dockerBuildVersion ==~/.*develop.*/)) { additionalTags.add('latest') additionalTags.add(dockerBuildVersion.split(/\./)[0..1].join('.')) } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManager.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManager.java index e4469337d4b..505e38aa865 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManager.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManager.java @@ -52,7 +52,7 @@ public void onDisconnect( final boolean initiatedByPeer) { // we have a number of reasons that use the same code, but with different message strings // so here we use the code of the reason param to ensure we get the no-message version - if (shouldBlock(DisconnectReason.forCode(reason.getValue().get(0)), initiatedByPeer)) { + if (shouldBlock(DisconnectReason.forCode(reason.getValue()), initiatedByPeer)) { if (maintainedPeers.contains(connection.getPeer())) { LOG.debug( "Skip adding maintained peer {} to peer denylist for reason {}", diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java index ae19e71fff5..66337903358 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/wire/messages/DisconnectMessage.java @@ -174,6 +174,14 @@ public static DisconnectReason forCode(final Byte code) { return BY_ID[code]; } + public static DisconnectReason forCode(final Bytes codeBytes) { + if (codeBytes == null || codeBytes.isEmpty()) { + return UNKNOWN; + } else { + return forCode(codeBytes.get(0)); + } + } + DisconnectReason(final Byte code) { this.code = Optional.ofNullable(code); this.message = Optional.empty(); diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManagerTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManagerTest.java index a8091e1f8df..bef39a2a09b 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManagerTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/PeerDenylistManagerTest.java @@ -111,6 +111,15 @@ public void denylistIncompatiblePeerWhoIssuesDisconnect() { checkPermissions(denylist, peer.getPeer(), false); } + @Test + public void disconnectReasonWithEmptyValue_doesNotAddToDenylist() { + final PeerConnection peer = generatePeerConnection(); + + checkPermissions(denylist, peer.getPeer(), true); + peerDenylistManager.onDisconnect(peer, DisconnectReason.UNKNOWN, false); + checkPermissions(denylist, peer.getPeer(), true); + } + private void checkPermissions( final PeerPermissionsDenylist denylist, final Peer remotePeer, final boolean expectedResult) { for (PeerPermissions.Action action : PeerPermissions.Action.values()) {