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