mirror of https://github.com/hyperledger/besu
Common protocol schedule config handling (#250)
* Introduce ProtocolScheduleBuilder and use it for Clique, MainNet, IBFT and dev. * Remove default milestone blocks and simplify MainnetProtocolSchedule. All milestone blocks must now be defined in the genesis file (previously ethash chains would get Mainnet milestone blocks by default).
parent
b1fec1b6bf
commit
2b661e7382
@ -0,0 +1,102 @@ |
|||||||
|
/* |
||||||
|
* 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 java.util.OptionalInt; |
||||||
|
import java.util.OptionalLong; |
||||||
|
|
||||||
|
import io.vertx.core.json.JsonObject; |
||||||
|
|
||||||
|
public class JsonGenesisConfigOptions implements GenesisConfigOptions { |
||||||
|
|
||||||
|
private static final String ETHASH_CONFIG_KEY = "ethash"; |
||||||
|
private static final String IBFT_CONFIG_KEY = "ibft"; |
||||||
|
private static final String CLIQUE_CONFIG_KEY = "clique"; |
||||||
|
private final JsonObject configRoot; |
||||||
|
|
||||||
|
JsonGenesisConfigOptions(final JsonObject configRoot) { |
||||||
|
this.configRoot = configRoot != null ? configRoot : new JsonObject(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEthHash() { |
||||||
|
return configRoot.containsKey(ETHASH_CONFIG_KEY); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isIbft() { |
||||||
|
return configRoot.containsKey(IBFT_CONFIG_KEY); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isClique() { |
||||||
|
return configRoot.containsKey(CLIQUE_CONFIG_KEY); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public IbftConfigOptions getIbftConfigOptions() { |
||||||
|
return isIbft() |
||||||
|
? new IbftConfigOptions(configRoot.getJsonObject(IBFT_CONFIG_KEY)) |
||||||
|
: IbftConfigOptions.DEFAULT; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CliqueConfigOptions getCliqueConfigOptions() { |
||||||
|
return isClique() |
||||||
|
? new CliqueConfigOptions(configRoot.getJsonObject(CLIQUE_CONFIG_KEY)) |
||||||
|
: CliqueConfigOptions.DEFAULT; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getHomesteadBlockNumber() { |
||||||
|
return getOptionalLong("homesteadblock"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getDaoForkBlock() { |
||||||
|
return getOptionalLong("daoforkblock"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getTangerineWhistleBlockNumber() { |
||||||
|
return getOptionalLong("eip150block"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getSpuriousDragonBlockNumber() { |
||||||
|
return getOptionalLong("eip158block"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getByzantiumBlockNumber() { |
||||||
|
return getOptionalLong("byzantiumblock"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getConstantinopleBlockNumber() { |
||||||
|
return getOptionalLong("constantinopleblock"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalInt getChainId() { |
||||||
|
return configRoot.containsKey("chainid") |
||||||
|
? OptionalInt.of(configRoot.getInteger("chainid")) |
||||||
|
: OptionalInt.empty(); |
||||||
|
} |
||||||
|
|
||||||
|
private OptionalLong getOptionalLong(final String key) { |
||||||
|
return configRoot.containsKey(key) |
||||||
|
? OptionalLong.of(configRoot.getLong(key)) |
||||||
|
: OptionalLong.empty(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,122 @@ |
|||||||
|
/* |
||||||
|
* 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 java.util.OptionalInt; |
||||||
|
import java.util.OptionalLong; |
||||||
|
|
||||||
|
public class StubGenesisConfigOptions implements GenesisConfigOptions { |
||||||
|
|
||||||
|
private OptionalLong homesteadBlockNumber = OptionalLong.empty(); |
||||||
|
private OptionalLong daoForkBlock = OptionalLong.empty(); |
||||||
|
private OptionalLong tangerineWhistleBlockNumber = OptionalLong.empty(); |
||||||
|
private OptionalLong spuriousDragonBlockNumber = OptionalLong.empty(); |
||||||
|
private OptionalLong byzantiumBlockNumber = OptionalLong.empty(); |
||||||
|
private OptionalLong constantinopleBlockNumber = OptionalLong.empty(); |
||||||
|
private OptionalInt chainId = OptionalInt.empty(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isEthHash() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isIbft() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isClique() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public IbftConfigOptions getIbftConfigOptions() { |
||||||
|
return IbftConfigOptions.DEFAULT; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CliqueConfigOptions getCliqueConfigOptions() { |
||||||
|
return CliqueConfigOptions.DEFAULT; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getHomesteadBlockNumber() { |
||||||
|
return homesteadBlockNumber; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getDaoForkBlock() { |
||||||
|
return daoForkBlock; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getTangerineWhistleBlockNumber() { |
||||||
|
return tangerineWhistleBlockNumber; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getSpuriousDragonBlockNumber() { |
||||||
|
return spuriousDragonBlockNumber; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getByzantiumBlockNumber() { |
||||||
|
return byzantiumBlockNumber; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalLong getConstantinopleBlockNumber() { |
||||||
|
return constantinopleBlockNumber; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public OptionalInt getChainId() { |
||||||
|
return chainId; |
||||||
|
} |
||||||
|
|
||||||
|
public StubGenesisConfigOptions homesteadBlock(final long blockNumber) { |
||||||
|
homesteadBlockNumber = OptionalLong.of(blockNumber); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public StubGenesisConfigOptions daoForkBlock(final long blockNumber) { |
||||||
|
daoForkBlock = OptionalLong.of(blockNumber); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public StubGenesisConfigOptions eip150Block(final long blockNumber) { |
||||||
|
tangerineWhistleBlockNumber = OptionalLong.of(blockNumber); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public StubGenesisConfigOptions eip158Block(final long blockNumber) { |
||||||
|
spuriousDragonBlockNumber = OptionalLong.of(blockNumber); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public StubGenesisConfigOptions byzantiumBlock(final long blockNumber) { |
||||||
|
byzantiumBlockNumber = OptionalLong.of(blockNumber); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public StubGenesisConfigOptions constantinopleBlock(final long blockNumber) { |
||||||
|
constantinopleBlockNumber = OptionalLong.of(blockNumber); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public StubGenesisConfigOptions chainId(final int chainId) { |
||||||
|
this.chainId = OptionalInt.of(chainId); |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
@ -1,87 +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.consensus.clique; |
|
||||||
|
|
||||||
import static tech.pegasys.pantheon.consensus.clique.BlockHeaderValidationRulesetFactory.cliqueBlockHeaderValidator; |
|
||||||
|
|
||||||
import tech.pegasys.pantheon.consensus.common.EpochManager; |
|
||||||
import tech.pegasys.pantheon.ethereum.core.Address; |
|
||||||
import tech.pegasys.pantheon.ethereum.core.Wei; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockBodyValidator; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockImporter; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSpecs; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder; |
|
||||||
|
|
||||||
/** Factory for producing Clique protocol specs for given configurations and known fork points */ |
|
||||||
public class CliqueProtocolSpecs { |
|
||||||
|
|
||||||
private final long secondsBetweenBlocks; |
|
||||||
private final long epochLength; |
|
||||||
private final Address localNodeAddress; |
|
||||||
private final ProtocolSchedule<CliqueContext> protocolSchedule; |
|
||||||
|
|
||||||
public CliqueProtocolSpecs( |
|
||||||
final long secondsBetweenBlocks, |
|
||||||
final long epochLength, |
|
||||||
final Address localNodeAddress, |
|
||||||
final ProtocolSchedule<CliqueContext> protocolSchedule) { |
|
||||||
this.secondsBetweenBlocks = secondsBetweenBlocks; |
|
||||||
this.epochLength = epochLength; |
|
||||||
this.localNodeAddress = localNodeAddress; |
|
||||||
this.protocolSchedule = protocolSchedule; |
|
||||||
} |
|
||||||
|
|
||||||
public ProtocolSpec<CliqueContext> frontier() { |
|
||||||
return applyCliqueSpecificModifications(MainnetProtocolSpecs.frontierDefinition()); |
|
||||||
} |
|
||||||
|
|
||||||
public ProtocolSpec<CliqueContext> homestead() { |
|
||||||
return applyCliqueSpecificModifications(MainnetProtocolSpecs.homesteadDefinition()); |
|
||||||
} |
|
||||||
|
|
||||||
public ProtocolSpec<CliqueContext> tangerineWhistle() { |
|
||||||
return applyCliqueSpecificModifications(MainnetProtocolSpecs.tangerineWhistleDefinition()); |
|
||||||
} |
|
||||||
|
|
||||||
public ProtocolSpec<CliqueContext> spuriousDragon() { |
|
||||||
return applyCliqueSpecificModifications( |
|
||||||
MainnetProtocolSpecs.spuriousDragonDefinition(protocolSchedule.getChainId())); |
|
||||||
} |
|
||||||
|
|
||||||
public ProtocolSpec<CliqueContext> byzantium() { |
|
||||||
return applyCliqueSpecificModifications( |
|
||||||
MainnetProtocolSpecs.byzantiumDefinition(protocolSchedule.getChainId())); |
|
||||||
} |
|
||||||
|
|
||||||
public ProtocolSpec<CliqueContext> constantinople() { |
|
||||||
return applyCliqueSpecificModifications( |
|
||||||
MainnetProtocolSpecs.constantinopleDefinition(protocolSchedule.getChainId())); |
|
||||||
} |
|
||||||
|
|
||||||
private ProtocolSpec<CliqueContext> applyCliqueSpecificModifications( |
|
||||||
final ProtocolSpecBuilder<Void> specBuilder) { |
|
||||||
final EpochManager epochManager = new EpochManager(epochLength); |
|
||||||
return specBuilder |
|
||||||
.<CliqueContext>changeConsensusContextType( |
|
||||||
difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager), |
|
||||||
difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager), |
|
||||||
MainnetBlockBodyValidator::new, |
|
||||||
MainnetBlockImporter::new, |
|
||||||
new CliqueDifficultyCalculator(localNodeAddress)) |
|
||||||
.blockReward(Wei.ZERO) |
|
||||||
.miningBeneficiaryCalculator(CliqueHelpers::getProposerOfBlock) |
|
||||||
.build(protocolSchedule); |
|
||||||
} |
|
||||||
} |
|
@ -1,57 +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.consensus.clique; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Java6Assertions.assertThat; |
|
||||||
|
|
||||||
import tech.pegasys.pantheon.ethereum.core.AddressHelpers; |
|
||||||
import tech.pegasys.pantheon.ethereum.core.Wei; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSpecs; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
|
|
||||||
public class CliqueProtocolSpecsTest { |
|
||||||
|
|
||||||
private static final int CHAIN_ID = 5; |
|
||||||
CliqueProtocolSpecs protocolSpecs = |
|
||||||
new CliqueProtocolSpecs( |
|
||||||
15, 30_000, AddressHelpers.ofValue(5), new MutableProtocolSchedule<>(CHAIN_ID)); |
|
||||||
|
|
||||||
@Test |
|
||||||
public void homsteadParametersAlignWithMainnetWithAdjustments() { |
|
||||||
final ProtocolSpec<CliqueContext> homestead = protocolSpecs.homestead(); |
|
||||||
|
|
||||||
assertThat(homestead.getName()).isEqualTo("Homestead"); |
|
||||||
assertThat(homestead.getBlockReward()).isEqualTo(Wei.ZERO); |
|
||||||
assertThat(homestead.getDifficultyCalculator()).isInstanceOf(CliqueDifficultyCalculator.class); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void allSpecsInheritFromMainnetCounterparts() { |
|
||||||
final ProtocolSchedule<Void> mainnetProtocolSchedule = new MutableProtocolSchedule<>(CHAIN_ID); |
|
||||||
|
|
||||||
assertThat(protocolSpecs.frontier().getName()) |
|
||||||
.isEqualTo(MainnetProtocolSpecs.frontier(mainnetProtocolSchedule).getName()); |
|
||||||
assertThat(protocolSpecs.homestead().getName()) |
|
||||||
.isEqualTo(MainnetProtocolSpecs.homestead(mainnetProtocolSchedule).getName()); |
|
||||||
assertThat(protocolSpecs.tangerineWhistle().getName()) |
|
||||||
.isEqualTo(MainnetProtocolSpecs.tangerineWhistle(mainnetProtocolSchedule).getName()); |
|
||||||
assertThat(protocolSpecs.spuriousDragon().getName()) |
|
||||||
.isEqualTo(MainnetProtocolSpecs.spuriousDragon(1, mainnetProtocolSchedule).getName()); |
|
||||||
assertThat(protocolSpecs.byzantium().getName()) |
|
||||||
.isEqualTo(MainnetProtocolSpecs.byzantium(1, mainnetProtocolSchedule).getName()); |
|
||||||
} |
|
||||||
} |
|
@ -1,63 +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.consensus.ibftlegacy; |
|
||||||
|
|
||||||
import static tech.pegasys.pantheon.consensus.ibftlegacy.IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator; |
|
||||||
|
|
||||||
import tech.pegasys.pantheon.consensus.common.EpochManager; |
|
||||||
import tech.pegasys.pantheon.consensus.ibft.IbftBlockImporter; |
|
||||||
import tech.pegasys.pantheon.consensus.ibft.IbftContext; |
|
||||||
import tech.pegasys.pantheon.ethereum.core.Wei; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockBodyValidator; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockImporter; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSpecs; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; |
|
||||||
|
|
||||||
import java.math.BigInteger; |
|
||||||
|
|
||||||
/** Factory for producing Ibft protocol specs for given configurations and known fork points */ |
|
||||||
public class IbftProtocolSpecs { |
|
||||||
|
|
||||||
/** |
|
||||||
* Produce the ProtocolSpec for an IBFT chain that uses spurious dragon milestone configuration |
|
||||||
* |
|
||||||
* @param secondsBetweenBlocks the block period in seconds |
|
||||||
* @param epochLength the number of blocks in each epoch |
|
||||||
* @param chainId the id of the Chain. |
|
||||||
* @param protocolSchedule the {@link ProtocolSchedule} this spec will be part of |
|
||||||
* @return a configured ProtocolSpec for dealing with IBFT blocks |
|
||||||
*/ |
|
||||||
public static ProtocolSpec<IbftContext> spuriousDragon( |
|
||||||
final long secondsBetweenBlocks, |
|
||||||
final long epochLength, |
|
||||||
final int chainId, |
|
||||||
final ProtocolSchedule<IbftContext> protocolSchedule) { |
|
||||||
final EpochManager epochManager = new EpochManager(epochLength); |
|
||||||
return MainnetProtocolSpecs.spuriousDragonDefinition(chainId) |
|
||||||
.<IbftContext>changeConsensusContextType( |
|
||||||
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), |
|
||||||
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), |
|
||||||
MainnetBlockBodyValidator::new, |
|
||||||
(blockHeaderValidator, blockBodyValidator, blockProcessor) -> |
|
||||||
new IbftBlockImporter( |
|
||||||
new MainnetBlockImporter<>( |
|
||||||
blockHeaderValidator, blockBodyValidator, blockProcessor), |
|
||||||
new IbftVoteTallyUpdater(epochManager)), |
|
||||||
(time, parent, protocolContext) -> BigInteger.ONE) |
|
||||||
.blockReward(Wei.ZERO) |
|
||||||
.blockHashFunction(IbftBlockHashing::calculateHashOfIbftBlockOnChain) |
|
||||||
.name("IBFT") |
|
||||||
.build(protocolSchedule); |
|
||||||
} |
|
||||||
} |
|
@ -1,36 +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.development; |
|
||||||
|
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSpecs; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; |
|
||||||
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; |
|
||||||
|
|
||||||
/** |
|
||||||
* Provides a protocol specification which is suitable for use on private, PoW networks, where block |
|
||||||
* mining is performed on CPUs alone. |
|
||||||
*/ |
|
||||||
public class DevelopmentProtocolSpecs { |
|
||||||
|
|
||||||
/* |
|
||||||
* The DevelopmentProtocolSpecification is the same as the byzantium spec, but with a much reduced |
|
||||||
* difficulty calculator (to support CPU mining). |
|
||||||
*/ |
|
||||||
public static ProtocolSpec<Void> first( |
|
||||||
final Integer chainId, final ProtocolSchedule<Void> protocolSchedule) { |
|
||||||
return MainnetProtocolSpecs.byzantiumDefinition(chainId) |
|
||||||
.difficultyCalculator(DevelopmentDifficultyCalculators.DEVELOPER) |
|
||||||
.name("first") |
|
||||||
.build(protocolSchedule); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,96 @@ |
|||||||
|
/* |
||||||
|
* 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.mainnet; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.config.GenesisConfigOptions; |
||||||
|
|
||||||
|
import java.util.OptionalLong; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
public class ProtocolScheduleBuilder<C> { |
||||||
|
|
||||||
|
private final GenesisConfigOptions config; |
||||||
|
private final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter; |
||||||
|
private final int defaultChainId; |
||||||
|
|
||||||
|
public ProtocolScheduleBuilder( |
||||||
|
final GenesisConfigOptions config, |
||||||
|
final int defaultChainId, |
||||||
|
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter) { |
||||||
|
this.config = config; |
||||||
|
this.protocolSpecAdapter = protocolSpecAdapter; |
||||||
|
this.defaultChainId = defaultChainId; |
||||||
|
} |
||||||
|
|
||||||
|
public ProtocolSchedule<C> createProtocolSchedule() { |
||||||
|
final int chainId = config.getChainId().orElse(defaultChainId); |
||||||
|
final MutableProtocolSchedule<C> protocolSchedule = new MutableProtocolSchedule<>(chainId); |
||||||
|
|
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, OptionalLong.of(0), MainnetProtocolSpecs.frontierDefinition()); |
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, |
||||||
|
config.getHomesteadBlockNumber(), |
||||||
|
MainnetProtocolSpecs.homesteadDefinition()); |
||||||
|
|
||||||
|
config |
||||||
|
.getDaoForkBlock() |
||||||
|
.ifPresent( |
||||||
|
daoBlockNumber -> { |
||||||
|
if (daoBlockNumber > 0) { |
||||||
|
final ProtocolSpec<C> originalProtocolSpec = |
||||||
|
protocolSchedule.getByBlockNumber(daoBlockNumber); |
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, |
||||||
|
OptionalLong.of(daoBlockNumber), |
||||||
|
MainnetProtocolSpecs.daoRecoveryInitDefinition()); |
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, |
||||||
|
OptionalLong.of(daoBlockNumber + 1), |
||||||
|
MainnetProtocolSpecs.daoRecoveryTransitionDefinition()); |
||||||
|
|
||||||
|
// Return to the previous protocol spec after the dao fork has completed.
|
||||||
|
protocolSchedule.putMilestone(daoBlockNumber + 10, originalProtocolSpec); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, |
||||||
|
config.getTangerineWhistleBlockNumber(), |
||||||
|
MainnetProtocolSpecs.tangerineWhistleDefinition()); |
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, |
||||||
|
config.getSpuriousDragonBlockNumber(), |
||||||
|
MainnetProtocolSpecs.spuriousDragonDefinition(chainId)); |
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, |
||||||
|
config.getByzantiumBlockNumber(), |
||||||
|
MainnetProtocolSpecs.byzantiumDefinition(chainId)); |
||||||
|
addProtocolSpec( |
||||||
|
protocolSchedule, |
||||||
|
config.getConstantinopleBlockNumber(), |
||||||
|
MainnetProtocolSpecs.constantinopleDefinition(chainId)); |
||||||
|
|
||||||
|
return protocolSchedule; |
||||||
|
} |
||||||
|
|
||||||
|
private void addProtocolSpec( |
||||||
|
final MutableProtocolSchedule<C> protocolSchedule, |
||||||
|
final OptionalLong blockNumber, |
||||||
|
final ProtocolSpecBuilder<Void> definition) { |
||||||
|
blockNumber.ifPresent( |
||||||
|
number -> |
||||||
|
protocolSchedule.putMilestone( |
||||||
|
number, protocolSpecAdapter.apply(definition).build(protocolSchedule))); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue