[PAN-3126] add an override facility for genesis configs (#1915)

Add a generalized genesis config override facility for command line use. Only useful for string or integer config values, not object values.

Sample use - enable Istanbul fork on block 99 million
--override-genesis-config=istanbulFork=99000000

Overriding a value with an empty string unsets the value

Sample use - disable Istanbul fork by un-setting istanbulFork:
--override-genesis-config=istanbulFork=
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Danno Ferrin 5 years ago committed by GitHub
parent 4ccfa71ed8
commit 82f9d5c002
  1. 8
      config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigFile.java
  2. 62
      config/src/main/java/tech/pegasys/pantheon/config/JsonGenesisConfigOptions.java
  3. 74
      config/src/test/java/tech/pegasys/pantheon/config/GenesisConfigFileTest.java
  4. 18
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java
  5. 7
      pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java
  6. 6
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java
  7. 9
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java
  8. 4
      pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java
  9. 18
      pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java
  10. 13
      pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonControllerBuilder.java
  11. 5
      pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java
  12. 38
      pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java

@ -16,6 +16,8 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static tech.pegasys.pantheon.config.JsonUtil.normalizeKeys;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
@ -82,9 +84,13 @@ public class GenesisConfigFile {
}
public GenesisConfigOptions getConfigOptions() {
return getConfigOptions(Collections.emptyMap());
}
public GenesisConfigOptions getConfigOptions(final Map<String, String> overrides) {
ObjectNode config =
JsonUtil.getObjectNode(configRoot, "config").orElse(JsonUtil.createEmptyObjectNode());
return new JsonGenesisConfigOptions(config);
return new JsonGenesisConfigOptions(config, overrides);
}
public Stream<GenesisAllocation> streamAllocations() {

@ -15,10 +15,12 @@ package tech.pegasys.pantheon.config;
import static java.util.Objects.isNull;
import java.math.BigInteger;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.TreeMap;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableMap;
@ -30,13 +32,22 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
private static final String IBFT2_CONFIG_KEY = "ibft2";
private static final String CLIQUE_CONFIG_KEY = "clique";
private final ObjectNode configRoot;
private final Map<String, String> configOverrides = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
public static JsonGenesisConfigOptions fromJsonObject(final ObjectNode configRoot) {
return new JsonGenesisConfigOptions(configRoot);
}
JsonGenesisConfigOptions(final ObjectNode maybeConfig) {
private JsonGenesisConfigOptions(final ObjectNode maybeConfig) {
this(maybeConfig, Collections.emptyMap());
}
JsonGenesisConfigOptions(
final ObjectNode maybeConfig, final Map<String, String> configOverrides) {
this.configRoot = isNull(maybeConfig) ? JsonUtil.createEmptyObjectNode() : maybeConfig;
if (configOverrides != null) {
this.configOverrides.putAll(configOverrides);
}
}
@Override
@ -148,17 +159,17 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
@Override
public Optional<BigInteger> getChainId() {
return JsonUtil.getValueAsString(configRoot, "chainid").map(BigInteger::new);
return getOptionalBigInteger("chainid");
}
@Override
public OptionalInt getContractSizeLimit() {
return JsonUtil.getInt(configRoot, "contractsizelimit");
return getOptionalInt("contractsizelimit");
}
@Override
public OptionalInt getEvmStackSize() {
return JsonUtil.getInt(configRoot, "evmstacksize");
return getOptionalInt("evmstacksize");
}
@Override
@ -176,9 +187,8 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
.ifPresent(
l -> {
builder.put("eip150Block", l);
if (configRoot.has("eip150hash")) {
builder.put("eip150Hash", configRoot.get("eip150hash").asText());
}
getOptionalString("eip150hash")
.ifPresent(eip150hash -> builder.put("eip150Hash", eip150hash));
});
getSpuriousDragonBlockNumber()
.ifPresent(
@ -207,7 +217,45 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return builder.build();
}
private Optional<String> getOptionalString(final String key) {
if (configOverrides.containsKey(key)) {
final String value = configOverrides.get(key);
return value == null || value.isEmpty() ? Optional.empty() : Optional.of(value);
} else {
return JsonUtil.getString(configRoot, key);
}
}
private OptionalLong getOptionalLong(final String key) {
if (configOverrides.containsKey(key)) {
final String value = configOverrides.get(key);
return value == null || value.isEmpty()
? OptionalLong.empty()
: OptionalLong.of(Long.valueOf(configOverrides.get(key), 10));
} else {
return JsonUtil.getLong(configRoot, key);
}
}
private OptionalInt getOptionalInt(final String key) {
if (configOverrides.containsKey(key)) {
final String value = configOverrides.get(key);
return value == null || value.isEmpty()
? OptionalInt.empty()
: OptionalInt.of(Integer.valueOf(configOverrides.get(key), 10));
} else {
return JsonUtil.getInt(configRoot, key);
}
}
private Optional<BigInteger> getOptionalBigInteger(final String key) {
if (configOverrides.containsKey(key)) {
final String value = configOverrides.get(key);
return value == null || value.isEmpty()
? Optional.empty()
: Optional.of(new BigInteger(value));
} else {
return JsonUtil.getValueAsString(configRoot, key).map(s -> new BigInteger(s, 10));
}
}
}

@ -16,7 +16,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -214,6 +216,78 @@ public class GenesisConfigFileTest {
// Unfortunately there is no good (non-flakey) way to assert logs.
}
@Test
public void testOverridePresent() {
final GenesisConfigFile config = GenesisConfigFile.development();
final int bigBlock = 999_999_999;
final String bigBlockString = Integer.toString(bigBlock);
final Map<String, String> override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
override.put("istanbulBlock", bigBlockString);
override.put("chainId", bigBlockString);
override.put("contractSizeLimit", bigBlockString);
assertThat(config.getConfigOptions(override).getIstanbulBlockNumber()).hasValue(bigBlock);
assertThat(config.getConfigOptions(override).getChainId())
.hasValue(BigInteger.valueOf(bigBlock));
assertThat(config.getConfigOptions(override).getContractSizeLimit()).hasValue(bigBlock);
}
@Test
public void testOverrideNull() {
final GenesisConfigFile config = GenesisConfigFile.development();
final Map<String, String> override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
override.put("istanbulBlock", null);
override.put("chainId", null);
override.put("contractSizeLimit", null);
assertThat(config.getConfigOptions(override).getIstanbulBlockNumber()).isNotPresent();
assertThat(config.getConfigOptions(override).getChainId()).isNotPresent();
assertThat(config.getConfigOptions(override).getContractSizeLimit()).isNotPresent();
}
@Test
public void testOverrideCaseInsensitivity() {
final GenesisConfigFile config = GenesisConfigFile.development();
final int bigBlock = 999_999_999;
final String bigBlockString = Integer.toString(bigBlock);
final Map<String, String> override = new HashMap<>();
// as speicified
override.put("istanbulBlock", bigBlockString);
// ALL CAPS
override.put("CHAINID", bigBlockString);
// all lower case
override.put("contractsizelimit", bigBlockString);
assertThat(config.getConfigOptions(override).getIstanbulBlockNumber()).hasValue(bigBlock);
assertThat(config.getConfigOptions(override).getChainId())
.hasValue(BigInteger.valueOf(bigBlock));
assertThat(config.getConfigOptions(override).getContractSizeLimit()).hasValue(bigBlock);
}
@Test
public void testOverrideEmptyString() {
final GenesisConfigFile config = GenesisConfigFile.development();
final Map<String, String> override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
override.put("istanbulBlock", "");
override.put("chainId", "");
override.put("contractSizeLimit", "");
assertThat(config.getConfigOptions(override).getIstanbulBlockNumber()).isNotPresent();
assertThat(config.getConfigOptions(override).getChainId()).isNotPresent();
assertThat(config.getConfigOptions(override).getContractSizeLimit()).isNotPresent();
}
@Test
public void testNoOverride() {
final GenesisConfigFile config = GenesisConfigFile.development();
assertThat(config.getConfigOptions().getConstantinopleFixBlockNumber()).hasValue(0);
assertThat(config.getConfigOptions().getIstanbulBlockNumber()).isNotPresent();
assertThat(config.getConfigOptions().getChainId()).hasValue(BigInteger.valueOf(2018));
assertThat(config.getConfigOptions().getContractSizeLimit()).hasValue(2147483647);
assertThat(config.getConfigOptions().getEvmStackSize()).isNotPresent();
}
private GenesisConfigFile configWithProperty(final String key, final String value) {
return GenesisConfigFile.fromConfig("{\"" + key + "\":\"" + value + "\"}");
}

@ -118,6 +118,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@ -650,6 +651,16 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
private final Integer pendingTxRetentionPeriod =
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS;
@Option(
names = {"--override-genesis-config"},
paramLabel = "NAME=VALUE",
description = "Overrides configuration values in the genesis file. Use with care.",
arity = "*",
hidden = true,
split = ",")
private final Map<String, String> genesisConfigOverrides =
new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private EthNetworkConfig ethNetworkConfig;
private JsonRpcConfiguration jsonRpcConfiguration;
private GraphQLConfiguration graphQLConfiguration;
@ -932,7 +943,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
public PantheonControllerBuilder<?> getControllerBuilder() {
try {
return controllerBuilderFactory
.fromEthNetworkConfig(updateNetworkConfig(getNetwork()))
.fromEthNetworkConfig(updateNetworkConfig(getNetwork()), genesisConfigOverrides)
.synchronizerConfiguration(buildSyncConfig())
.ethProtocolConfiguration(ethProtocolOptions.toDomainObject())
.rocksDbConfiguration(buildRocksDbConfiguration())
@ -946,7 +957,8 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
.clock(Clock.systemUTC())
.isRevertReasonEnabled(isRevertReasonEnabled)
.isPruningEnabled(isPruningEnabled)
.pruningConfiguration(buildPruningConfiguration());
.pruningConfiguration(buildPruningConfiguration())
.genesisConfigOverrides(genesisConfigOverrides);
} catch (final IOException e) {
throw new ExecutionException(this.commandLine, "Invalid path", e);
}
@ -1351,7 +1363,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(genesisConfig());
builder.setNetworkId(
genesisConfigFile
.getConfigOptions()
.getConfigOptions(genesisConfigOverrides)
.getChainId()
.orElse(EthNetworkConfig.getNetworkConfig(MAINNET).getNetworkId()));
} catch (final DecodeException e) {

@ -59,7 +59,7 @@ public class CliquePantheonControllerBuilder extends PantheonControllerBuilder<C
protected void prepForBuild() {
localAddress = Util.publicKeyToAddress(nodeKeys.getPublicKey());
final CliqueConfigOptions cliqueConfig =
genesisConfig.getConfigOptions().getCliqueConfigOptions();
genesisConfig.getConfigOptions(genesisConfigOverrides).getCliqueConfigOptions();
final long blocksPerEpoch = cliqueConfig.getEpochLength();
secondsBetweenBlocks = cliqueConfig.getBlockPeriodSeconds();
@ -121,7 +121,10 @@ public class CliquePantheonControllerBuilder extends PantheonControllerBuilder<C
@Override
protected ProtocolSchedule<CliqueContext> createProtocolSchedule() {
return CliqueProtocolSchedule.create(
genesisConfig.getConfigOptions(), nodeKeys, privacyParameters, isRevertReasonEnabled);
genesisConfig.getConfigOptions(genesisConfigOverrides),
nodeKeys,
privacyParameters,
isRevertReasonEnabled);
}
@Override

@ -64,14 +64,16 @@ public class IbftLegacyPantheonControllerBuilder extends PantheonControllerBuild
@Override
protected ProtocolSchedule<IbftContext> createProtocolSchedule() {
return IbftProtocolSchedule.create(
genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled);
genesisConfig.getConfigOptions(genesisConfigOverrides),
privacyParameters,
isRevertReasonEnabled);
}
@Override
protected IbftContext createConsensusContext(
final Blockchain blockchain, final WorldStateArchive worldStateArchive) {
final IbftConfigOptions ibftConfig =
genesisConfig.getConfigOptions().getIbftLegacyConfigOptions();
genesisConfig.getConfigOptions(genesisConfigOverrides).getIbftLegacyConfigOptions();
final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());
final VoteTallyCache voteTallyCache =
new VoteTallyCache(

@ -81,7 +81,7 @@ public class IbftPantheonControllerBuilder extends PantheonControllerBuilder<Ibf
@Override
protected void prepForBuild() {
ibftConfig = genesisConfig.getConfigOptions().getIbft2ConfigOptions();
ibftConfig = genesisConfig.getConfigOptions(genesisConfigOverrides).getIbft2ConfigOptions();
ibftEventQueue = new IbftEventQueue(ibftConfig.getMessageQueueLimit());
}
@ -211,7 +211,9 @@ public class IbftPantheonControllerBuilder extends PantheonControllerBuilder<Ibf
@Override
protected ProtocolSchedule<IbftContext> createProtocolSchedule() {
return IbftProtocolSchedule.create(
genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled);
genesisConfig.getConfigOptions(genesisConfigOverrides),
privacyParameters,
isRevertReasonEnabled);
}
@Override
@ -226,7 +228,8 @@ public class IbftPantheonControllerBuilder extends PantheonControllerBuilder<Ibf
@Override
protected IbftContext createConsensusContext(
final Blockchain blockchain, final WorldStateArchive worldStateArchive) {
final IbftConfigOptions ibftConfig = genesisConfig.getConfigOptions().getIbft2ConfigOptions();
final IbftConfigOptions ibftConfig =
genesisConfig.getConfigOptions(genesisConfigOverrides).getIbft2ConfigOptions();
final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());
return new IbftContext(
new VoteTallyCache(

@ -86,6 +86,8 @@ public class MainnetPantheonControllerBuilder extends PantheonControllerBuilder<
@Override
protected ProtocolSchedule<Void> createProtocolSchedule() {
return MainnetProtocolSchedule.fromConfig(
genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled);
genesisConfig.getConfigOptions(genesisConfigOverrides),
privacyParameters,
isRevertReasonEnabled);
}
}

@ -29,6 +29,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
public class PantheonController<C> implements java.io.Closeable {
@ -129,12 +130,25 @@ public class PantheonController<C> implements java.io.Closeable {
public PantheonControllerBuilder<?> fromEthNetworkConfig(
final EthNetworkConfig ethNetworkConfig) {
return fromGenesisConfig(GenesisConfigFile.fromConfig(ethNetworkConfig.getGenesisConfig()))
return fromEthNetworkConfig(ethNetworkConfig, Collections.emptyMap());
}
public PantheonControllerBuilder<?> fromEthNetworkConfig(
final EthNetworkConfig ethNetworkConfig, final Map<String, String> genesisConfigOverrides) {
return fromGenesisConfig(
GenesisConfigFile.fromConfig(ethNetworkConfig.getGenesisConfig()),
genesisConfigOverrides)
.networkId(ethNetworkConfig.getNetworkId());
}
public PantheonControllerBuilder<?> fromGenesisConfig(final GenesisConfigFile genesisConfig) {
final GenesisConfigOptions configOptions = genesisConfig.getConfigOptions();
return fromGenesisConfig(genesisConfig, Collections.emptyMap());
}
public PantheonControllerBuilder<?> fromGenesisConfig(
final GenesisConfigFile genesisConfig, final Map<String, String> genesisConfigOverrides) {
final GenesisConfigOptions configOptions =
genesisConfig.getConfigOptions(genesisConfigOverrides);
final PantheonControllerBuilder<?> builder;
if (configOptions.isEthHash()) {

@ -60,6 +60,7 @@ import java.time.Clock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.concurrent.Executors;
@ -89,6 +90,7 @@ public abstract class PantheonControllerBuilder<C> {
private RocksDbConfiguration rocksDbConfiguration;
private boolean isPruningEnabled;
private PruningConfiguration pruningConfiguration;
Map<String, String> genesisConfigOverrides;
public PantheonControllerBuilder<C> rocksDbConfiguration(
final RocksDbConfiguration rocksDbConfiguration) {
@ -181,6 +183,12 @@ public abstract class PantheonControllerBuilder<C> {
return this;
}
public PantheonControllerBuilder<C> genesisConfigOverrides(
final Map<String, String> genesisConfigOverrides) {
this.genesisConfigOverrides = genesisConfigOverrides;
return this;
}
public PantheonController<C> build() throws IOException {
checkNotNull(genesisConfig, "Missing genesis config");
checkNotNull(syncConfig, "Missing sync config");
@ -272,7 +280,8 @@ public abstract class PantheonControllerBuilder<C> {
clock,
metricsSystem);
final OptionalLong daoBlock = genesisConfig.getConfigOptions().getDaoForkBlock();
final OptionalLong daoBlock =
genesisConfig.getConfigOptions(genesisConfigOverrides).getDaoForkBlock();
if (daoBlock.isPresent()) {
// Setup dao validator
final EthContext ethContext = ethProtocolManager.ethContext();
@ -311,7 +320,7 @@ public abstract class PantheonControllerBuilder<C> {
protocolSchedule,
protocolContext,
ethProtocolManager,
genesisConfig.getConfigOptions(),
genesisConfig.getConfigOptions(genesisConfigOverrides),
subProtocolConfiguration,
synchronizer,
additionalJsonRpcMethodFactory,

@ -139,7 +139,9 @@ public abstract class CommandTestAbstract {
public void initMocks() throws Exception {
// doReturn used because of generic PantheonController
doReturn(mockControllerBuilder).when(mockControllerBuilderFactory).fromEthNetworkConfig(any());
doReturn(mockControllerBuilder)
.when(mockControllerBuilderFactory)
.fromEthNetworkConfig(any(), any());
when(mockControllerBuilder.synchronizerConfiguration(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.ethProtocolConfiguration(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.rocksDbConfiguration(any())).thenReturn(mockControllerBuilder);
@ -154,6 +156,7 @@ public abstract class CommandTestAbstract {
when(mockControllerBuilder.isRevertReasonEnabled(false)).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.isPruningEnabled(anyBoolean())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.pruningConfiguration(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.genesisConfigOverrides(any())).thenReturn(mockControllerBuilder);
// doReturn used because of generic PantheonController
doReturn(mockController).when(mockControllerBuilder).build();

@ -17,6 +17,7 @@ import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.Mockito.atLeast;
@ -70,6 +71,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -168,7 +170,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
verify(mockRunnerBuilder).ethNetworkConfig(ethNetworkArg.capture());
verify(mockRunnerBuilder).build();
verify(mockControllerBuilderFactory).fromEthNetworkConfig(ethNetworkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(ethNetworkArg.capture(), any());
final ArgumentCaptor<MiningParameters> miningArg =
ArgumentCaptor.forClass(MiningParameters.class);
verify(mockControllerBuilder).synchronizerConfiguration(syncConfigurationCaptor.capture());
@ -333,7 +335,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
.setBootNodes(nodes)
.build();
verify(mockControllerBuilder).dataDirectory(eq(Paths.get("/opt/pantheon").toAbsolutePath()));
verify(mockControllerBuilderFactory).fromEthNetworkConfig(eq(networkConfig));
verify(mockControllerBuilderFactory).fromEthNetworkConfig(eq(networkConfig), any());
verify(mockControllerBuilder).synchronizerConfiguration(syncConfigurationCaptor.capture());
assertThat(syncConfigurationCaptor.getValue().getSyncMode()).isEqualTo(SyncMode.FAST);
@ -891,7 +893,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
parseCommand("--genesis-file", genesisFile.toString());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue().getGenesisConfig())
@ -927,7 +929,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue().getGenesisConfig())
@ -950,7 +952,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue().getGenesisConfig())
@ -963,6 +965,22 @@ public class PantheonCommandTest extends CommandTestAbstract {
assertThat(commandErrorOutput.toString()).isEmpty();
}
@Test
@SuppressWarnings("unchecked")
public void overrideGenesisConfigFileChange() throws Exception {
final ArgumentCaptor<Map<String, String>> overrides = ArgumentCaptor.forClass(Map.class);
parseCommand("--network=dev", "--override-genesis-config=chainId=8675309");
verify(mockControllerBuilderFactory).fromEthNetworkConfig(any(), overrides.capture());
verify(mockControllerBuilder).build();
assertThat(overrides.getValue()).containsOnlyKeys("chainId");
assertThat(overrides.getValue()).containsEntry("chainId", "8675309");
assertThat(commandOutput.toString()).isEmpty();
assertThat(commandErrorOutput.toString()).isEmpty();
}
@Test
public void predefinedNetworkIdsMustBeEqualToChainIds() {
// check the network id against the one in mainnet genesis config
@ -2344,7 +2362,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(DEV));
@ -2360,7 +2378,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(RINKEBY));
@ -2376,7 +2394,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(ROPSTEN));
@ -2392,7 +2410,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(GOERLI));
@ -2433,7 +2451,7 @@ public class PantheonCommandTest extends CommandTestAbstract {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture());
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue().getBootNodes())

Loading…
Cancel
Save