diff --git a/config/build.gradle b/config/build.gradle index 8ebd43abe7..536905c4c2 100644 --- a/config/build.gradle +++ b/config/build.gradle @@ -24,6 +24,7 @@ jar { dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'io.vertx:vertx-core' + implementation 'com.google.guava:guava' implementation 'org.apache.logging.log4j:log4j-api' runtime 'org.apache.logging.log4j:log4j-core' diff --git a/config/src/main/java/tech/pegasys/pantheon/config/CliqueConfigOptions.java b/config/src/main/java/tech/pegasys/pantheon/config/CliqueConfigOptions.java index d716bdf356..242d4c5348 100644 --- a/config/src/main/java/tech/pegasys/pantheon/config/CliqueConfigOptions.java +++ b/config/src/main/java/tech/pegasys/pantheon/config/CliqueConfigOptions.java @@ -23,15 +23,15 @@ public class CliqueConfigOptions { private final JsonObject cliqueConfigRoot; - public CliqueConfigOptions(final JsonObject cliqueConfigRoot) { + CliqueConfigOptions(final JsonObject cliqueConfigRoot) { this.cliqueConfigRoot = cliqueConfigRoot; } public long getEpochLength() { - return cliqueConfigRoot.getLong("epochLength", DEFAULT_EPOCH_LENGTH); + return cliqueConfigRoot.getLong("epochlength", DEFAULT_EPOCH_LENGTH); } public int getBlockPeriodSeconds() { - return cliqueConfigRoot.getInteger("blockPeriodSeconds", DEFAULT_BLOCK_PERIOD_SECONDS); + return cliqueConfigRoot.getInteger("blockperiodseconds", DEFAULT_BLOCK_PERIOD_SECONDS); } } diff --git a/config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java b/config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java new file mode 100644 index 0000000000..93772a792a --- /dev/null +++ b/config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java @@ -0,0 +1,33 @@ +/* + * Copyright 2018 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. + */ +package tech.pegasys.pantheon.config; + +import io.vertx.core.json.JsonObject; + +public class GenesisAllocation { + private final String address; + private final JsonObject data; + + public GenesisAllocation(final String address, final JsonObject data) { + this.address = address; + this.data = data; + } + + public String getAddress() { + return address; + } + + public String getBalance() { + return data.getString("balance", "0"); + } +} diff --git a/config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigFile.java b/config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigFile.java new file mode 100644 index 0000000000..b45ae9587a --- /dev/null +++ b/config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigFile.java @@ -0,0 +1,137 @@ +/* + * Copyright 2018 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. + */ +package tech.pegasys.pantheon.config; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +import com.google.common.io.Resources; +import io.vertx.core.json.JsonObject; + +public class GenesisConfigFile { + + public static final GenesisConfigFile DEFAULT = new GenesisConfigFile(new JsonObject()); + + private final JsonObject configRoot; + + private GenesisConfigFile(final JsonObject config) { + this.configRoot = config; + } + + public static GenesisConfigFile mainnet() { + try { + return fromConfig(Resources.toString(Resources.getResource("mainnet.json"), UTF_8)); + } catch (final IOException e) { + throw new IllegalStateException(e); + } + } + + public static GenesisConfigFile development() { + try { + return fromConfig(Resources.toString(Resources.getResource("dev.json"), UTF_8)); + } catch (final IOException e) { + throw new IllegalStateException(e); + } + } + + public static GenesisConfigFile fromConfig(final String config) { + return fromConfig(new JsonObject(config)); + } + + public static GenesisConfigFile fromConfig(final JsonObject config) { + return new GenesisConfigFile(normalizeKeys(config)); + } + + public GenesisConfigOptions getConfigOptions() { + return new GenesisConfigOptions(configRoot.getJsonObject("config")); + } + + public Stream getAllocations() { + final JsonObject allocations = configRoot.getJsonObject("alloc"); + return allocations + .fieldNames() + .stream() + .map(key -> new GenesisAllocation(key, allocations.getJsonObject(key))); + } + + public String getParentHash() { + return configRoot.getString("parenthash", ""); + } + + public String getDifficulty() { + return getRequiredString("difficulty"); + } + + public String getExtraData() { + return configRoot.getString("extradata", ""); + } + + public Long getGasLimit() { + return Long.decode(getRequiredString("gaslimit")); + } + + public String getMixHash() { + return configRoot.getString("mixhash", ""); + } + + public String getNonce() { + return configRoot.getString("nonce", ""); + } + + public Optional getCoinbase() { + return Optional.ofNullable(configRoot.getString("coinbase")); + } + + public long getTimestamp() { + return Long.parseLong(configRoot.getString("timestamp", "0x0").substring(2), 16); + } + + private String getRequiredString(final String key) { + if (!configRoot.containsKey(key)) { + throw new IllegalArgumentException( + String.format("Invalid Genesis block configuration, missing value for '%s'", key)); + } + return configRoot.getString(key); + } + + /* Converts the {@link JsonObject} describing the Genesis Block to a {@link Map}. This method + * converts all nested {@link JsonObject} to {@link Map} as well. Also, note that all keys are + * converted to lowercase for easier lookup since the keys in a 'genesis.json' file are assumed + * case insensitive. + */ + @SuppressWarnings("unchecked") + private static JsonObject normalizeKeys(final JsonObject genesis) { + final Map normalized = new HashMap<>(); + genesis + .getMap() + .forEach( + (key, value) -> { + final String normalizedKey = key.toLowerCase(Locale.US); + if (value instanceof JsonObject) { + normalized.put(normalizedKey, normalizeKeys((JsonObject) value)); + } else if (value instanceof Map) { + normalized.put( + normalizedKey, normalizeKeys(new JsonObject((Map) value))); + } else { + normalized.put(normalizedKey, value); + } + }); + return new JsonObject(normalized); + } +} diff --git a/config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigOptions.java b/config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigOptions.java index 8b201591a8..c94fc3f995 100644 --- a/config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigOptions.java +++ b/config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigOptions.java @@ -24,18 +24,10 @@ public class GenesisConfigOptions { private static final String CLIQUE_CONFIG_KEY = "clique"; private final JsonObject configRoot; - private GenesisConfigOptions(final JsonObject configRoot) { + GenesisConfigOptions(final JsonObject configRoot) { this.configRoot = configRoot != null ? configRoot : new JsonObject(); } - public static GenesisConfigOptions fromGenesisConfig(final String genesisConfig) { - return fromGenesisConfig(new JsonObject(genesisConfig)); - } - - public static GenesisConfigOptions fromGenesisConfig(final JsonObject genesisConfig) { - return new GenesisConfigOptions(genesisConfig.getJsonObject("config")); - } - public boolean isEthHash() { return configRoot.containsKey(ETHASH_CONFIG_KEY); } @@ -61,32 +53,32 @@ public class GenesisConfigOptions { } public OptionalLong getHomesteadBlockNumber() { - return getOptionalLong("homesteadBlock"); + return getOptionalLong("homesteadblock"); } public OptionalLong getDaoForkBlock() { - return getOptionalLong("daoForkBlock"); + return getOptionalLong("daoforkblock"); } public OptionalLong getTangerineWhistleBlockNumber() { - return getOptionalLong("eip150Block"); + return getOptionalLong("eip150block"); } public OptionalLong getSpuriousDragonBlockNumber() { - return getOptionalLong("eip158Block"); + return getOptionalLong("eip158block"); } public OptionalLong getByzantiumBlockNumber() { - return getOptionalLong("byzantiumBlock"); + return getOptionalLong("byzantiumblock"); } public OptionalLong getConstantinopleBlockNumber() { - return getOptionalLong("constantinopleBlock"); + return getOptionalLong("constantinopleblock"); } public OptionalInt getChainId() { - return configRoot.containsKey("chainId") - ? OptionalInt.of(configRoot.getInteger("chainId")) + return configRoot.containsKey("chainid") + ? OptionalInt.of(configRoot.getInteger("chainid")) : OptionalInt.empty(); } diff --git a/config/src/main/java/tech/pegasys/pantheon/config/IbftConfigOptions.java b/config/src/main/java/tech/pegasys/pantheon/config/IbftConfigOptions.java index 54cb05cfc5..bf1febc117 100644 --- a/config/src/main/java/tech/pegasys/pantheon/config/IbftConfigOptions.java +++ b/config/src/main/java/tech/pegasys/pantheon/config/IbftConfigOptions.java @@ -24,19 +24,19 @@ public class IbftConfigOptions { private final JsonObject ibftConfigRoot; - public IbftConfigOptions(final JsonObject ibftConfigRoot) { + IbftConfigOptions(final JsonObject ibftConfigRoot) { this.ibftConfigRoot = ibftConfigRoot; } public long getEpochLength() { - return ibftConfigRoot.getLong("epochLength", DEFAULT_EPOCH_LENGTH); + return ibftConfigRoot.getLong("epochlength", DEFAULT_EPOCH_LENGTH); } public int getBlockPeriodSeconds() { - return ibftConfigRoot.getInteger("blockPeriodSeconds", DEFAULT_BLOCK_PERIOD_SECONDS); + return ibftConfigRoot.getInteger("blockperiodseconds", DEFAULT_BLOCK_PERIOD_SECONDS); } public int getRequestTimeoutMillis() { - return ibftConfigRoot.getInteger("requestTimeout", DEFAULT_ROUND_EXPIRY_MILLISECONDS); + return ibftConfigRoot.getInteger("requesttimeout", DEFAULT_ROUND_EXPIRY_MILLISECONDS); } } diff --git a/ethereum/core/src/main/resources/dev.json b/config/src/main/resources/dev.json similarity index 100% rename from ethereum/core/src/main/resources/dev.json rename to config/src/main/resources/dev.json diff --git a/ethereum/core/src/main/resources/mainnet.json b/config/src/main/resources/mainnet.json similarity index 100% rename from ethereum/core/src/main/resources/mainnet.json rename to config/src/main/resources/mainnet.json diff --git a/ethereum/core/src/main/resources/rinkeby.json b/config/src/main/resources/rinkeby.json similarity index 100% rename from ethereum/core/src/main/resources/rinkeby.json rename to config/src/main/resources/rinkeby.json diff --git a/ethereum/core/src/main/resources/ropsten.json b/config/src/main/resources/ropsten.json similarity index 100% rename from ethereum/core/src/main/resources/ropsten.json rename to config/src/main/resources/ropsten.json diff --git a/config/src/test/java/tech/pegasys/pantheon/config/CliqueConfigOptionsTest.java b/config/src/test/java/tech/pegasys/pantheon/config/CliqueConfigOptionsTest.java index 554eedcd6e..5cc9790236 100644 --- a/config/src/test/java/tech/pegasys/pantheon/config/CliqueConfigOptionsTest.java +++ b/config/src/test/java/tech/pegasys/pantheon/config/CliqueConfigOptionsTest.java @@ -28,7 +28,7 @@ public class CliqueConfigOptionsTest { @Test public void shouldGetEpochLengthFromConfig() { - final CliqueConfigOptions config = fromConfigOptions(singletonMap("epochLength", 10_000)); + final CliqueConfigOptions config = fromConfigOptions(singletonMap("EpochLength", 10_000)); assertThat(config.getEpochLength()).isEqualTo(10_000); } @@ -46,7 +46,7 @@ public class CliqueConfigOptionsTest { @Test public void shouldGetBlockPeriodFromConfig() { - final CliqueConfigOptions config = fromConfigOptions(singletonMap("blockPeriodSeconds", 5)); + final CliqueConfigOptions config = fromConfigOptions(singletonMap("BlockPeriodSeconds", 5)); assertThat(config.getBlockPeriodSeconds()).isEqualTo(5); } @@ -63,8 +63,9 @@ public class CliqueConfigOptionsTest { } private CliqueConfigOptions fromConfigOptions(final Map cliqueConfigOptions) { - return GenesisConfigOptions.fromGenesisConfig( + return GenesisConfigFile.fromConfig( new JsonObject(singletonMap("config", singletonMap("clique", cliqueConfigOptions)))) + .getConfigOptions() .getCliqueConfigOptions(); } } diff --git a/config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigFileTest.java b/config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigFileTest.java new file mode 100644 index 0000000000..3b68b73661 --- /dev/null +++ b/config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigFileTest.java @@ -0,0 +1,176 @@ +/* + * Copyright 2018 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. + */ +package tech.pegasys.pantheon.config; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.entry; + +import java.util.Map; +import java.util.stream.Collectors; + +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.Test; + +public class GenesisConfigFileTest { + + private static final int MAINNET_CHAIN_ID = 1; + private static final int DEVELOPMENT_CHAIN_ID = 2018; + private static final GenesisConfigFile EMPTY_CONFIG = GenesisConfigFile.fromConfig("{}"); + + @Test + public void shouldLoadMainnetConfigFile() { + final GenesisConfigFile config = GenesisConfigFile.mainnet(); + // Sanity check some basic properties to confirm this is the mainnet file. + assertThat(config.getConfigOptions().isEthHash()).isTrue(); + assertThat(config.getConfigOptions().getChainId()).hasValue(MAINNET_CHAIN_ID); + assertThat(config.getAllocations().map(GenesisAllocation::getAddress)) + .contains( + "000d836201318ec6899a67540690382780743280", + "001762430ea9c3a26e5749afdb70da5f78ddbb8c", + "001d14804b399c6ef80e64576f657660804fec0b"); + } + + @Test + public void shouldLoadDevelopmentConfigFile() { + final GenesisConfigFile config = GenesisConfigFile.development(); + // Sanity check some basic properties to confirm this is the dev file. + assertThat(config.getConfigOptions().isEthHash()).isTrue(); + assertThat(config.getConfigOptions().getChainId()).hasValue(DEVELOPMENT_CHAIN_ID); + assertThat(config.getAllocations().map(GenesisAllocation::getAddress)) + .contains( + "fe3b557e8fb62b89f4916b721be55ceb828dbd73", + "627306090abab3a6e1400e9345bc60c78a8bef57", + "f17f52151ebef6c7334fad080c5704d77216b732"); + } + + @Test + public void shouldGetParentHash() { + assertThat(configWithProperty("parentHash", "844633").getParentHash()).isEqualTo("844633"); + } + + @Test + public void shouldDefaultParentHashToEmptyString() { + assertThat(EMPTY_CONFIG.getParentHash()).isEmpty(); + } + + @Test + public void shouldGetDifficulty() { + assertThat(configWithProperty("difficulty", "1234").getDifficulty()).isEqualTo("1234"); + } + + @Test + public void shouldRequireDifficulty() { + assertInvalidConfiguration(EMPTY_CONFIG::getDifficulty); + } + + @Test + public void shouldGetExtraData() { + assertThat(configWithProperty("extraData", "yay").getExtraData()).isEqualTo("yay"); + } + + @Test + public void shouldDefaultExtraDataToEmptyString() { + assertThat(EMPTY_CONFIG.getExtraData()).isEmpty(); + } + + @Test + public void shouldGetGasLimit() { + assertThat(configWithProperty("gasLimit", "1000").getGasLimit()).isEqualTo(1000); + } + + @Test + public void shouldRequireGasLimit() { + assertInvalidConfiguration(EMPTY_CONFIG::getGasLimit); + } + + @Test + public void shouldGetMixHash() { + assertThat(configWithProperty("mixHash", "asdf").getMixHash()).isEqualTo("asdf"); + } + + @Test + public void shouldDefaultMixHashToEmptyString() { + assertThat(EMPTY_CONFIG.getMixHash()).isEmpty(); + } + + @Test + public void shouldGetNonce() { + assertThat(configWithProperty("nonce", "ABCD").getNonce()).isEqualTo("ABCD"); + } + + @Test + public void shouldDefaultNonceToEmptyString() { + assertThat(EMPTY_CONFIG.getNonce()).isEmpty(); + } + + @Test + public void shouldGetCoinbase() { + assertThat(configWithProperty("coinbase", "abcd").getCoinbase()).contains("abcd"); + } + + @Test + public void shouldReturnEmptyWhenCoinbaseNotSpecified() { + assertThat(EMPTY_CONFIG.getCoinbase()).isEmpty(); + } + + @Test + public void shouldGetTimestamp() { + assertThat(configWithProperty("timestamp", "0x10").getTimestamp()).isEqualTo(16L); + } + + @Test + public void shouldDefaultTimestampToZero() { + assertThat(EMPTY_CONFIG.getTimestamp()).isZero(); + } + + @Test + public void shouldGetAllocations() { + final GenesisConfigFile config = + GenesisConfigFile.fromConfig( + "{" + + " \"alloc\": {" + + " \"fe3b557e8fb62b89f4916b721be55ceb828dbd73\": {" + + " \"balance\": \"0xad78ebc5ac6200000\"" + + " }," + + " \"627306090abaB3A6e1400e9345bC60c78a8BEf57\": {" + + " \"balance\": \"1000\"" + + " }," + + " \"f17f52151EbEF6C7334FAD080c5704D77216b732\": {" + + " \"balance\": \"90000000000000000000000\"" + + " }" + + " }" + + "}"); + + final Map allocations = + config + .getAllocations() + .collect( + Collectors.toMap(GenesisAllocation::getAddress, GenesisAllocation::getBalance)); + assertThat(allocations) + .containsOnly( + entry("fe3b557e8fb62b89f4916b721be55ceb828dbd73", "0xad78ebc5ac6200000"), + entry("627306090abab3a6e1400e9345bc60c78a8bef57", "1000"), + entry("f17f52151ebef6c7334fad080c5704d77216b732", "90000000000000000000000")); + } + + private GenesisConfigFile configWithProperty(final String key, final String value) { + return GenesisConfigFile.fromConfig("{\"" + key + "\":\"" + value + "\"}"); + } + + private void assertInvalidConfiguration(final ThrowingCallable getter) { + assertThatThrownBy(getter) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid Genesis block configuration"); + } +} diff --git a/config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigOptionsTest.java b/config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigOptionsTest.java index d9b89f1f99..c4a385b934 100644 --- a/config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigOptionsTest.java +++ b/config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigOptionsTest.java @@ -120,7 +120,7 @@ public class GenesisConfigOptionsTest { @Test public void shouldSupportEmptyGenesisConfig() { - final GenesisConfigOptions config = GenesisConfigOptions.fromGenesisConfig("{}"); + final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions(); assertThat(config.isEthHash()).isFalse(); assertThat(config.isIbft()).isFalse(); assertThat(config.isClique()).isFalse(); @@ -128,7 +128,7 @@ public class GenesisConfigOptionsTest { } private GenesisConfigOptions fromConfigOptions(final Map options) { - return GenesisConfigOptions.fromGenesisConfig( - new JsonObject(Collections.singletonMap("config", options))); + return GenesisConfigFile.fromConfig(new JsonObject(Collections.singletonMap("config", options))) + .getConfigOptions(); } } diff --git a/config/src/test/java/tech/pegasys/pantheon/config/IbftConfigOptionsTest.java b/config/src/test/java/tech/pegasys/pantheon/config/IbftConfigOptionsTest.java index 048f3ba0cf..9ed52d2356 100644 --- a/config/src/test/java/tech/pegasys/pantheon/config/IbftConfigOptionsTest.java +++ b/config/src/test/java/tech/pegasys/pantheon/config/IbftConfigOptionsTest.java @@ -29,7 +29,7 @@ public class IbftConfigOptionsTest { @Test public void shouldGetEpochLengthFromConfig() { - final IbftConfigOptions config = fromConfigOptions(singletonMap("epochLength", 10_000)); + final IbftConfigOptions config = fromConfigOptions(singletonMap("EpochLength", 10_000)); assertThat(config.getEpochLength()).isEqualTo(10_000); } @@ -46,7 +46,7 @@ public class IbftConfigOptionsTest { @Test public void shouldGetBlockPeriodFromConfig() { - final IbftConfigOptions config = fromConfigOptions(singletonMap("blockPeriodSeconds", 5)); + final IbftConfigOptions config = fromConfigOptions(singletonMap("BlockPeriodSeconds", 5)); assertThat(config.getBlockPeriodSeconds()).isEqualTo(5); } @@ -64,7 +64,7 @@ public class IbftConfigOptionsTest { @Test public void shouldGetRequestTimeoutFromConfig() { - final IbftConfigOptions config = fromConfigOptions(singletonMap("requestTimeout", 5)); + final IbftConfigOptions config = fromConfigOptions(singletonMap("RequestTimeout", 5)); assertThat(config.getRequestTimeoutMillis()).isEqualTo(5); } @@ -81,8 +81,9 @@ public class IbftConfigOptionsTest { } private IbftConfigOptions fromConfigOptions(final Map ibftConfigOptions) { - return GenesisConfigOptions.fromGenesisConfig( + return GenesisConfigFile.fromConfig( new JsonObject(singletonMap("config", singletonMap("ibft", ibftConfigOptions)))) + .getConfigOptions() .getIbftConfigOptions(); } } diff --git a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java index a5675ef667..747283c434 100644 --- a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java +++ b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java @@ -20,7 +20,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; /** Defines the protocol behaviours for a blockchain using Clique. */ -public class CliqueProtocolSchedule extends MutableProtocolSchedule { +public class CliqueProtocolSchedule { private static final int DEFAULT_CHAIN_ID = 4; @@ -33,14 +33,14 @@ public class CliqueProtocolSchedule extends MutableProtocolSchedule protocolSchedule = new CliqueProtocolSchedule(); + final MutableProtocolSchedule protocolSchedule = + new MutableProtocolSchedule<>(chainId); // TODO(tmm) replace address with passed in node data (coming later) final CliqueProtocolSpecs specs = new CliqueProtocolSpecs( blockPeriod, epochLength, - chainId, Util.publicKeyToAddress(nodeKeys.getPublicKey()), protocolSchedule); diff --git a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecs.java b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecs.java index 773a33c88f..a6fc274551 100644 --- a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecs.java +++ b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecs.java @@ -29,19 +29,16 @@ public class CliqueProtocolSpecs { private final long secondsBetweenBlocks; private final long epochLength; - private final int chainId; private final Address localNodeAddress; private final ProtocolSchedule protocolSchedule; public CliqueProtocolSpecs( final long secondsBetweenBlocks, final long epochLength, - final int chainId, final Address localNodeAddress, final ProtocolSchedule protocolSchedule) { this.secondsBetweenBlocks = secondsBetweenBlocks; this.epochLength = epochLength; - this.chainId = chainId; this.localNodeAddress = localNodeAddress; this.protocolSchedule = protocolSchedule; } @@ -59,15 +56,18 @@ public class CliqueProtocolSpecs { } public ProtocolSpec spuriousDragon() { - return applyCliqueSpecificModifications(MainnetProtocolSpecs.spuriousDragonDefinition(chainId)); + return applyCliqueSpecificModifications( + MainnetProtocolSpecs.spuriousDragonDefinition(protocolSchedule.getChainId())); } public ProtocolSpec byzantium() { - return applyCliqueSpecificModifications(MainnetProtocolSpecs.byzantiumDefinition(chainId)); + return applyCliqueSpecificModifications( + MainnetProtocolSpecs.byzantiumDefinition(protocolSchedule.getChainId())); } public ProtocolSpec constantinople() { - return applyCliqueSpecificModifications(MainnetProtocolSpecs.constantinopleDefinition(chainId)); + return applyCliqueSpecificModifications( + MainnetProtocolSpecs.constantinopleDefinition(protocolSchedule.getChainId())); } private ProtocolSpec applyCliqueSpecificModifications( diff --git a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java index 6c1953cc29..b6369eefe7 100644 --- a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java +++ b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java @@ -14,6 +14,7 @@ package tech.pegasys.pantheon.consensus.clique; import static org.assertj.core.api.Java6Assertions.assertThat; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; @@ -35,7 +36,7 @@ public class CliqueProtocolScheduleTest { + "\"byzantiumBlock\": 1035301}" + "}"; - final GenesisConfigOptions config = GenesisConfigOptions.fromGenesisConfig(jsonInput); + final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions(); final ProtocolSchedule protocolSchedule = CliqueProtocolSchedule.create(config, KeyPair.generate()); diff --git a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecsTest.java b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecsTest.java index ff2f849b1e..92163c7883 100644 --- a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecsTest.java +++ b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecsTest.java @@ -25,9 +25,10 @@ import org.junit.Test; public class CliqueProtocolSpecsTest { + private static final int CHAIN_ID = 5; CliqueProtocolSpecs protocolSpecs = new CliqueProtocolSpecs( - 15, 30_000, 5, AddressHelpers.ofValue(5), new MutableProtocolSchedule<>()); + 15, 30_000, AddressHelpers.ofValue(5), new MutableProtocolSchedule<>(CHAIN_ID)); @Test public void homsteadParametersAlignWithMainnetWithAdjustments() { @@ -40,7 +41,7 @@ public class CliqueProtocolSpecsTest { @Test public void allSpecsInheritFromMainnetCounterparts() { - final ProtocolSchedule mainnetProtocolSchedule = new MutableProtocolSchedule<>(); + final ProtocolSchedule mainnetProtocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); assertThat(protocolSpecs.frontier().getName()) .isEqualTo(MainnetProtocolSpecs.frontier(mainnetProtocolSchedule).getName()); diff --git a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index a9c8314830..10f5c81541 100644 --- a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -19,10 +19,10 @@ import static org.mockito.Mockito.when; import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryBlockchain; import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.consensus.clique.CliqueContext; import tech.pegasys.pantheon.consensus.clique.CliqueExtraData; import tech.pegasys.pantheon.consensus.clique.CliqueHelpers; -import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule; import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSpecs; import tech.pegasys.pantheon.consensus.clique.TestHelpers; import tech.pegasys.pantheon.consensus.clique.VoteTallyCache; @@ -31,7 +31,7 @@ import tech.pegasys.pantheon.consensus.common.VoteTally; import tech.pegasys.pantheon.consensus.common.VoteType; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.AddressHelpers; @@ -53,29 +53,25 @@ import org.junit.Test; public class CliqueBlockCreatorTest { + private static final int CHAIN_ID = 1; private final KeyPair proposerKeyPair = KeyPair.generate(); private final Address proposerAddress = Util.publicKeyToAddress(proposerKeyPair.getPublicKey()); private final KeyPair otherKeyPair = KeyPair.generate(); private final List
validatorList = Lists.newArrayList(); - private final Block genesis = GenesisConfig.mainnet().getBlock(); - private final MutableBlockchain blockchain = createInMemoryBlockchain(genesis); + private final MutableProtocolSchedule protocolSchedule = + new MutableProtocolSchedule<>(CHAIN_ID); private final WorldStateArchive stateArchive = createInMemoryWorldStateArchive(); + private MutableBlockchain blockchain; private ProtocolContext protocolContext; - private final MutableProtocolSchedule protocolSchedule = - new CliqueProtocolSchedule(); private VoteProposer voteProposer; @Before public void setup() { final CliqueProtocolSpecs specs = new CliqueProtocolSpecs( - 15, - 30_000, - 1, - Util.publicKeyToAddress(proposerKeyPair.getPublicKey()), - protocolSchedule); + 15, 30_000, Util.publicKeyToAddress(proposerKeyPair.getPublicKey()), protocolSchedule); protocolSchedule.putMilestone(0, specs.frontier()); @@ -87,6 +83,9 @@ public class CliqueBlockCreatorTest { voteProposer = new VoteProposer(); final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); + final Block genesis = + GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule).getBlock(); + blockchain = createInMemoryBlockchain(genesis); protocolContext = new ProtocolContext<>(blockchain, stateArchive, cliqueContext); // Add a block above the genesis diff --git a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java index e2e83ddca0..aa2b0c6772 100644 --- a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java +++ b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java @@ -17,6 +17,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.consensus.clique.CliqueContext; import tech.pegasys.pantheon.consensus.clique.CliqueExtraData; @@ -49,7 +50,7 @@ import org.junit.Test; public class CliqueMinerExecutorTest { private static final GenesisConfigOptions GENESIS_CONFIG_OPTIONS = - GenesisConfigOptions.fromGenesisConfig(new JsonObject()); + GenesisConfigFile.fromConfig(new JsonObject()).getConfigOptions(); private final KeyPair proposerKeyPair = KeyPair.generate(); private Address localAddress; private final List
validatorList = Lists.newArrayList(); diff --git a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java index 4f93d56027..9e15320812 100644 --- a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java @@ -30,7 +30,8 @@ public class IbftProtocolSchedule { final long epochLength = ibftConfig.getEpochLength(); final long blockPeriod = ibftConfig.getBlockPeriodSeconds(); - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = + new MutableProtocolSchedule<>(chainId); protocolSchedule.putMilestone( spuriousDragonBlock, IbftProtocolSpecs.spuriousDragon(blockPeriod, epochLength, chainId, protocolSchedule)); diff --git a/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java index 1fa99e33c6..660d8c6de9 100644 --- a/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java @@ -18,7 +18,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; -import tech.pegasys.pantheon.config.GenesisConfigOptions; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.consensus.common.VoteProposer; import tech.pegasys.pantheon.consensus.common.VoteTally; import tech.pegasys.pantheon.consensus.ibft.IbftContext; @@ -78,7 +78,8 @@ public class IbftBlockCreatorTest { final ProtocolSchedule protocolSchedule = IbftProtocolSchedule.create( - GenesisConfigOptions.fromGenesisConfig("{\"config\": {\"spuriousDragonBlock\":0}}")); + GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}") + .getConfigOptions()); final ProtocolContext protContext = new ProtocolContext<>( blockchain, diff --git a/ethereum/blockcreation/build.gradle b/ethereum/blockcreation/build.gradle index 7dd341f421..7422551f99 100644 --- a/ethereum/blockcreation/build.gradle +++ b/ethereum/blockcreation/build.gradle @@ -12,6 +12,7 @@ dependencies { implementation project(':ethereum:core') implementation project(':ethereum:eth') implementation project(':util') + implementation project(':config') implementation project(':crypto') implementation project(':services:kvstore') diff --git a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMinerTest.java b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMinerTest.java index a0f2bc9163..aa4d10a210 100644 --- a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMinerTest.java +++ b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMinerTest.java @@ -124,7 +124,7 @@ public class BlockMinerTest { } private ProtocolSchedule singleSpecSchedule(final ProtocolSpec protocolSpec) { - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(1234); protocolSchedule.putMilestone(0, protocolSpec); return protocolSchedule; } diff --git a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java index debbd42104..a3b2f5a3d2 100644 --- a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.NONCE_TOO_LOW; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.chain.Blockchain; import tech.pegasys.pantheon.ethereum.core.Address; @@ -53,7 +54,6 @@ import java.util.List; import java.util.function.Supplier; import com.google.common.collect.Lists; -import io.vertx.core.json.JsonObject; import org.junit.Test; public class BlockTransactionSelectorTest { @@ -63,7 +63,7 @@ public class BlockTransactionSelectorTest { @Test public void emptyPendingTransactionsResultsInEmptyVettingResult() { final ProtocolSchedule protocolSchedule = - DevelopmentProtocolSchedule.create(new JsonObject()); + DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions()); final Blockchain blockchain = new TestBlockchain(); final TransactionProcessor transactionProcessor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor(); diff --git a/ethereum/core/src/integration-test/java/tech/pegasys/pantheon/ethereum/vm/TraceTransactionIntegrationTest.java b/ethereum/core/src/integration-test/java/tech/pegasys/pantheon/ethereum/vm/TraceTransactionIntegrationTest.java index 7a8b818fd3..8d89c1ed25 100644 --- a/ethereum/core/src/integration-test/java/tech/pegasys/pantheon/ethereum/vm/TraceTransactionIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/tech/pegasys/pantheon/ethereum/vm/TraceTransactionIntegrationTest.java @@ -14,16 +14,13 @@ package tech.pegasys.pantheon.ethereum.vm; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryBlockchain; -import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Account; import tech.pegasys.pantheon.ethereum.core.Block; +import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture; import tech.pegasys.pantheon.ethereum.core.Gas; -import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.MutableWorldState; import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.Wei; @@ -63,12 +60,11 @@ public class TraceTransactionIntegrationTest { @Before public void setUp() { - final GenesisConfig genesisConfig = GenesisConfig.development(); - genesisBlock = genesisConfig.getBlock(); - blockchain = createInMemoryBlockchain(genesisBlock); - worldStateArchive = createInMemoryWorldStateArchive(); - final ProtocolSchedule protocolSchedule = genesisConfig.getProtocolSchedule(); - genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); + final ExecutionContextTestFixture contextTestFixture = ExecutionContextTestFixture.create(); + genesisBlock = contextTestFixture.getGenesis(); + blockchain = contextTestFixture.getBlockchain(); + worldStateArchive = contextTestFixture.getStateArchive(); + final ProtocolSchedule protocolSchedule = contextTestFixture.getProtocolSchedule(); transactionProcessor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor(); blockHashLookup = new BlockHashLookup(genesisBlock.getHeader(), blockchain); } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisConfig.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisConfig.java deleted file mode 100644 index cf981e120a..0000000000 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisConfig.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright 2018 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. - */ -package tech.pegasys.pantheon.ethereum.chain; - -import tech.pegasys.pantheon.config.GenesisConfigOptions; -import tech.pegasys.pantheon.ethereum.core.Address; -import tech.pegasys.pantheon.ethereum.core.Block; -import tech.pegasys.pantheon.ethereum.core.BlockBody; -import tech.pegasys.pantheon.ethereum.core.BlockHeader; -import tech.pegasys.pantheon.ethereum.core.BlockHeaderBuilder; -import tech.pegasys.pantheon.ethereum.core.Hash; -import tech.pegasys.pantheon.ethereum.core.LogsBloomFilter; -import tech.pegasys.pantheon.ethereum.core.MutableWorldState; -import tech.pegasys.pantheon.ethereum.core.Wei; -import tech.pegasys.pantheon.ethereum.core.WorldUpdater; -import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule; -import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule; -import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; -import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction; -import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState; -import tech.pegasys.pantheon.ethereum.worldstate.KeyValueStorageWorldStateStorage; -import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage; -import tech.pegasys.pantheon.util.bytes.Bytes32; -import tech.pegasys.pantheon.util.bytes.BytesValue; -import tech.pegasys.pantheon.util.uint.UInt256; - -import java.io.IOException; -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.google.common.base.MoreObjects; -import com.google.common.io.Resources; -import io.vertx.core.json.JsonObject; - -public final class GenesisConfig { - - private static final BlockBody BODY = - new BlockBody(Collections.emptyList(), Collections.emptyList()); - private static final String MAINNET_FILE = "mainnet.json"; - - private final Block block; - private final int chainId; - private final ProtocolSchedule protocolSchedule; - private final List genesisAccounts; - - private GenesisConfig( - final Block block, - final int chainId, - final ProtocolSchedule protocolSchedule, - final List genesisAccounts) { - this.block = block; - this.chainId = chainId; - this.protocolSchedule = protocolSchedule; - this.genesisAccounts = genesisAccounts; - } - - public static GenesisConfig mainnet() { - try { - final JsonObject config = - new JsonObject( - Resources.toString(Resources.getResource(MAINNET_FILE), StandardCharsets.UTF_8)); - final GenesisConfigOptions configOptions = GenesisConfigOptions.fromGenesisConfig(config); - return GenesisConfig.fromConfig(config, MainnetProtocolSchedule.fromConfig(configOptions)); - } catch (final IOException ex) { - throw new IllegalStateException(ex); - } - } - - public static GenesisConfig development() { - try { - final JsonObject config = - new JsonObject( - Resources.toString(Resources.getResource("dev.json"), StandardCharsets.UTF_8)); - return GenesisConfig.fromConfig( - config, DevelopmentProtocolSchedule.create(config.getJsonObject("config"))); - } catch (final IOException ex) { - throw new IllegalStateException(ex); - } - } - - /** - * Construct a {@link GenesisConfig} from a JSON string. - * - * @param json A JSON string describing the genesis block - * @param protocolSchedule A protocol Schedule associated with - * @param The consensus context type - * @return A new genesis block. - */ - public static GenesisConfig fromJson( - final String json, final ProtocolSchedule protocolSchedule) { - return fromConfig(new JsonObject(json), protocolSchedule); - } - - /** - * Construct a {@link GenesisConfig} from a JSON object. - * - * @param jsonConfig A {@link JsonObject} describing the genesis block. - * @param protocolSchedule A protocol Schedule associated with - * @param The consensus context type - * @return A new genesis block. - */ - @SuppressWarnings("unchecked") - public static GenesisConfig fromConfig( - final JsonObject jsonConfig, final ProtocolSchedule protocolSchedule) { - final Map definition = toNormalizedMap(jsonConfig); - final List genesisAccounts = - parseAllocations(definition).collect(Collectors.toList()); - final Block block = - new Block( - buildHeader(definition, calculateGenesisStateHash(genesisAccounts), protocolSchedule), - BODY); - final int chainId = - GenesisConfigOptions.fromGenesisConfig(jsonConfig) - .getChainId() - .orElse(MainnetProtocolSchedule.DEFAULT_CHAIN_ID); - return new GenesisConfig<>(block, chainId, protocolSchedule, genesisAccounts); - } - - public Block getBlock() { - return block; - } - - public int getChainId() { - return chainId; - } - - /** - * Writes the genesis block's world state to the given {@link MutableWorldState}. - * - * @param target WorldView to write genesis state to - */ - public void writeStateTo(final MutableWorldState target) { - writeAccountsTo(target, genesisAccounts); - } - - private static void writeAccountsTo( - final MutableWorldState target, final List genesisAccounts) { - final WorldUpdater updater = target.updater(); - genesisAccounts.forEach( - account -> updater.getOrCreate(account.address).setBalance(account.balance)); - updater.commit(); - target.persist(); - } - - public ProtocolSchedule getProtocolSchedule() { - return protocolSchedule; - } - - private static Hash calculateGenesisStateHash(final List genesisAccounts) { - final MutableWorldState worldState = - new DefaultMutableWorldState( - new KeyValueStorageWorldStateStorage(new InMemoryKeyValueStorage())); - writeAccountsTo(worldState, genesisAccounts); - return worldState.rootHash(); - } - - private static BlockHeader buildHeader( - final Map genesis, - final Hash genesisRootHash, - final ProtocolSchedule protocolSchedule) { - - return BlockHeaderBuilder.create() - .parentHash(parseParentHash(genesis)) - .ommersHash(Hash.EMPTY_LIST_HASH) - .coinbase(parseCoinbase(genesis)) - .stateRoot(genesisRootHash) - .transactionsRoot(Hash.EMPTY_TRIE_HASH) - .receiptsRoot(Hash.EMPTY_TRIE_HASH) - .logsBloom(LogsBloomFilter.empty()) - .difficulty(parseDifficulty(genesis)) - .number(BlockHeader.GENESIS_BLOCK_NUMBER) - .gasLimit(parseGasLimit(genesis)) - .gasUsed(0L) - .timestamp(parseTimestamp(genesis)) - .extraData(parseExtraData(genesis)) - .mixHash(parseMixHash(genesis)) - .nonce(parseNonce(genesis)) - .blockHashFunction(ScheduleBasedBlockHashFunction.create(protocolSchedule)) - .buildBlockHeader(); - } - - /* Converts the {@link JsonObject} describing the Genesis Block to a {@link Map}. This method - * converts all nested {@link JsonObject} to {@link Map} as well. Also, note that all keys are - * converted to lowercase for easier lookup since the keys in a 'genesis.json' file are assumed - * case insensitive. - */ - private static Map toNormalizedMap(final JsonObject genesis) { - final Map normalized = new HashMap<>(); - genesis - .getMap() - .forEach( - (key, value) -> { - final String normalizedKey = key.toLowerCase(Locale.US); - if (value instanceof JsonObject) { - normalized.put(normalizedKey, toNormalizedMap((JsonObject) value)); - } else { - normalized.put(normalizedKey, value); - } - }); - return normalized; - } - - private static String getString( - final Map map, final String key, final String def) { - return entryAsString(map.getOrDefault(key.toLowerCase(Locale.US), def)); - } - - private static String getString(final Map map, final String key) { - final String keyy = key.toLowerCase(Locale.US); - if (!map.containsKey(keyy)) { - throw new IllegalArgumentException( - String.format("Invalid Genesis block configuration, missing value for '%s'", key)); - } - return entryAsString(map.get(keyy)); - } - - private static String entryAsString(final Object value) { - return ((CharSequence) value).toString(); - } - - private static long parseTimestamp(final Map genesis) { - return Long.parseLong(getString(genesis, "timestamp", "0x0").substring(2), 16); - } - - private static Address parseCoinbase(final Map genesis) { - final Address coinbase; - final String key = "coinbase"; - if (genesis.containsKey(key)) { - coinbase = Address.fromHexString(getString(genesis, key)); - } else { - coinbase = Address.wrap(BytesValue.wrap(new byte[Address.SIZE])); - } - return coinbase; - } - - private static Hash parseParentHash(final Map genesis) { - return Hash.wrap(Bytes32.fromHexString(getString(genesis, "parentHash", ""))); - } - - private static BytesValue parseExtraData(final Map genesis) { - return BytesValue.fromHexString(getString(genesis, "extraData", "")); - } - - private static UInt256 parseDifficulty(final Map genesis) { - return UInt256.fromHexString(getString(genesis, "difficulty")); - } - - private static long parseGasLimit(final Map genesis) { - return Long.decode(getString(genesis, "gasLimit")); - } - - private static Hash parseMixHash(final Map genesis) { - return Hash.wrap(Bytes32.fromHexString(getString(genesis, "mixHash", ""))); - } - - private static long parseNonce(final Map genesis) { - String nonce = getString(genesis, "nonce", "").toLowerCase(); - if (nonce.startsWith("0x")) { - nonce = nonce.substring(2); - } - return Long.parseUnsignedLong(nonce, 16); - } - - @SuppressWarnings("unchecked") - private static Stream parseAllocations(final Map genesis) { - final Map alloc = (Map) genesis.get("alloc"); - return alloc - .entrySet() - .stream() - .map( - entry -> { - final Address address = Address.fromHexString(entry.getKey()); - final String balance = getString((Map) entry.getValue(), "balance"); - return new GenesisAccount(address, balance); - }); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("block", block) - .add("chainId", chainId) - .add("protocolSchedule", protocolSchedule) - .add("genesisAccounts", genesisAccounts) - .toString(); - } - - private static final class GenesisAccount { - - final Address address; - final Wei balance; - - GenesisAccount(final Address address, final String balance) { - this.address = address; - this.balance = parseBalance(balance); - } - - private Wei parseBalance(final String balance) { - final BigInteger val; - if (balance.startsWith("0x")) { - val = new BigInteger(1, BytesValue.fromHexStringLenient(balance).extractArray()); - } else { - val = new BigInteger(balance); - } - - return Wei.of(val); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("address", address) - .add("balance", balance) - .toString(); - } - } -} diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java new file mode 100644 index 0000000000..e6b307c2b4 --- /dev/null +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java @@ -0,0 +1,223 @@ +/* + * Copyright 2018 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. + */ +package tech.pegasys.pantheon.ethereum.chain; + +import tech.pegasys.pantheon.config.GenesisConfigFile; +import tech.pegasys.pantheon.ethereum.core.Address; +import tech.pegasys.pantheon.ethereum.core.Block; +import tech.pegasys.pantheon.ethereum.core.BlockBody; +import tech.pegasys.pantheon.ethereum.core.BlockHeader; +import tech.pegasys.pantheon.ethereum.core.BlockHeaderBuilder; +import tech.pegasys.pantheon.ethereum.core.Hash; +import tech.pegasys.pantheon.ethereum.core.LogsBloomFilter; +import tech.pegasys.pantheon.ethereum.core.MutableWorldState; +import tech.pegasys.pantheon.ethereum.core.Wei; +import tech.pegasys.pantheon.ethereum.core.WorldUpdater; +import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; +import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction; +import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState; +import tech.pegasys.pantheon.ethereum.worldstate.KeyValueStorageWorldStateStorage; +import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage; +import tech.pegasys.pantheon.util.bytes.Bytes32; +import tech.pegasys.pantheon.util.bytes.BytesValue; +import tech.pegasys.pantheon.util.uint.UInt256; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.base.MoreObjects; + +public final class GenesisState { + + private static final BlockBody BODY = + new BlockBody(Collections.emptyList(), Collections.emptyList()); + + private final Block block; + private final List genesisAccounts; + + private GenesisState(final Block block, final List genesisAccounts) { + this.block = block; + this.genesisAccounts = genesisAccounts; + } + + /** + * Construct a {@link GenesisState} from a JSON string. + * + * @param json A JSON string describing the genesis block + * @param protocolSchedule A protocol Schedule associated with + * @param The consensus context type + * @return A new {@link GenesisState}. + */ + public static GenesisState fromJson( + final String json, final ProtocolSchedule protocolSchedule) { + return fromConfig(GenesisConfigFile.fromConfig(json), protocolSchedule); + } + + /** + * Construct a {@link GenesisState} from a JSON object. + * + * @param config A {@link GenesisConfigFile} describing the genesis block. + * @param protocolSchedule A protocol Schedule associated with + * @param The consensus context type + * @return A new {@link GenesisState}. + */ + @SuppressWarnings("unchecked") + public static GenesisState fromConfig( + final GenesisConfigFile config, final ProtocolSchedule protocolSchedule) { + final List genesisAccounts = + parseAllocations(config).collect(Collectors.toList()); + final Block block = + new Block( + buildHeader(config, calculateGenesisStateHash(genesisAccounts), protocolSchedule), + BODY); + return new GenesisState(block, genesisAccounts); + } + + public Block getBlock() { + return block; + } + + /** + * Writes the genesis block's world state to the given {@link MutableWorldState}. + * + * @param target WorldView to write genesis state to + */ + public void writeStateTo(final MutableWorldState target) { + writeAccountsTo(target, genesisAccounts); + } + + private static void writeAccountsTo( + final MutableWorldState target, final List genesisAccounts) { + final WorldUpdater updater = target.updater(); + genesisAccounts.forEach( + account -> updater.getOrCreate(account.address).setBalance(account.balance)); + updater.commit(); + target.persist(); + } + + private static Hash calculateGenesisStateHash(final List genesisAccounts) { + final MutableWorldState worldState = + new DefaultMutableWorldState( + new KeyValueStorageWorldStateStorage(new InMemoryKeyValueStorage())); + writeAccountsTo(worldState, genesisAccounts); + return worldState.rootHash(); + } + + private static BlockHeader buildHeader( + final GenesisConfigFile genesis, + final Hash genesisRootHash, + final ProtocolSchedule protocolSchedule) { + + return BlockHeaderBuilder.create() + .parentHash(parseParentHash(genesis)) + .ommersHash(Hash.EMPTY_LIST_HASH) + .coinbase(parseCoinbase(genesis)) + .stateRoot(genesisRootHash) + .transactionsRoot(Hash.EMPTY_TRIE_HASH) + .receiptsRoot(Hash.EMPTY_TRIE_HASH) + .logsBloom(LogsBloomFilter.empty()) + .difficulty(parseDifficulty(genesis)) + .number(BlockHeader.GENESIS_BLOCK_NUMBER) + .gasLimit(genesis.getGasLimit()) + .gasUsed(0L) + .timestamp(genesis.getTimestamp()) + .extraData(parseExtraData(genesis)) + .mixHash(parseMixHash(genesis)) + .nonce(parseNonce(genesis)) + .blockHashFunction(ScheduleBasedBlockHashFunction.create(protocolSchedule)) + .buildBlockHeader(); + } + + private static Address parseCoinbase(final GenesisConfigFile genesis) { + return genesis + .getCoinbase() + .map(Address::fromHexString) + .orElseGet(() -> Address.wrap(BytesValue.wrap(new byte[Address.SIZE]))); + } + + private static Hash parseParentHash(final GenesisConfigFile genesis) { + return Hash.wrap(Bytes32.fromHexString(genesis.getParentHash())); + } + + private static BytesValue parseExtraData(final GenesisConfigFile genesis) { + return BytesValue.fromHexString(genesis.getExtraData()); + } + + private static UInt256 parseDifficulty(final GenesisConfigFile genesis) { + return UInt256.fromHexString(genesis.getDifficulty()); + } + + private static Hash parseMixHash(final GenesisConfigFile genesis) { + return Hash.wrap(Bytes32.fromHexString(genesis.getMixHash())); + } + + private static long parseNonce(final GenesisConfigFile genesis) { + String nonce = genesis.getNonce().toLowerCase(Locale.US); + if (nonce.startsWith("0x")) { + nonce = nonce.substring(2); + } + return Long.parseUnsignedLong(nonce, 16); + } + + @SuppressWarnings("unchecked") + private static Stream parseAllocations(final GenesisConfigFile genesis) { + return genesis + .getAllocations() + .map( + allocation -> + new GenesisAccount( + Address.fromHexString(allocation.getAddress()), allocation.getBalance())); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("block", block) + .add("genesisAccounts", genesisAccounts) + .toString(); + } + + private static final class GenesisAccount { + + final Address address; + final Wei balance; + + GenesisAccount(final Address address, final String balance) { + this.address = address; + this.balance = parseBalance(balance); + } + + private Wei parseBalance(final String balance) { + final BigInteger val; + if (balance.startsWith("0x")) { + val = new BigInteger(1, BytesValue.fromHexStringLenient(balance).extractArray()); + } else { + val = new BigInteger(balance); + } + + return Wei.of(val); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("address", address) + .add("balance", balance) + .toString(); + } + } +} diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolSchedule.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolSchedule.java index bd9d1b110d..f3647d5531 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolSchedule.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolSchedule.java @@ -14,20 +14,19 @@ package tech.pegasys.pantheon.ethereum.development; import static tech.pegasys.pantheon.ethereum.mainnet.MainnetTransactionValidator.NO_CHAIN_ID; +import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; -import io.vertx.core.json.JsonObject; - /** - * A mock ProtocolSchedule which behaves similarly to Frontier (but for all blocks), albeit with a + * A mock ProtocolSchedule which behaves similarly to Byzantium (but for all blocks), albeit with a * much reduced difficulty (which supports testing on CPU alone). */ public class DevelopmentProtocolSchedule { - public static ProtocolSchedule create(final JsonObject config) { - final Integer chainId = config.getInteger("chainId", NO_CHAIN_ID); - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + public static ProtocolSchedule create(final GenesisConfigOptions config) { + final Integer chainId = config.getChainId().orElse(NO_CHAIN_ID); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(chainId); protocolSchedule.putMilestone(0, DevelopmentProtocolSpecs.first(chainId, protocolSchedule)); return protocolSchedule; } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java index 936e7a9a91..2a24ecce8a 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java @@ -14,8 +14,6 @@ package tech.pegasys.pantheon.ethereum.mainnet; import tech.pegasys.pantheon.config.GenesisConfigOptions; -import io.vertx.core.json.JsonObject; - /** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */ public class MainnetProtocolSchedule { @@ -49,7 +47,7 @@ public class MainnetProtocolSchedule { final long constantinopleBlockNumber, final int chainId) { - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(chainId); protocolSchedule.putMilestone(0, MainnetProtocolSpecs.frontier(protocolSchedule)); final ProtocolSpec homestead = MainnetProtocolSpecs.homestead(protocolSchedule); protocolSchedule.putMilestone(homesteadBlockNumber, homestead); @@ -90,8 +88,8 @@ public class MainnetProtocolSchedule { /** * Create a Mainnet protocol schedule from a config object * - * @param config {@link JsonObject} containing the config options for the milestone starting - * points + * @param config {@link GenesisConfigOptions} containing the config options for the milestone + * starting points * @return A configured mainnet protocol schedule */ public static ProtocolSchedule fromConfig(final GenesisConfigOptions config) { diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MutableProtocolSchedule.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MutableProtocolSchedule.java index 0c589fd842..ca3bdd87da 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MutableProtocolSchedule.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MutableProtocolSchedule.java @@ -24,6 +24,16 @@ public class MutableProtocolSchedule implements ProtocolSchedule { new TreeSet<>( Comparator., Long>comparing(ScheduledProtocolSpec::getBlock) .reversed()); + private final int chainId; + + public MutableProtocolSchedule(final int chainId) { + this.chainId = chainId; + } + + @Override + public int getChainId() { + return chainId; + } public void putMilestone(final long blockNumber, final ProtocolSpec protocolSpec) { final ScheduledProtocolSpec scheduledProtocolSpec = diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSchedule.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSchedule.java index 8fa9285b11..6d53b22d30 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSchedule.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSchedule.java @@ -15,4 +15,6 @@ package tech.pegasys.pantheon.ethereum.mainnet; public interface ProtocolSchedule { ProtocolSpec getByBlockNumber(long number); + + int getChainId(); } diff --git a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java index 9927433114..69851c0bf3 100644 --- a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java @@ -12,8 +12,9 @@ */ package tech.pegasys.pantheon.ethereum.core; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.ethereum.ProtocolContext; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.db.DefaultMutableBlockchain; import tech.pegasys.pantheon.ethereum.db.KeyValueStoragePrefixedKeyBlockchainStorage; @@ -38,8 +39,9 @@ public class ExecutionContextTestFixture { private ExecutionContextTestFixture( final ProtocolSchedule protocolSchedule, final KeyValueStorage keyValueStorage) { - final GenesisConfig genesisConfig = GenesisConfig.mainnet(); - this.genesis = genesisConfig.getBlock(); + final GenesisState genesisState = + GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule); + this.genesis = genesisState.getBlock(); this.keyValueStorage = keyValueStorage; this.blockchain = new DefaultMutableBlockchain( @@ -51,7 +53,7 @@ public class ExecutionContextTestFixture { this.protocolSchedule = protocolSchedule; this.protocolContext = new ProtocolContext<>(blockchain, stateArchive, null); - genesisConfig.writeStateTo( + genesisState.writeStateTo( new DefaultMutableWorldState(new KeyValueStorageWorldStateStorage(keyValueStorage))); } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisConfigTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java similarity index 84% rename from ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisConfigTest.java rename to ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java index 446a273df2..29eab6a7b8 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisConfigTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java @@ -30,7 +30,7 @@ import com.google.common.io.Resources; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; -public final class GenesisConfigTest { +public final class GenesisStateTest { /** Known RLP encoded bytes of the Olympic Genesis Block. */ private static final String OLYMPIC_RLP = @@ -42,12 +42,11 @@ public final class GenesisConfigTest { @Test public void createFromJsonWithAllocs() throws Exception { - final GenesisConfig genesisConfig = - GenesisConfig.fromJson( - Resources.toString( - GenesisConfigTest.class.getResource("genesis1.json"), Charsets.UTF_8), + final GenesisState genesisState = + GenesisState.fromJson( + Resources.toString(GenesisStateTest.class.getResource("genesis1.json"), Charsets.UTF_8), MainnetProtocolSchedule.create()); - final BlockHeader header = genesisConfig.getBlock().getHeader(); + final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getStateRoot()) .isEqualTo( Hash.fromHexString( @@ -60,7 +59,7 @@ public final class GenesisConfigTest { final DefaultMutableWorldState worldState = new DefaultMutableWorldState( new KeyValueStorageWorldStateStorage(new InMemoryKeyValueStorage())); - genesisConfig.writeStateTo(worldState); + genesisState.writeStateTo(worldState); final Account first = worldState.get(Address.fromHexString("0x0000000000000000000000000000000000000001")); final Account second = @@ -73,12 +72,11 @@ public final class GenesisConfigTest { @Test public void createFromJsonNoAllocs() throws Exception { - final GenesisConfig genesisConfig = - GenesisConfig.fromJson( - Resources.toString( - GenesisConfigTest.class.getResource("genesis2.json"), Charsets.UTF_8), + final GenesisState genesisState = + GenesisState.fromJson( + Resources.toString(GenesisStateTest.class.getResource("genesis2.json"), Charsets.UTF_8), MainnetProtocolSchedule.create()); - final BlockHeader header = genesisConfig.getBlock().getHeader(); + final BlockHeader header = genesisState.getBlock().getHeader(); assertThat(header.getStateRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); assertThat(header.getTransactionsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); assertThat(header.getReceiptsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); @@ -89,14 +87,14 @@ public final class GenesisConfigTest { @Test public void encodeOlympicBlock() throws Exception { - final GenesisConfig genesisConfig = - GenesisConfig.fromJson( + final GenesisState genesisState = + GenesisState.fromJson( Resources.toString( - GenesisConfigTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8), + GenesisStateTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8), MainnetProtocolSchedule.create()); final BytesValueRLPOutput tmp = new BytesValueRLPOutput(); - genesisConfig.getBlock().writeTo(tmp); - assertThat(Hex.toHexString(genesisConfig.getBlock().getHeader().getHash().extractArray())) + genesisState.getBlock().writeTo(tmp); + assertThat(Hex.toHexString(genesisState.getBlock().getHeader().getHash().extractArray())) .isEqualTo(OLYMPIC_HASH); assertThat(Hex.toHexString(tmp.encoded().extractArray())).isEqualTo(OLYMPIC_RLP); } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionPoolTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionPoolTest.java index ff9aa88cc5..e72b1b0413 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionPoolTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionPoolTest.java @@ -28,18 +28,14 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; -import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryBlockchain; -import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.EXCEEDS_BLOCK_GAS_LIMIT; import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.NONCE_TOO_LOW; import static tech.pegasys.pantheon.ethereum.mainnet.ValidationResult.valid; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.TransactionPool.TransactionBatchAddedListener; -import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; import tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator; @@ -77,16 +73,12 @@ public class TransactionPoolTest { @Before public void setUp() { - final GenesisConfig genesisConfig = GenesisConfig.development(); - final Block genesisBlock = genesisConfig.getBlock(); - blockchain = createInMemoryBlockchain(genesisBlock); - final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); - final ProtocolContext protocolContext = - new ProtocolContext<>(blockchain, worldStateArchive, null); - genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); + final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create(); + blockchain = executionContext.getBlockchain(); + final ProtocolContext protocolContext = executionContext.getProtocolContext(); when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(protocolSpec); when(protocolSpec.getTransactionValidator()).thenReturn(transactionValidator); - genesisBlockGasLimit = genesisBlock.getHeader().getGasLimit(); + genesisBlockGasLimit = executionContext.getGenesis().getHeader().getGasLimit(); transactionPool = new TransactionPool(transactions, protocolSchedule, protocolContext, batchAddedListener); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolScheduleTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolScheduleTest.java index e11d82e204..6fcc902ca8 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolScheduleTest.java @@ -14,11 +14,11 @@ package tech.pegasys.pantheon.ethereum.development; import static org.assertj.core.api.Assertions.assertThat; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; -import io.vertx.core.json.JsonObject; import org.junit.Test; public class DevelopmentProtocolScheduleTest { @@ -26,8 +26,8 @@ public class DevelopmentProtocolScheduleTest { @Test public void reportedDifficultyForAllBlocksIsAFixedValue() { - final JsonObject config = new JsonObject(); - final ProtocolSchedule schedule = DevelopmentProtocolSchedule.create(config); + final ProtocolSchedule schedule = + DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions()); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockProcessorTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockProcessorTest.java index c63edda63b..1d22cbb414 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockProcessorTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockProcessorTest.java @@ -18,8 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import tech.pegasys.pantheon.ethereum.chain.Blockchain; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.core.BlockHeader; +import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.MutableWorldState; import tech.pegasys.pantheon.ethereum.core.Wei; @@ -45,7 +45,11 @@ public class MainnetBlockProcessorTest { final MutableWorldState worldState = WorldStateMock.create(emptyMap()); final Hash initialHash = worldState.rootHash(); - final BlockHeader emptyBlockHeader = GenesisConfig.mainnet().getBlock().getHeader(); + final BlockHeader emptyBlockHeader = + new BlockHeaderTestFixture() + .transactionsRoot(Hash.EMPTY_LIST_HASH) + .ommersHash(Hash.EMPTY_LIST_HASH) + .buildHeader(); blockProcessor.processBlock(blockchain, worldState, emptyBlockHeader, emptyList(), emptyList()); // An empty block with 0 reward should not change the world state diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java index 42d2474bdf..a78d96ad1f 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java @@ -12,7 +12,7 @@ */ package tech.pegasys.pantheon.ethereum.mainnet; -import tech.pegasys.pantheon.config.GenesisConfigOptions; +import tech.pegasys.pantheon.config.GenesisConfigFile; import io.vertx.core.json.JsonObject; import org.assertj.core.api.Assertions; @@ -55,7 +55,7 @@ public class MainnetProtocolScheduleTest { public void shouldReturnDefaultProtocolSpecsWhenEmptyJsonConfigIsUsed() { final JsonObject json = new JsonObject("{}"); final ProtocolSchedule sched = - MainnetProtocolSchedule.fromConfig(GenesisConfigOptions.fromGenesisConfig(json)); + MainnetProtocolSchedule.fromConfig(GenesisConfigFile.fromConfig(json).getConfigOptions()); Assertions.assertThat(sched.getByBlockNumber(1L).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(1_150_000L).getName()).isEqualTo("Homestead"); Assertions.assertThat(sched.getByBlockNumber(1_920_000L).getName()) @@ -76,7 +76,7 @@ public class MainnetProtocolScheduleTest { new JsonObject( "{\"config\": {\"homesteadBlock\": 2, \"daoForkBlock\": 3, \"eip150Block\": 14, \"eip158Block\": 15, \"byzantiumBlock\": 16, \"constantinopleBlock\": 18, \"chainId\":1234}}"); final ProtocolSchedule sched = - MainnetProtocolSchedule.fromConfig(GenesisConfigOptions.fromGenesisConfig(json)); + MainnetProtocolSchedule.fromConfig(GenesisConfigFile.fromConfig(json).getConfigOptions()); Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(2).getName()).isEqualTo("Homestead"); Assertions.assertThat(sched.getByBlockNumber(3).getName()).isEqualTo("DaoRecoveryInit"); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleTest.java index 98b7fd0271..6b1871690a 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleTest.java @@ -20,6 +20,8 @@ import org.junit.Test; public class ProtocolScheduleTest { + private static final int CHAIN_ID = 1; + @SuppressWarnings("unchecked") @Test public void getByBlockNumber() { @@ -28,7 +30,7 @@ public class ProtocolScheduleTest { final ProtocolSpec spec3 = mock(ProtocolSpec.class); final ProtocolSpec spec4 = mock(ProtocolSpec.class); - final MutableProtocolSchedule schedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule schedule = new MutableProtocolSchedule<>(CHAIN_ID); schedule.putMilestone(20, spec3); schedule.putMilestone(0, spec1); schedule.putMilestone(30, spec4); @@ -42,7 +44,7 @@ public class ProtocolScheduleTest { @Test public void emptySchedule() { - Assertions.assertThatThrownBy(() -> new MutableProtocolSchedule<>().getByBlockNumber(0)) + Assertions.assertThatThrownBy(() -> new MutableProtocolSchedule<>(CHAIN_ID).getByBlockNumber(0)) .hasMessage("At least 1 milestone must be provided to the protocol schedule"); } @@ -52,7 +54,7 @@ public class ProtocolScheduleTest { final ProtocolSpec spec1 = mock(ProtocolSpec.class); final ProtocolSpec spec2 = mock(ProtocolSpec.class); - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); protocolSchedule.putMilestone(0, spec1); protocolSchedule.putMilestone(0, spec2); assertThat(protocolSchedule.getByBlockNumber(0)).isSameAs(spec2); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java index e95ce4f9fe..d28d21228e 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java @@ -63,27 +63,27 @@ public class ReferenceTestProtocolSchedules { private static ProtocolSchedule createSchedule( final Function, ProtocolSpec> specCreator) { - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); protocolSchedule.putMilestone(0, specCreator.apply(protocolSchedule)); return protocolSchedule; } private static ProtocolSchedule frontierToHomesteadAt5() { - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); protocolSchedule.putMilestone(0, MainnetProtocolSpecs.frontier(protocolSchedule)); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.homestead(protocolSchedule)); return protocolSchedule; } private static ProtocolSchedule homesteadToEip150At5() { - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); protocolSchedule.putMilestone(0, MainnetProtocolSpecs.homestead(protocolSchedule)); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.tangerineWhistle(protocolSchedule)); return protocolSchedule; } private static ProtocolSchedule homesteadToDaoAt5() { - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); final ProtocolSpec homestead = MainnetProtocolSpecs.homestead(protocolSchedule); protocolSchedule.putMilestone(0, homestead); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.daoRecoveryInit(protocolSchedule)); @@ -93,7 +93,7 @@ public class ReferenceTestProtocolSchedules { } private static ProtocolSchedule eip158ToByzantiumAt5() { - final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(); + final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); protocolSchedule.putMilestone( 0, MainnetProtocolSpecs.spuriousDragon(CHAIN_ID, protocolSchedule)); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.byzantium(CHAIN_ID, protocolSchedule)); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java index 690eb175b3..1e44310fe2 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java @@ -90,6 +90,7 @@ public class VMReferenceTest extends AbstractRetryingTest { "CallToPrecompiledContract", "createNameRegistrator" }; + private static final int CHAIN_ID = 1; private final String name; private final VMReferenceTestCaseSpec spec; @@ -114,7 +115,7 @@ public class VMReferenceTest extends AbstractRetryingTest { final EnvironmentInformation execEnv = spec.getExec(); final ProtocolSpec protocolSpec = - MainnetProtocolSpecs.frontier(new MutableProtocolSchedule<>()); + MainnetProtocolSpecs.frontier(new MutableProtocolSchedule<>(CHAIN_ID)); final TestBlockchain blockchain = new TestBlockchain(execEnv.getBlockHeader().getNumber()); final MessageFrame frame = diff --git a/ethereum/eth/build.gradle b/ethereum/eth/build.gradle index 33fb5da964..1ea34365a9 100644 --- a/ethereum/eth/build.gradle +++ b/ethereum/eth/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation 'io.vertx:vertx-core' implementation 'com.google.guava:guava' + testImplementation project(':config') testImplementation project(':crypto') testImplementation project( path: ':ethereum:core', configuration: 'testArtifacts') testImplementation project( path: ':ethereum:core', configuration: 'testSupportArtifacts') diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java index 90eac9d982..4d87bbae24 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java @@ -14,11 +14,14 @@ package tech.pegasys.pantheon.ethereum.eth.manager; import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryBlockchain; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.ethereum.chain.Blockchain; import tech.pegasys.pantheon.ethereum.chain.ChainHead; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.eth.EthProtocol; import tech.pegasys.pantheon.ethereum.eth.manager.DeterministicEthScheduler.TimeoutPolicy; +import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule; +import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.p2p.api.MessageData; import tech.pegasys.pantheon.ethereum.p2p.wire.DefaultMessage; import tech.pegasys.pantheon.util.uint.UInt256; @@ -38,7 +41,10 @@ public class EthProtocolManagerTestUtil { } public static EthProtocolManager create() { - final Blockchain blockchain = createInMemoryBlockchain(GenesisConfig.mainnet().getBlock()); + final ProtocolSchedule protocolSchedule = MainnetProtocolSchedule.create(); + final GenesisConfigFile config = GenesisConfigFile.mainnet(); + final GenesisState genesisState = GenesisState.fromConfig(config, protocolSchedule); + final Blockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); return create(blockchain); } diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java index 69876f42e3..531dda7f49 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java @@ -18,7 +18,7 @@ import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMe import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.chain.Blockchain; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; @@ -46,7 +46,7 @@ import com.google.common.io.Resources; import org.junit.rules.TemporaryFolder; public class BlockchainSetupUtil { - private final GenesisConfig genesisConfig; + private final GenesisState genesisState; private final MutableBlockchain blockchain; private final ProtocolContext protocolContext; private final ProtocolSchedule protocolSchedule; @@ -55,13 +55,13 @@ public class BlockchainSetupUtil { private long maxBlockNumber; public BlockchainSetupUtil( - final GenesisConfig genesisConfig, + final GenesisState genesisState, final MutableBlockchain blockchain, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final WorldStateArchive worldArchive, final List blocks) { - this.genesisConfig = genesisConfig; + this.genesisState = genesisState; this.blockchain = blockchain; this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; @@ -97,13 +97,13 @@ public class BlockchainSetupUtil { try { temp.create(); final URL genesisFileUrl = getResourceUrl(temp, "testGenesis.json"); - final GenesisConfig genesisConfig = - GenesisConfig.fromJson( + final GenesisState genesisState = + GenesisState.fromJson( Resources.toString(genesisFileUrl, Charsets.UTF_8), protocolSchedule); - final MutableBlockchain blockchain = createInMemoryBlockchain(genesisConfig.getBlock()); + final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final WorldStateArchive worldArchive = createInMemoryWorldStateArchive(); - genesisConfig.writeStateTo(worldArchive.getMutable()); + genesisState.writeStateTo(worldArchive.getMutable()); final ProtocolContext protocolContext = new ProtocolContext<>(blockchain, worldArchive, null); @@ -118,7 +118,7 @@ public class BlockchainSetupUtil { } } return new BlockchainSetupUtil<>( - genesisConfig, blockchain, protocolContext, protocolSchedule, worldArchive, blocks); + genesisState, blockchain, protocolContext, protocolSchedule, worldArchive, blocks); } catch (final IOException ex) { throw new IllegalStateException(ex); } finally { @@ -148,8 +148,8 @@ public class BlockchainSetupUtil { return maxBlockNumber; } - public GenesisConfig getGenesisConfig() { - return genesisConfig; + public GenesisState getGenesisState() { + return genesisState; } public MutableBlockchain getBlockchain() { diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java index 8594d10645..ee9051c645 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java @@ -12,6 +12,7 @@ */ package tech.pegasys.pantheon.ethereum.eth.messages; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.ethereum.core.BlockBody; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.Transaction; @@ -33,7 +34,6 @@ import java.util.List; import com.google.common.io.Resources; import io.netty.buffer.ByteBuf; -import io.vertx.core.json.JsonObject; import org.assertj.core.api.Assertions; import org.junit.Test; @@ -67,7 +67,10 @@ public final class BlockBodiesMessageTest { final BlockBodiesMessage message = BlockBodiesMessage.readFrom(raw); try { final Iterator readBodies = - message.bodies(DevelopmentProtocolSchedule.create(new JsonObject())).iterator(); + message + .bodies( + DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions())) + .iterator(); for (int i = 0; i < 50; ++i) { Assertions.assertThat(readBodies.next()).isEqualTo(bodies.get(i)); } diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java index ebadbabd3b..e23275b9d9 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java @@ -12,6 +12,7 @@ */ package tech.pegasys.pantheon.ethereum.eth.messages; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction; @@ -31,7 +32,6 @@ import java.util.List; import com.google.common.io.Resources; import io.netty.buffer.ByteBuf; -import io.vertx.core.json.JsonObject; import org.assertj.core.api.Assertions; import org.junit.Test; @@ -61,7 +61,8 @@ public final class BlockHeadersMessageTest { final BlockHeadersMessage message = BlockHeadersMessage.readFrom(raw); try { final Iterator readHeaders = - message.getHeaders(DevelopmentProtocolSchedule.create(new JsonObject())); + message.getHeaders( + DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions())); for (int i = 0; i < 50; ++i) { Assertions.assertThat(readHeaders.next()).isEqualTo(headers.get(i)); } diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java index e822ed3c7c..4f2afe187b 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java @@ -15,9 +15,10 @@ package tech.pegasys.pantheon.ethereum.eth.sync; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Hash; +import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule; import tech.pegasys.pantheon.ethereum.eth.manager.ChainState; import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManagerTestUtil; @@ -42,7 +43,7 @@ public class ChainHeadTrackerTest { blockchain.getChainHead().getTotalDifficulty(), 0); private final ProtocolSchedule protocolSchedule = - GenesisConfig.development().getProtocolSchedule(); + DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions()); private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class); private final ChainHeadTracker chainHeadTracker = new ChainHeadTracker(ethProtocolManager.ethContext(), protocolSchedule, trailingPeerLimiter); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java index 537bba1dd7..8978c34eba 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java @@ -17,14 +17,16 @@ import static org.assertj.core.util.Preconditions.checkNotNull; import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryBlockchain; import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.crypto.SECP256K1; import tech.pegasys.pantheon.ethereum.ProtocolContext; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.TransactionPool; import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; +import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule; import tech.pegasys.pantheon.ethereum.eth.EthProtocol; import tech.pegasys.pantheon.ethereum.eth.manager.EthContext; import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; @@ -84,14 +86,16 @@ public class TestNode implements Closeable { .setRlpx(RlpxConfiguration.create().setBindPort(listenPort)) .setSupportedProtocols(EthProtocol.get()); - final GenesisConfig genesisConfig = GenesisConfig.development(); - final ProtocolSchedule protocolSchedule = genesisConfig.getProtocolSchedule(); + final GenesisConfigFile genesisConfigFile = GenesisConfigFile.development(); + final ProtocolSchedule protocolSchedule = + DevelopmentProtocolSchedule.create(genesisConfigFile.getConfigOptions()); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule); final BlockHashFunction blockHashFunction = ScheduleBasedBlockHashFunction.create(protocolSchedule); final MutableBlockchain blockchain = - createInMemoryBlockchain(genesisConfig.getBlock(), blockHashFunction); + createInMemoryBlockchain(genesisState.getBlock(), blockHashFunction); final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); - genesisConfig.writeStateTo(worldStateArchive.getMutable()); + genesisState.writeStateTo(worldStateArchive.getMutable()); final ProtocolContext protocolContext = new ProtocolContext<>(blockchain, worldStateArchive, null); final EthProtocolManager ethProtocolManager = new EthProtocolManager(blockchain, 1, false, 1); diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java index 8cb5fa702e..6e316a62cb 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java @@ -12,8 +12,8 @@ */ package tech.pegasys.pantheon.ethereum.jsonrpc; -import tech.pegasys.pantheon.config.GenesisConfigOptions; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.config.GenesisConfigFile; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction; @@ -29,7 +29,7 @@ import java.util.List; /** Creates a block chain from a genesis and a blocks files. */ public class BlockchainImporter { - private final GenesisConfig genesisConfig; + private final GenesisState genesisState; private final ProtocolSchedule protocolSchedule; @@ -39,7 +39,8 @@ public class BlockchainImporter { public BlockchainImporter(final URL blocksUrl, final String genesisJson) throws Exception { protocolSchedule = - MainnetProtocolSchedule.fromConfig(GenesisConfigOptions.fromGenesisConfig(genesisJson)); + MainnetProtocolSchedule.fromConfig( + GenesisConfigFile.fromConfig(genesisJson).getConfigOptions()); blocks = new ArrayList<>(); try (final RawBlockIterator iterator = @@ -52,11 +53,11 @@ public class BlockchainImporter { } genesisBlock = blocks.get(0); - genesisConfig = GenesisConfig.fromJson(genesisJson, protocolSchedule); + genesisState = GenesisState.fromJson(genesisJson, protocolSchedule); } - public GenesisConfig getGenesisConfig() { - return genesisConfig; + public GenesisState getGenesisState() { + return genesisState; } public ProtocolSchedule getProtocolSchedule() { diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java index 3f23027ea6..4d685b1180 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java @@ -49,10 +49,10 @@ public class JsonRpcTestMethodsFactory { this.importer = importer; } - public Map methods(final int chainId) { + public Map methods() { final WorldStateArchive stateArchive = InMemoryTestFixture.createInMemoryWorldStateArchive(); - importer.getGenesisConfig().writeStateTo(stateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); + importer.getGenesisState().writeStateTo(stateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); final MutableBlockchain blockchain = InMemoryTestFixture.createInMemoryBlockchain(importer.getGenesisBlock()); @@ -79,7 +79,6 @@ public class JsonRpcTestMethodsFactory { return new JsonRpcMethodsFactory() .methods( CLIENT_VERSION, - chainId, peerDiscovery, blockchainQueries, synchronizer, diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthCallIntegrationTest.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthCallIntegrationTest.java index 04bd37583a..1629dc621c 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthCallIntegrationTest.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthCallIntegrationTest.java @@ -37,7 +37,6 @@ import org.junit.Test; public class EthCallIntegrationTest { - private static final int CHAIN_ID = 123; private static JsonRpcTestMethodsFactory BLOCKCHAIN; private JsonRpcMethod method; @@ -64,7 +63,7 @@ public class EthCallIntegrationTest { @Before public void setUp() { - final Map methods = BLOCKCHAIN.methods(CHAIN_ID); + final Map methods = BLOCKCHAIN.methods(); method = methods.get("eth_call"); } diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthEstimateGasIntegrationTest.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthEstimateGasIntegrationTest.java index 427f9efbf2..271fb558f5 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthEstimateGasIntegrationTest.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthEstimateGasIntegrationTest.java @@ -33,7 +33,6 @@ import org.junit.Test; public class EthEstimateGasIntegrationTest { - private static final int CHAIN_ID = 123; private static JsonRpcTestMethodsFactory BLOCKCHAIN; private JsonRpcMethod method; @@ -60,7 +59,7 @@ public class EthEstimateGasIntegrationTest { @Before public void setUp() { - final Map methods = BLOCKCHAIN.methods(CHAIN_ID); + final Map methods = BLOCKCHAIN.methods(); method = methods.get("eth_estimateGas"); } diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByHashIntegrationTest.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByHashIntegrationTest.java index 7f39a1c063..fed4dda077 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByHashIntegrationTest.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByHashIntegrationTest.java @@ -58,7 +58,6 @@ public class EthGetBlockByHashIntegrationTest { private Map methods; private static JsonRpcTestMethodsFactory BLOCKCHAIN; private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils(); - private static final int CHAIN_ID = 123; private final String ETH_METHOD = "eth_getBlockByHash"; private final String JSON_RPC_VERSION = "2.0"; private final String ZERO_HASH = String.valueOf(Hash.ZERO); @@ -85,7 +84,7 @@ public class EthGetBlockByHashIntegrationTest { @Before public void setUp() { - methods = BLOCKCHAIN.methods(CHAIN_ID); + methods = BLOCKCHAIN.methods(); } @Test diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByNumberIntegrationTest.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByNumberIntegrationTest.java index d662cf6e2d..06df52e1ec 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByNumberIntegrationTest.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByNumberIntegrationTest.java @@ -59,7 +59,6 @@ import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class EthGetBlockByNumberIntegrationTest { - private static final int CHAIN_ID = 123; private static final String ETH_METHOD = "eth_getBlockByNumber"; private static final String JSON_RPC_VERSION = "2.0"; private static JsonRpcTestMethodsFactory BLOCKCHAIN; @@ -89,7 +88,7 @@ public class EthGetBlockByNumberIntegrationTest { @Before public void setUp() { - methods = BLOCKCHAIN.methods(CHAIN_ID); + methods = BLOCKCHAIN.methods(); } @Test diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java index 8572ee8b21..7390ecc264 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java @@ -19,21 +19,19 @@ import static org.assertj.core.api.Assertions.assertThat; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.BlockBody; import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; -import tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture; +import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture; import tech.pegasys.pantheon.ethereum.core.PendingTransactions; import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.TransactionPool; import tech.pegasys.pantheon.ethereum.core.TransactionPool.TransactionBatchAddedListener; import tech.pegasys.pantheon.ethereum.core.TransactionReceipt; import tech.pegasys.pantheon.ethereum.core.Wei; -import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterIdGenerator; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterManager; @@ -75,18 +73,17 @@ public class EthGetFilterChangesIntegrationTest { @Before public void setUp() { - final GenesisConfig genesisConfig = GenesisConfig.mainnet(); - final Block genesisBlock = genesisConfig.getBlock(); - blockchain = InMemoryTestFixture.createInMemoryBlockchain(genesisBlock); - final WorldStateArchive worldStateArchive = - InMemoryTestFixture.createInMemoryWorldStateArchive(); - final ProtocolContext protocolContext = - new ProtocolContext<>(blockchain, worldStateArchive, null); + final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create(); + blockchain = executionContext.getBlockchain(); + final ProtocolContext protocolContext = executionContext.getProtocolContext(); transactionPool = new TransactionPool( - transactions, genesisConfig.getProtocolSchedule(), protocolContext, batchAddedListener); + transactions, + executionContext.getProtocolSchedule(), + protocolContext, + batchAddedListener); final BlockchainQueries blockchainQueries = - new BlockchainQueries(blockchain, worldStateArchive); + new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive()); filterManager = new FilterManager( blockchainQueries, transactionPool, new FilterIdGenerator(), new FilterRepository()); diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockHashAndIndexIntegrationTest.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockHashAndIndexIntegrationTest.java index 63f77fe4d1..b61d1312b2 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockHashAndIndexIntegrationTest.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockHashAndIndexIntegrationTest.java @@ -52,7 +52,6 @@ import org.junit.Test; public class EthGetUncleByBlockHashAndIndexIntegrationTest { - private static final int CHAIN_ID = 123; private static JsonRpcTestMethodsFactory BLOCKCHAIN; private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils(); @@ -80,7 +79,7 @@ public class EthGetUncleByBlockHashAndIndexIntegrationTest { @Before public void setUp() { - method = BLOCKCHAIN.methods(CHAIN_ID).get("eth_getUncleByBlockHashAndIndex"); + method = BLOCKCHAIN.methods().get("eth_getUncleByBlockHashAndIndex"); } @Test diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockNumberAndIndexIntegrationTest.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockNumberAndIndexIntegrationTest.java index 46f1f4555c..ed2b219d1a 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockNumberAndIndexIntegrationTest.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockNumberAndIndexIntegrationTest.java @@ -52,7 +52,6 @@ import org.junit.Test; public class EthGetUncleByBlockNumberAndIndexIntegrationTest { - private static final int CHAIN_ID = 123; private static JsonRpcTestMethodsFactory BLOCKCHAIN; private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils(); @@ -80,7 +79,7 @@ public class EthGetUncleByBlockNumberAndIndexIntegrationTest { @Before public void setUp() { - method = BLOCKCHAIN.methods(CHAIN_ID).get("eth_getUncleByBlockNumberAndIndex"); + method = BLOCKCHAIN.methods().get("eth_getUncleByBlockNumberAndIndex"); } @Test diff --git a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcMethodsFactory.java b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcMethodsFactory.java index ffb6bf5da9..c38ef427fe 100644 --- a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcMethodsFactory.java +++ b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcMethodsFactory.java @@ -88,7 +88,6 @@ public class JsonRpcMethodsFactory { public Map methods( final String clientVersion, - final int chainId, final P2PNetwork peerNetworkingService, final Blockchain blockchain, final WorldStateArchive worldStateArchive, @@ -103,7 +102,6 @@ public class JsonRpcMethodsFactory { new BlockchainQueries(blockchain, worldStateArchive); return methods( clientVersion, - chainId, peerNetworkingService, blockchainQueries, synchronizer, @@ -117,7 +115,6 @@ public class JsonRpcMethodsFactory { public Map methods( final String clientVersion, - final int chainId, final P2PNetwork p2pNetwork, final BlockchainQueries blockchainQueries, final Synchronizer synchronizer, @@ -180,7 +177,7 @@ public class JsonRpcMethodsFactory { new EthProtocolVersion(supportedCapabilities), new EthGasPrice(miningCoordinator), new EthGetWork(miningCoordinator), - new EthChainId(chainId)); + new EthChainId(protocolSchedule.getChainId())); } if (rpcApis.contains(RpcApis.DEBUG)) { final BlockReplay blockReplay = @@ -197,7 +194,7 @@ public class JsonRpcMethodsFactory { if (rpcApis.contains(RpcApis.NET)) { addMethods( enabledMethods, - new NetVersion(chainId), + new NetVersion(protocolSchedule.getChainId()), new NetListening(p2pNetwork), new NetPeerCount(p2pNetwork), new AdminPeers(p2pNetwork)); diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java index cddb041bcd..8a3977772d 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java @@ -21,7 +21,7 @@ import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMe import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMiningCoordinator; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.BlockHeader; @@ -78,7 +78,7 @@ public abstract class AbstractEthJsonRpcHttpServiceTest { protected static Block GENESIS_BLOCK; - protected static GenesisConfig GENESIS_CONFIG; + protected static GenesisState GENESIS_CONFIG; protected final Vertx vertx = Vertx.vertx(); @@ -92,8 +92,6 @@ public abstract class AbstractEthJsonRpcHttpServiceTest { protected final String CLIENT_VERSION = "TestClientVersion/0.1.0"; - protected final int NET_VERSION = 123; - protected static final Collection JSON_RPC_APIS = Arrays.asList(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3); @@ -135,7 +133,7 @@ public abstract class AbstractEthJsonRpcHttpServiceTest { final String gensisjson = Resources.toString(genesisJsonUrl, Charsets.UTF_8); GENESIS_BLOCK = BLOCKS.get(0); - GENESIS_CONFIG = GenesisConfig.fromJson(gensisjson, PROTOCOL_SCHEDULE); + GENESIS_CONFIG = GenesisState.fromJson(gensisjson, PROTOCOL_SCHEDULE); } @Before @@ -170,7 +168,6 @@ public abstract class AbstractEthJsonRpcHttpServiceTest { new JsonRpcMethodsFactory() .methods( CLIENT_VERSION, - NET_VERSION, peerDiscoveryMock, blockchainQueries, synchronizerMock, diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java index dfbb1be539..a38d0ceac4 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java @@ -61,7 +61,6 @@ public class JsonRpcHttpServiceRpcApisTest { private static String baseUrl; private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); private static final String CLIENT_VERSION = "TestClientVersion/0.1.0"; - private static final int NET_VERSION = 123; private JsonRpcConfiguration configuration; @Mock protected static BlockchainQueries blockchainQueries; @@ -170,7 +169,6 @@ public class JsonRpcHttpServiceRpcApisTest { new JsonRpcMethodsFactory() .methods( CLIENT_VERSION, - NET_VERSION, mock(P2PNetwork.class), blockchainQueries, mock(Synchronizer.class), diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java index 926132e856..b15794721f 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java @@ -87,7 +87,7 @@ public class JsonRpcHttpServiceTest { protected static String baseUrl; protected static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); protected static final String CLIENT_VERSION = "TestClientVersion/0.1.0"; - protected static final int NET_VERSION = 123; + protected static final int CHAIN_ID = 123; protected static P2PNetwork peerDiscoveryMock; protected static BlockchainQueries blockchainQueries; protected static Synchronizer synchronizer; @@ -110,11 +110,10 @@ public class JsonRpcHttpServiceTest { new JsonRpcMethodsFactory() .methods( CLIENT_VERSION, - NET_VERSION, peerDiscoveryMock, blockchainQueries, synchronizer, - MainnetProtocolSchedule.create(), + MainnetProtocolSchedule.create(0, 0, 0, 0, 0, 0, CHAIN_ID), mock(FilterManager.class), mock(TransactionPool.class), mock(EthHashMiningCoordinator.class), @@ -266,7 +265,7 @@ public class JsonRpcHttpServiceTest { testHelper.assertValidJsonRpcResult(json, id); // Check result final String result = json.getString("result"); - assertThat(result).isEqualTo(String.valueOf(NET_VERSION)); + assertThat(result).isEqualTo(String.valueOf(CHAIN_ID)); } } @@ -1544,7 +1543,7 @@ public class JsonRpcHttpServiceTest { // Check result net_version final JsonObject jsonNetVersion = responses.get(netVersionRequestId); testHelper.assertValidJsonRpcResult(jsonNetVersion, netVersionRequestId); - assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(NET_VERSION)); + assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(CHAIN_ID)); } } @@ -1600,7 +1599,7 @@ public class JsonRpcHttpServiceTest { // Check result net_version final JsonObject jsonNetVersion = responses.get(netVersionRequestId); testHelper.assertValidJsonRpcResult(jsonNetVersion, netVersionRequestId); - assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(NET_VERSION)); + assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(CHAIN_ID)); } } @@ -1661,7 +1660,7 @@ public class JsonRpcHttpServiceTest { // Check result net_version final JsonObject jsonNetVersion = responses.get(netVersionRequestId); testHelper.assertValidJsonRpcResult(jsonNetVersion, netVersionRequestId); - assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(NET_VERSION)); + assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(CHAIN_ID)); } } diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java index dacdaf3e71..b01d73c3fe 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java @@ -149,7 +149,6 @@ public class RunnerBuilder { jsonRpcMethods( context, protocolSchedule, - pantheonController, networkRunner, synchronizer, transactionPool, @@ -167,7 +166,6 @@ public class RunnerBuilder { jsonRpcMethods( context, protocolSchedule, - pantheonController, networkRunner, synchronizer, transactionPool, @@ -212,7 +210,6 @@ public class RunnerBuilder { private Map jsonRpcMethods( final ProtocolContext context, final ProtocolSchedule protocolSchedule, - final PantheonController pantheonController, final NetworkRunner networkRunner, final Synchronizer synchronizer, final TransactionPool transactionPool, @@ -224,7 +221,6 @@ public class RunnerBuilder { new JsonRpcMethodsFactory() .methods( PantheonInfo.version(), - pantheonController.getGenesisConfig().getChainId(), networkRunner.getNetwork(), context.getBlockchain(), context.getWorldStateArchive(), diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java index d4c56ff1c0..14688a6210 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java @@ -15,11 +15,12 @@ package tech.pegasys.pantheon.cli; import static java.nio.charset.StandardCharsets.UTF_8; import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.controller.MainnetPantheonController; import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.core.MiningParameters; +import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule; import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import java.io.IOException; @@ -41,9 +42,11 @@ public class PantheonControllerBuilder { // otherwise use the indicated genesis file final KeyPair nodeKeys = loadKeyPair(homePath); if (isDevMode) { + final GenesisConfigFile genesisConfig = GenesisConfigFile.development(); return MainnetPantheonController.init( homePath, - GenesisConfig.development(), + genesisConfig, + DevelopmentProtocolSchedule.create(genesisConfig.getConfigOptions()), synchronizerConfiguration, miningParameters, nodeKeys); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java index d0ca5fd834..63debc2eb1 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java @@ -15,7 +15,10 @@ package tech.pegasys.pantheon.controller; import static org.apache.logging.log4j.LogManager.getLogger; import tech.pegasys.pantheon.config.CliqueConfigOptions; +import tech.pegasys.pantheon.config.GenesisConfigFile; +import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.consensus.clique.CliqueContext; +import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule; import tech.pegasys.pantheon.consensus.clique.CliqueVoteTallyUpdater; import tech.pegasys.pantheon.consensus.clique.VoteTallyCache; import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueBlockScheduler; @@ -26,7 +29,7 @@ import tech.pegasys.pantheon.consensus.common.VoteProposer; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.Hash; @@ -65,7 +68,8 @@ import org.apache.logging.log4j.Logger; public class CliquePantheonController implements PantheonController { private static final Logger LOG = getLogger(); - private final GenesisConfig genesisConfig; + private final GenesisConfigOptions genesisConfigOptions; + private final ProtocolSchedule protocolSchedule; private final ProtocolContext context; private final Synchronizer synchronizer; private final ProtocolManager ethProtocolManager; @@ -76,7 +80,8 @@ public class CliquePantheonController implements PantheonController genesisConfig, + final GenesisConfigOptions genesisConfigOptions, + final ProtocolSchedule protocolSchedule, final ProtocolContext context, final ProtocolManager ethProtocolManager, final Synchronizer synchronizer, @@ -85,7 +90,8 @@ public class CliquePantheonController implements PantheonController init( final Path home, - final GenesisConfig genesisConfig, + final GenesisConfigFile genesisConfig, final SynchronizerConfiguration taintedSyncConfig, final MiningParameters miningParams, - final CliqueConfigOptions cliqueConfig, final int networkId, final KeyPair nodeKeys) throws IOException { + final CliqueConfigOptions cliqueConfig = + genesisConfig.getConfigOptions().getCliqueConfigOptions(); final long blocksPerEpoch = cliqueConfig.getEpochLength(); final long secondsBetweenBlocks = cliqueConfig.getBlockPeriodSeconds(); final EpochManager epochManger = new EpochManager(blocksPerEpoch); final KeyValueStorage kv = RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH))); - final ProtocolSchedule protocolSchedule = genesisConfig.getProtocolSchedule(); - + final ProtocolSchedule protocolSchedule = + CliqueProtocolSchedule.create(genesisConfig.getConfigOptions(), nodeKeys); final BlockHashFunction blockHashFunction = ScheduleBasedBlockHashFunction.create(protocolSchedule); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction); final MutableBlockchain blockchain = - new DefaultMutableBlockchain(genesisConfig.getBlock(), blockchainStorage); + new DefaultMutableBlockchain(genesisState.getBlock(), blockchainStorage); final KeyValueStorageWorldStateStorage worldStateStorage = new KeyValueStorageWorldStateStorage(kv); final WorldStateArchive worldStateArchive = new WorldStateArchive(worldStateStorage); - genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); + genesisState.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); final ProtocolContext protocolContext = new ProtocolContext<>( @@ -139,9 +147,9 @@ public class CliquePantheonController implements PantheonController getGenesisConfig() { - return genesisConfig; + public ProtocolSchedule getProtocolSchedule() { + return protocolSchedule; + } + + @Override + public GenesisConfigOptions getGenesisConfigOptions() { + return genesisConfigOptions; } @Override diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java index bcaebe3645..67f36af604 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java @@ -14,6 +14,8 @@ package tech.pegasys.pantheon.controller; import static org.apache.logging.log4j.LogManager.getLogger; +import tech.pegasys.pantheon.config.GenesisConfigFile; +import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.config.IbftConfigOptions; import tech.pegasys.pantheon.consensus.common.EpochManager; import tech.pegasys.pantheon.consensus.common.VoteProposer; @@ -26,13 +28,14 @@ import tech.pegasys.pantheon.consensus.ibft.IbftStateMachine; import tech.pegasys.pantheon.consensus.ibft.network.IbftNetworkPeers; import tech.pegasys.pantheon.consensus.ibft.protocol.IbftProtocolManager; import tech.pegasys.pantheon.consensus.ibft.protocol.IbftSubProtocol; +import tech.pegasys.pantheon.consensus.ibftlegacy.IbftProtocolSchedule; import tech.pegasys.pantheon.consensus.ibftlegacy.IbftVoteTallyUpdater; import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64Protocol; import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64ProtocolManager; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.Hash; @@ -69,7 +72,8 @@ import org.apache.logging.log4j.Logger; public class IbftPantheonController implements PantheonController { private static final Logger LOG = getLogger(); - private final GenesisConfig genesisConfig; + private final GenesisConfigOptions genesisConfig; + private final ProtocolSchedule protocolSchedule; private final ProtocolContext context; private final Synchronizer synchronizer; private final SubProtocol ethSubProtocol; @@ -81,7 +85,8 @@ public class IbftPantheonController implements PantheonController { private final Runnable closer; IbftPantheonController( - final GenesisConfig genesisConfig, + final GenesisConfigOptions genesisConfig, + final ProtocolSchedule protocolSchedule, final ProtocolContext context, final SubProtocol ethSubProtocol, final ProtocolManager ethProtocolManager, @@ -93,6 +98,7 @@ public class IbftPantheonController implements PantheonController { final Runnable closer) { this.genesisConfig = genesisConfig; + this.protocolSchedule = protocolSchedule; this.context = context; this.ethSubProtocol = ethSubProtocol; this.ethProtocolManager = ethProtocolManager; @@ -106,29 +112,30 @@ public class IbftPantheonController implements PantheonController { public static PantheonController init( final Path home, - final GenesisConfig genesisConfig, + final GenesisConfigFile genesisConfig, final SynchronizerConfiguration taintedSyncConfig, final boolean ottomanTestnetOperation, - final IbftConfigOptions ibftConfig, final int networkId, final KeyPair nodeKeys) throws IOException { final KeyValueStorage kv = RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH))); - final ProtocolSchedule protocolSchedule = genesisConfig.getProtocolSchedule(); - + final ProtocolSchedule protocolSchedule = + IbftProtocolSchedule.create(genesisConfig.getConfigOptions()); final BlockHashFunction blockHashFunction = ScheduleBasedBlockHashFunction.create(protocolSchedule); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction); final MutableBlockchain blockchain = - new DefaultMutableBlockchain(genesisConfig.getBlock(), blockchainStorage); + new DefaultMutableBlockchain(genesisState.getBlock(), blockchainStorage); final KeyValueStorageWorldStateStorage worldStateStorage = new KeyValueStorageWorldStateStorage(kv); final WorldStateArchive worldStateArchive = new WorldStateArchive(worldStateStorage); - genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); + genesisState.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); + final IbftConfigOptions ibftConfig = genesisConfig.getConfigOptions().getIbftConfigOptions(); final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength()); final VoteTally voteTally = @@ -149,11 +156,18 @@ public class IbftPantheonController implements PantheonController { ethSubProtocol = Istanbul64Protocol.get(); ethProtocolManager = new Istanbul64ProtocolManager( - protocolContext.getBlockchain(), networkId, fastSyncEnabled, 1); + protocolContext.getBlockchain(), + networkId, + fastSyncEnabled, + syncConfig.downloaderParallelism()); } else { ethSubProtocol = EthProtocol.get(); ethProtocolManager = - new EthProtocolManager(protocolContext.getBlockchain(), networkId, fastSyncEnabled, 1); + new EthProtocolManager( + protocolContext.getBlockchain(), + networkId, + fastSyncEnabled, + syncConfig.downloaderParallelism()); } final SyncState syncState = new SyncState( @@ -200,7 +214,8 @@ public class IbftPantheonController implements PantheonController { new IbftNetworkPeers(protocolContext.getConsensusState().getVoteTally()); return new IbftPantheonController( - genesisConfig, + genesisConfig.getConfigOptions(), + protocolSchedule, protocolContext, ethSubProtocol, ethProtocolManager, @@ -218,7 +233,12 @@ public class IbftPantheonController implements PantheonController { } @Override - public GenesisConfig getGenesisConfig() { + public ProtocolSchedule getProtocolSchedule() { + return protocolSchedule; + } + + @Override + public GenesisConfigOptions getGenesisConfigOptions() { return genesisConfig; } diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java index f7605c47c3..944c4a94aa 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java @@ -14,13 +14,15 @@ package tech.pegasys.pantheon.controller; import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; +import tech.pegasys.pantheon.config.GenesisConfigFile; +import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.DefaultBlockScheduler; import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMinerExecutor; import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMiningCoordinator; import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.Hash; @@ -38,6 +40,7 @@ import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState; import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHeaderValidator; +import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction; import tech.pegasys.pantheon.ethereum.p2p.api.ProtocolManager; @@ -61,7 +64,8 @@ public class MainnetPantheonController implements PantheonController { private static final Logger LOG = LogManager.getLogger(); - private final GenesisConfig genesisConfig; + private final GenesisConfigFile genesisConfig; + private final ProtocolSchedule protocolSchedule; private final ProtocolContext protocolContext; private final ProtocolManager ethProtocolManager; private final KeyPair keyPair; @@ -72,7 +76,8 @@ public class MainnetPantheonController implements PantheonController { private final Runnable close; public MainnetPantheonController( - final GenesisConfig genesisConfig, + final GenesisConfigFile genesisConfig, + final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final ProtocolManager ethProtocolManager, final Synchronizer synchronizer, @@ -81,6 +86,7 @@ public class MainnetPantheonController implements PantheonController { final MiningCoordinator miningCoordinator, final Runnable close) { this.genesisConfig = genesisConfig; + this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.ethProtocolManager = ethProtocolManager; this.synchronizer = synchronizer; @@ -95,7 +101,8 @@ public class MainnetPantheonController implements PantheonController { final KeyPair nodeKeys = loadKeyPair(home); return init( home, - GenesisConfig.mainnet(), + GenesisConfigFile.mainnet(), + MainnetProtocolSchedule.create(), SynchronizerConfiguration.builder().build(), miningParams, nodeKeys); @@ -103,25 +110,26 @@ public class MainnetPantheonController implements PantheonController { public static PantheonController init( final Path home, - final GenesisConfig genesisConfig, + final GenesisConfigFile genesisConfig, + final ProtocolSchedule protocolSchedule, final SynchronizerConfiguration taintedSyncConfig, final MiningParameters miningParams, final KeyPair nodeKeys) throws IOException { + + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); final KeyValueStorage kv = RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH))); - final ProtocolSchedule protocolSchedule = genesisConfig.getProtocolSchedule(); - final BlockHashFunction blockHashFunction = ScheduleBasedBlockHashFunction.create(protocolSchedule); final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage = new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction); final MutableBlockchain blockchain = - new DefaultMutableBlockchain(genesisConfig.getBlock(), blockchainStorage); + new DefaultMutableBlockchain(genesisState.getBlock(), blockchainStorage); final WorldStateArchive worldStateArchive = new WorldStateArchive(new KeyValueStorageWorldStateStorage(kv)); - genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); + genesisState.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); final ProtocolContext protocolContext = new ProtocolContext<>(blockchain, worldStateArchive, null); @@ -131,7 +139,10 @@ public class MainnetPantheonController implements PantheonController { final EthProtocolManager ethProtocolManager = new EthProtocolManager( protocolContext.getBlockchain(), - genesisConfig.getChainId(), + genesisConfig + .getConfigOptions() + .getChainId() + .orElse(MainnetProtocolSchedule.DEFAULT_CHAIN_ID), fastSyncEnabled, syncConfig.downloaderParallelism()); final SyncState syncState = @@ -171,6 +182,7 @@ public class MainnetPantheonController implements PantheonController { return new MainnetPantheonController( genesisConfig, + protocolSchedule, protocolContext, ethProtocolManager, synchronizer, @@ -199,8 +211,13 @@ public class MainnetPantheonController implements PantheonController { } @Override - public GenesisConfig getGenesisConfig() { - return genesisConfig; + public ProtocolSchedule getProtocolSchedule() { + return protocolSchedule; + } + + @Override + public GenesisConfigOptions getGenesisConfigOptions() { + return genesisConfig.getConfigOptions(); } @Override diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java index 0fc330a9f4..f0445d3f7c 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java @@ -12,13 +12,11 @@ */ package tech.pegasys.pantheon.controller; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.config.GenesisConfigOptions; -import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule; -import tech.pegasys.pantheon.consensus.ibftlegacy.IbftProtocolSchedule; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.core.MiningParameters; import tech.pegasys.pantheon.ethereum.core.Synchronizer; import tech.pegasys.pantheon.ethereum.core.TransactionPool; @@ -31,8 +29,6 @@ import java.io.Closeable; import java.io.IOException; import java.nio.file.Path; -import io.vertx.core.json.JsonObject; - public interface PantheonController extends Closeable { String DATABASE_PATH = "database"; @@ -47,46 +43,33 @@ public interface PantheonController extends Closeable { final KeyPair nodeKeys) throws IOException { - final JsonObject config = new JsonObject(configContents); - final GenesisConfigOptions configOptions = GenesisConfigOptions.fromGenesisConfig(config); + final GenesisConfigFile config = GenesisConfigFile.fromConfig(configContents); + final GenesisConfigOptions configOptions = config.getConfigOptions(); if (configOptions.isEthHash()) { return MainnetPantheonController.init( pantheonHome, - GenesisConfig.fromConfig(config, MainnetProtocolSchedule.fromConfig(configOptions)), + config, + MainnetProtocolSchedule.fromConfig(configOptions), syncConfig, miningParameters, nodeKeys); } else if (configOptions.isIbft()) { return IbftPantheonController.init( - pantheonHome, - GenesisConfig.fromConfig(config, IbftProtocolSchedule.create(configOptions)), - syncConfig, - ottomanTestnetOperation, - configOptions.getIbftConfigOptions(), - networkId, - nodeKeys); + pantheonHome, config, syncConfig, ottomanTestnetOperation, networkId, nodeKeys); } else if (configOptions.isClique()) { return CliquePantheonController.init( - pantheonHome, - GenesisConfig.fromConfig(config, CliqueProtocolSchedule.create(configOptions, nodeKeys)), - syncConfig, - miningParameters, - configOptions.getCliqueConfigOptions(), - networkId, - nodeKeys); + pantheonHome, config, syncConfig, miningParameters, networkId, nodeKeys); } else { throw new IllegalArgumentException("Unknown consensus mechanism defined"); } } - default ProtocolSchedule getProtocolSchedule() { - return getGenesisConfig().getProtocolSchedule(); - } - ProtocolContext getProtocolContext(); - GenesisConfig getGenesisConfig(); + ProtocolSchedule getProtocolSchedule(); + + GenesisConfigOptions getGenesisConfigOptions(); Synchronizer getSynchronizer(); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/util/BlockImporter.java b/pantheon/src/main/java/tech/pegasys/pantheon/util/BlockImporter.java index 74c3181af0..38dfc47502 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/util/BlockImporter.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/util/BlockImporter.java @@ -18,7 +18,6 @@ import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator; import tech.pegasys.pantheon.ethereum.blockcreation.BlockMiner; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.BlockHeader; @@ -55,7 +54,6 @@ public class BlockImporter { final Path blocks, final PantheonController pantheonController) throws IOException { final ProtocolSchedule protocolSchedule = pantheonController.getProtocolSchedule(); final ProtocolContext context = pantheonController.getProtocolContext(); - final GenesisConfig genesis = pantheonController.getGenesisConfig(); try (final RawBlockIterator iterator = new RawBlockIterator( @@ -69,7 +67,7 @@ public class BlockImporter { while (iterator.hasNext()) { final Block block = iterator.next(); final BlockHeader header = block.getHeader(); - if (header.getNumber() == genesis.getBlock().getHeader().getNumber()) { + if (header.getNumber() == BlockHeader.GENESIS_BLOCK_NUMBER) { continue; } if (header.getNumber() % 100 == 0) { diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java index 0cd9ace49a..3984adfb81 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java @@ -15,11 +15,11 @@ package tech.pegasys.pantheon; import static org.assertj.core.api.Assertions.assertThat; import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; +import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.controller.MainnetPantheonController; import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; -import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.BlockImporter; import tech.pegasys.pantheon.ethereum.core.BlockSyncTestUtils; @@ -29,6 +29,7 @@ import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration; import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration; import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode; +import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer; @@ -93,7 +94,8 @@ public final class RunnerTest { try (final PantheonController controller = MainnetPantheonController.init( dbAhead, - GenesisConfig.mainnet(), + GenesisConfigFile.mainnet(), + MainnetProtocolSchedule.create(), fastSyncConfig, new MiningParametersTestBuilder().enabled(false).build(), aheadDbNodeKeys)) { @@ -104,7 +106,8 @@ public final class RunnerTest { final PantheonController controllerAhead = MainnetPantheonController.init( dbAhead, - GenesisConfig.mainnet(), + GenesisConfigFile.mainnet(), + MainnetProtocolSchedule.create(), fastSyncConfig, new MiningParametersTestBuilder().enabled(false).build(), aheadDbNodeKeys); @@ -137,7 +140,8 @@ public final class RunnerTest { final PantheonController controllerBehind = MainnetPantheonController.init( temp.newFolder().toPath(), - GenesisConfig.mainnet(), + GenesisConfigFile.mainnet(), + MainnetProtocolSchedule.create(), fastSyncConfig, new MiningParametersTestBuilder().enabled(false).build(), behindDbNodeKeys);