mirror of https://github.com/hyperledger/besu
pull/7638/head
commit
b13ac925fa
@ -1,80 +0,0 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.cli.options.unstable; |
||||
|
||||
import org.hyperledger.besu.cli.options.CLIOptions; |
||||
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import picocli.CommandLine; |
||||
|
||||
/** The Metrics cli options. */ |
||||
// TODO: combine into MetricsOptionGroup, use Unstable inner class pattern (see MiningOptions)
|
||||
public class MetricsCLIOptions implements CLIOptions<MetricsConfiguration.Builder> { |
||||
private static final String TIMERS_ENABLED_FLAG = "--Xmetrics-timers-enabled"; |
||||
private static final String IDLE_TIMEOUT_FLAG = "--Xmetrics-idle-timeout"; |
||||
|
||||
@CommandLine.Option( |
||||
names = TIMERS_ENABLED_FLAG, |
||||
hidden = true, |
||||
description = "Whether to enable timer metrics (default: ${DEFAULT-VALUE}).") |
||||
private Boolean timersEnabled = MetricsConfiguration.DEFAULT_METRICS_TIMERS_ENABLED; |
||||
|
||||
@CommandLine.Option( |
||||
hidden = true, |
||||
names = {IDLE_TIMEOUT_FLAG}, |
||||
paramLabel = "<INTEGER>", |
||||
description = "Timeout for metrics TCP connections, in seconds (default: ${DEFAULT-VALUE})", |
||||
arity = "1") |
||||
private int idleTimeout = MetricsConfiguration.DEFAULT_METRICS_IDLE_TIMEOUT_SECONDS; |
||||
|
||||
private MetricsCLIOptions() {} |
||||
|
||||
/** |
||||
* Create metrics cli options. |
||||
* |
||||
* @return the metrics cli options |
||||
*/ |
||||
public static MetricsCLIOptions create() { |
||||
return new MetricsCLIOptions(); |
||||
} |
||||
|
||||
/** |
||||
* From configuration metrics cli options. |
||||
* |
||||
* @param config the config |
||||
* @return the metrics cli options |
||||
*/ |
||||
public static MetricsCLIOptions fromConfiguration(final MetricsConfiguration config) { |
||||
final MetricsCLIOptions metricsOptions = create(); |
||||
metricsOptions.timersEnabled = config.isTimersEnabled(); |
||||
metricsOptions.idleTimeout = config.getIdleTimeout(); |
||||
return metricsOptions; |
||||
} |
||||
|
||||
@Override |
||||
public MetricsConfiguration.Builder toDomainObject() { |
||||
return MetricsConfiguration.builder().timersEnabled(timersEnabled).idleTimeout(idleTimeout); |
||||
} |
||||
|
||||
@Override |
||||
public List<String> getCLIOptions() { |
||||
return Arrays.asList( |
||||
TIMERS_ENABLED_FLAG + "=" + timersEnabled.toString(), |
||||
IDLE_TIMEOUT_FLAG + "=" + idleTimeout); |
||||
} |
||||
} |
@ -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
@ -0,0 +1,46 @@ |
||||
/* |
||||
* 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.ethereum.core.json; |
||||
|
||||
import java.io.IOException; |
||||
import java.math.BigInteger; |
||||
|
||||
import com.fasterxml.jackson.core.JsonParser; |
||||
import com.fasterxml.jackson.databind.DeserializationContext; |
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer; |
||||
import org.apache.tuweni.units.bigints.UInt256; |
||||
|
||||
public class ChainIdDeserializer extends StdDeserializer<BigInteger> { |
||||
|
||||
public ChainIdDeserializer() { |
||||
this(null); |
||||
} |
||||
|
||||
public ChainIdDeserializer(final Class<?> vc) { |
||||
super(vc); |
||||
} |
||||
|
||||
@Override |
||||
public BigInteger deserialize(final JsonParser jsonparser, final DeserializationContext context) |
||||
throws IOException { |
||||
final var chainId = |
||||
UInt256.fromHexString(jsonparser.getCodec().readValue(jsonparser, String.class)) |
||||
.toBigInteger(); |
||||
if (chainId.signum() <= 0) { |
||||
throw new IllegalArgumentException("Non positive chain id: " + chainId); |
||||
} |
||||
return chainId; |
||||
} |
||||
} |
Loading…
Reference in new issue