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.
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Adrian Sutton 6 years ago committed by GitHub
parent a44d696117
commit 09a3c61f72
  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 {
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'io.vertx:vertx-core'
implementation 'com.google.guava:guava'
implementation 'org.apache.logging.log4j:log4j-api'
runtime 'org.apache.logging.log4j:log4j-core'

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

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

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

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

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

@ -20,7 +20,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
/** Defines the protocol behaviours for a blockchain using Clique. */
public class CliqueProtocolSchedule extends MutableProtocolSchedule<CliqueContext> {
public class CliqueProtocolSchedule {
private static final int DEFAULT_CHAIN_ID = 4;
@ -33,14 +33,14 @@ public class CliqueProtocolSchedule extends MutableProtocolSchedule<CliqueContex
final long blockPeriod = cliqueConfig.getBlockPeriodSeconds();
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)
final CliqueProtocolSpecs specs =
new CliqueProtocolSpecs(
blockPeriod,
epochLength,
chainId,
Util.publicKeyToAddress(nodeKeys.getPublicKey()),
protocolSchedule);

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

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

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

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

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

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

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

@ -124,7 +124,7 @@ public class BlockMinerTest {
}
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);
return protocolSchedule;
}

@ -19,6 +19,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.NONCE_TOO_LOW;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Address;
@ -53,7 +54,6 @@ import java.util.List;
import java.util.function.Supplier;
import com.google.common.collect.Lists;
import io.vertx.core.json.JsonObject;
import org.junit.Test;
public class BlockTransactionSelectorTest {
@ -63,7 +63,7 @@ public class BlockTransactionSelectorTest {
@Test
public void emptyPendingTransactionsResultsInEmptyVettingResult() {
final ProtocolSchedule<Void> protocolSchedule =
DevelopmentProtocolSchedule.create(new JsonObject());
DevelopmentProtocolSchedule.create(GenesisConfigFile.DEFAULT.getConfigOptions());
final Blockchain blockchain = new TestBlockchain();
final TransactionProcessor transactionProcessor =
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.entry;
import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryBlockchain;
import static tech.pegasys.pantheon.ethereum.core.InMemoryTestFixture.createInMemoryWorldStateArchive;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Account;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture;
import tech.pegasys.pantheon.ethereum.core.Gas;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.MutableWorldState;
import tech.pegasys.pantheon.ethereum.core.Transaction;
import tech.pegasys.pantheon.ethereum.core.Wei;
@ -63,12 +60,11 @@ public class TraceTransactionIntegrationTest {
@Before
public void setUp() {
final GenesisConfig<Void> genesisConfig = GenesisConfig.development();
genesisBlock = genesisConfig.getBlock();
blockchain = createInMemoryBlockchain(genesisBlock);
worldStateArchive = createInMemoryWorldStateArchive();
final ProtocolSchedule<Void> protocolSchedule = genesisConfig.getProtocolSchedule();
genesisConfig.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH));
final ExecutionContextTestFixture contextTestFixture = ExecutionContextTestFixture.create();
genesisBlock = contextTestFixture.getGenesis();
blockchain = contextTestFixture.getBlockchain();
worldStateArchive = contextTestFixture.getStateArchive();
final ProtocolSchedule<Void> protocolSchedule = contextTestFixture.getProtocolSchedule();
transactionProcessor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor();
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 tech.pegasys.pantheon.config.GenesisConfigOptions;
import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import io.vertx.core.json.JsonObject;
/**
* A mock ProtocolSchedule which behaves similarly to Frontier (but for all blocks), albeit with a
* A mock ProtocolSchedule which behaves similarly to Byzantium (but for all blocks), albeit with a
* much reduced difficulty (which supports testing on CPU alone).
*/
public class DevelopmentProtocolSchedule {
public static ProtocolSchedule<Void> create(final JsonObject config) {
final Integer chainId = config.getInteger("chainId", NO_CHAIN_ID);
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>();
public static ProtocolSchedule<Void> create(final GenesisConfigOptions config) {
final Integer chainId = config.getChainId().orElse(NO_CHAIN_ID);
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(chainId);
protocolSchedule.putMilestone(0, DevelopmentProtocolSpecs.first(chainId, protocolSchedule));
return protocolSchedule;
}

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

@ -24,6 +24,16 @@ public class MutableProtocolSchedule<C> implements ProtocolSchedule<C> {
new TreeSet<>(
Comparator.<ScheduledProtocolSpec<C>, Long>comparing(ScheduledProtocolSpec::getBlock)
.reversed());
private final int chainId;
public MutableProtocolSchedule(final int chainId) {
this.chainId = chainId;
}
@Override
public int getChainId() {
return chainId;
}
public void putMilestone(final long blockNumber, final ProtocolSpec<C> protocolSpec) {
final ScheduledProtocolSpec<C> scheduledProtocolSpec =

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

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

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

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

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

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

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

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

@ -63,27 +63,27 @@ public class ReferenceTestProtocolSchedules {
private static ProtocolSchedule<Void> createSchedule(
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));
return protocolSchedule;
}
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(5, MainnetProtocolSpecs.homestead(protocolSchedule));
return protocolSchedule;
}
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(5, MainnetProtocolSpecs.tangerineWhistle(protocolSchedule));
return protocolSchedule;
}
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);
protocolSchedule.putMilestone(0, homestead);
protocolSchedule.putMilestone(5, MainnetProtocolSpecs.daoRecoveryInit(protocolSchedule));
@ -93,7 +93,7 @@ public class ReferenceTestProtocolSchedules {
}
private static ProtocolSchedule<Void> eip158ToByzantiumAt5() {
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>();
final MutableProtocolSchedule<Void> protocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID);
protocolSchedule.putMilestone(
0, MainnetProtocolSpecs.spuriousDragon(CHAIN_ID, protocolSchedule));
protocolSchedule.putMilestone(5, MainnetProtocolSpecs.byzantium(CHAIN_ID, protocolSchedule));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading…
Cancel
Save