Skip to content

Solved Add db reset for Ephemery network on restart #8180 #8618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
import org.hyperledger.besu.ethereum.trie.pathbased.common.storage.PathBasedWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.ImmutablePathBasedExtraStorageConfiguration;
Expand Down Expand Up @@ -199,6 +200,7 @@
import org.hyperledger.besu.services.TransactionSimulationServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
import org.hyperledger.besu.util.BesuVersionUtils;
import org.hyperledger.besu.util.EphemeryDatabaseReset;
import org.hyperledger.besu.util.EphemeryGenesisUpdater;
import org.hyperledger.besu.util.InvalidConfigurationException;
import org.hyperledger.besu.util.LogConfigurator;
Expand Down Expand Up @@ -1673,6 +1675,28 @@ private GenesisConfig readGenesisConfig() {
? GenesisConfig.fromSource(genesisConfigSource(genesisFile))
: GenesisConfig.fromResource(
Optional.ofNullable(network).orElse(MAINNET).getGenesisFile());

// Check if database reset is needed for Ephemery network
if (network.equals(EPHEMERY)) {
try {
long genesisTimestamp = effectiveGenesisFile.getTimestamp();
if (EphemeryDatabaseReset.isResetNeeded(genesisTimestamp)) {
logger.info("Ephemery network period has elapsed, resetting database");
// Get storage provider and reset database
StorageProvider storageProvider = getStorageProvider();
if (storageProvider instanceof PathBasedWorldStateKeyValueStorage) {
EphemeryDatabaseReset.resetDatabase(
(PathBasedWorldStateKeyValueStorage) storageProvider);
logger.info("Database reset completed for Ephemery network");
} else {
logger.warn("Cannot reset database - incompatible storage provider type");
}
}
} catch (Exception e) {
logger.error("Failed to reset database for Ephemery network: {}", e.getMessage());
logger.debug("Database reset failure", e);
}
}
return effectiveGenesisFile.withOverrides(genesisConfigOverrides);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.util;

import org.hyperledger.besu.ethereum.trie.pathbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.pathbased.common.storage.PathBasedWorldStateKeyValueStorage;

import java.time.Instant;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The Ephemery Database Reset utility. Handles database reset functionality for the Ephemery
* network based on the predefined period.
*/
public class EphemeryDatabaseReset {
private static final Logger LOG = LoggerFactory.getLogger(EphemeryDatabaseReset.class);
private static final int PERIOD_IN_DAYS = 28;

/** Private constructor to prevent instantiation. */
private EphemeryDatabaseReset() {
// Private constructor to prevent instantiation
}

/**
* Checks if the database needs to be reset based on the genesis timestamp and current time.
*
* @param genesisTimestamp The genesis block timestamp
* @return true if database reset is needed, false otherwise
*/
public static boolean isResetNeeded(final long genesisTimestamp) {
long currentTimestamp = Instant.now().getEpochSecond();
long periodInSeconds = PERIOD_IN_DAYS * 24 * 60 * 60;
return (currentTimestamp - genesisTimestamp) >= periodInSeconds;
}

/**
* Resets the database for Ephemery network.
*
* @param worldStateStorage The world state storage to reset
*/
public static void resetDatabase(final PathBasedWorldStateKeyValueStorage worldStateStorage) {
try {
// Clear the flat database
worldStateStorage.clearFlatDatabase();
LOG.info("Cleared flat database");

// Clear the trie log
worldStateStorage.clearTrieLog();
LOG.info("Cleared trie log");

// Clear the trie
worldStateStorage.clearTrie();
LOG.info("Cleared trie");

// If using Bonsai storage, upgrade to full flat database mode
if (worldStateStorage instanceof BonsaiWorldStateKeyValueStorage bonsaiStorage) {
bonsaiStorage.upgradeToFullFlatDbMode();
LOG.info("Upgraded to full flat database mode");
}
} catch (Exception e) {
LOG.error("Failed to reset database: {}", e.getMessage());
throw new RuntimeException("Failed to reset database", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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.util;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import org.hyperledger.besu.ethereum.trie.pathbased.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.trie.pathbased.common.storage.PathBasedWorldStateKeyValueStorage;

import org.junit.jupiter.api.Test;

class EphemeryDatabaseResetTest {

@Test
void isResetNeeded_shouldReturnTrue_whenPeriodHasElapsed() {
// Given
long genesisTimestamp = System.currentTimeMillis() / 1000 - (29 * 24 * 60 * 60); // 29 days ago

// When
boolean result = EphemeryDatabaseReset.isResetNeeded(genesisTimestamp);

// Then
assertThat(result).isTrue();
}

@Test
void isResetNeeded_shouldReturnFalse_whenPeriodHasNotElapsed() {
// Given
long genesisTimestamp = System.currentTimeMillis() / 1000 - (27 * 24 * 60 * 60); // 27 days ago

// When
boolean result = EphemeryDatabaseReset.isResetNeeded(genesisTimestamp);

// Then
assertThat(result).isFalse();
}

@Test
void resetDatabase_shouldClearAllStorages() {
// Given
PathBasedWorldStateKeyValueStorage storage = mock(PathBasedWorldStateKeyValueStorage.class);

// When
EphemeryDatabaseReset.resetDatabase(storage);

// Then
verify(storage).clearFlatDatabase();
verify(storage).clearTrieLog();
verify(storage).clearTrie();
}

@Test
void resetDatabase_shouldUpgradeToFullFlatDbMode_whenUsingBonsaiStorage() {
// Given
BonsaiWorldStateKeyValueStorage storage = mock(BonsaiWorldStateKeyValueStorage.class);

// When
EphemeryDatabaseReset.resetDatabase(storage);

// Then
verify(storage).clearFlatDatabase();
verify(storage).clearTrieLog();
verify(storage).clearTrie();
verify(storage).upgradeToFullFlatDbMode();
}
}