mirror of https://github.com/hyperledger/besu
Add ephemery network config (#7563)
* Add Ephemery genesis config file Signed-off-by: gconnect <agatevureglory@gmail.com> --------- Signed-off-by: gconnect <agatevureglory@gmail.com> Signed-off-by: Glory Agatevure <agatevureglory@gmail.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>pull/7722/head
parent
911f12efa0
commit
67d738c8a1
@ -0,0 +1,81 @@ |
|||||||
|
/* |
||||||
|
* 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.hyperledger.besu.cli.config.NetworkName.EPHEMERY; |
||||||
|
|
||||||
|
import org.hyperledger.besu.config.GenesisConfigFile; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.math.BigInteger; |
||||||
|
import java.time.Instant; |
||||||
|
import java.time.temporal.ChronoUnit; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
/** |
||||||
|
* The Generate Ephemery Genesis Updater. Checks for update based on the set period and update the |
||||||
|
* Ephemery genesis in memory |
||||||
|
*/ |
||||||
|
public class EphemeryGenesisUpdater { |
||||||
|
private static final int PERIOD_IN_DAYS = 28; |
||||||
|
private static final long PERIOD_IN_SECONDS = (PERIOD_IN_DAYS * 24 * 60 * 60); |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for EphemeryGenesisUpdater. Initializes the genesis updater for the Ephemery |
||||||
|
* network. |
||||||
|
*/ |
||||||
|
public EphemeryGenesisUpdater() {} |
||||||
|
|
||||||
|
/** |
||||||
|
* Updates the Ephemery genesis configuration based on the predefined period. |
||||||
|
* |
||||||
|
* @param overrides a map of configuration overrides |
||||||
|
* @return the updated GenesisConfigFile |
||||||
|
* @throws RuntimeException if an error occurs during the update process |
||||||
|
*/ |
||||||
|
public static GenesisConfigFile updateGenesis(final Map<String, String> overrides) |
||||||
|
throws RuntimeException { |
||||||
|
GenesisConfigFile genesisConfigFile; |
||||||
|
try { |
||||||
|
if (EPHEMERY.getGenesisFile() == null) { |
||||||
|
throw new IOException("Genesis file or config options are null"); |
||||||
|
} |
||||||
|
genesisConfigFile = GenesisConfigFile.fromResource(EPHEMERY.getGenesisFile()); |
||||||
|
long genesisTimestamp = genesisConfigFile.getTimestamp(); |
||||||
|
Optional<BigInteger> genesisChainId = genesisConfigFile.getConfigOptions().getChainId(); |
||||||
|
long currentTimestamp = Instant.now().getEpochSecond(); |
||||||
|
long periodsSinceGenesis = |
||||||
|
ChronoUnit.DAYS.between(Instant.ofEpochSecond(genesisTimestamp), Instant.now()) |
||||||
|
/ PERIOD_IN_DAYS; |
||||||
|
|
||||||
|
long updatedTimestamp = genesisTimestamp + (periodsSinceGenesis * PERIOD_IN_SECONDS); |
||||||
|
BigInteger updatedChainId = |
||||||
|
genesisChainId |
||||||
|
.orElseThrow(() -> new IllegalStateException("ChainId not present")) |
||||||
|
.add(BigInteger.valueOf(periodsSinceGenesis)); |
||||||
|
// has a period elapsed since original ephemery genesis time? if so, override chainId and
|
||||||
|
// timestamp
|
||||||
|
if (currentTimestamp > (genesisTimestamp + PERIOD_IN_SECONDS)) { |
||||||
|
overrides.put("chainId", String.valueOf(updatedChainId)); |
||||||
|
overrides.put("timestamp", String.valueOf(updatedTimestamp)); |
||||||
|
genesisConfigFile = genesisConfigFile.withOverrides(overrides); |
||||||
|
} |
||||||
|
return genesisConfigFile.withOverrides(overrides); |
||||||
|
} catch (IOException e) { |
||||||
|
throw new RuntimeException("Error updating ephemery genesis: " + e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,139 @@ |
|||||||
|
/* |
||||||
|
* 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.assertj.core.api.Assertions.assertThatThrownBy; |
||||||
|
import static org.hyperledger.besu.config.GenesisConfigFile.fromConfig; |
||||||
|
|
||||||
|
import org.hyperledger.besu.config.GenesisConfigFile; |
||||||
|
|
||||||
|
import java.math.BigInteger; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.TreeMap; |
||||||
|
|
||||||
|
import io.vertx.core.json.JsonObject; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.junit.jupiter.api.extension.ExtendWith; |
||||||
|
import org.mockito.junit.jupiter.MockitoExtension; |
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class) |
||||||
|
public class EphemeryGenesisUpdaterTest { |
||||||
|
private static final int GENESIS_CONFIG_TEST_CHAINID = 39438135; |
||||||
|
private static final long GENESIS_TEST_TIMESTAMP = 1720119600; |
||||||
|
private static final long EARLIER_TIMESTAMP = 1712041200; |
||||||
|
private static final long LATER_TIMESTAMP = 1922041200; |
||||||
|
private static final long PERIOD_IN_SECONDS = 28 * 24 * 60 * 60; |
||||||
|
private static final long PERIOD_SINCE_GENESIS = 3; |
||||||
|
|
||||||
|
private static final JsonObject VALID_GENESIS_JSON = |
||||||
|
(new JsonObject()) |
||||||
|
.put("config", (new JsonObject()).put("chainId", GENESIS_CONFIG_TEST_CHAINID)) |
||||||
|
.put("timestamp", GENESIS_TEST_TIMESTAMP); |
||||||
|
|
||||||
|
private static final GenesisConfigFile INVALID_GENESIS_JSON = fromConfig("{}"); |
||||||
|
private static final JsonObject INVALID_GENESIS_JSON_WITHOUT_CHAINID = |
||||||
|
(new JsonObject()).put("timestamp", GENESIS_TEST_TIMESTAMP); |
||||||
|
|
||||||
|
private static final JsonObject INVALID_GENESIS_JSON_WITHOUT_TIMESTAMP = |
||||||
|
new JsonObject() |
||||||
|
.put("config", (new JsonObject()).put("chainId", GENESIS_CONFIG_TEST_CHAINID)); |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEphemeryWhenChainIdIsAbsent() { |
||||||
|
final GenesisConfigFile config = |
||||||
|
GenesisConfigFile.fromConfig(INVALID_GENESIS_JSON_WITHOUT_CHAINID.toString()); |
||||||
|
Optional<BigInteger> chainId = config.getConfigOptions().getChainId(); |
||||||
|
assertThat(chainId).isNotPresent(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testShouldDefaultTimestampToZero() { |
||||||
|
final GenesisConfigFile config = |
||||||
|
GenesisConfigFile.fromConfig(INVALID_GENESIS_JSON_WITHOUT_TIMESTAMP.toString()); |
||||||
|
assertThat(config.getTimestamp()).isZero(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEphemeryWhenGenesisJsonIsInvalid() { |
||||||
|
assertThatThrownBy(INVALID_GENESIS_JSON::getDifficulty) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("Invalid genesis block configuration"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEphemeryWhenGenesisJsonIsValid() { |
||||||
|
final GenesisConfigFile config = GenesisConfigFile.fromConfig(VALID_GENESIS_JSON.toString()); |
||||||
|
assertThat(String.valueOf(config.getTimestamp())) |
||||||
|
.isEqualTo(String.valueOf(GENESIS_TEST_TIMESTAMP)); |
||||||
|
assertThat(config.getConfigOptions().getChainId()) |
||||||
|
.hasValue(BigInteger.valueOf(GENESIS_CONFIG_TEST_CHAINID)); |
||||||
|
assertThat(String.valueOf(config.getTimestamp())).isNotNull(); |
||||||
|
assertThat(String.valueOf(config.getTimestamp())).isNotEmpty(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEphemeryNotYetDueForUpdate() { |
||||||
|
final GenesisConfigFile config = GenesisConfigFile.fromConfig(VALID_GENESIS_JSON.toString()); |
||||||
|
assertThat(EARLIER_TIMESTAMP).isLessThan(config.getTimestamp() + PERIOD_IN_SECONDS); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testOverrideWithUpdatedChainIdAndTimeStamp() { |
||||||
|
BigInteger expectedChainId = |
||||||
|
BigInteger.valueOf(GENESIS_CONFIG_TEST_CHAINID) |
||||||
|
.add(BigInteger.valueOf(PERIOD_SINCE_GENESIS)); |
||||||
|
|
||||||
|
long expectedGenesisTimestamp = |
||||||
|
GENESIS_TEST_TIMESTAMP + (PERIOD_SINCE_GENESIS * PERIOD_IN_SECONDS); |
||||||
|
|
||||||
|
final GenesisConfigFile config = GenesisConfigFile.fromResource("/ephemery.json"); |
||||||
|
|
||||||
|
final Map<String, String> override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); |
||||||
|
override.put("chainId", String.valueOf(expectedChainId)); |
||||||
|
override.put("timestamp", String.valueOf(expectedGenesisTimestamp)); |
||||||
|
|
||||||
|
assertThat(config.withOverrides(override).getConfigOptions().getChainId()).isPresent(); |
||||||
|
assertThat(config.withOverrides(override).getConfigOptions().getChainId()) |
||||||
|
.hasValue(expectedChainId); |
||||||
|
assertThat(config.withOverrides(override).getTimestamp()).isNotNull(); |
||||||
|
assertThat(expectedChainId).isEqualTo(override.get("chainId")); |
||||||
|
assertThat(String.valueOf(expectedGenesisTimestamp)).isEqualTo(override.get("timestamp")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testEphemeryWhenSuccessful() { |
||||||
|
final GenesisConfigFile config = GenesisConfigFile.fromConfig(VALID_GENESIS_JSON.toString()); |
||||||
|
|
||||||
|
BigInteger expectedChainId = |
||||||
|
BigInteger.valueOf(GENESIS_CONFIG_TEST_CHAINID) |
||||||
|
.add(BigInteger.valueOf(PERIOD_SINCE_GENESIS)); |
||||||
|
|
||||||
|
long expectedGenesisTimestamp = |
||||||
|
GENESIS_TEST_TIMESTAMP + (PERIOD_SINCE_GENESIS * PERIOD_IN_SECONDS); |
||||||
|
final Map<String, String> override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); |
||||||
|
override.put("chainId", String.valueOf(expectedChainId)); |
||||||
|
override.put("timestamp", String.valueOf(expectedGenesisTimestamp)); |
||||||
|
final GenesisConfigFile updatedConfig = config.withOverrides(override); |
||||||
|
|
||||||
|
assertThat(LATER_TIMESTAMP) |
||||||
|
.isGreaterThan(Long.parseLong(String.valueOf(GENESIS_TEST_TIMESTAMP + PERIOD_IN_SECONDS))); |
||||||
|
assertThat(updatedConfig.getConfigOptions().getChainId()).hasValue(expectedChainId); |
||||||
|
assertThat(updatedConfig.getTimestamp()).isEqualTo(expectedGenesisTimestamp); |
||||||
|
assertThat(override.get("timestamp")).isEqualTo(String.valueOf(expectedGenesisTimestamp)); |
||||||
|
assertThat(override.get("chainId")).isEqualTo(expectedChainId.toString()); |
||||||
|
} |
||||||
|
} |
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue