Split parsing of genesis config from creating initial state (#209)

* Make GenesisConfigFile responsible for handling all the content in the genesis config file and rename GenesisConfig to GenesisState as it is now just responsible for creating the initial state at genesis.

* In CliqueProtocolController, pass the network ID to EthProtocolManager instead of the chain ID and use  downloader parallelism setting instead of network ID for the number of threads.
Adrian Sutton 6 years ago committed by GitHub
parent b020029802
commit 5566eb36d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      config/build.gradle
  2. 6
      config/src/main/java/tech/pegasys/pantheon/config/CliqueConfigOptions.java
  3. 33
      config/src/main/java/tech/pegasys/pantheon/config/GenesisAllocation.java
  4. 137
      config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigFile.java
  5. 26
      config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigOptions.java
  6. 8
      config/src/main/java/tech/pegasys/pantheon/config/IbftConfigOptions.java
  7. 0
      config/src/main/resources/dev.json
  8. 0
      config/src/main/resources/mainnet.json
  9. 0
      config/src/main/resources/rinkeby.json
  10. 0
      config/src/main/resources/ropsten.json
  11. 7
      config/src/test/java/tech/pegasys/pantheon/config/CliqueConfigOptionsTest.java
  12. 176
      config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigFileTest.java
  13. 6
      config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigOptionsTest.java
  14. 9
      config/src/test/java/tech/pegasys/pantheon/config/IbftConfigOptionsTest.java
  15. 6
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java
  16. 12
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecs.java
  17. 3
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java
  18. 5
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSpecsTest.java
  19. 21
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  20. 3
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java
  21. 3
      consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java
  22. 5
      consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java
  23. 1
      ethereum/blockcreation/build.gradle
  24. 2
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMinerTest.java
  25. 4
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java
  26. 16
      ethereum/core/src/integration-test/java/tech/pegasys/pantheon/ethereum/vm/TraceTransactionIntegrationTest.java
  27. 334
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisConfig.java
  28. 223
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/GenesisState.java
  29. 11
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolSchedule.java
  30. 8
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java
  31. 10
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MutableProtocolSchedule.java
  32. 2
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolSchedule.java
  33. 10
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java
  34. 32
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java
  35. 16
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/core/TransactionPoolTest.java
  36. 6
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/development/DevelopmentProtocolScheduleTest.java
  37. 8
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockProcessorTest.java
  38. 6
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java
  39. 8
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleTest.java
  40. 10
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java
  41. 3
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java
  42. 1
      ethereum/eth/build.gradle
  43. 10
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java
  44. 22
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java
  45. 7
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java
  46. 5
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java
  47. 5
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java
  48. 14
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java
  49. 15
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java
  50. 5
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java
  51. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthCallIntegrationTest.java
  52. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthEstimateGasIntegrationTest.java
  53. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByHashIntegrationTest.java
  54. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetBlockByNumberIntegrationTest.java
  55. 21
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetFilterChangesIntegrationTest.java
  56. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockHashAndIndexIntegrationTest.java
  57. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/EthGetUncleByBlockNumberAndIndexIntegrationTest.java
  58. 7
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcMethodsFactory.java
  59. 9
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java
  60. 2
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java
  61. 13
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java
  62. 4
      pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java
  63. 7
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java
  64. 44
      pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java
  65. 46
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java
  66. 41
      pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java
  67. 37
      pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java
  68. 4
      pantheon/src/main/java/tech/pegasys/pantheon/util/BlockImporter.java
  69. 12
      pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java

@ -24,6 +24,7 @@ jar {
dependencies { dependencies {
implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'io.vertx:vertx-core' implementation 'io.vertx:vertx-core'
implementation 'com.google.guava:guava'
implementation 'org.apache.logging.log4j:log4j-api' implementation 'org.apache.logging.log4j:log4j-api'
runtime 'org.apache.logging.log4j:log4j-core' runtime 'org.apache.logging.log4j:log4j-core'

@ -23,15 +23,15 @@ public class CliqueConfigOptions {
private final JsonObject cliqueConfigRoot; private final JsonObject cliqueConfigRoot;
public CliqueConfigOptions(final JsonObject cliqueConfigRoot) { CliqueConfigOptions(final JsonObject cliqueConfigRoot) {
this.cliqueConfigRoot = cliqueConfigRoot; this.cliqueConfigRoot = cliqueConfigRoot;
} }
public long getEpochLength() { public long getEpochLength() {
return cliqueConfigRoot.getLong("epochLength", DEFAULT_EPOCH_LENGTH); return cliqueConfigRoot.getLong("epochlength", DEFAULT_EPOCH_LENGTH);
} }
public int getBlockPeriodSeconds() { public int getBlockPeriodSeconds() {
return cliqueConfigRoot.getInteger("blockPeriodSeconds", DEFAULT_BLOCK_PERIOD_SECONDS); return cliqueConfigRoot.getInteger("blockperiodseconds", DEFAULT_BLOCK_PERIOD_SECONDS);
} }
} }

@ -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");
}
}

@ -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<GenesisAllocation> 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<String> 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<String, Object> 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<String, Object>) value)));
} else {
normalized.put(normalizedKey, value);
}
});
return new JsonObject(normalized);
}
}

@ -24,18 +24,10 @@ public class GenesisConfigOptions {
private static final String CLIQUE_CONFIG_KEY = "clique"; private static final String CLIQUE_CONFIG_KEY = "clique";
private final JsonObject configRoot; private final JsonObject configRoot;
private GenesisConfigOptions(final JsonObject configRoot) { GenesisConfigOptions(final JsonObject configRoot) {
this.configRoot = configRoot != null ? configRoot : new JsonObject(); 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() { public boolean isEthHash() {
return configRoot.containsKey(ETHASH_CONFIG_KEY); return configRoot.containsKey(ETHASH_CONFIG_KEY);
} }
@ -61,32 +53,32 @@ public class GenesisConfigOptions {
} }
public OptionalLong getHomesteadBlockNumber() { public OptionalLong getHomesteadBlockNumber() {
return getOptionalLong("homesteadBlock"); return getOptionalLong("homesteadblock");
} }
public OptionalLong getDaoForkBlock() { public OptionalLong getDaoForkBlock() {
return getOptionalLong("daoForkBlock"); return getOptionalLong("daoforkblock");
} }
public OptionalLong getTangerineWhistleBlockNumber() { public OptionalLong getTangerineWhistleBlockNumber() {
return getOptionalLong("eip150Block"); return getOptionalLong("eip150block");
} }
public OptionalLong getSpuriousDragonBlockNumber() { public OptionalLong getSpuriousDragonBlockNumber() {
return getOptionalLong("eip158Block"); return getOptionalLong("eip158block");
} }
public OptionalLong getByzantiumBlockNumber() { public OptionalLong getByzantiumBlockNumber() {
return getOptionalLong("byzantiumBlock"); return getOptionalLong("byzantiumblock");
} }
public OptionalLong getConstantinopleBlockNumber() { public OptionalLong getConstantinopleBlockNumber() {
return getOptionalLong("constantinopleBlock"); return getOptionalLong("constantinopleblock");
} }
public OptionalInt getChainId() { public OptionalInt getChainId() {
return configRoot.containsKey("chainId") return configRoot.containsKey("chainid")
? OptionalInt.of(configRoot.getInteger("chainId")) ? OptionalInt.of(configRoot.getInteger("chainid"))
: OptionalInt.empty(); : OptionalInt.empty();
} }

@ -24,19 +24,19 @@ public class IbftConfigOptions {
private final JsonObject ibftConfigRoot; private final JsonObject ibftConfigRoot;
public IbftConfigOptions(final JsonObject ibftConfigRoot) { IbftConfigOptions(final JsonObject ibftConfigRoot) {
this.ibftConfigRoot = ibftConfigRoot; this.ibftConfigRoot = ibftConfigRoot;
} }
public long getEpochLength() { public long getEpochLength() {
return ibftConfigRoot.getLong("epochLength", DEFAULT_EPOCH_LENGTH); return ibftConfigRoot.getLong("epochlength", DEFAULT_EPOCH_LENGTH);
} }
public int getBlockPeriodSeconds() { public int getBlockPeriodSeconds() {
return ibftConfigRoot.getInteger("blockPeriodSeconds", DEFAULT_BLOCK_PERIOD_SECONDS); return ibftConfigRoot.getInteger("blockperiodseconds", DEFAULT_BLOCK_PERIOD_SECONDS);
} }
public int getRequestTimeoutMillis() { public int getRequestTimeoutMillis() {
return ibftConfigRoot.getInteger("requestTimeout", DEFAULT_ROUND_EXPIRY_MILLISECONDS); return ibftConfigRoot.getInteger("requesttimeout", DEFAULT_ROUND_EXPIRY_MILLISECONDS);
} }
} }

@ -28,7 +28,7 @@ public class CliqueConfigOptionsTest {
@Test @Test
public void shouldGetEpochLengthFromConfig() { 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); assertThat(config.getEpochLength()).isEqualTo(10_000);
} }
@ -46,7 +46,7 @@ public class CliqueConfigOptionsTest {
@Test @Test
public void shouldGetBlockPeriodFromConfig() { public void shouldGetBlockPeriodFromConfig() {
final CliqueConfigOptions config = fromConfigOptions(singletonMap("blockPeriodSeconds", 5)); final CliqueConfigOptions config = fromConfigOptions(singletonMap("BlockPeriodSeconds", 5));
assertThat(config.getBlockPeriodSeconds()).isEqualTo(5); assertThat(config.getBlockPeriodSeconds()).isEqualTo(5);
} }
@ -63,8 +63,9 @@ public class CliqueConfigOptionsTest {
} }
private CliqueConfigOptions fromConfigOptions(final Map<String, Object> cliqueConfigOptions) { private CliqueConfigOptions fromConfigOptions(final Map<String, Object> cliqueConfigOptions) {
return GenesisConfigOptions.fromGenesisConfig( return GenesisConfigFile.fromConfig(
new JsonObject(singletonMap("config", singletonMap("clique", cliqueConfigOptions)))) new JsonObject(singletonMap("config", singletonMap("clique", cliqueConfigOptions))))
.getConfigOptions()
.getCliqueConfigOptions(); .getCliqueConfigOptions();
} }
} }

@ -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<String, String> 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");
}
}

@ -120,7 +120,7 @@ public class GenesisConfigOptionsTest {
@Test @Test
public void shouldSupportEmptyGenesisConfig() { public void shouldSupportEmptyGenesisConfig() {
final GenesisConfigOptions config = GenesisConfigOptions.fromGenesisConfig("{}"); final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions();
assertThat(config.isEthHash()).isFalse(); assertThat(config.isEthHash()).isFalse();
assertThat(config.isIbft()).isFalse(); assertThat(config.isIbft()).isFalse();
assertThat(config.isClique()).isFalse(); assertThat(config.isClique()).isFalse();
@ -128,7 +128,7 @@ public class GenesisConfigOptionsTest {
} }
private GenesisConfigOptions fromConfigOptions(final Map<String, Object> options) { private GenesisConfigOptions fromConfigOptions(final Map<String, Object> options) {
return GenesisConfigOptions.fromGenesisConfig( return GenesisConfigFile.fromConfig(new JsonObject(Collections.singletonMap("config", options)))
new JsonObject(Collections.singletonMap("config", options))); .getConfigOptions();
} }
} }

@ -29,7 +29,7 @@ public class IbftConfigOptionsTest {
@Test @Test
public void shouldGetEpochLengthFromConfig() { 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); assertThat(config.getEpochLength()).isEqualTo(10_000);
} }
@ -46,7 +46,7 @@ public class IbftConfigOptionsTest {
@Test @Test
public void shouldGetBlockPeriodFromConfig() { public void shouldGetBlockPeriodFromConfig() {
final IbftConfigOptions config = fromConfigOptions(singletonMap("blockPeriodSeconds", 5)); final IbftConfigOptions config = fromConfigOptions(singletonMap("BlockPeriodSeconds", 5));
assertThat(config.getBlockPeriodSeconds()).isEqualTo(5); assertThat(config.getBlockPeriodSeconds()).isEqualTo(5);
} }
@ -64,7 +64,7 @@ public class IbftConfigOptionsTest {
@Test @Test
public void shouldGetRequestTimeoutFromConfig() { public void shouldGetRequestTimeoutFromConfig() {
final IbftConfigOptions config = fromConfigOptions(singletonMap("requestTimeout", 5)); final IbftConfigOptions config = fromConfigOptions(singletonMap("RequestTimeout", 5));
assertThat(config.getRequestTimeoutMillis()).isEqualTo(5); assertThat(config.getRequestTimeoutMillis()).isEqualTo(5);
} }
@ -81,8 +81,9 @@ public class IbftConfigOptionsTest {
} }
private IbftConfigOptions fromConfigOptions(final Map<String, Object> ibftConfigOptions) { private IbftConfigOptions fromConfigOptions(final Map<String, Object> ibftConfigOptions) {
return GenesisConfigOptions.fromGenesisConfig( return GenesisConfigFile.fromConfig(
new JsonObject(singletonMap("config", singletonMap("ibft", ibftConfigOptions)))) new JsonObject(singletonMap("config", singletonMap("ibft", ibftConfigOptions))))
.getConfigOptions()
.getIbftConfigOptions(); .getIbftConfigOptions();
} }
} }

