Skip to content

Commit

Permalink
Add deposit chainId to the network.yml file and database reset
Browse files Browse the repository at this point in the history
Signed-off-by: gconnect <[email protected]>
  • Loading branch information
gconnect committed Sep 21, 2024
1 parent 665dbcd commit 243f927
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Optional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import tech.pegasys.teku.ethereum.execution.types.Eth1Address;
import tech.pegasys.teku.infrastructure.io.SyncDataAccessor;
import tech.pegasys.teku.networks.Eth2NetworkConfiguration;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.networks.Eth2Network;
import tech.pegasys.teku.storage.server.kvstore.KvStoreConfiguration;
import tech.pegasys.teku.storage.server.kvstore.schema.V6SchemaCombinedSnapshot;
import tech.pegasys.teku.storage.server.leveldb.LevelDbDatabaseFactory;
Expand Down Expand Up @@ -166,7 +169,10 @@ public StateStorageMode getStateStorageMode() {
private Database createV4Database() {
try {
DatabaseNetwork.init(
getNetworkFile(), spec.getGenesisSpecConfig().getGenesisForkVersion(), eth1Address);
getNetworkFile(),
spec.getGenesisSpecConfig().getGenesisForkVersion(),
eth1Address,
Optional.of(String.valueOf(spec.getGenesisSpecConfig().getDepositChainId())));
return RocksDbDatabaseFactory.createV4(
metricsSystem,
KvStoreConfiguration.v4Settings(dbDirectory.toPath()),
Expand All @@ -190,7 +196,10 @@ private Database createV5Database() {
final V5DatabaseMetadata metaData =
V5DatabaseMetadata.init(getMetadataFile(), V5DatabaseMetadata.v5Defaults());
DatabaseNetwork.init(
getNetworkFile(), spec.getGenesisSpecConfig().getGenesisForkVersion(), eth1Address);
getNetworkFile(),
spec.getGenesisSpecConfig().getGenesisForkVersion(),
eth1Address,
Optional.of(String.valueOf(spec.getGenesisSpecConfig().getDepositChainId())));
return RocksDbDatabaseFactory.createV4(
metricsSystem,
metaData.getHotDbConfiguration().withDatabaseDir(dbDirectory.toPath()),
Expand Down Expand Up @@ -233,7 +242,10 @@ private Database createLevelDbV1Database() {
final V5DatabaseMetadata metaData =
V5DatabaseMetadata.init(getMetadataFile(), V5DatabaseMetadata.v5Defaults());
DatabaseNetwork.init(
getNetworkFile(), spec.getGenesisSpecConfig().getGenesisForkVersion(), eth1Address);
getNetworkFile(),
spec.getGenesisSpecConfig().getGenesisForkVersion(),
eth1Address,
Optional.of(String.valueOf(spec.getGenesisSpecConfig().getDepositChainId())));
return LevelDbDatabaseFactory.createLevelDb(
metricsSystem,
metaData.getHotDbConfiguration().withDatabaseDir(dbDirectory.toPath()),
Expand Down Expand Up @@ -284,7 +296,10 @@ private KvStoreConfiguration initV6Configuration() throws IOException {
V6DatabaseMetadata.init(getMetadataFile(), V6DatabaseMetadata.singleDBDefault());

DatabaseNetwork.init(
getNetworkFile(), spec.getGenesisSpecConfig().getGenesisForkVersion(), eth1Address);
getNetworkFile(),
spec.getGenesisSpecConfig().getGenesisForkVersion(),
eth1Address,
Optional.of(String.valueOf(spec.getGenesisSpecConfig().getDepositChainId())));

return metaData.getSingleDbConfiguration().getConfiguration();
}
Expand All @@ -307,6 +322,12 @@ private void validateDataPaths() {
}

private void createDirectories(final DatabaseVersion dbVersion) {
final Eth2NetworkConfiguration networkConfig =
Eth2NetworkConfiguration.builder(Eth2Network.EPHEMERY).build();

if (networkConfig.getEth2Network().equals(Optional.of(Eth2Network.EPHEMERY))) {
resetDatabaseDirectories();
}
if (!dbDirectory.mkdirs() && !dbDirectory.isDirectory()) {
throw DatabaseStorageException.unrecoverable(
String.format(
Expand Down Expand Up @@ -372,4 +393,48 @@ private void saveStorageMode(final StateStorageMode storageMode) {
e);
}
}

// This implementation is required for Ephemery Network
private void resetDatabaseDirectories() {
File networkFile = getNetworkFile();

try {
if (dbDirectory.exists()) {
deleteDirectoryRecursively(dbDirectory.toPath());
}
if (v5ArchiveDirectory.exists()) {
deleteDirectoryRecursively(v5ArchiveDirectory.toPath());
}
if (networkFile.exists()) {
try {
LOG.info("Resetting network file at: {}", networkFile.getAbsolutePath());
Files.delete(networkFile.toPath());
System.out.println("Database directories reset successfully.");
} catch (IOException e) {
throw DatabaseStorageException.unrecoverable(
String.format("Failed to reset network file at %s", networkFile.getAbsolutePath()),
e);
}
}
} catch (IOException e) {
throw DatabaseStorageException.unrecoverable("Failed to reset database directories", e);
}
}

private void deleteDirectoryRecursively(final Path path) throws IOException {
if (Files.isDirectory(path)) {
try (var stream = Files.walk(path)) {
stream
.sorted((o1, o2) -> o2.compareTo(o1))
.forEach(
p -> {
try {
Files.delete(p);
} catch (IOException e) {
throw new RuntimeException("Failed to delete file: " + p, e);
}
});
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
import java.io.IOException;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import tech.pegasys.teku.ethereum.execution.types.Eth1Address;
import tech.pegasys.teku.infrastructure.bytes.Bytes4;
import tech.pegasys.teku.networks.Eth2NetworkConfiguration;
import tech.pegasys.teku.spec.networks.Eth2Network;
import tech.pegasys.teku.storage.server.DatabaseStorageException;

@JsonIgnoreProperties(ignoreUnknown = true)
Expand All @@ -39,39 +42,81 @@ public class DatabaseNetwork {
@VisibleForTesting
final String depositContract;

@JsonProperty("deposit_chain_id")
@VisibleForTesting
final String depositChainId; // Can be null for non-Ephemery networks

static final Eth2NetworkConfiguration NETWORK_CONFIG =
Eth2NetworkConfiguration.builder(Eth2Network.EPHEMERY).build();

// Single constructor that handles both cases
@JsonCreator
DatabaseNetwork(
@JsonProperty("fork_version") final String forkVersion,
@JsonProperty("deposit_contract") final String depositContract) {
@JsonProperty("deposit_contract") final String depositContract,
@JsonProperty("deposit_chain_id") final String depositChainId) {
this.forkVersion = forkVersion;
this.depositContract = depositContract;
this.depositChainId = depositChainId; // Can be null for non-Ephemery networks
}

// Initialization logic
public static DatabaseNetwork init(
final File source, final Bytes4 forkVersion, final Eth1Address depositContract)
final File source,
final Bytes4 forkVersion,
final Eth1Address depositContract,
final Optional<String> depositChainId)
throws IOException {
final String forkVersionString = forkVersion.toHexString().toLowerCase(Locale.ROOT);
final String depositContractString = depositContract.toHexString().toLowerCase(Locale.ROOT);
final ObjectMapper objectMapper =
new ObjectMapper(new YAMLFactory().disable(WRITE_DOC_START_MARKER));

if (source.exists()) {
final DatabaseNetwork databaseNetwork =
objectMapper.readerFor(DatabaseNetwork.class).readValue(source);

// Fork version validation
if (!forkVersionString.equals(databaseNetwork.forkVersion)) {
throw DatabaseStorageException.unrecoverable(
formatMessage("fork version", forkVersionString, databaseNetwork.forkVersion));
}

// Deposit contract validation
if (databaseNetwork.depositContract != null
&& !databaseNetwork.depositContract.equals(depositContractString)) {
throw DatabaseStorageException.unrecoverable(
formatMessage(
"deposit contract", depositContractString, databaseNetwork.depositContract));
}

if (NETWORK_CONFIG.getEth2Network().equals(Optional.of(Eth2Network.EPHEMERY))) {

// Deposit chain ID validation
if (depositChainId.isPresent()
&& databaseNetwork.depositChainId != null
&& !databaseNetwork.depositChainId.equals(depositChainId.get())) {
throw DatabaseStorageException.unrecoverable(
formatMessage(
"deposit chain ID",
depositChainId.get(),
String.valueOf(databaseNetwork.depositChainId)));
}
}
return databaseNetwork;
} else {
DatabaseNetwork databaseNetwork =
new DatabaseNetwork(forkVersionString, depositContractString);
// Handle Ephemery or other networks
String depositChainIdString = depositChainId.orElse(null);
DatabaseNetwork databaseNetwork;
System.out.println(
"network " + NETWORK_CONFIG.getEth2Network().equals(Optional.of(Eth2Network.EPHEMERY)));
if (NETWORK_CONFIG.getEth2Network().equals(Optional.of(Eth2Network.EPHEMERY))) {
databaseNetwork =
new DatabaseNetwork(forkVersionString, depositContractString, depositChainIdString);
} else {
databaseNetwork = new DatabaseNetwork(forkVersionString, depositContractString, null);
}

objectMapper.writerFor(DatabaseNetwork.class).writeValue(source, databaseNetwork);
return databaseNetwork;
}
Expand All @@ -95,11 +140,12 @@ public boolean equals(final Object o) {
}
final DatabaseNetwork that = (DatabaseNetwork) o;
return Objects.equals(forkVersion, that.forkVersion)
&& Objects.equals(depositContract, that.depositContract);
&& Objects.equals(depositContract, that.depositContract)
&& Objects.equals(depositChainId, that.depositChainId); // Compare deposit_chain_id
}

@Override
public int hashCode() {
return Objects.hash(forkVersion, depositContract);
return Objects.hash(forkVersion, depositContract, depositChainId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ public void shouldCreateNetworkFile(@TempDir final File tempDir) throws IOExcept
assertThat(networkFile).doesNotExist();
final Bytes4 fork = dataStructureUtil.randomFork().getCurrentVersion();
final Eth1Address eth1Address = dataStructureUtil.randomEth1Address();
assertThat(DatabaseNetwork.init(networkFile, fork, eth1Address))
assertThat(DatabaseNetwork.init(networkFile, fork, eth1Address, null))
.isEqualTo(
new DatabaseNetwork(
fork.toHexString().toLowerCase(Locale.ROOT),
eth1Address.toHexString().toLowerCase(Locale.ROOT)));
eth1Address.toHexString().toLowerCase(Locale.ROOT),
null));
assertThat(networkFile).exists();
}

Expand All @@ -52,9 +53,9 @@ public void shouldThrowIfForkDiffers(@TempDir final File tempDir) throws IOExcep
final Bytes4 fork = dataStructureUtil.randomFork().getCurrentVersion();
final Eth1Address eth1Address = dataStructureUtil.randomEth1Address();
DatabaseNetwork.init(
networkFile, dataStructureUtil.randomFork().getCurrentVersion(), eth1Address);
networkFile, dataStructureUtil.randomFork().getCurrentVersion(), eth1Address, null);

assertThatThrownBy(() -> DatabaseNetwork.init(networkFile, fork, eth1Address))
assertThatThrownBy(() -> DatabaseNetwork.init(networkFile, fork, eth1Address, null))
.isInstanceOf(DatabaseStorageException.class)
.hasMessageStartingWith("Supplied fork version");
}
Expand All @@ -65,9 +66,9 @@ public void shouldThrowIfDepositContractDiffers(@TempDir final File tempDir) thr
assertThat(networkFile).doesNotExist();
final Bytes4 fork = dataStructureUtil.randomFork().getCurrentVersion();
final Eth1Address eth1Address = dataStructureUtil.randomEth1Address();
DatabaseNetwork.init(networkFile, fork, dataStructureUtil.randomEth1Address());
DatabaseNetwork.init(networkFile, fork, dataStructureUtil.randomEth1Address(), null);

assertThatThrownBy(() -> DatabaseNetwork.init(networkFile, fork, eth1Address))
assertThatThrownBy(() -> DatabaseNetwork.init(networkFile, fork, eth1Address, null))
.isInstanceOf(DatabaseStorageException.class)
.hasMessageStartingWith("Supplied deposit contract");
}
Expand All @@ -78,8 +79,8 @@ public void shouldNotThrowIfForkAndContractMatch(@TempDir final File tempDir) th
assertThat(networkFile).doesNotExist();
final Bytes4 fork = dataStructureUtil.randomFork().getCurrentVersion();
final Eth1Address eth1Address = dataStructureUtil.randomEth1Address();
DatabaseNetwork.init(networkFile, fork, eth1Address);
DatabaseNetwork.init(networkFile, fork, eth1Address, null);

assertDoesNotThrow(() -> DatabaseNetwork.init(networkFile, fork, eth1Address));
assertDoesNotThrow(() -> DatabaseNetwork.init(networkFile, fork, eth1Address, null));
}
}

0 comments on commit 243f927

Please sign in to comment.