Skip to content

Commit

Permalink
Tidy up and tests for the new class
Browse files Browse the repository at this point in the history
Signed-off-by: Matthew Whitehead <matthew1001@gmail.com>
  • Loading branch information
matthew1001 committed Dec 20, 2023
1 parent 96f5080 commit 9dce227
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 36 deletions.
25 changes: 22 additions & 3 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -1466,12 +1466,13 @@ public void run() {
vertx = createVertx(createVertxOptions(metricsSystem.get()));

validateOptions();

performDowngradeCheck();

configure();
configureNativeLibs();
besuController = initController();

performDowngradeCheck();

besuPluginContext.beforeExternalServices();

final var runner = buildRunner();
Expand All @@ -1491,6 +1492,14 @@ public void run() {
}
}

/**
* This function is designed to protect a Besu instance from being unintentionally started at a lower
* version than the previous instance. Doing so could cause unexpected data corruption (depending on
* the storage provider that is in use), so this check prompts the user if a downgrade is detected
* and requires them to opt-in by setting --allow-downgrade. The --allow-downgrade flag only needs
* to be passed in once, and then the version information is updated to the lower version number, meaning
* future restarts will pass the check.
*/
private void performDowngradeCheck() throws IOException {
final VersionMetadata versionMetaData = VersionMetadata.lookUpFrom(dataDir());
if (versionMetaData.getBesuVersion().equals(VersionMetadata.BESU_VERSION_UNKNOWN)) {
Expand Down Expand Up @@ -1528,7 +1537,7 @@ private void performDowngradeCheck() throws IOException {
+ " is lower than version "
+ metadataVersion
+ " that last started."
+ ". Specify --allow-downgrade to allow Besu to start at the lower version (warning - this may have unrecoverable effects on the database).";
+ "Specify --allow-downgrade to allow Besu to start at the lower version (warning - this may have unrecoverable effects on the database).";

Check notice

Code scanning / CodeQL

Missing space in string literal Note

This string appears to be missing a space after 'started.'.
logger.error(message);
throw new StorageException(message);
}
Expand Down Expand Up @@ -3432,6 +3441,16 @@ String getLogLevel() {
return loggingLevelOption.getLogLevel();
}

/**
* Returns the flag indicating that downgrades are allowed.
*
* @return true if downgrades are allowed, otherwise false
*/
@VisibleForTesting
public Boolean getAllowDowngrade() {
return allowDowngrade;
}

private class BesuCommandConfigurationService implements BesuConfiguration {

@Override
Expand Down
20 changes: 7 additions & 13 deletions besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1989,19 +1989,6 @@ public void parsesInvalidBonsaiTrieLimitBackLayersOption() {
"Invalid value for option '--bonsai-maximum-back-layers-to-load': 'ten' is not a long");
}

@Test
public void parsesValidAllowDowngradeOption() {
parseCommand("--allow-dowgrade", "true");
verify(mockControllerBuilder)
.dataStorageConfiguration(dataStorageConfigurationArgumentCaptor.capture());

final DataStorageConfiguration dataStorageConfiguration =
dataStorageConfigurationArgumentCaptor.getValue();
assertThat(dataStorageConfiguration.getAllowDowngrade()).isEqualTo(Boolean.valueOf("true"));
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}

@Test
public void dnsEnabledOptionIsParsedCorrectly() {
final TestBesuCommand besuCommand = parseCommand("--Xdns-enabled", "true");
Expand All @@ -2010,6 +1997,13 @@ public void dnsEnabledOptionIsParsedCorrectly() {
assertThat(besuCommand.getEnodeDnsConfiguration().updateEnabled()).isFalse();
}

@Test
public void allowDowngradeTrueOptionIsParsedCorrectly() {
final TestBesuCommand besuCommand = parseCommand("--allow-downgrade", "true");

assertThat(besuCommand.getAllowDowngrade()).isTrue();
}

@Test
public void dnsUpdateEnabledOptionIsParsedCorrectly() {
final TestBesuCommand besuCommand =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright Hyperledger Besu contributors.
*
* 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
Expand Down Expand Up @@ -29,7 +29,7 @@
public class VersionMetadata {
private static final Logger LOG = LoggerFactory.getLogger(VersionMetadata.class);

/** Represents an unknown Besu version in the database metadata file */
/** Represents an unknown Besu version in the version metadata file */
public static final String BESU_VERSION_UNKNOWN = "UNKNOWN";

private static final String METADATA_FILENAME = "VERSION_METADATA.json";
Expand All @@ -56,7 +56,7 @@ public String getBesuVersion() {

public static VersionMetadata lookUpFrom(final Path dataDir) throws IOException {
LOG.info("Lookup version metadata file in data directory: {}", dataDir.toString());
return resolveDatabaseMetadata(getDefaultMetadataFile(dataDir));
return resolveVersionMetadata(getDefaultMetadataFile(dataDir));
}

public void writeToDirectory(final Path dataDir) throws IOException {
Expand All @@ -67,18 +67,18 @@ private static File getDefaultMetadataFile(final Path dataDir) {
return dataDir.resolve(METADATA_FILENAME).toFile();
}

private static VersionMetadata resolveDatabaseMetadata(final File metadataFile)
private static VersionMetadata resolveVersionMetadata(final File metadataFile)
throws IOException {
VersionMetadata databaseMetadata;
VersionMetadata versionMetadata;
try {
databaseMetadata = MAPPER.readValue(metadataFile, VersionMetadata.class);
LOG.info("Existing version data detected. Besu version {}", databaseMetadata.besuVersion);
versionMetadata = MAPPER.readValue(metadataFile, VersionMetadata.class);
LOG.info("Existing version data detected. Besu version {}", versionMetadata.besuVersion);
} catch (FileNotFoundException fnfe) {
databaseMetadata = new VersionMetadata(BESU_VERSION_UNKNOWN);
versionMetadata = new VersionMetadata(BESU_VERSION_UNKNOWN);
} catch (JsonProcessingException jpe) {
throw new IllegalStateException(
java.lang.String.format("Invalid metadata file %s", metadataFile.getAbsolutePath()), jpe);
}
return databaseMetadata;
return versionMetadata;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright Hyperledger Besu contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.hyperledger.besu.ethereum.core;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

class VersionMetadataTest {
@TempDir public Path temporaryFolder;

@Test
void getVersion() {
final VersionMetadata versionMetadata = new VersionMetadata("23.10.2");
assertThat(versionMetadata).isNotNull();
assertThat(versionMetadata.getBesuVersion()).isEqualTo("23.10.2");
}

@Test
void metaFileShouldContain() throws Exception {
final Path tempDataDir =
createAndWrite("data", "VERSION_METADATA.json", "{\"besuVersion\":\"23.10.3\"}");

final VersionMetadata versionMetadata = VersionMetadata.lookUpFrom(tempDataDir);
assertThat(versionMetadata).isNotNull();
assertThat(versionMetadata.getBesuVersion()).isEqualTo("23.10.3");
}

private Path createAndWrite(final String dir, final String file, final String content)
throws IOException {
return createAndWrite(temporaryFolder, dir, file, content);
}

private Path createAndWrite(
final Path temporaryFolder, final String dir, final String file, final String content)
throws IOException {
final Path tmpDir = temporaryFolder.resolve(dir);
Files.createDirectories(tmpDir);
createAndWrite(tmpDir.resolve(file), content);
return tmpDir;
}

private void createAndWrite(final Path path, final String content) throws IOException {
path.toFile().createNewFile();
Files.writeString(path, content);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,4 @@
* All services that can be resolved via {@link BesuContext#getService(Class)} must implement {@link
* BesuService}
*/
public interface BesuService {

/**
* Get the version of Besu that is running.
*
* @return the version of Besu
*/
default String getBesuVersion() {
return BesuService.class.getPackage().getImplementationVersion();
}
}
public interface BesuService {}

0 comments on commit 9dce227

Please sign in to comment.