@ -20,7 +20,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
/** Defines the protocol behaviours for a blockchain using Clique. */ /** Defines the protocol behaviours for a blockchain using Clique. */
public class CliqueProtocolSchedule extends MutableProtocolSchedule<CliqueContext> { public class CliqueProtocolSchedule {
private static final int DEFAULT_CHAIN_ID = 4; private static final int DEFAULT_CHAIN_ID = 4;
@ -33,14 +33,14 @@ public class CliqueProtocolSchedule extends MutableProtocolSchedule<CliqueContex
final long blockPeriod = cliqueConfig.getBlockPeriodSeconds(); final long blockPeriod = cliqueConfig.getBlockPeriodSeconds();
final int chainId = config.getChainId().orElse(DEFAULT_CHAIN_ID); final int chainId = config.getChainId().orElse(DEFAULT_CHAIN_ID);
final MutableProtocolSchedule<CliqueContext> protocolSchedule = new CliqueProtocolSchedule(); final MutableProtocolSchedule<CliqueContext> protocolSchedule =
new MutableProtocolSchedule<>(chainId);
// TODO(tmm) replace address with passed in node data (coming later) // TODO(tmm) replace address with passed in node data (coming later)
final CliqueProtocolSpecs specs = final CliqueProtocolSpecs specs =
new CliqueProtocolSpecs( new CliqueProtocolSpecs(
blockPeriod, blockPeriod,
epochLength, epochLength,
chainId,
Util.publicKeyToAddress(nodeKeys.getPublicKey()), Util.publicKeyToAddress(nodeKeys.getPublicKey()),
protocolSchedule); protocolSchedule);

@ -29,19 +29,16 @@ public class CliqueProtocolSpecs {
private final long secondsBetweenBlocks; private final long secondsBetweenBlocks;
private final long epochLength; private final long epochLength;
private final int chainId;
private final Address localNodeAddress; private final Address localNodeAddress;
private final ProtocolSchedule<CliqueContext> protocolSchedule; private final ProtocolSchedule<CliqueContext> protocolSchedule;
public CliqueProtocolSpecs( public CliqueProtocolSpecs(
final long secondsBetweenBlocks, final long secondsBetweenBlocks,
final long epochLength, final long epochLength,
final int chainId,
final Address localNodeAddress, final Address localNodeAddress,
final ProtocolSchedule<CliqueContext> protocolSchedule) { final ProtocolSchedule<CliqueContext> protocolSchedule) {
this.secondsBetweenBlocks = secondsBetweenBlocks; this.secondsBetweenBlocks = secondsBetweenBlocks;
this.epochLength = epochLength; this.epochLength = epochLength;
this.chainId = chainId;
this.localNodeAddress = localNodeAddress; this.localNodeAddress = localNodeAddress;
this.protocolSchedule = protocolSchedule; this.protocolSchedule = protocolSchedule;
} }
@ -59,15 +56,18 @@ public class CliqueProtocolSpecs {
} }
public ProtocolSpec<CliqueContext> spuriousDragon() { public ProtocolSpec<CliqueContext> spuriousDragon() {
return applyCliqueSpecificModifications(MainnetProtocolSpecs.spuriousDragonDefinition(chainId)); return applyCliqueSpecificModifications(
MainnetProtocolSpecs.spuriousDragonDefinition(protocolSchedule.getChainId()));
} }
public ProtocolSpec<CliqueContext> byzantium() { public ProtocolSpec<CliqueContext> byzantium() {
return applyCliqueSpecificModifications(MainnetProtocolSpecs.byzantiumDefinition(chainId)); return applyCliqueSpecificModifications(
MainnetProtocolSpecs.byzantiumDefinition(protocolSchedule.getChainId()));
} }
public ProtocolSpec<CliqueContext> constantinople() { public ProtocolSpec<CliqueContext> constantinople() {
return applyCliqueSpecificModifications(MainnetProtocolSpecs.constantinopleDefinition(chainId)); return applyCliqueSpecificModifications(
MainnetProtocolSpecs.constantinopleDefinition(protocolSchedule.getChainId()));
} }
private ProtocolSpec<CliqueContext> applyCliqueSpecificModifications( private ProtocolSpec<CliqueContext> applyCliqueSpecificModifications(

@ -14,6 +14,7 @@ package tech.pegasys.pantheon.consensus.clique;
import static org.assertj.core.api.Java6Assertions.assertThat; import static org.assertj.core.api.Java6Assertions.assertThat;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.config.GenesisConfigOptions;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
@ -35,7 +36,7 @@ public class CliqueProtocolScheduleTest {
+ "\"byzantiumBlock\": 1035301}" + "\"byzantiumBlock\": 1035301}"
+ "}"; + "}";
final GenesisConfigOptions config = GenesisConfigOptions.fromGenesisConfig(jsonInput); final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions();
final ProtocolSchedule<CliqueContext> protocolSchedule = final ProtocolSchedule<CliqueContext> protocolSchedule =
CliqueProtocolSchedule.create(config, KeyPair.generate()); CliqueProtocolSchedule.create(config, KeyPair.generate());

@ -25,9 +25,10 @@ import org.junit.Test;
public class CliqueProtocolSpecsTest { public class CliqueProtocolSpecsTest {
private static final int CHAIN_ID = 5;
CliqueProtocolSpecs protocolSpecs = CliqueProtocolSpecs protocolSpecs =
new CliqueProtocolSpecs( new CliqueProtocolSpecs(
15, 30_000, 5, AddressHelpers.ofValue(5), new MutableProtocolSchedule<>()); 15, 30_000, AddressHelpers.ofValue(5), new MutableProtocolSchedule<>(CHAIN_ID));
@Test @Test
public void homsteadParametersAlignWithMainnetWithAdjustments() { public void homsteadParametersAlignWithMainnetWithAdjustments() {
@ -40,7 +41,7 @@ public class CliqueProtocolSpecsTest {
@Test @Test
public void allSpecsInheritFromMainnetCounterparts() { public void allSpecsInheritFromMainnetCounterparts() {
final ProtocolSchedule<Void> mainnetProtocolSchedule = new MutableProtocolSchedule<>(); final ProtocolSchedule<Void> mainnetProtocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
assertThat(protocolSpecs.frontier().getName()) assertThat(protocolSpecs.frontier().getName())
.isEqualTo(MainnetProtocolSpecs.frontier(mainnetProtocolSchedule).getName()); .isEqualTo(MainnetProtocolSpecs.frontier(mainnetProtocolSchedule).getName());

@ -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.createInMemoryBlockchain;
import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; 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.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueExtraData; import tech.pegasys.pantheon.consensus.clique.CliqueExtraData;
import tech.pegasys.pantheon.consensus.clique.CliqueHelpers; 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.CliqueProtocolSpecs;
import tech.pegasys.pantheon.consensus.clique.TestHelpers; import tech.pegasys.pantheon.consensus.clique.TestHelpers;
import tech.pegasys.pantheon.consensus.clique.VoteTallyCache; 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.consensus.common.VoteType;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.AddressHelpers; import tech.pegasys.pantheon.ethereum.core.AddressHelpers;
@ -53,29 +53,25 @@ import org.junit.Test;
public class CliqueBlockCreatorTest { public class CliqueBlockCreatorTest {
private static final int CHAIN_ID = 1;
private final KeyPair proposerKeyPair = KeyPair.generate(); private final KeyPair proposerKeyPair = KeyPair.generate();
private final Address proposerAddress = Util.publicKeyToAddress(proposerKeyPair.getPublicKey()); private final Address proposerAddress = Util.publicKeyToAddress(proposerKeyPair.getPublicKey());
private final KeyPair otherKeyPair = KeyPair.generate(); private final KeyPair otherKeyPair = KeyPair.generate();
private final List<Address> validatorList = Lists.newArrayList(); private final List<Address> validatorList = Lists.newArrayList();
private final Block genesis = GenesisConfig.mainnet().getBlock(); private final MutableProtocolSchedule<CliqueContext> protocolSchedule =
private final MutableBlockchain blockchain = createInMemoryBlockchain(genesis); new MutableProtocolSchedule<>(CHAIN_ID);
private final WorldStateArchive stateArchive = createInMemoryWorldStateArchive(); private final WorldStateArchive stateArchive = createInMemoryWorldStateArchive();
private MutableBlockchain blockchain;
private ProtocolContext<CliqueContext> protocolContext; private ProtocolContext<CliqueContext> protocolContext;
private final MutableProtocolSchedule<CliqueContext> protocolSchedule =
new CliqueProtocolSchedule();
private VoteProposer voteProposer; private VoteProposer voteProposer;
@Before @Before
public void setup() { public void setup() {
final CliqueProtocolSpecs specs = final CliqueProtocolSpecs specs =
new CliqueProtocolSpecs( new CliqueProtocolSpecs(
15, 15, 30_000, Util.publicKeyToAddress(proposerKeyPair.getPublicKey()), protocolSchedule);
30_000,
1,
Util.publicKeyToAddress(proposerKeyPair.getPublicKey()),
protocolSchedule);
protocolSchedule.putMilestone(0, specs.frontier()); protocolSchedule.putMilestone(0, specs.frontier());
@ -87,6 +83,9 @@ public class CliqueBlockCreatorTest {
voteProposer = new VoteProposer(); voteProposer = new VoteProposer();
final CliqueContext cliqueContext = new CliqueContext(voteTallyCache, voteProposer, null); 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); protocolContext = new ProtocolContext<>(blockchain, stateArchive, cliqueContext);
// Add a block above the genesis // Add a block above the genesis

@ -17,6 +17,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.config.GenesisConfigOptions;
import tech.pegasys.pantheon.consensus.clique.CliqueContext; import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueExtraData; import tech.pegasys.pantheon.consensus.clique.CliqueExtraData;
@ -49,7 +50,7 @@ import org.junit.Test;
public class CliqueMinerExecutorTest { public class CliqueMinerExecutorTest {
private static final GenesisConfigOptions GENESIS_CONFIG_OPTIONS = private static final GenesisConfigOptions GENESIS_CONFIG_OPTIONS =
GenesisConfigOptions.fromGenesisConfig(new JsonObject()); GenesisConfigFile.fromConfig(new JsonObject()).getConfigOptions();
private final KeyPair proposerKeyPair = KeyPair.generate(); private final KeyPair proposerKeyPair = KeyPair.generate();
private Address localAddress; private Address localAddress;
private final List<Address> validatorList = Lists.newArrayList(); private final List<Address> validatorList = Lists.newArrayList();

@ -30,7 +30,8 @@ public class IbftProtocolSchedule {
final long epochLength = ibftConfig.getEpochLength(); final long epochLength = ibftConfig.getEpochLength();
final long blockPeriod = ibftConfig.getBlockPeriodSeconds(); final long blockPeriod = ibftConfig.getBlockPeriodSeconds();
final MutableProtocolSchedule<IbftContext> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<IbftContext> protocolSchedule =
new MutableProtocolSchedule<>(chainId);
protocolSchedule.putMilestone( protocolSchedule.putMilestone(
spuriousDragonBlock, spuriousDragonBlock,
IbftProtocolSpecs.spuriousDragon(blockPeriod, epochLength, chainId, protocolSchedule)); IbftProtocolSpecs.spuriousDragon(blockPeriod, epochLength, chainId, protocolSchedule));

@ -18,7 +18,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; 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.VoteProposer;
import tech.pegasys.pantheon.consensus.common.VoteTally; import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.consensus.ibft.IbftContext; import tech.pegasys.pantheon.consensus.ibft.IbftContext;
@ -78,7 +78,8 @@ public class IbftBlockCreatorTest {
final ProtocolSchedule<IbftContext> protocolSchedule = final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create( IbftProtocolSchedule.create(
GenesisConfigOptions.fromGenesisConfig("{\"config\": {\"spuriousDragonBlock\":0}}")); GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}")
.getConfigOptions());
final ProtocolContext<IbftContext> protContext = final ProtocolContext<IbftContext> protContext =
new ProtocolContext<>( new ProtocolContext<>(
blockchain, blockchain,

@ -12,6 +12,7 @@ dependencies {
implementation project(':ethereum:core') implementation project(':ethereum:core')
implementation project(':ethereum:eth') implementation project(':ethereum:eth')
implementation project(':util') implementation project(':util')
implementation project(':config')
implementation project(':crypto') implementation project(':crypto')
implementation project(':services:kvstore') implementation project(':services:kvstore')

@ -124,7 +124,7 @@ public class BlockMinerTest {
} }
private ProtocolSchedule<Void> singleSpecSchedule(final ProtocolSpec<Void> protocolSpec) { private ProtocolSchedule<Void> singleSpecSchedule(final ProtocolSpec<Void> protocolSpec) {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(1234);
protocolSchedule.putMilestone(0, protocolSpec); protocolSchedule.putMilestone(0, protocolSpec);
return protocolSchedule; return protocolSchedule;
} }

@ -19,6 +19,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.NONCE_TOO_LOW; 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.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.chain.Blockchain; import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
@ -53,7 +54,6 @@ import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import io.vertx.core.json.JsonObject;
import org.junit.Test; import org.junit.Test;
public class BlockTransactionSelectorTest { public class BlockTransactionSelectorTest {
@ -63,7 +63,7 @@ public class BlockTransactionSelectorTest {
@Test @Test
public void emptyPendingTransactionsResultsInEmptyVettingResult() { public void emptyPendingTransactionsResultsInEmptyVettingResult() {
final ProtocolSchedule<Void> protocolSchedule = final ProtocolSchedule<Void> protocolSchedule =
DevelopmentProtocolSchedule.create(new JsonObject()); DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions());
final Blockchain blockchain = new TestBlockchain(); final Blockchain blockchain = new TestBlockchain();
final TransactionProcessor transactionProcessor = final TransactionProcessor transactionProcessor =
protocolSchedule.getByBlockNumber(0).getTransactionProcessor(); protocolSchedule.getByBlockNumber(0).getTransactionProcessor();

@ -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.assertThat;
import static org.assertj.core.api.Assertions.entry; 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.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Account; import tech.pegasys.pantheon.ethereum.core.Account;
import tech.pegasys.pantheon.ethereum.core.Block; 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.Gas;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.MutableWorldState; import tech.pegasys.pantheon.ethereum.core.MutableWorldState;
import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.Transaction;
import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.core.Wei;
@ -63,12 +60,11 @@ public class TraceTransactionIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
final GenesisConfig<Void> genesisConfig = GenesisConfig.development(); final ExecutionContextTestFixture contextTestFixture = ExecutionContextTestFixture.create();
genesisBlock = genesisConfig.getBlock(); genesisBlock = contextTestFixture.getGenesis();
blockchain = createInMemoryBlockchain(genesisBlock); blockchain = contextTestFixture.getBlockchain();
worldStateArchive = createInMemoryWorldStateArchive(); worldStateArchive = contextTestFixture.getStateArchive();
final ProtocolSchedule<Void> protocolSchedule = genesisConfig.getProtocolSchedule(); final ProtocolSchedule<Void> protocolSchedule = contextTestFixture.getProtocolSchedule();
genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH));
transactionProcessor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor(); transactionProcessor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor();
blockHashLookup = new BlockHashLookup(genesisBlock.getHeader(), blockchain); blockHashLookup = new BlockHashLookup(genesisBlock.getHeader(), blockchain);
} }

@ -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<C> {
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<C> protocolSchedule;
private final List<GenesisAccount> genesisAccounts;
private GenesisConfig(
final Block block,
final int chainId,
final ProtocolSchedule<C> protocolSchedule,
final List<GenesisAccount> genesisAccounts) {
this.block = block;
this.chainId = chainId;
this.protocolSchedule = protocolSchedule;
this.genesisAccounts = genesisAccounts;
}
public static GenesisConfig<Void> 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<Void> 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 <C> The consensus context type
* @return A new genesis block.
*/
public static <C> GenesisConfig<C> fromJson(
final String json, final ProtocolSchedule<C> 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 <C> The consensus context type
* @return A new genesis block.
*/
@SuppressWarnings("unchecked")
public static <C> GenesisConfig<C> fromConfig(
final JsonObject jsonConfig, final ProtocolSchedule<C> protocolSchedule) {
final Map<String, Object> definition = toNormalizedMap(jsonConfig);
final List<GenesisAccount> 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<GenesisAccount> genesisAccounts) {
final WorldUpdater updater = target.updater();
genesisAccounts.forEach(
account -> updater.getOrCreate(account.address).setBalance(account.balance));
updater.commit();
target.persist();
}
public ProtocolSchedule<C> getProtocolSchedule() {
return protocolSchedule;
}
private static Hash calculateGenesisStateHash(final List<GenesisAccount> genesisAccounts) {
final MutableWorldState worldState =
new DefaultMutableWorldState(
new KeyValueStorageWorldStateStorage(new InMemoryKeyValueStorage()));
writeAccountsTo(worldState, genesisAccounts);
return worldState.rootHash();
}
private static <C> BlockHeader buildHeader(
final Map<String, Object> genesis,
final Hash genesisRootHash,
final ProtocolSchedule<C> 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<String, Object> toNormalizedMap(final JsonObject genesis) {
final Map<String, Object> 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<String, Object> map, final String key, final String def) {
return entryAsString(map.getOrDefault(key.toLowerCase(Locale.US), def));
}
private static String getString(final Map<String, Object> 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<String, Object> genesis) {
return Long.parseLong(getString(genesis, "timestamp", "0x0").substring(2), 16);
}
private static Address parseCoinbase(final Map<String, Object> 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<String, Object> genesis) {
return Hash.wrap(Bytes32.fromHexString(getString(genesis, "parentHash", "")));
}
private static BytesValue parseExtraData(final Map<String, Object> genesis) {
return BytesValue.fromHexString(getString(genesis, "extraData", ""));
}
private static UInt256 parseDifficulty(final Map<String, Object> genesis) {
return UInt256.fromHexString(getString(genesis, "difficulty"));
}
private static long parseGasLimit(final Map<String, Object> genesis) {
return Long.decode(getString(genesis, "gasLimit"));
}
private static Hash parseMixHash(final Map<String, Object> genesis) {
return Hash.wrap(Bytes32.fromHexString(getString(genesis, "mixHash", "")));
}
private static long parseNonce(final Map<String, Object> 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<GenesisAccount> parseAllocations(final Map<String, Object> genesis) {
final Map<String, Object> alloc = (Map<String, Object>) genesis.get("alloc");
return alloc
.entrySet()
.stream()
.map(
entry -> {
final Address address = Address.fromHexString(entry.getKey());
final String balance = getString((Map<String, Object>) 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();
}
}
}

@ -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<GenesisAccount> genesisAccounts;
private GenesisState(final Block block, final List<GenesisAccount> 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 <C> The consensus context type
* @return A new {@link GenesisState}.
*/
public static <C> GenesisState fromJson(
final String json, final ProtocolSchedule<C> 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 <C> The consensus context type
* @return A new {@link GenesisState}.
*/
@SuppressWarnings("unchecked")
public static <C> GenesisState fromConfig(
final GenesisConfigFile config, final ProtocolSchedule<C> protocolSchedule) {
final List<GenesisAccount> 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<GenesisAccount> 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<GenesisAccount> genesisAccounts) {
final MutableWorldState worldState =
new DefaultMutableWorldState(
new KeyValueStorageWorldStateStorage(new InMemoryKeyValueStorage()));
writeAccountsTo(worldState, genesisAccounts);
return worldState.rootHash();
}
private static <C> BlockHeader buildHeader(
final GenesisConfigFile genesis,
final Hash genesisRootHash,
final ProtocolSchedule<C> 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<GenesisAccount> 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();
}
}
}

@ -14,20 +14,19 @@ package tech.pegasys.pantheon.ethereum.development;
import static tech.pegasys.pantheon.ethereum.mainnet.MainnetTransactionValidator.NO_CHAIN_ID; 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.MutableProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; 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). * much reduced difficulty (which supports testing on CPU alone).
*/ */
public class DevelopmentProtocolSchedule { public class DevelopmentProtocolSchedule {
public static ProtocolSchedule<Void> create(final JsonObject config) { public static ProtocolSchedule<Void> create(final GenesisConfigOptions config) {
final Integer chainId = config.getInteger("chainId", NO_CHAIN_ID); final Integer chainId = config.getChainId().orElse(NO_CHAIN_ID);
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(chainId);
protocolSchedule.putMilestone(0, DevelopmentProtocolSpecs.first(chainId, protocolSchedule)); protocolSchedule.putMilestone(0, DevelopmentProtocolSpecs.first(chainId, protocolSchedule));
return protocolSchedule; return protocolSchedule;
} }

@ -14,8 +14,6 @@ package tech.pegasys.pantheon.ethereum.mainnet;
import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.config.GenesisConfigOptions;
import io.vertx.core.json.JsonObject;
/** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */ /** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */
public class MainnetProtocolSchedule { public class MainnetProtocolSchedule {
@ -49,7 +47,7 @@ public class MainnetProtocolSchedule {
final long constantinopleBlockNumber, final long constantinopleBlockNumber,
final int chainId) { final int chainId) {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(chainId);
protocolSchedule.putMilestone(0, MainnetProtocolSpecs.frontier(protocolSchedule)); protocolSchedule.putMilestone(0, MainnetProtocolSpecs.frontier(protocolSchedule));
final ProtocolSpec<Void> homestead = MainnetProtocolSpecs.homestead(protocolSchedule); final ProtocolSpec<Void> homestead = MainnetProtocolSpecs.homestead(protocolSchedule);
protocolSchedule.putMilestone(homesteadBlockNumber, homestead); protocolSchedule.putMilestone(homesteadBlockNumber, homestead);
@ -90,8 +88,8 @@ public class MainnetProtocolSchedule {
/** /**
* Create a Mainnet protocol schedule from a config object * Create a Mainnet protocol schedule from a config object
* *
* @param config {@link JsonObject} containing the config options for the milestone starting * @param config {@link GenesisConfigOptions} containing the config options for the milestone
* points * starting points
* @return A configured mainnet protocol schedule * @return A configured mainnet protocol schedule
*/ */
public static ProtocolSchedule<Void> fromConfig(final GenesisConfigOptions config) { public static ProtocolSchedule<Void> fromConfig(final GenesisConfigOptions config) {

@ -24,6 +24,16 @@ public class MutableProtocolSchedule<C> implements ProtocolSchedule<C> {
new TreeSet<>( new TreeSet<>(
Comparator.<ScheduledProtocolSpec<C>, Long>comparing(ScheduledProtocolSpec::getBlock) Comparator.<ScheduledProtocolSpec<C>, Long>comparing(ScheduledProtocolSpec::getBlock)
.reversed()); .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<C> protocolSpec) { public void putMilestone(final long blockNumber, final ProtocolSpec<C> protocolSpec) {
final ScheduledProtocolSpec<C> scheduledProtocolSpec = final ScheduledProtocolSpec<C> scheduledProtocolSpec =

@ -15,4 +15,6 @@ package tech.pegasys.pantheon.ethereum.mainnet;
public interface ProtocolSchedule<C> { public interface ProtocolSchedule<C> {
ProtocolSpec<C> getByBlockNumber(long number); ProtocolSpec<C> getByBlockNumber(long number);
int getChainId();
} }

@ -12,8 +12,9 @@
*/ */
package tech.pegasys.pantheon.ethereum.core; package tech.pegasys.pantheon.ethereum.core;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.ethereum.ProtocolContext; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.db.DefaultMutableBlockchain; import tech.pegasys.pantheon.ethereum.db.DefaultMutableBlockchain;
import tech.pegasys.pantheon.ethereum.db.KeyValueStoragePrefixedKeyBlockchainStorage; import tech.pegasys.pantheon.ethereum.db.KeyValueStoragePrefixedKeyBlockchainStorage;
@ -38,8 +39,9 @@ public class ExecutionContextTestFixture {
private ExecutionContextTestFixture( private ExecutionContextTestFixture(
final ProtocolSchedule<Void> protocolSchedule, final KeyValueStorage keyValueStorage) { final ProtocolSchedule<Void> protocolSchedule, final KeyValueStorage keyValueStorage) {
final GenesisConfig<Void> genesisConfig = GenesisConfig.mainnet(); final GenesisState genesisState =
this.genesis = genesisConfig.getBlock(); GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule);
this.genesis = genesisState.getBlock();
this.keyValueStorage = keyValueStorage; this.keyValueStorage = keyValueStorage;
this.blockchain = this.blockchain =
new DefaultMutableBlockchain( new DefaultMutableBlockchain(
@ -51,7 +53,7 @@ public class ExecutionContextTestFixture {
this.protocolSchedule = protocolSchedule; this.protocolSchedule = protocolSchedule;
this.protocolContext = new ProtocolContext<>(blockchain, stateArchive, null); this.protocolContext = new ProtocolContext<>(blockchain, stateArchive, null);
genesisConfig.writeStateTo( genesisState.writeStateTo(
new DefaultMutableWorldState(new KeyValueStorageWorldStateStorage(keyValueStorage))); new DefaultMutableWorldState(new KeyValueStorageWorldStateStorage(keyValueStorage)));
} }

@ -30,7 +30,7 @@ import com.google.common.io.Resources;
import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.encoders.Hex;
import org.junit.Test; import org.junit.Test;
public final class GenesisConfigTest { public final class GenesisStateTest {
/** Known RLP encoded bytes of the Olympic Genesis Block. */ /** Known RLP encoded bytes of the Olympic Genesis Block. */
private static final String OLYMPIC_RLP = private static final String OLYMPIC_RLP =
@ -42,12 +42,11 @@ public final class GenesisConfigTest {
@Test @Test
public void createFromJsonWithAllocs() throws Exception { public void createFromJsonWithAllocs() throws Exception {
final GenesisConfig<?> genesisConfig = final GenesisState genesisState =
GenesisConfig.fromJson( GenesisState.fromJson(
Resources.toString( Resources.toString(GenesisStateTest.class.getResource("genesis1.json"), Charsets.UTF_8),
GenesisConfigTest.class.getResource("genesis1.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create());
final BlockHeader header = genesisConfig.getBlock().getHeader(); final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getStateRoot()) assertThat(header.getStateRoot())
.isEqualTo( .isEqualTo(
Hash.fromHexString( Hash.fromHexString(
@ -60,7 +59,7 @@ public final class GenesisConfigTest {
final DefaultMutableWorldState worldState = final DefaultMutableWorldState worldState =
new DefaultMutableWorldState( new DefaultMutableWorldState(
new KeyValueStorageWorldStateStorage(new InMemoryKeyValueStorage())); new KeyValueStorageWorldStateStorage(new InMemoryKeyValueStorage()));
genesisConfig.writeStateTo(worldState); genesisState.writeStateTo(worldState);
final Account first = final Account first =
worldState.get(Address.fromHexString("0x0000000000000000000000000000000000000001")); worldState.get(Address.fromHexString("0x0000000000000000000000000000000000000001"));
final Account second = final Account second =
@ -73,12 +72,11 @@ public final class GenesisConfigTest {
@Test @Test
public void createFromJsonNoAllocs() throws Exception { public void createFromJsonNoAllocs() throws Exception {
final GenesisConfig<?> genesisConfig = final GenesisState genesisState =
GenesisConfig.fromJson( GenesisState.fromJson(
Resources.toString( Resources.toString(GenesisStateTest.class.getResource("genesis2.json"), Charsets.UTF_8),
GenesisConfigTest.class.getResource("genesis2.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create());
final BlockHeader header = genesisConfig.getBlock().getHeader(); final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getStateRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); assertThat(header.getStateRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH);
assertThat(header.getTransactionsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); assertThat(header.getTransactionsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH);
assertThat(header.getReceiptsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); assertThat(header.getReceiptsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH);
@ -89,14 +87,14 @@ public final class GenesisConfigTest {
@Test @Test
public void encodeOlympicBlock() throws Exception { public void encodeOlympicBlock() throws Exception {
final GenesisConfig<?> genesisConfig = final GenesisState genesisState =
GenesisConfig.fromJson( GenesisState.fromJson(
Resources.toString( Resources.toString(
GenesisConfigTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8), GenesisStateTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create());
final BytesValueRLPOutput tmp = new BytesValueRLPOutput(); final BytesValueRLPOutput tmp = new BytesValueRLPOutput();
genesisConfig.getBlock().writeTo(tmp); genesisState.getBlock().writeTo(tmp);
assertThat(Hex.toHexString(genesisConfig.getBlock().getHeader().getHash().extractArray())) assertThat(Hex.toHexString(genesisState.getBlock().getHeader().getHash().extractArray()))
.isEqualTo(OLYMPIC_HASH); .isEqualTo(OLYMPIC_HASH);
assertThat(Hex.toHexString(tmp.encoded().extractArray())).isEqualTo(OLYMPIC_RLP); assertThat(Hex.toHexString(tmp.encoded().extractArray())).isEqualTo(OLYMPIC_RLP);
} }

@ -28,18 +28,14 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when; 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.EXCEEDS_BLOCK_GAS_LIMIT;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.NONCE_TOO_LOW; import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.NONCE_TOO_LOW;
import static tech.pegasys.pantheon.ethereum.mainnet.ValidationResult.valid; import static tech.pegasys.pantheon.ethereum.mainnet.ValidationResult.valid;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.TransactionPool.TransactionBatchAddedListener; 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.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator; import tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator;
@ -77,16 +73,12 @@ public class TransactionPoolTest {
@Before @Before
public void setUp() { public void setUp() {
final GenesisConfig<Void> genesisConfig = GenesisConfig.development(); final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create();
final Block genesisBlock = genesisConfig.getBlock(); blockchain = executionContext.getBlockchain();
blockchain = createInMemoryBlockchain(genesisBlock); final ProtocolContext<Void> protocolContext = executionContext.getProtocolContext();
final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive();
final ProtocolContext<Void> protocolContext =
new ProtocolContext<>(blockchain, worldStateArchive, null);
genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH));
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(protocolSpec); when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(protocolSpec);
when(protocolSpec.getTransactionValidator()).thenReturn(transactionValidator); when(protocolSpec.getTransactionValidator()).thenReturn(transactionValidator);
genesisBlockGasLimit = genesisBlock.getHeader().getGasLimit(); genesisBlockGasLimit = executionContext.getGenesis().getHeader().getGasLimit();
transactionPool = transactionPool =
new TransactionPool(transactions, protocolSchedule, protocolContext, batchAddedListener); new TransactionPool(transactions, protocolSchedule, protocolContext, batchAddedListener);

@ -14,11 +14,11 @@ package tech.pegasys.pantheon.ethereum.development;
import static org.assertj.core.api.Assertions.assertThat; 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.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import io.vertx.core.json.JsonObject;
import org.junit.Test; import org.junit.Test;
public class DevelopmentProtocolScheduleTest { public class DevelopmentProtocolScheduleTest {
@ -26,8 +26,8 @@ public class DevelopmentProtocolScheduleTest {
@Test @Test
public void reportedDifficultyForAllBlocksIsAFixedValue() { public void reportedDifficultyForAllBlocksIsAFixedValue() {
final JsonObject config = new JsonObject(); final ProtocolSchedule<Void> schedule =
final ProtocolSchedule<Void> schedule = DevelopmentProtocolSchedule.create(config); DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions());
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();

@ -18,8 +18,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import tech.pegasys.pantheon.ethereum.chain.Blockchain; 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.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.MutableWorldState; import tech.pegasys.pantheon.ethereum.core.MutableWorldState;
import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.core.Wei;
@ -45,7 +45,11 @@ public class MainnetBlockProcessorTest {
final MutableWorldState worldState = WorldStateMock.create(emptyMap()); final MutableWorldState worldState = WorldStateMock.create(emptyMap());
final Hash initialHash = worldState.rootHash(); 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()); blockProcessor.processBlock(blockchain, worldState, emptyBlockHeader, emptyList(), emptyList());
// An empty block with 0 reward should not change the world state // An empty block with 0 reward should not change the world state

@ -12,7 +12,7 @@
*/ */
package tech.pegasys.pantheon.ethereum.mainnet; 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 io.vertx.core.json.JsonObject;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
@ -55,7 +55,7 @@ public class MainnetProtocolScheduleTest {
public void shouldReturnDefaultProtocolSpecsWhenEmptyJsonConfigIsUsed() { public void shouldReturnDefaultProtocolSpecsWhenEmptyJsonConfigIsUsed() {
final JsonObject json = new JsonObject("{}"); final JsonObject json = new JsonObject("{}");
final ProtocolSchedule<Void> sched = final ProtocolSchedule<Void> sched =
MainnetProtocolSchedule.fromConfig(GenesisConfigOptions.fromGenesisConfig(json)); MainnetProtocolSchedule.fromConfig(GenesisConfigFile.fromConfig(json).getConfigOptions());
Assertions.assertThat(sched.getByBlockNumber(1L).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(1L).getName()).isEqualTo("Frontier");
Assertions.assertThat(sched.getByBlockNumber(1_150_000L).getName()).isEqualTo("Homestead"); Assertions.assertThat(sched.getByBlockNumber(1_150_000L).getName()).isEqualTo("Homestead");
Assertions.assertThat(sched.getByBlockNumber(1_920_000L).getName()) Assertions.assertThat(sched.getByBlockNumber(1_920_000L).getName())
@ -76,7 +76,7 @@ public class MainnetProtocolScheduleTest {
new JsonObject( new JsonObject(
"{\"config\": {\"homesteadBlock\": 2, \"daoForkBlock\": 3, \"eip150Block\": 14, \"eip158Block\": 15, \"byzantiumBlock\": 16, \"constantinopleBlock\": 18, \"chainId\":1234}}"); "{\"config\": {\"homesteadBlock\": 2, \"daoForkBlock\": 3, \"eip150Block\": 14, \"eip158Block\": 15, \"byzantiumBlock\": 16, \"constantinopleBlock\": 18, \"chainId\":1234}}");
final ProtocolSchedule<Void> sched = final ProtocolSchedule<Void> sched =
MainnetProtocolSchedule.fromConfig(GenesisConfigOptions.fromGenesisConfig(json)); MainnetProtocolSchedule.fromConfig(GenesisConfigFile.fromConfig(json).getConfigOptions());
Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("Frontier");
Assertions.assertThat(sched.getByBlockNumber(2).getName()).isEqualTo("Homestead"); Assertions.assertThat(sched.getByBlockNumber(2).getName()).isEqualTo("Homestead");
Assertions.assertThat(sched.getByBlockNumber(3).getName()).isEqualTo("DaoRecoveryInit"); Assertions.assertThat(sched.getByBlockNumber(3).getName()).isEqualTo("DaoRecoveryInit");

@ -20,6 +20,8 @@ import org.junit.Test;
public class ProtocolScheduleTest { public class ProtocolScheduleTest {
private static final int CHAIN_ID = 1;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void getByBlockNumber() { public void getByBlockNumber() {
@ -28,7 +30,7 @@ public class ProtocolScheduleTest {
final ProtocolSpec<Void> spec3 = mock(ProtocolSpec.class); final ProtocolSpec<Void> spec3 = mock(ProtocolSpec.class);
final ProtocolSpec<Void> spec4 = mock(ProtocolSpec.class); final ProtocolSpec<Void> spec4 = mock(ProtocolSpec.class);
final MutableProtocolSchedule<Void> schedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> schedule = new MutableProtocolSchedule<>(CHAIN_ID);
schedule.putMilestone(20, spec3); schedule.putMilestone(20, spec3);
schedule.putMilestone(0, spec1); schedule.putMilestone(0, spec1);
schedule.putMilestone(30, spec4); schedule.putMilestone(30, spec4);
@ -42,7 +44,7 @@ public class ProtocolScheduleTest {
@Test @Test
public void emptySchedule() { 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"); .hasMessage("At least 1 milestone must be provided to the protocol schedule");
} }
@ -52,7 +54,7 @@ public class ProtocolScheduleTest {
final ProtocolSpec<Void> spec1 = mock(ProtocolSpec.class); final ProtocolSpec<Void> spec1 = mock(ProtocolSpec.class);
final ProtocolSpec<Void> spec2 = mock(ProtocolSpec.class); final ProtocolSpec<Void> spec2 = mock(ProtocolSpec.class);
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
protocolSchedule.putMilestone(0, spec1); protocolSchedule.putMilestone(0, spec1);
protocolSchedule.putMilestone(0, spec2); protocolSchedule.putMilestone(0, spec2);
assertThat(protocolSchedule.getByBlockNumber(0)).isSameAs(spec2); assertThat(protocolSchedule.getByBlockNumber(0)).isSameAs(spec2);

@ -63,27 +63,27 @@ public class ReferenceTestProtocolSchedules {
private static ProtocolSchedule<Void> createSchedule( private static ProtocolSchedule<Void> createSchedule(
final Function<ProtocolSchedule<Void>, ProtocolSpec<Void>> specCreator) { final Function<ProtocolSchedule<Void>, ProtocolSpec<Void>> specCreator) {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
protocolSchedule.putMilestone(0, specCreator.apply(protocolSchedule)); protocolSchedule.putMilestone(0, specCreator.apply(protocolSchedule));
return protocolSchedule; return protocolSchedule;
} }
private static ProtocolSchedule<Void> frontierToHomesteadAt5() { private static ProtocolSchedule<Void> frontierToHomesteadAt5() {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
protocolSchedule.putMilestone(0, MainnetProtocolSpecs.frontier(protocolSchedule)); protocolSchedule.putMilestone(0, MainnetProtocolSpecs.frontier(protocolSchedule));
protocolSchedule.putMilestone(5, MainnetProtocolSpecs.homestead(protocolSchedule)); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.homestead(protocolSchedule));
return protocolSchedule; return protocolSchedule;
} }
private static ProtocolSchedule<Void> homesteadToEip150At5() { private static ProtocolSchedule<Void> homesteadToEip150At5() {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
protocolSchedule.putMilestone(0, MainnetProtocolSpecs.homestead(protocolSchedule)); protocolSchedule.putMilestone(0, MainnetProtocolSpecs.homestead(protocolSchedule));
protocolSchedule.putMilestone(5, MainnetProtocolSpecs.tangerineWhistle(protocolSchedule)); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.tangerineWhistle(protocolSchedule));
return protocolSchedule; return protocolSchedule;
} }
private static ProtocolSchedule<Void> homesteadToDaoAt5() { private static ProtocolSchedule<Void> homesteadToDaoAt5() {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
final ProtocolSpec<Void> homestead = MainnetProtocolSpecs.homestead(protocolSchedule); final ProtocolSpec<Void> homestead = MainnetProtocolSpecs.homestead(protocolSchedule);
protocolSchedule.putMilestone(0, homestead); protocolSchedule.putMilestone(0, homestead);
protocolSchedule.putMilestone(5, MainnetProtocolSpecs.daoRecoveryInit(protocolSchedule)); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.daoRecoveryInit(protocolSchedule));
@ -93,7 +93,7 @@ public class ReferenceTestProtocolSchedules {
} }
private static ProtocolSchedule<Void> eip158ToByzantiumAt5() { private static ProtocolSchedule<Void> eip158ToByzantiumAt5() {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(); final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
protocolSchedule.putMilestone( protocolSchedule.putMilestone(
0, MainnetProtocolSpecs.spuriousDragon(CHAIN_ID, protocolSchedule)); 0, MainnetProtocolSpecs.spuriousDragon(CHAIN_ID, protocolSchedule));
protocolSchedule.putMilestone(5, MainnetProtocolSpecs.byzantium(CHAIN_ID, protocolSchedule)); protocolSchedule.putMilestone(5, MainnetProtocolSpecs.byzantium(CHAIN_ID, protocolSchedule));

@ -90,6 +90,7 @@ public class VMReferenceTest extends AbstractRetryingTest {
"CallToPrecompiledContract", "CallToPrecompiledContract",
"createNameRegistrator" "createNameRegistrator"
}; };
private static final int CHAIN_ID = 1;
private final String name; private final String name;
private final VMReferenceTestCaseSpec spec; private final VMReferenceTestCaseSpec spec;
@ -114,7 +115,7 @@ public class VMReferenceTest extends AbstractRetryingTest {
final EnvironmentInformation execEnv = spec.getExec(); final EnvironmentInformation execEnv = spec.getExec();
final ProtocolSpec<Void> protocolSpec = final ProtocolSpec<Void> protocolSpec =
MainnetProtocolSpecs.frontier(new MutableProtocolSchedule<>()); MainnetProtocolSpecs.frontier(new MutableProtocolSchedule<>(CHAIN_ID));
final TestBlockchain blockchain = new TestBlockchain(execEnv.getBlockHeader().getNumber()); final TestBlockchain blockchain = new TestBlockchain(execEnv.getBlockHeader().getNumber());
final MessageFrame frame = final MessageFrame frame =

@ -30,6 +30,7 @@ dependencies {
implementation 'io.vertx:vertx-core' implementation 'io.vertx:vertx-core'
implementation 'com.google.guava:guava' implementation 'com.google.guava:guava'
testImplementation project(':config')
testImplementation project(':crypto') testImplementation project(':crypto')
testImplementation project( path: ':ethereum:core', configuration: 'testArtifacts') testImplementation project( path: ':ethereum:core', configuration: 'testArtifacts')
testImplementation project( path: ':ethereum:core', configuration: 'testSupportArtifacts') testImplementation project( path: ':ethereum:core', configuration: 'testSupportArtifacts')

@ -14,11 +14,14 @@ package tech.pegasys.pantheon.ethereum.eth.manager;
import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryBlockchain; 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.Blockchain;
import tech.pegasys.pantheon.ethereum.chain.ChainHead; 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.EthProtocol;
import tech.pegasys.pantheon.ethereum.eth.manager.DeterministicEthScheduler.TimeoutPolicy; 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.api.MessageData;
import tech.pegasys.pantheon.ethereum.p2p.wire.DefaultMessage; import tech.pegasys.pantheon.ethereum.p2p.wire.DefaultMessage;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
@ -38,7 +41,10 @@ public class EthProtocolManagerTestUtil {
} }
public static EthProtocolManager create() { public static EthProtocolManager create() {
final Blockchain blockchain = createInMemoryBlockchain(GenesisConfig.mainnet().getBlock()); final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create();
final GenesisConfigFile config = GenesisConfigFile.mainnet();
final GenesisState genesisState = GenesisState.fromConfig(config, protocolSchedule);
final Blockchain blockchain = createInMemoryBlockchain(genesisState.getBlock());
return create(blockchain); return create(blockchain);
} }

@ -18,7 +18,7 @@ import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMe
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.chain.Blockchain; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction;
@ -46,7 +46,7 @@ import com.google.common.io.Resources;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
public class BlockchainSetupUtil<C> { public class BlockchainSetupUtil<C> {
private final GenesisConfig<C> genesisConfig; private final GenesisState genesisState;
private final MutableBlockchain blockchain; private final MutableBlockchain blockchain;
private final ProtocolContext<C> protocolContext; private final ProtocolContext<C> protocolContext;
private final ProtocolSchedule<C> protocolSchedule; private final ProtocolSchedule<C> protocolSchedule;
@ -55,13 +55,13 @@ public class BlockchainSetupUtil<C> {
private long maxBlockNumber; private long maxBlockNumber;
public BlockchainSetupUtil( public BlockchainSetupUtil(
final GenesisConfig<C> genesisConfig, final GenesisState genesisState,
final MutableBlockchain blockchain, final MutableBlockchain blockchain,
final ProtocolContext<C> protocolContext, final ProtocolContext<C> protocolContext,
final ProtocolSchedule<C> protocolSchedule, final ProtocolSchedule<C> protocolSchedule,
final WorldStateArchive worldArchive, final WorldStateArchive worldArchive,
final List<Block> blocks) { final List<Block> blocks) {
this.genesisConfig = genesisConfig; this.genesisState = genesisState;
this.blockchain = blockchain; this.blockchain = blockchain;
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule; this.protocolSchedule = protocolSchedule;
@ -97,13 +97,13 @@ public class BlockchainSetupUtil<C> {
try { try {
temp.create(); temp.create();
final URL genesisFileUrl = getResourceUrl(temp, "testGenesis.json"); final URL genesisFileUrl = getResourceUrl(temp, "testGenesis.json");
final GenesisConfig<Void> genesisConfig = final GenesisState genesisState =
GenesisConfig.fromJson( GenesisState.fromJson(
Resources.toString(genesisFileUrl, Charsets.UTF_8), protocolSchedule); Resources.toString(genesisFileUrl, Charsets.UTF_8), protocolSchedule);
final MutableBlockchain blockchain = createInMemoryBlockchain(genesisConfig.getBlock()); final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock());
final WorldStateArchive worldArchive = createInMemoryWorldStateArchive(); final WorldStateArchive worldArchive = createInMemoryWorldStateArchive();
genesisConfig.writeStateTo(worldArchive.getMutable()); genesisState.writeStateTo(worldArchive.getMutable());
final ProtocolContext<Void> protocolContext = final ProtocolContext<Void> protocolContext =
new ProtocolContext<>(blockchain, worldArchive, null); new ProtocolContext<>(blockchain, worldArchive, null);
@ -118,7 +118,7 @@ public class BlockchainSetupUtil<C> {
} }
} }
return new BlockchainSetupUtil<>( return new BlockchainSetupUtil<>(
genesisConfig, blockchain, protocolContext, protocolSchedule, worldArchive, blocks); genesisState, blockchain, protocolContext, protocolSchedule, worldArchive, blocks);
} catch (final IOException ex) { } catch (final IOException ex) {
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} finally { } finally {
@ -148,8 +148,8 @@ public class BlockchainSetupUtil<C> {
return maxBlockNumber; return maxBlockNumber;
} }
public GenesisConfig<C> getGenesisConfig() { public GenesisState getGenesisState() {
return genesisConfig; return genesisState;
} }
public MutableBlockchain getBlockchain() { public MutableBlockchain getBlockchain() {

@ -12,6 +12,7 @@
*/ */
package tech.pegasys.pantheon.ethereum.eth.messages; 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.BlockBody;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.Transaction;
@ -33,7 +34,6 @@ import java.util.List;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.vertx.core.json.JsonObject;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
@ -67,7 +67,10 @@ public final class BlockBodiesMessageTest {
final BlockBodiesMessage message = BlockBodiesMessage.readFrom(raw); final BlockBodiesMessage message = BlockBodiesMessage.readFrom(raw);
try { try {
final Iterator<BlockBody> readBodies = final Iterator<BlockBody> readBodies =
message.bodies(DevelopmentProtocolSchedule.create(new JsonObject())).iterator(); message
.bodies(
DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions()))
.iterator();
for (int i = 0; i < 50; ++i) { for (int i = 0; i < 50; ++i) {
Assertions.assertThat(readBodies.next()).isEqualTo(bodies.get(i)); Assertions.assertThat(readBodies.next()).isEqualTo(bodies.get(i));
} }

@ -12,6 +12,7 @@
*/ */
package tech.pegasys.pantheon.ethereum.eth.messages; 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.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule; import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction;
@ -31,7 +32,6 @@ import java.util.List;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.vertx.core.json.JsonObject;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
@ -61,7 +61,8 @@ public final class BlockHeadersMessageTest {
final BlockHeadersMessage message = BlockHeadersMessage.readFrom(raw); final BlockHeadersMessage message = BlockHeadersMessage.readFrom(raw);
try { try {
final Iterator<BlockHeader> readHeaders = final Iterator<BlockHeader> readHeaders =
message.getHeaders(DevelopmentProtocolSchedule.create(new JsonObject())); message.getHeaders(
DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions()));
for (int i = 0; i < 50; ++i) { for (int i = 0; i < 50; ++i) {
Assertions.assertThat(readHeaders.next()).isEqualTo(headers.get(i)); Assertions.assertThat(readHeaders.next()).isEqualTo(headers.get(i));
} }

@ -15,9 +15,10 @@ package tech.pegasys.pantheon.ethereum.eth.sync;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Hash; 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.ChainState;
import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager;
import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManagerTestUtil; import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManagerTestUtil;
@ -42,7 +43,7 @@ public class ChainHeadTrackerTest {
blockchain.getChainHead().getTotalDifficulty(), blockchain.getChainHead().getTotalDifficulty(),
0); 0);
private final ProtocolSchedule<Void> protocolSchedule = private final ProtocolSchedule<Void> protocolSchedule =
GenesisConfig.development().getProtocolSchedule(); DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions());
private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class); private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class);
private final ChainHeadTracker chainHeadTracker = private final ChainHeadTracker chainHeadTracker =
new ChainHeadTracker(ethProtocolManager.ethContext(), protocolSchedule, trailingPeerLimiter); new ChainHeadTracker(ethProtocolManager.ethContext(), protocolSchedule, trailingPeerLimiter);

@ -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.createInMemoryBlockchain;
import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive; 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.crypto.SECP256K1;
import tech.pegasys.pantheon.ethereum.ProtocolContext; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction;
import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.Transaction;
import tech.pegasys.pantheon.ethereum.core.TransactionPool; import tech.pegasys.pantheon.ethereum.core.TransactionPool;
import tech.pegasys.pantheon.ethereum.db.WorldStateArchive; 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.EthProtocol;
import tech.pegasys.pantheon.ethereum.eth.manager.EthContext; import tech.pegasys.pantheon.ethereum.eth.manager.EthContext;
import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager;
@ -84,14 +86,16 @@ public class TestNode implements Closeable {
.setRlpx(RlpxConfiguration.create().setBindPort(listenPort)) .setRlpx(RlpxConfiguration.create().setBindPort(listenPort))
.setSupportedProtocols(EthProtocol.get()); .setSupportedProtocols(EthProtocol.get());
final GenesisConfig<Void> genesisConfig = GenesisConfig.development(); final GenesisConfigFile genesisConfigFile = GenesisConfigFile.development();
final ProtocolSchedule<Void> protocolSchedule = genesisConfig.getProtocolSchedule(); final ProtocolSchedule<Void> protocolSchedule =
DevelopmentProtocolSchedule.create(genesisConfigFile.getConfigOptions());
final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule);
final BlockHashFunction blockHashFunction = final BlockHashFunction blockHashFunction =
ScheduleBasedBlockHashFunction.create(protocolSchedule); ScheduleBasedBlockHashFunction.create(protocolSchedule);
final MutableBlockchain blockchain = final MutableBlockchain blockchain =
createInMemoryBlockchain(genesisConfig.getBlock(), blockHashFunction); createInMemoryBlockchain(genesisState.getBlock(), blockHashFunction);
final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive();
genesisConfig.writeStateTo(worldStateArchive.getMutable()); genesisState.writeStateTo(worldStateArchive.getMutable());
final ProtocolContext<Void> protocolContext = final ProtocolContext<Void> protocolContext =
new ProtocolContext<>(blockchain, worldStateArchive, null); new ProtocolContext<>(blockchain, worldStateArchive, null);
final EthProtocolManager ethProtocolManager = new EthProtocolManager(blockchain, 1, false, 1); final EthProtocolManager ethProtocolManager = new EthProtocolManager(blockchain, 1, false, 1);

@ -12,8 +12,8 @@
*/ */
package tech.pegasys.pantheon.ethereum.jsonrpc; package tech.pegasys.pantheon.ethereum.jsonrpc;
import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig; import tech.pegasys.pantheon.ethereum.chain.GenesisState;
import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction; 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. */ /** Creates a block chain from a genesis and a blocks files. */
public class BlockchainImporter { public class BlockchainImporter {
private final GenesisConfig<?> genesisConfig; private final GenesisState genesisState;
private final ProtocolSchedule<Void> protocolSchedule; private final ProtocolSchedule<Void> protocolSchedule;
@ -39,7 +39,8 @@ public class BlockchainImporter {
public BlockchainImporter(final URL blocksUrl, final String genesisJson) throws Exception { public BlockchainImporter(final URL blocksUrl, final String genesisJson) throws Exception {
protocolSchedule = protocolSchedule =
MainnetProtocolSchedule.fromConfig(GenesisConfigOptions.fromGenesisConfig(genesisJson)); MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(genesisJson).getConfigOptions());
blocks = new ArrayList<>(); blocks = new ArrayList<>();
try (final RawBlockIterator iterator = try (final RawBlockIterator iterator =
@ -52,11 +53,11 @@ public class BlockchainImporter {
} }
genesisBlock = blocks.get(0); genesisBlock = blocks.get(0);
genesisConfig = GenesisConfig.fromJson(genesisJson, protocolSchedule); genesisState = GenesisState.fromJson(genesisJson, protocolSchedule);
} }
public GenesisConfig<?> getGenesisConfig() { public GenesisState getGenesisState() {
return genesisConfig; return genesisState;
} }
public ProtocolSchedule<Void> getProtocolSchedule() { public ProtocolSchedule<Void> getProtocolSchedule() {

@ -49,10 +49,10 @@ public class JsonRpcTestMethodsFactory {
this.importer = importer; this.importer = importer;
} }
public Map<String, JsonRpcMethod> methods(final int chainId) { public Map<String, JsonRpcMethod> methods() {
final WorldStateArchive stateArchive = InMemoryTestFixture.createInMemoryWorldStateArchive(); 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 = final MutableBlockchain blockchain =
InMemoryTestFixture.createInMemoryBlockchain(importer.getGenesisBlock()); InMemoryTestFixture.createInMemoryBlockchain(importer.getGenesisBlock());
@ -79,7 +79,6 @@ public class JsonRpcTestMethodsFactory {
return new JsonRpcMethodsFactory() return new JsonRpcMethodsFactory()
.methods( .methods(
CLIENT_VERSION, CLIENT_VERSION,
chainId,
peerDiscovery, peerDiscovery,
blockchainQueries, blockchainQueries,
synchronizer, synchronizer,

@ -37,7 +37,6 @@ import org.junit.Test;
public class EthCallIntegrationTest { public class EthCallIntegrationTest {
private static final int CHAIN_ID = 123;
private static JsonRpcTestMethodsFactory BLOCKCHAIN; private static JsonRpcTestMethodsFactory BLOCKCHAIN;
private JsonRpcMethod method; private JsonRpcMethod method;
@ -64,7 +63,7 @@ public class EthCallIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
final Map<String, JsonRpcMethod> methods = BLOCKCHAIN.methods(CHAIN_ID); final Map<String, JsonRpcMethod> methods = BLOCKCHAIN.methods();
method = methods.get("eth_call"); method = methods.get("eth_call");
} }

@ -33,7 +33,6 @@ import org.junit.Test;
public class EthEstimateGasIntegrationTest { public class EthEstimateGasIntegrationTest {
private static final int CHAIN_ID = 123;
private static JsonRpcTestMethodsFactory BLOCKCHAIN; private static JsonRpcTestMethodsFactory BLOCKCHAIN;
private JsonRpcMethod method; private JsonRpcMethod method;
@ -60,7 +59,7 @@ public class EthEstimateGasIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
final Map<String, JsonRpcMethod> methods = BLOCKCHAIN.methods(CHAIN_ID); final Map<String, JsonRpcMethod> methods = BLOCKCHAIN.methods();
method = methods.get("eth_estimateGas"); method = methods.get("eth_estimateGas");
} }

@ -58,7 +58,6 @@ public class EthGetBlockByHashIntegrationTest {
private Map<String, JsonRpcMethod> methods; private Map<String, JsonRpcMethod> methods;
private static JsonRpcTestMethodsFactory BLOCKCHAIN; private static JsonRpcTestMethodsFactory BLOCKCHAIN;
private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils(); private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils();
private static final int CHAIN_ID = 123;
private final String ETH_METHOD = "eth_getBlockByHash"; private final String ETH_METHOD = "eth_getBlockByHash";
private final String JSON_RPC_VERSION = "2.0"; private final String JSON_RPC_VERSION = "2.0";
private final String ZERO_HASH = String.valueOf(Hash.ZERO); private final String ZERO_HASH = String.valueOf(Hash.ZERO);
@ -85,7 +84,7 @@ public class EthGetBlockByHashIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
methods = BLOCKCHAIN.methods(CHAIN_ID); methods = BLOCKCHAIN.methods();
} }
@Test @Test

@ -59,7 +59,6 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class EthGetBlockByNumberIntegrationTest { public class EthGetBlockByNumberIntegrationTest {
private static final int CHAIN_ID = 123;
private static final String ETH_METHOD = "eth_getBlockByNumber"; private static final String ETH_METHOD = "eth_getBlockByNumber";
private static final String JSON_RPC_VERSION = "2.0"; private static final String JSON_RPC_VERSION = "2.0";
private static JsonRpcTestMethodsFactory BLOCKCHAIN; private static JsonRpcTestMethodsFactory BLOCKCHAIN;
@ -89,7 +88,7 @@ public class EthGetBlockByNumberIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
methods = BLOCKCHAIN.methods(CHAIN_ID); methods = BLOCKCHAIN.methods();
} }
@Test @Test

@ -19,21 +19,19 @@ import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockBody; import tech.pegasys.pantheon.ethereum.core.BlockBody;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; 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.PendingTransactions;
import tech.pegasys.pantheon.ethereum.core.Transaction; import tech.pegasys.pantheon.ethereum.core.Transaction;
import tech.pegasys.pantheon.ethereum.core.TransactionPool; import tech.pegasys.pantheon.ethereum.core.TransactionPool;
import tech.pegasys.pantheon.ethereum.core.TransactionPool.TransactionBatchAddedListener; import tech.pegasys.pantheon.ethereum.core.TransactionPool.TransactionBatchAddedListener;
import tech.pegasys.pantheon.ethereum.core.TransactionReceipt; import tech.pegasys.pantheon.ethereum.core.TransactionReceipt;
import tech.pegasys.pantheon.ethereum.core.Wei; 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.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterIdGenerator; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterIdGenerator;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterManager; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.filter.FilterManager;
@ -75,18 +73,17 @@ public class EthGetFilterChangesIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
final GenesisConfig<Void> genesisConfig = GenesisConfig.mainnet(); final ExecutionContextTestFixture executionContext = ExecutionContextTestFixture.create();
final Block genesisBlock = genesisConfig.getBlock(); blockchain = executionContext.getBlockchain();
blockchain = InMemoryTestFixture.createInMemoryBlockchain(genesisBlock); final ProtocolContext<Void> protocolContext = executionContext.getProtocolContext();
final WorldStateArchive worldStateArchive =
InMemoryTestFixture.createInMemoryWorldStateArchive();
final ProtocolContext<Void> protocolContext =
new ProtocolContext<>(blockchain, worldStateArchive, null);
transactionPool = transactionPool =
new TransactionPool( new TransactionPool(
transactions, genesisConfig.getProtocolSchedule(), protocolContext, batchAddedListener); transactions,
executionContext.getProtocolSchedule(),
protocolContext,
batchAddedListener);
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, worldStateArchive); new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive());
filterManager = filterManager =
new FilterManager( new FilterManager(
blockchainQueries, transactionPool, new FilterIdGenerator(), new FilterRepository()); blockchainQueries, transactionPool, new FilterIdGenerator(), new FilterRepository());

@ -52,7 +52,6 @@ import org.junit.Test;
public class EthGetUncleByBlockHashAndIndexIntegrationTest { public class EthGetUncleByBlockHashAndIndexIntegrationTest {
private static final int CHAIN_ID = 123;
private static JsonRpcTestMethodsFactory BLOCKCHAIN; private static JsonRpcTestMethodsFactory BLOCKCHAIN;
private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils(); private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils();
@ -80,7 +79,7 @@ public class EthGetUncleByBlockHashAndIndexIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
method = BLOCKCHAIN.methods(CHAIN_ID).get("eth_getUncleByBlockHashAndIndex"); method = BLOCKCHAIN.methods().get("eth_getUncleByBlockHashAndIndex");
} }
@Test @Test

@ -52,7 +52,6 @@ import org.junit.Test;
public class EthGetUncleByBlockNumberAndIndexIntegrationTest { public class EthGetUncleByBlockNumberAndIndexIntegrationTest {
private static final int CHAIN_ID = 123;
private static JsonRpcTestMethodsFactory BLOCKCHAIN; private static JsonRpcTestMethodsFactory BLOCKCHAIN;
private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils(); private final JsonRpcResponseUtils responseUtils = new JsonRpcResponseUtils();
@ -80,7 +79,7 @@ public class EthGetUncleByBlockNumberAndIndexIntegrationTest {
@Before @Before
public void setUp() { public void setUp() {
method = BLOCKCHAIN.methods(CHAIN_ID).get("eth_getUncleByBlockNumberAndIndex"); method = BLOCKCHAIN.methods().get("eth_getUncleByBlockNumberAndIndex");
} }
@Test @Test

@ -88,7 +88,6 @@ public class JsonRpcMethodsFactory {
public Map<String, JsonRpcMethod> methods( public Map<String, JsonRpcMethod> methods(
final String clientVersion, final String clientVersion,
final int chainId,
final P2PNetwork peerNetworkingService, final P2PNetwork peerNetworkingService,
final Blockchain blockchain, final Blockchain blockchain,
final WorldStateArchive worldStateArchive, final WorldStateArchive worldStateArchive,
@ -103,7 +102,6 @@ public class JsonRpcMethodsFactory {
new BlockchainQueries(blockchain, worldStateArchive); new BlockchainQueries(blockchain, worldStateArchive);
return methods( return methods(
clientVersion, clientVersion,
chainId,
peerNetworkingService, peerNetworkingService,
blockchainQueries, blockchainQueries,
synchronizer, synchronizer,
@ -117,7 +115,6 @@ public class JsonRpcMethodsFactory {
public Map<String, JsonRpcMethod> methods( public Map<String, JsonRpcMethod> methods(
final String clientVersion, final String clientVersion,
final int chainId,
final P2PNetwork p2pNetwork, final P2PNetwork p2pNetwork,
final BlockchainQueries blockchainQueries, final BlockchainQueries blockchainQueries,
final Synchronizer synchronizer, final Synchronizer synchronizer,
@ -180,7 +177,7 @@ public class JsonRpcMethodsFactory {
new EthProtocolVersion(supportedCapabilities), new EthProtocolVersion(supportedCapabilities),
new EthGasPrice(miningCoordinator), new EthGasPrice(miningCoordinator),
new EthGetWork(miningCoordinator), new EthGetWork(miningCoordinator),
new EthChainId(chainId)); new EthChainId(protocolSchedule.getChainId()));
} }
if (rpcApis.contains(RpcApis.DEBUG)) { if (rpcApis.contains(RpcApis.DEBUG)) {
final BlockReplay blockReplay = final BlockReplay blockReplay =
@ -197,7 +194,7 @@ public class JsonRpcMethodsFactory {
if (rpcApis.contains(RpcApis.NET)) { if (rpcApis.contains(RpcApis.NET)) {
addMethods( addMethods(
enabledMethods, enabledMethods,
new NetVersion(chainId), new NetVersion(protocolSchedule.getChainId()),
new NetListening(p2pNetwork), new NetListening(p2pNetwork),
new NetPeerCount(p2pNetwork), new NetPeerCount(p2pNetwork),
new AdminPeers(p2pNetwork)); new AdminPeers(p2pNetwork));

@ -21,7 +21,7 @@ import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMe
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMiningCoordinator; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
@ -78,7 +78,7 @@ public abstract class AbstractEthJsonRpcHttpServiceTest {
protected static Block GENESIS_BLOCK; protected static Block GENESIS_BLOCK;
protected static GenesisConfig<?> GENESIS_CONFIG; protected static GenesisState GENESIS_CONFIG;
protected final Vertx vertx = Vertx.vertx(); 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 String CLIENT_VERSION = "TestClientVersion/0.1.0";
protected final int NET_VERSION = 123;
protected static final Collection<RpcApi> JSON_RPC_APIS = protected static final Collection<RpcApi> JSON_RPC_APIS =
Arrays.asList(RpcApis.ETH, RpcApis.NET, RpcApis.WEB3); 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); final String gensisjson = Resources.toString(genesisJsonUrl, Charsets.UTF_8);
GENESIS_BLOCK = BLOCKS.get(0); GENESIS_BLOCK = BLOCKS.get(0);
GENESIS_CONFIG = GenesisConfig.fromJson(gensisjson, PROTOCOL_SCHEDULE); GENESIS_CONFIG = GenesisState.fromJson(gensisjson, PROTOCOL_SCHEDULE);
} }
@Before @Before
@ -170,7 +168,6 @@ public abstract class AbstractEthJsonRpcHttpServiceTest {
new JsonRpcMethodsFactory() new JsonRpcMethodsFactory()
.methods( .methods(
CLIENT_VERSION, CLIENT_VERSION,
NET_VERSION,
peerDiscoveryMock, peerDiscoveryMock,
blockchainQueries, blockchainQueries,
synchronizerMock, synchronizerMock,

@ -61,7 +61,6 @@ public class JsonRpcHttpServiceRpcApisTest {
private static String baseUrl; private static String baseUrl;
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); 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 String CLIENT_VERSION = "TestClientVersion/0.1.0";
private static final int NET_VERSION = 123;
private JsonRpcConfiguration configuration; private JsonRpcConfiguration configuration;
@Mock protected static BlockchainQueries blockchainQueries; @Mock protected static BlockchainQueries blockchainQueries;
@ -170,7 +169,6 @@ public class JsonRpcHttpServiceRpcApisTest {
new JsonRpcMethodsFactory() new JsonRpcMethodsFactory()
.methods( .methods(
CLIENT_VERSION, CLIENT_VERSION,
NET_VERSION,
mock(P2PNetwork.class), mock(P2PNetwork.class),
blockchainQueries, blockchainQueries,
mock(Synchronizer.class), mock(Synchronizer.class),

@ -87,7 +87,7 @@ public class JsonRpcHttpServiceTest {
protected static String baseUrl; protected static String baseUrl;
protected static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); 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 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 P2PNetwork peerDiscoveryMock;
protected static BlockchainQueries blockchainQueries; protected static BlockchainQueries blockchainQueries;
protected static Synchronizer synchronizer; protected static Synchronizer synchronizer;
@ -110,11 +110,10 @@ public class JsonRpcHttpServiceTest {
new JsonRpcMethodsFactory() new JsonRpcMethodsFactory()
.methods( .methods(
CLIENT_VERSION, CLIENT_VERSION,
NET_VERSION,
peerDiscoveryMock, peerDiscoveryMock,
blockchainQueries, blockchainQueries,
synchronizer, synchronizer,
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(0, 0, 0, 0, 0, 0, CHAIN_ID),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(EthHashMiningCoordinator.class),
@ -266,7 +265,7 @@ public class JsonRpcHttpServiceTest {
testHelper.assertValidJsonRpcResult(json, id); testHelper.assertValidJsonRpcResult(json, id);
// Check result // Check result
final String result = json.getString("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 // Check result net_version
final JsonObject jsonNetVersion = responses.get(netVersionRequestId); final JsonObject jsonNetVersion = responses.get(netVersionRequestId);
testHelper.assertValidJsonRpcResult(jsonNetVersion, 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 // Check result net_version
final JsonObject jsonNetVersion = responses.get(netVersionRequestId); final JsonObject jsonNetVersion = responses.get(netVersionRequestId);
testHelper.assertValidJsonRpcResult(jsonNetVersion, 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 // Check result net_version
final JsonObject jsonNetVersion = responses.get(netVersionRequestId); final JsonObject jsonNetVersion = responses.get(netVersionRequestId);
testHelper.assertValidJsonRpcResult(jsonNetVersion, netVersionRequestId); testHelper.assertValidJsonRpcResult(jsonNetVersion, netVersionRequestId);
assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(NET_VERSION)); assertThat(jsonNetVersion.getString("result")).isEqualTo(String.valueOf(CHAIN_ID));
} }
} }

@ -149,7 +149,6 @@ public class RunnerBuilder {
jsonRpcMethods( jsonRpcMethods(
context, context,
protocolSchedule, protocolSchedule,
pantheonController,
networkRunner, networkRunner,
synchronizer, synchronizer,
transactionPool, transactionPool,
@ -167,7 +166,6 @@ public class RunnerBuilder {
jsonRpcMethods( jsonRpcMethods(
context, context,
protocolSchedule, protocolSchedule,
pantheonController,
networkRunner, networkRunner,
synchronizer, synchronizer,
transactionPool, transactionPool,
@ -212,7 +210,6 @@ public class RunnerBuilder {
private Map<String, JsonRpcMethod> jsonRpcMethods( private Map<String, JsonRpcMethod> jsonRpcMethods(
final ProtocolContext<?> context, final ProtocolContext<?> context,
final ProtocolSchedule<?> protocolSchedule, final ProtocolSchedule<?> protocolSchedule,
final PantheonController<?> pantheonController,
final NetworkRunner networkRunner, final NetworkRunner networkRunner,
final Synchronizer synchronizer, final Synchronizer synchronizer,
final TransactionPool transactionPool, final TransactionPool transactionPool,
@ -224,7 +221,6 @@ public class RunnerBuilder {
new JsonRpcMethodsFactory() new JsonRpcMethodsFactory()
.methods( .methods(
PantheonInfo.version(), PantheonInfo.version(),
pantheonController.getGenesisConfig().getChainId(),
networkRunner.getNetwork(), networkRunner.getNetwork(),
context.getBlockchain(), context.getBlockchain(),
context.getWorldStateArchive(), context.getWorldStateArchive(),

@ -15,11 +15,12 @@ package tech.pegasys.pantheon.cli;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; 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.MainnetPantheonController;
import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; 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.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.development.DevelopmentProtocolSchedule;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;
import java.io.IOException; import java.io.IOException;
@ -41,9 +42,11 @@ public class PantheonControllerBuilder {
// otherwise use the indicated genesis file // otherwise use the indicated genesis file
final KeyPair nodeKeys = loadKeyPair(homePath); final KeyPair nodeKeys = loadKeyPair(homePath);
if (isDevMode) { if (isDevMode) {
final GenesisConfigFile genesisConfig = GenesisConfigFile.development();
return MainnetPantheonController.init( return MainnetPantheonController.init(
homePath, homePath,
GenesisConfig.development(), genesisConfig,
DevelopmentProtocolSchedule.create(genesisConfig.getConfigOptions()),
synchronizerConfiguration, synchronizerConfiguration,
miningParameters, miningParameters,
nodeKeys); nodeKeys);

@ -15,7 +15,10 @@ package tech.pegasys.pantheon.controller;
import static org.apache.logging.log4j.LogManager.getLogger; import static org.apache.logging.log4j.LogManager.getLogger;
import tech.pegasys.pantheon.config.CliqueConfigOptions; 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.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule;
import tech.pegasys.pantheon.consensus.clique.CliqueVoteTallyUpdater; import tech.pegasys.pantheon.consensus.clique.CliqueVoteTallyUpdater;
import tech.pegasys.pantheon.consensus.clique.VoteTallyCache; import tech.pegasys.pantheon.consensus.clique.VoteTallyCache;
import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueBlockScheduler; 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.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction;
import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.Hash;
@ -65,7 +68,8 @@ import org.apache.logging.log4j.Logger;
public class CliquePantheonController implements PantheonController<CliqueContext> { public class CliquePantheonController implements PantheonController<CliqueContext> {
private static final Logger LOG = getLogger(); private static final Logger LOG = getLogger();
private final GenesisConfig<CliqueContext> genesisConfig; private final GenesisConfigOptions genesisConfigOptions;
private final ProtocolSchedule<CliqueContext> protocolSchedule;
private final ProtocolContext<CliqueContext> context; private final ProtocolContext<CliqueContext> context;
private final Synchronizer synchronizer; private final Synchronizer synchronizer;
private final ProtocolManager ethProtocolManager; private final ProtocolManager ethProtocolManager;
@ -76,7 +80,8 @@ public class CliquePantheonController implements PantheonController<CliqueContex
private final MiningCoordinator miningCoordinator; private final MiningCoordinator miningCoordinator;
CliquePantheonController( CliquePantheonController(
final GenesisConfig<CliqueContext> genesisConfig, final GenesisConfigOptions genesisConfigOptions,
final ProtocolSchedule<CliqueContext> protocolSchedule,
final ProtocolContext<CliqueContext> context, final ProtocolContext<CliqueContext> context,
final ProtocolManager ethProtocolManager, final ProtocolManager ethProtocolManager,
final Synchronizer synchronizer, final Synchronizer synchronizer,
@ -85,7 +90,8 @@ public class CliquePantheonController implements PantheonController<CliqueContex
final MiningCoordinator miningCoordinator, final MiningCoordinator miningCoordinator,
final Runnable closer) { final Runnable closer) {
this.genesisConfig = genesisConfig; this.genesisConfigOptions = genesisConfigOptions;
this.protocolSchedule = protocolSchedule;
this.context = context; this.context = context;
this.ethProtocolManager = ethProtocolManager; this.ethProtocolManager = ethProtocolManager;
this.synchronizer = synchronizer; this.synchronizer = synchronizer;
@ -97,32 +103,34 @@ public class CliquePantheonController implements PantheonController<CliqueContex
public static PantheonController<CliqueContext> init( public static PantheonController<CliqueContext> init(
final Path home, final Path home,
final GenesisConfig<CliqueContext> genesisConfig, final GenesisConfigFile genesisConfig,
final SynchronizerConfiguration taintedSyncConfig, final SynchronizerConfiguration taintedSyncConfig,
final MiningParameters miningParams, final MiningParameters miningParams,
final CliqueConfigOptions cliqueConfig,
final int networkId, final int networkId,
final KeyPair nodeKeys) final KeyPair nodeKeys)
throws IOException { throws IOException {
final CliqueConfigOptions cliqueConfig =
genesisConfig.getConfigOptions().getCliqueConfigOptions();
final long blocksPerEpoch = cliqueConfig.getEpochLength(); final long blocksPerEpoch = cliqueConfig.getEpochLength();
final long secondsBetweenBlocks = cliqueConfig.getBlockPeriodSeconds(); final long secondsBetweenBlocks = cliqueConfig.getBlockPeriodSeconds();
final EpochManager epochManger = new EpochManager(blocksPerEpoch); final EpochManager epochManger = new EpochManager(blocksPerEpoch);
final KeyValueStorage kv = final KeyValueStorage kv =
RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH))); RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH)));
final ProtocolSchedule<CliqueContext> protocolSchedule = genesisConfig.getProtocolSchedule(); final ProtocolSchedule<CliqueContext> protocolSchedule =
CliqueProtocolSchedule.create(genesisConfig.getConfigOptions(), nodeKeys);
final BlockHashFunction blockHashFunction = final BlockHashFunction blockHashFunction =
ScheduleBasedBlockHashFunction.create(protocolSchedule); ScheduleBasedBlockHashFunction.create(protocolSchedule);
final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule);
final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage = final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage =
new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction); new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction);
final MutableBlockchain blockchain = final MutableBlockchain blockchain =
new DefaultMutableBlockchain(genesisConfig.getBlock(), blockchainStorage); new DefaultMutableBlockchain(genesisState.getBlock(), blockchainStorage);
final KeyValueStorageWorldStateStorage worldStateStorage = final KeyValueStorageWorldStateStorage worldStateStorage =
new KeyValueStorageWorldStateStorage(kv); new KeyValueStorageWorldStateStorage(kv);
final WorldStateArchive worldStateArchive = new WorldStateArchive(worldStateStorage); final WorldStateArchive worldStateArchive = new WorldStateArchive(worldStateStorage);
genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); genesisState.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH));
final ProtocolContext<CliqueContext> protocolContext = final ProtocolContext<CliqueContext> protocolContext =
new ProtocolContext<>( new ProtocolContext<>(
@ -139,9 +147,9 @@ public class CliquePantheonController implements PantheonController<CliqueContex
final EthProtocolManager ethProtocolManager = final EthProtocolManager ethProtocolManager =
new EthProtocolManager( new EthProtocolManager(
protocolContext.getBlockchain(), protocolContext.getBlockchain(),
genesisConfig.getChainId(), networkId,
fastSyncEnabled, fastSyncEnabled,
networkId); syncConfig.downloaderParallelism());
final SyncState syncState = final SyncState syncState =
new SyncState( new SyncState(
protocolContext.getBlockchain(), ethProtocolManager.ethContext().getEthPeers()); protocolContext.getBlockchain(), ethProtocolManager.ethContext().getEthPeers());
@ -180,7 +188,8 @@ public class CliquePantheonController implements PantheonController<CliqueContex
miningCoordinator.enable(); miningCoordinator.enable();
return new CliquePantheonController( return new CliquePantheonController(
genesisConfig, genesisConfig.getConfigOptions(),
protocolSchedule,
protocolContext, protocolContext,
ethProtocolManager, ethProtocolManager,
synchronizer, synchronizer,
@ -209,8 +218,13 @@ public class CliquePantheonController implements PantheonController<CliqueContex
} }
@Override @Override
public GenesisConfig<CliqueContext> getGenesisConfig() { public ProtocolSchedule<CliqueContext> getProtocolSchedule() {
return genesisConfig; return protocolSchedule;
}
@Override
public GenesisConfigOptions getGenesisConfigOptions() {
return genesisConfigOptions;
} }
@Override @Override

@ -14,6 +14,8 @@ package tech.pegasys.pantheon.controller;
import static org.apache.logging.log4j.LogManager.getLogger; 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.config.IbftConfigOptions;
import tech.pegasys.pantheon.consensus.common.EpochManager; import tech.pegasys.pantheon.consensus.common.EpochManager;
import tech.pegasys.pantheon.consensus.common.VoteProposer; 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.network.IbftNetworkPeers;
import tech.pegasys.pantheon.consensus.ibft.protocol.IbftProtocolManager; import tech.pegasys.pantheon.consensus.ibft.protocol.IbftProtocolManager;
import tech.pegasys.pantheon.consensus.ibft.protocol.IbftSubProtocol; 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.IbftVoteTallyUpdater;
import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64Protocol; import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64Protocol;
import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64ProtocolManager; import tech.pegasys.pantheon.consensus.ibftlegacy.protocol.Istanbul64ProtocolManager;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction;
import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.Hash;
@ -69,7 +72,8 @@ import org.apache.logging.log4j.Logger;
public class IbftPantheonController implements PantheonController<IbftContext> { public class IbftPantheonController implements PantheonController<IbftContext> {
private static final Logger LOG = getLogger(); private static final Logger LOG = getLogger();
private final GenesisConfig<IbftContext> genesisConfig; private final GenesisConfigOptions genesisConfig;
private final ProtocolSchedule<IbftContext> protocolSchedule;
private final ProtocolContext<IbftContext> context; private final ProtocolContext<IbftContext> context;
private final Synchronizer synchronizer; private final Synchronizer synchronizer;
private final SubProtocol ethSubProtocol; private final SubProtocol ethSubProtocol;
@ -81,7 +85,8 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
private final Runnable closer; private final Runnable closer;
IbftPantheonController( IbftPantheonController(
final GenesisConfig<IbftContext> genesisConfig, final GenesisConfigOptions genesisConfig,
final ProtocolSchedule<IbftContext> protocolSchedule,
final ProtocolContext<IbftContext> context, final ProtocolContext<IbftContext> context,
final SubProtocol ethSubProtocol, final SubProtocol ethSubProtocol,
final ProtocolManager ethProtocolManager, final ProtocolManager ethProtocolManager,
@ -93,6 +98,7 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
final Runnable closer) { final Runnable closer) {
this.genesisConfig = genesisConfig; this.genesisConfig = genesisConfig;
this.protocolSchedule = protocolSchedule;
this.context = context; this.context = context;
this.ethSubProtocol = ethSubProtocol; this.ethSubProtocol = ethSubProtocol;
this.ethProtocolManager = ethProtocolManager; this.ethProtocolManager = ethProtocolManager;
@ -106,29 +112,30 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
public static PantheonController<IbftContext> init( public static PantheonController<IbftContext> init(
final Path home, final Path home,
final GenesisConfig<IbftContext> genesisConfig, final GenesisConfigFile genesisConfig,
final SynchronizerConfiguration taintedSyncConfig, final SynchronizerConfiguration taintedSyncConfig,
final boolean ottomanTestnetOperation, final boolean ottomanTestnetOperation,
final IbftConfigOptions ibftConfig,
final int networkId, final int networkId,
final KeyPair nodeKeys) final KeyPair nodeKeys)
throws IOException { throws IOException {
final KeyValueStorage kv = final KeyValueStorage kv =
RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH))); RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH)));
final ProtocolSchedule<IbftContext> protocolSchedule = genesisConfig.getProtocolSchedule(); final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create(genesisConfig.getConfigOptions());
final BlockHashFunction blockHashFunction = final BlockHashFunction blockHashFunction =
ScheduleBasedBlockHashFunction.create(protocolSchedule); ScheduleBasedBlockHashFunction.create(protocolSchedule);
final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule);
final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage = final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage =
new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction); new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction);
final MutableBlockchain blockchain = final MutableBlockchain blockchain =
new DefaultMutableBlockchain(genesisConfig.getBlock(), blockchainStorage); new DefaultMutableBlockchain(genesisState.getBlock(), blockchainStorage);
final KeyValueStorageWorldStateStorage worldStateStorage = final KeyValueStorageWorldStateStorage worldStateStorage =
new KeyValueStorageWorldStateStorage(kv); new KeyValueStorageWorldStateStorage(kv);
final WorldStateArchive worldStateArchive = new WorldStateArchive(worldStateStorage); 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 EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());
final VoteTally voteTally = final VoteTally voteTally =
@ -149,11 +156,18 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
ethSubProtocol = Istanbul64Protocol.get(); ethSubProtocol = Istanbul64Protocol.get();
ethProtocolManager = ethProtocolManager =
new Istanbul64ProtocolManager( new Istanbul64ProtocolManager(
protocolContext.getBlockchain(), networkId, fastSyncEnabled, 1); protocolContext.getBlockchain(),
networkId,
fastSyncEnabled,
syncConfig.downloaderParallelism());
} else { } else {
ethSubProtocol = EthProtocol.get(); ethSubProtocol = EthProtocol.get();
ethProtocolManager = ethProtocolManager =
new EthProtocolManager(protocolContext.getBlockchain(), networkId, fastSyncEnabled, 1); new EthProtocolManager(
protocolContext.getBlockchain(),
networkId,
fastSyncEnabled,
syncConfig.downloaderParallelism());
} }
final SyncState syncState = final SyncState syncState =
new SyncState( new SyncState(
@ -200,7 +214,8 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
new IbftNetworkPeers(protocolContext.getConsensusState().getVoteTally()); new IbftNetworkPeers(protocolContext.getConsensusState().getVoteTally());
return new IbftPantheonController( return new IbftPantheonController(
genesisConfig, genesisConfig.getConfigOptions(),
protocolSchedule,
protocolContext, protocolContext,
ethSubProtocol, ethSubProtocol,
ethProtocolManager, ethProtocolManager,
@ -218,7 +233,12 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
} }
@Override @Override
public GenesisConfig<IbftContext> getGenesisConfig() { public ProtocolSchedule<IbftContext> getProtocolSchedule() {
return protocolSchedule;
}
@Override
public GenesisConfigOptions getGenesisConfigOptions() {
return genesisConfig; return genesisConfig;
} }

@ -14,13 +14,15 @@ package tech.pegasys.pantheon.controller;
import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; 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.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.DefaultBlockScheduler; import tech.pegasys.pantheon.ethereum.blockcreation.DefaultBlockScheduler;
import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMinerExecutor; import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMinerExecutor;
import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMiningCoordinator; import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMiningCoordinator;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.BlockHashFunction; import tech.pegasys.pantheon.ethereum.core.BlockHashFunction;
import tech.pegasys.pantheon.ethereum.core.Hash; 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.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory; import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHeaderValidator; 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.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction; import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction;
import tech.pegasys.pantheon.ethereum.p2p.api.ProtocolManager; import tech.pegasys.pantheon.ethereum.p2p.api.ProtocolManager;
@ -61,7 +64,8 @@ public class MainnetPantheonController implements PantheonController<Void> {
private static final Logger LOG = LogManager.getLogger(); private static final Logger LOG = LogManager.getLogger();
private final GenesisConfig<Void> genesisConfig; private final GenesisConfigFile genesisConfig;
private final ProtocolSchedule<Void> protocolSchedule;
private final ProtocolContext<Void> protocolContext; private final ProtocolContext<Void> protocolContext;
private final ProtocolManager ethProtocolManager; private final ProtocolManager ethProtocolManager;
private final KeyPair keyPair; private final KeyPair keyPair;
@ -72,7 +76,8 @@ public class MainnetPantheonController implements PantheonController<Void> {
private final Runnable close; private final Runnable close;
public MainnetPantheonController( public MainnetPantheonController(
final GenesisConfig<Void> genesisConfig, final GenesisConfigFile genesisConfig,
final ProtocolSchedule<Void> protocolSchedule,
final ProtocolContext<Void> protocolContext, final ProtocolContext<Void> protocolContext,
final ProtocolManager ethProtocolManager, final ProtocolManager ethProtocolManager,
final Synchronizer synchronizer, final Synchronizer synchronizer,
@ -81,6 +86,7 @@ public class MainnetPantheonController implements PantheonController<Void> {
final MiningCoordinator miningCoordinator, final MiningCoordinator miningCoordinator,
final Runnable close) { final Runnable close) {
this.genesisConfig = genesisConfig; this.genesisConfig = genesisConfig;
this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
this.ethProtocolManager = ethProtocolManager; this.ethProtocolManager = ethProtocolManager;
this.synchronizer = synchronizer; this.synchronizer = synchronizer;
@ -95,7 +101,8 @@ public class MainnetPantheonController implements PantheonController<Void> {
final KeyPair nodeKeys = loadKeyPair(home); final KeyPair nodeKeys = loadKeyPair(home);
return init( return init(
home, home,
GenesisConfig.mainnet(), GenesisConfigFile.mainnet(),
MainnetProtocolSchedule.create(),
SynchronizerConfiguration.builder().build(), SynchronizerConfiguration.builder().build(),
miningParams, miningParams,
nodeKeys); nodeKeys);
@ -103,25 +110,26 @@ public class MainnetPantheonController implements PantheonController<Void> {
public static PantheonController<Void> init( public static PantheonController<Void> init(
final Path home, final Path home,
final GenesisConfig<Void> genesisConfig, final GenesisConfigFile genesisConfig,
final ProtocolSchedule<Void> protocolSchedule,
final SynchronizerConfiguration taintedSyncConfig, final SynchronizerConfiguration taintedSyncConfig,
final MiningParameters miningParams, final MiningParameters miningParams,
final KeyPair nodeKeys) final KeyPair nodeKeys)
throws IOException { throws IOException {
final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule);
final KeyValueStorage kv = final KeyValueStorage kv =
RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH))); RocksDbKeyValueStorage.create(Files.createDirectories(home.resolve(DATABASE_PATH)));
final ProtocolSchedule<Void> protocolSchedule = genesisConfig.getProtocolSchedule();
final BlockHashFunction blockHashFunction = final BlockHashFunction blockHashFunction =
ScheduleBasedBlockHashFunction.create(protocolSchedule); ScheduleBasedBlockHashFunction.create(protocolSchedule);
final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage = final KeyValueStoragePrefixedKeyBlockchainStorage blockchainStorage =
new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction); new KeyValueStoragePrefixedKeyBlockchainStorage(kv, blockHashFunction);
final MutableBlockchain blockchain = final MutableBlockchain blockchain =
new DefaultMutableBlockchain(genesisConfig.getBlock(), blockchainStorage); new DefaultMutableBlockchain(genesisState.getBlock(), blockchainStorage);
final WorldStateArchive worldStateArchive = final WorldStateArchive worldStateArchive =
new WorldStateArchive(new KeyValueStorageWorldStateStorage(kv)); new WorldStateArchive(new KeyValueStorageWorldStateStorage(kv));
genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH)); genesisState.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH));
final ProtocolContext<Void> protocolContext = final ProtocolContext<Void> protocolContext =
new ProtocolContext<>(blockchain, worldStateArchive, null); new ProtocolContext<>(blockchain, worldStateArchive, null);
@ -131,7 +139,10 @@ public class MainnetPantheonController implements PantheonController<Void> {
final EthProtocolManager ethProtocolManager = final EthProtocolManager ethProtocolManager =
new EthProtocolManager( new EthProtocolManager(
protocolContext.getBlockchain(), protocolContext.getBlockchain(),
genesisConfig.getChainId(), genesisConfig
.getConfigOptions()
.getChainId()
.orElse(MainnetProtocolSchedule.DEFAULT_CHAIN_ID),
fastSyncEnabled, fastSyncEnabled,
syncConfig.downloaderParallelism()); syncConfig.downloaderParallelism());
final SyncState syncState = final SyncState syncState =
@ -171,6 +182,7 @@ public class MainnetPantheonController implements PantheonController<Void> {
return new MainnetPantheonController( return new MainnetPantheonController(
genesisConfig, genesisConfig,
protocolSchedule,
protocolContext, protocolContext,
ethProtocolManager, ethProtocolManager,
synchronizer, synchronizer,
@ -199,8 +211,13 @@ public class MainnetPantheonController implements PantheonController<Void> {
} }
@Override @Override
public GenesisConfig<Void> getGenesisConfig() { public ProtocolSchedule<Void> getProtocolSchedule() {
return genesisConfig; return protocolSchedule;
}
@Override
public GenesisConfigOptions getGenesisConfigOptions() {
return genesisConfig.getConfigOptions();
} }
@Override @Override

@ -12,13 +12,11 @@
*/ */
package tech.pegasys.pantheon.controller; package tech.pegasys.pantheon.controller;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.config.GenesisConfigOptions; 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.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; 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.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Synchronizer; import tech.pegasys.pantheon.ethereum.core.Synchronizer;
import tech.pegasys.pantheon.ethereum.core.TransactionPool; import tech.pegasys.pantheon.ethereum.core.TransactionPool;
@ -31,8 +29,6 @@ import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import io.vertx.core.json.JsonObject;
public interface PantheonController<C> extends Closeable { public interface PantheonController<C> extends Closeable {
String DATABASE_PATH = "database"; String DATABASE_PATH = "database";
@ -47,46 +43,33 @@ public interface PantheonController<C> extends Closeable {
final KeyPair nodeKeys) final KeyPair nodeKeys)
throws IOException { throws IOException {
final JsonObject config = new JsonObject(configContents); final GenesisConfigFile config = GenesisConfigFile.fromConfig(configContents);
final GenesisConfigOptions configOptions = GenesisConfigOptions.fromGenesisConfig(config); final GenesisConfigOptions configOptions = config.getConfigOptions();
if (configOptions.isEthHash()) { if (configOptions.isEthHash()) {
return MainnetPantheonController.init( return MainnetPantheonController.init(
pantheonHome, pantheonHome,
GenesisConfig.fromConfig(config, MainnetProtocolSchedule.fromConfig(configOptions)), config,
MainnetProtocolSchedule.fromConfig(configOptions),
syncConfig, syncConfig,
miningParameters, miningParameters,
nodeKeys); nodeKeys);
} else if (configOptions.isIbft()) { } else if (configOptions.isIbft()) {
return IbftPantheonController.init( return IbftPantheonController.init(
pantheonHome, pantheonHome, config, syncConfig, ottomanTestnetOperation, networkId, nodeKeys);
GenesisConfig.fromConfig(config, IbftProtocolSchedule.create(configOptions)),
syncConfig,
ottomanTestnetOperation,
configOptions.getIbftConfigOptions(),
networkId,
nodeKeys);
} else if (configOptions.isClique()) { } else if (configOptions.isClique()) {
return CliquePantheonController.init( return CliquePantheonController.init(
pantheonHome, pantheonHome, config, syncConfig, miningParameters, networkId, nodeKeys);
GenesisConfig.fromConfig(config, CliqueProtocolSchedule.create(configOptions, nodeKeys)),
syncConfig,
miningParameters,
configOptions.getCliqueConfigOptions(),
networkId,
nodeKeys);
} else { } else {
throw new IllegalArgumentException("Unknown consensus mechanism defined"); throw new IllegalArgumentException("Unknown consensus mechanism defined");
} }
} }
default ProtocolSchedule<C> getProtocolSchedule() {
return getGenesisConfig().getProtocolSchedule();
}
ProtocolContext<C> getProtocolContext(); ProtocolContext<C> getProtocolContext();
GenesisConfig<C> getGenesisConfig(); ProtocolSchedule<C> getProtocolSchedule();
GenesisConfigOptions getGenesisConfigOptions();
Synchronizer getSynchronizer(); Synchronizer getSynchronizer();

@ -18,7 +18,6 @@ import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator; import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator;
import tech.pegasys.pantheon.ethereum.blockcreation.BlockMiner; 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.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Block; import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
@ -55,7 +54,6 @@ public class BlockImporter {
final Path blocks, final PantheonController<C> pantheonController) throws IOException { final Path blocks, final PantheonController<C> pantheonController) throws IOException {
final ProtocolSchedule<C> protocolSchedule = pantheonController.getProtocolSchedule(); final ProtocolSchedule<C> protocolSchedule = pantheonController.getProtocolSchedule();
final ProtocolContext<C> context = pantheonController.getProtocolContext(); final ProtocolContext<C> context = pantheonController.getProtocolContext();
final GenesisConfig<C> genesis = pantheonController.getGenesisConfig();
try (final RawBlockIterator iterator = try (final RawBlockIterator iterator =
new RawBlockIterator( new RawBlockIterator(
@ -69,7 +67,7 @@ public class BlockImporter {
while (iterator.hasNext()) { while (iterator.hasNext()) {
final Block block = iterator.next(); final Block block = iterator.next();
final BlockHeader header = block.getHeader(); final BlockHeader header = block.getHeader();
if (header.getNumber() == genesis.getBlock().getHeader().getNumber()) { if (header.getNumber() == BlockHeader.GENESIS_BLOCK_NUMBER) {
continue; continue;
} }
if (header.getNumber() % 100 == 0) { if (header.getNumber() % 100 == 0) {

@ -15,11 +15,11 @@ package tech.pegasys.pantheon;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; 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.MainnetPantheonController;
import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext; 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.Block;
import tech.pegasys.pantheon.ethereum.core.BlockImporter; import tech.pegasys.pantheon.ethereum.core.BlockImporter;
import tech.pegasys.pantheon.ethereum.core.BlockSyncTestUtils; 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.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration; import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode; 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.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer; import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer;
@ -93,7 +94,8 @@ public final class RunnerTest {
try (final PantheonController<Void> controller = try (final PantheonController<Void> controller =
MainnetPantheonController.init( MainnetPantheonController.init(
dbAhead, dbAhead,
GenesisConfig.mainnet(), GenesisConfigFile.mainnet(),
MainnetProtocolSchedule.create(),
fastSyncConfig, fastSyncConfig,
new MiningParametersTestBuilder().enabled(false).build(), new MiningParametersTestBuilder().enabled(false).build(),
aheadDbNodeKeys)) { aheadDbNodeKeys)) {
@ -104,7 +106,8 @@ public final class RunnerTest {
final PantheonController<Void> controllerAhead = final PantheonController<Void> controllerAhead =
MainnetPantheonController.init( MainnetPantheonController.init(
dbAhead, dbAhead,
GenesisConfig.mainnet(), GenesisConfigFile.mainnet(),
MainnetProtocolSchedule.create(),
fastSyncConfig, fastSyncConfig,
new MiningParametersTestBuilder().enabled(false).build(), new MiningParametersTestBuilder().enabled(false).build(),
aheadDbNodeKeys); aheadDbNodeKeys);
@ -137,7 +140,8 @@ public final class RunnerTest {
final PantheonController<Void> controllerBehind = final PantheonController<Void> controllerBehind =
MainnetPantheonController.init( MainnetPantheonController.init(
temp.newFolder().toPath(), temp.newFolder().toPath(),
GenesisConfig.mainnet(), GenesisConfigFile.mainnet(),
MainnetProtocolSchedule.create(),
fastSyncConfig, fastSyncConfig,
new MiningParametersTestBuilder().enabled(false).build(), new MiningParametersTestBuilder().enabled(false).build(),
behindDbNodeKeys); behindDbNodeKeys);

Loading…
Cancel
Save