Config to support IBFT original and revised (#306)

With the advent of "IBFT 2.0" the config file parsing needed to be
updated such that both the original IBFT, and the new variant can be
uniquely identified at execution time.
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
tmohay 6 years ago committed by GitHub
parent 0ecefd1021
commit 6a8d5bbfb9
  1. 4
      config/src/main/java/tech/pegasys/pantheon/config/GenesisConfigOptions.java
  2. 13
      config/src/main/java/tech/pegasys/pantheon/config/JsonGenesisConfigOptions.java
  3. 10
      config/src/test-support/java/tech/pegasys/pantheon/config/StubGenesisConfigOptions.java
  4. 234
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonController.java
  5. 31
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java
  6. 6
      pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java

@ -21,12 +21,16 @@ public interface GenesisConfigOptions {
boolean isIbft();
boolean isRevisedIbft();
boolean isClique();
IbftConfigOptions getIbftConfigOptions();
CliqueConfigOptions getCliqueConfigOptions();
IbftConfigOptions getRevisedIbftConfigOptions();
OptionalLong getHomesteadBlockNumber();
OptionalLong getDaoForkBlock();

@ -21,6 +21,7 @@ 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 REVISED_IBFT_CONFIG_KEY = "revisedibft";
private static final String CLIQUE_CONFIG_KEY = "clique";
private final JsonObject configRoot;
@ -43,6 +44,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return configRoot.containsKey(CLIQUE_CONFIG_KEY);
}
@Override
public boolean isRevisedIbft() {
return configRoot.containsKey(REVISED_IBFT_CONFIG_KEY);
}
@Override
public IbftConfigOptions getIbftConfigOptions() {
return isIbft()
@ -50,6 +56,13 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
: IbftConfigOptions.DEFAULT;
}
@Override
public IbftConfigOptions getRevisedIbftConfigOptions() {
return isRevisedIbft()
? new IbftConfigOptions(configRoot.getJsonObject(REVISED_IBFT_CONFIG_KEY))
: IbftConfigOptions.DEFAULT;
}
@Override
public CliqueConfigOptions getCliqueConfigOptions() {
return isClique()

@ -40,6 +40,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return false;
}
@Override
public boolean isRevisedIbft() {
return false;
}
@Override
public IbftConfigOptions getIbftConfigOptions() {
return IbftConfigOptions.DEFAULT;
@ -50,6 +55,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return CliqueConfigOptions.DEFAULT;
}
@Override
public IbftConfigOptions getRevisedIbftConfigOptions() {
return IbftConfigOptions.DEFAULT;
}
@Override
public OptionalLong getHomesteadBlockNumber() {
return homesteadBlockNumber;

@ -0,0 +1,234 @@
/*
* 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.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;
import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater;
import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.consensus.ibft.jsonrpc.IbftJsonRpcMethodsFactory;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftLegacyBlockInterface;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftProtocolSchedule;
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.GenesisState;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.Synchronizer;
import tech.pegasys.pantheon.ethereum.core.TransactionPool;
import tech.pegasys.pantheon.ethereum.db.BlockchainStorage;
import tech.pegasys.pantheon.ethereum.db.DefaultMutableBlockchain;
import tech.pegasys.pantheon.ethereum.db.WorldStateArchive;
import tech.pegasys.pantheon.ethereum.eth.EthProtocol;
import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager;
import tech.pegasys.pantheon.ethereum.eth.sync.DefaultSynchronizer;
import tech.pegasys.pantheon.ethereum.eth.sync.SyncMode;
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.jsonrpc.RpcApi;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.p2p.api.ProtocolManager;
import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol;
import tech.pegasys.pantheon.ethereum.storage.StorageProvider;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateStorage;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import org.apache.logging.log4j.Logger;
public class IbftLegacyPantheonController implements PantheonController<IbftContext> {
private static final Logger LOG = getLogger();
private final GenesisConfigOptions genesisConfig;
private final ProtocolSchedule<IbftContext> protocolSchedule;
private final ProtocolContext<IbftContext> context;
private final Synchronizer synchronizer;
private final SubProtocol ethSubProtocol;
private final ProtocolManager ethProtocolManager;
private final KeyPair keyPair;
private final TransactionPool transactionPool;
private final Runnable closer;
IbftLegacyPantheonController(
final GenesisConfigOptions genesisConfig,
final ProtocolSchedule<IbftContext> protocolSchedule,
final ProtocolContext<IbftContext> context,
final SubProtocol ethSubProtocol,
final ProtocolManager ethProtocolManager,
final Synchronizer synchronizer,
final KeyPair keyPair,
final TransactionPool transactionPool,
final Runnable closer) {
this.genesisConfig = genesisConfig;
this.protocolSchedule = protocolSchedule;
this.context = context;
this.ethSubProtocol = ethSubProtocol;
this.ethProtocolManager = ethProtocolManager;
this.synchronizer = synchronizer;
this.keyPair = keyPair;
this.transactionPool = transactionPool;
this.closer = closer;
}
public static PantheonController<IbftContext> init(
final StorageProvider storageProvider,
final GenesisConfigFile genesisConfig,
final SynchronizerConfiguration taintedSyncConfig,
final boolean ottomanTestnetOperation,
final int networkId,
final KeyPair nodeKeys) {
final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create(genesisConfig.getConfigOptions());
final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule);
final BlockchainStorage blockchainStorage =
storageProvider.createBlockchainStorage(protocolSchedule);
final MutableBlockchain blockchain =
new DefaultMutableBlockchain(genesisState.getBlock(), blockchainStorage);
final WorldStateStorage worldStateStorage = storageProvider.createWorldStateStorage();
final WorldStateArchive worldStateArchive = new WorldStateArchive(worldStateStorage);
genesisState.writeStateTo(worldStateArchive.getMutable(Hash.EMPTY_TRIE_HASH));
final IbftConfigOptions ibftConfig = genesisConfig.getConfigOptions().getIbftConfigOptions();
final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength());
final VoteTally voteTally =
new VoteTallyUpdater(epochManager, new IbftLegacyBlockInterface())
.buildVoteTallyFromBlockchain(blockchain);
final VoteProposer voteProposer = new VoteProposer();
final ProtocolContext<IbftContext> protocolContext =
new ProtocolContext<>(
blockchain, worldStateArchive, new IbftContext(voteTally, voteProposer));
final SynchronizerConfiguration syncConfig = taintedSyncConfig.validated(blockchain);
final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST);
final EthProtocolManager ethProtocolManager;
final SubProtocol ethSubProtocol;
if (ottomanTestnetOperation) {
LOG.info("Operating on Ottoman testnet.");
ethSubProtocol = Istanbul64Protocol.get();
ethProtocolManager =
new Istanbul64ProtocolManager(
protocolContext.getBlockchain(),
networkId,
fastSyncEnabled,
syncConfig.downloaderParallelism());
} else {
ethSubProtocol = EthProtocol.get();
ethProtocolManager =
new EthProtocolManager(
protocolContext.getBlockchain(),
networkId,
fastSyncEnabled,
syncConfig.downloaderParallelism());
}
final SyncState syncState =
new SyncState(
protocolContext.getBlockchain(), ethProtocolManager.ethContext().getEthPeers());
final Synchronizer synchronizer =
new DefaultSynchronizer<>(
syncConfig,
protocolSchedule,
protocolContext,
ethProtocolManager.ethContext(),
syncState);
final Runnable closer =
() -> {
try {
storageProvider.close();
} catch (final IOException e) {
LOG.error("Failed to close storage provider", e);
}
};
final TransactionPool transactionPool =
TransactionPoolFactory.createTransactionPool(
protocolSchedule, protocolContext, ethProtocolManager.ethContext());
return new IbftLegacyPantheonController(
genesisConfig.getConfigOptions(),
protocolSchedule,
protocolContext,
ethSubProtocol,
ethProtocolManager,
synchronizer,
nodeKeys,
transactionPool,
closer);
}
@Override
public ProtocolContext<IbftContext> getProtocolContext() {
return context;
}
@Override
public ProtocolSchedule<IbftContext> getProtocolSchedule() {
return protocolSchedule;
}
@Override
public Synchronizer getSynchronizer() {
return synchronizer;
}
@Override
public SubProtocolConfiguration subProtocolConfiguration() {
return new SubProtocolConfiguration().withSubProtocol(ethSubProtocol, ethProtocolManager);
}
@Override
public KeyPair getLocalNodeKeyPair() {
return keyPair;
}
@Override
public TransactionPool getTransactionPool() {
return transactionPool;
}
@Override
public MiningCoordinator getMiningCoordinator() {
return null;
}
@Override
public Map<String, JsonRpcMethod> getAdditionalJsonRpcMethods(
final Collection<RpcApi> enabledRpcApis) {
return new IbftJsonRpcMethodsFactory().methods(context, enabledRpcApis);
}
@Override
public void close() {
closer.run();
}
}

@ -33,8 +33,6 @@ import tech.pegasys.pantheon.consensus.ibft.protocol.IbftProtocolManager;
import tech.pegasys.pantheon.consensus.ibft.protocol.IbftSubProtocol;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftLegacyBlockInterface;
import tech.pegasys.pantheon.consensus.ibftlegacy.IbftProtocolSchedule;
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;
@ -116,7 +114,6 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
final GenesisConfigFile genesisConfig,
final SynchronizerConfiguration taintedSyncConfig,
final MiningParameters miningParams,
final boolean ottomanTestnetOperation,
final int networkId,
final KeyPair nodeKeys) {
final ProtocolSchedule<IbftContext> protocolSchedule =
@ -146,26 +143,14 @@ public class IbftPantheonController implements PantheonController<IbftContext> {
final SynchronizerConfiguration syncConfig = taintedSyncConfig.validated(blockchain);
final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST);
final EthProtocolManager ethProtocolManager;
final SubProtocol ethSubProtocol;
if (ottomanTestnetOperation) {
LOG.info("Operating on Ottoman testnet.");
ethSubProtocol = Istanbul64Protocol.get();
ethProtocolManager =
new Istanbul64ProtocolManager(
protocolContext.getBlockchain(),
networkId,
fastSyncEnabled,
syncConfig.downloaderParallelism());
} else {
ethSubProtocol = EthProtocol.get();
ethProtocolManager =
new EthProtocolManager(
protocolContext.getBlockchain(),
networkId,
fastSyncEnabled,
syncConfig.downloaderParallelism());
}
final EthProtocolManager ethProtocolManager =
new EthProtocolManager(
protocolContext.getBlockchain(),
networkId,
fastSyncEnabled,
syncConfig.downloaderParallelism());
final SubProtocol ethSubProtocol = EthProtocol.get();
final SyncState syncState =
new SyncState(
protocolContext.getBlockchain(), ethProtocolManager.ethContext().getEthPeers());

@ -57,12 +57,14 @@ public interface PantheonController<C> extends Closeable {
syncConfig,
miningParameters,
nodeKeys);
} else if (configOptions.isIbft()) {
} else if (configOptions.isRevisedIbft()) {
return IbftPantheonController.init(
storageProvider, genesisConfigFile, syncConfig, miningParameters, networkId, nodeKeys);
} else if (configOptions.isIbft()) {
return IbftLegacyPantheonController.init(
storageProvider,
genesisConfigFile,
syncConfig,
miningParameters,
ottomanTestnetOperation,
networkId,
nodeKeys);

Loading…
Cancel
Save