diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java index 4467b0b85e..0fefa864d7 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java @@ -17,9 +17,9 @@ import tech.pegasys.pantheon.Runner; import tech.pegasys.pantheon.RunnerBuilder; import tech.pegasys.pantheon.cli.EthNetworkConfig; -import tech.pegasys.pantheon.cli.PantheonControllerBuilder; import tech.pegasys.pantheon.controller.KeyPairUtil; import tech.pegasys.pantheon.controller.PantheonController; +import tech.pegasys.pantheon.controller.PantheonControllerBuilder; import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import tech.pegasys.pantheon.ethereum.eth.transactions.PendingTransactions; @@ -29,6 +29,7 @@ import java.io.IOException; import java.nio.file.Path; +import java.time.Clock; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -55,12 +56,13 @@ public void startNode(final PantheonNode node) { } final MetricsSystem noOpMetricsSystem = new NoOpMetricsSystem(); - final PantheonControllerBuilder builder = new PantheonControllerBuilder(); final EthNetworkConfig.Builder networkConfigBuilder = new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(DEV)) .setBootNodes(node.getConfiguration().bootnodes()); node.getConfiguration().getGenesisConfig().ifPresent(networkConfigBuilder::setGenesisConfig); final EthNetworkConfig ethNetworkConfig = networkConfigBuilder.build(); + final PantheonControllerBuilder builder = + new PantheonController.Builder().fromEthNetworkConfig(ethNetworkConfig); final Path tempDir = Files.createTempDir().toPath(); final PantheonController pantheonController; @@ -68,15 +70,16 @@ public void startNode(final PantheonNode node) { pantheonController = builder .synchronizerConfiguration(new SynchronizerConfiguration.Builder().build()) - .homePath(node.homeDirectory()) - .ethNetworkConfig(ethNetworkConfig) + .dataDirectory(node.homeDirectory()) .miningParameters(node.getMiningParameters()) .privacyParameters(node.getPrivacyParameters()) .nodePrivateKeyFile(KeyPairUtil.getDefaultKeyFile(node.homeDirectory())) .metricsSystem(noOpMetricsSystem) .maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS) - .rocksDbConfiguration(new RocksDbConfiguration.Builder().databaseDir(tempDir).build()) + .rocksdDbConfiguration( + new RocksDbConfiguration.Builder().databaseDir(tempDir).build()) .ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig()) + .clock(Clock.systemUTC()) .build(); } catch (final IOException e) { throw new RuntimeException("Error building PantheonController", e); diff --git a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/jsonrpc/CliqueJsonRpcMethodsFactory.java b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/jsonrpc/CliqueJsonRpcMethodsFactory.java index 809afa5012..15239d415e 100644 --- a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/jsonrpc/CliqueJsonRpcMethodsFactory.java +++ b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/jsonrpc/CliqueJsonRpcMethodsFactory.java @@ -27,6 +27,7 @@ import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApi; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod; +import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethodFactory; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; @@ -35,10 +36,16 @@ import java.util.HashMap; import java.util.Map; -public class CliqueJsonRpcMethodsFactory { +public class CliqueJsonRpcMethodsFactory implements JsonRpcMethodFactory { - public Map methods( - final ProtocolContext context, final Collection jsonRpcApis) { + private final ProtocolContext context; + + public CliqueJsonRpcMethodsFactory(final ProtocolContext context) { + this.context = context; + } + + @Override + public Map createJsonRpcMethods(final Collection jsonRpcApis) { final Map rpcMethods = new HashMap<>(); if (!jsonRpcApis.contains(CliqueRpcApis.CLIQUE)) { return rpcMethods; diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/jsonrpc/IbftJsonRpcMethodsFactory.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/jsonrpc/IbftJsonRpcMethodsFactory.java index 94c4c5f440..230139a986 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/jsonrpc/IbftJsonRpcMethodsFactory.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/jsonrpc/IbftJsonRpcMethodsFactory.java @@ -24,6 +24,7 @@ import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApi; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod; +import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethodFactory; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries; @@ -31,13 +32,17 @@ import java.util.HashMap; import java.util.Map; -public class IbftJsonRpcMethodsFactory { +public class IbftJsonRpcMethodsFactory implements JsonRpcMethodFactory { private final JsonRpcParameter jsonRpcParameter = new JsonRpcParameter(); + private final ProtocolContext context; - public Map methods( - final ProtocolContext context, final Collection jsonRpcApis) { + public IbftJsonRpcMethodsFactory(final ProtocolContext context) { + this.context = context; + } + @Override + public Map createJsonRpcMethods(final Collection jsonRpcApis) { final Map rpcMethods = new HashMap<>(); if (jsonRpcApis.contains(IbftRpcApis.IBFT)) { diff --git a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/JsonRpcMethodFactory.java b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/JsonRpcMethodFactory.java new file mode 100644 index 0000000000..f71975c7ac --- /dev/null +++ b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/JsonRpcMethodFactory.java @@ -0,0 +1,22 @@ +/* + * Copyright 2019 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.jsonrpc.internal.methods; + +import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApi; + +import java.util.Collection; +import java.util.Map; + +public interface JsonRpcMethodFactory { + Map createJsonRpcMethods(Collection enabledRpcApis); +} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java b/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java index e5a376a3d8..24b07ce2b2 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java @@ -15,7 +15,7 @@ import static org.apache.logging.log4j.LogManager.getLogger; import tech.pegasys.pantheon.cli.PantheonCommand; -import tech.pegasys.pantheon.cli.PantheonControllerBuilder; +import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import tech.pegasys.pantheon.services.kvstore.RocksDbConfiguration; @@ -34,7 +34,7 @@ public static void main(final String... args) { getLogger(), new BlockImporter(), new RunnerBuilder(), - new PantheonControllerBuilder(), + new PantheonController.Builder(), new SynchronizerConfiguration.Builder(), EthereumWireProtocolConfiguration.builder(), new RocksDbConfiguration.Builder()); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java index a178514a97..02379df5e9 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java @@ -217,7 +217,7 @@ public Runner build() { final KeyPair keyPair = pantheonController.getLocalNodeKeyPair(); final SubProtocolConfiguration subProtocolConfiguration = - pantheonController.subProtocolConfiguration(); + pantheonController.getSubProtocolConfiguration(); final ProtocolSchedule protocolSchedule = pantheonController.getProtocolSchedule(); final ProtocolContext context = pantheonController.getProtocolContext(); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java index cc54fa7e4d..0252eb5f27 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java @@ -80,6 +80,7 @@ import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Clock; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -127,11 +128,11 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { private final BlockImporter blockImporter; - private final PantheonControllerBuilder controllerBuilder; private final SynchronizerConfiguration.Builder synchronizerConfigurationBuilder; private final EthereumWireProtocolConfiguration.Builder ethereumWireConfigurationBuilder; private final RocksDbConfiguration.Builder rocksDbConfigurationBuilder; private final RunnerBuilder runnerBuilder; + private final PantheonController.Builder controllerBuilderFactory; protected KeyLoader getKeyLoader() { return KeyPairUtil::loadKeyPair; @@ -521,14 +522,14 @@ public PantheonCommand( final Logger logger, final BlockImporter blockImporter, final RunnerBuilder runnerBuilder, - final PantheonControllerBuilder controllerBuilder, + final PantheonController.Builder controllerBuilderFactory, final SynchronizerConfiguration.Builder synchronizerConfigurationBuilder, final EthereumWireProtocolConfiguration.Builder ethereumWireConfigurationBuilder, final RocksDbConfiguration.Builder rocksDbConfigurationBuilder) { this.logger = logger; this.blockImporter = blockImporter; this.runnerBuilder = runnerBuilder; - this.controllerBuilder = controllerBuilder; + this.controllerBuilderFactory = controllerBuilderFactory; this.synchronizerConfigurationBuilder = synchronizerConfigurationBuilder; this.ethereumWireConfigurationBuilder = ethereumWireConfigurationBuilder; this.rocksDbConfigurationBuilder = rocksDbConfigurationBuilder; @@ -691,18 +692,19 @@ private void ensureAllNodesAreInWhitelist( PantheonController buildController() { try { - return controllerBuilder + return controllerBuilderFactory + .fromEthNetworkConfig(updateNetworkConfig(getNetwork())) .synchronizerConfiguration(buildSyncConfig()) .ethereumWireProtocolConfiguration(ethereumWireConfigurationBuilder.build()) - .rocksDbConfiguration(buildRocksDbConfiguration()) - .homePath(dataDir()) - .ethNetworkConfig(updateNetworkConfig(getNetwork())) + .rocksdDbConfiguration(buildRocksDbConfiguration()) + .dataDirectory(dataDir()) .miningParameters( new MiningParameters(coinbase, minTransactionGasPrice, extraData, isMiningEnabled)) .maxPendingTransactions(txPoolMaxSize) .nodePrivateKeyFile(nodePrivateKeyFile()) .metricsSystem(metricsSystem.get()) .privacyParameters(privacyParameters()) + .clock(Clock.systemUTC()) .build(); } catch (final InvalidConfigurationException e) { throw new ExecutionException(this.commandLine, e.getMessage()); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java deleted file mode 100644 index 1832065feb..0000000000 --- a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java +++ /dev/null @@ -1,138 +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.cli; - -import static com.google.common.base.Preconditions.checkNotNull; -import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; - -import tech.pegasys.pantheon.config.GenesisConfigFile; -import tech.pegasys.pantheon.controller.PantheonController; -import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; -import tech.pegasys.pantheon.ethereum.core.MiningParameters; -import tech.pegasys.pantheon.ethereum.core.PrivacyParameters; -import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; -import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; -import tech.pegasys.pantheon.ethereum.eth.transactions.PendingTransactions; -import tech.pegasys.pantheon.ethereum.storage.StorageProvider; -import tech.pegasys.pantheon.ethereum.storage.keyvalue.RocksDbStorageProvider; -import tech.pegasys.pantheon.metrics.MetricsSystem; -import tech.pegasys.pantheon.services.kvstore.RocksDbConfiguration; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.time.Clock; - -public class PantheonControllerBuilder { - - private SynchronizerConfiguration synchronizerConfiguration; - private EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration; - private RocksDbConfiguration rocksDbConfiguration; - private Path homePath; - private EthNetworkConfig ethNetworkConfig; - private MiningParameters miningParameters; - private File nodePrivateKeyFile; - private MetricsSystem metricsSystem; - private PrivacyParameters privacyParameters; - private Integer maxPendingTransactions = PendingTransactions.MAX_PENDING_TRANSACTIONS; - - public PantheonControllerBuilder synchronizerConfiguration( - final SynchronizerConfiguration synchronizerConfiguration) { - this.synchronizerConfiguration = synchronizerConfiguration; - return this; - } - - public PantheonControllerBuilder ethereumWireProtocolConfiguration( - final EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration) { - this.ethereumWireProtocolConfiguration = ethereumWireProtocolConfiguration; - return this; - } - - public PantheonControllerBuilder rocksDbConfiguration( - final RocksDbConfiguration rocksDbConfiguration) { - this.rocksDbConfiguration = rocksDbConfiguration; - return this; - } - - public PantheonControllerBuilder homePath(final Path homePath) { - this.homePath = homePath; - return this; - } - - public PantheonControllerBuilder ethNetworkConfig(final EthNetworkConfig ethNetworkConfig) { - this.ethNetworkConfig = ethNetworkConfig; - return this; - } - - public PantheonControllerBuilder miningParameters(final MiningParameters miningParameters) { - this.miningParameters = miningParameters; - return this; - } - - public PantheonControllerBuilder nodePrivateKeyFile(final File nodePrivateKeyFile) { - this.nodePrivateKeyFile = nodePrivateKeyFile; - return this; - } - - public PantheonControllerBuilder metricsSystem(final MetricsSystem metricsSystem) { - this.metricsSystem = metricsSystem; - return this; - } - - public PantheonControllerBuilder maxPendingTransactions(final Integer maxPendingTransactions) { - this.maxPendingTransactions = maxPendingTransactions; - return this; - } - - public PantheonControllerBuilder privacyParameters(final PrivacyParameters privacyParameters) { - this.privacyParameters = privacyParameters; - return this; - } - - public PantheonController build() throws IOException { - checkNotNull(nodePrivateKeyFile, "Missing node private key file"); - checkNotNull(synchronizerConfiguration, "Missing synchronizer configuration"); - checkNotNull(rocksDbConfiguration, "Missing rocksdb configuration"); - checkNotNull(homePath, "Missing home path"); - checkNotNull(ethNetworkConfig, "Missing Ethereum network config"); - checkNotNull(miningParameters, "Missing mining parameters"); - checkNotNull(metricsSystem, "Missing metrics system"); - checkNotNull(privacyParameters, "Missing privacy parameters"); - checkNotNull(ethereumWireProtocolConfiguration, "Missing Ethereum wire protocol config"); - - // instantiate a controller with mainnet config if no genesis file is defined - // otherwise use the indicated genesis file - final KeyPair nodeKeys = loadKeyPair(nodePrivateKeyFile); - privacyParameters.setSigningKeyPair(nodeKeys); - - final StorageProvider storageProvider = - RocksDbStorageProvider.create(rocksDbConfiguration, metricsSystem); - - final String genesisConfig = ethNetworkConfig.getGenesisConfig(); - final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(genesisConfig); - final Clock clock = Clock.systemUTC(); - return PantheonController.fromConfig( - genesisConfigFile, - synchronizerConfiguration, - ethereumWireProtocolConfiguration, - storageProvider, - ethNetworkConfig.getNetworkId(), - miningParameters, - nodeKeys, - metricsSystem, - privacyParameters, - homePath, - clock, - maxPendingTransactions); - } -} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java deleted file mode 100644 index 5c7ff97f65..0000000000 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java +++ /dev/null @@ -1,297 +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.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.CliqueBlockInterface; -import tech.pegasys.pantheon.consensus.clique.CliqueContext; -import tech.pegasys.pantheon.consensus.clique.CliqueMiningTracker; -import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule; -import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueBlockScheduler; -import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueMinerExecutor; -import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueMiningCoordinator; -import tech.pegasys.pantheon.consensus.clique.jsonrpc.CliqueJsonRpcMethodsFactory; -import tech.pegasys.pantheon.consensus.common.EpochManager; -import tech.pegasys.pantheon.consensus.common.VoteProposer; -import tech.pegasys.pantheon.consensus.common.VoteTallyCache; -import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater; -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.Address; -import tech.pegasys.pantheon.ethereum.core.MiningParameters; -import tech.pegasys.pantheon.ethereum.core.PrivacyParameters; -import tech.pegasys.pantheon.ethereum.core.Synchronizer; -import tech.pegasys.pantheon.ethereum.core.Util; -import tech.pegasys.pantheon.ethereum.eth.EthProtocol; -import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; -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.TransactionPool; -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.storage.StorageProvider; -import tech.pegasys.pantheon.metrics.MetricsSystem; - -import java.io.IOException; -import java.nio.file.Path; -import java.time.Clock; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.apache.logging.log4j.Logger; - -public class CliquePantheonController implements PantheonController { - - private static final Logger LOG = getLogger(); - private final ProtocolSchedule protocolSchedule; - private final ProtocolContext context; - private final GenesisConfigOptions genesisConfigOptions; - private final Synchronizer synchronizer; - private final ProtocolManager ethProtocolManager; - private final KeyPair keyPair; - private final TransactionPool transactionPool; - private final Runnable closer; - - private final MiningCoordinator miningCoordinator; - private final PrivacyParameters privacyParameters; - - private CliquePantheonController( - final ProtocolSchedule protocolSchedule, - final ProtocolContext context, - final GenesisConfigOptions genesisConfigOptions, - final ProtocolManager ethProtocolManager, - final Synchronizer synchronizer, - final KeyPair keyPair, - final TransactionPool transactionPool, - final MiningCoordinator miningCoordinator, - final PrivacyParameters privacyParameters, - final Runnable closer) { - - this.protocolSchedule = protocolSchedule; - this.context = context; - this.genesisConfigOptions = genesisConfigOptions; - this.ethProtocolManager = ethProtocolManager; - this.synchronizer = synchronizer; - this.keyPair = keyPair; - this.transactionPool = transactionPool; - this.closer = closer; - this.miningCoordinator = miningCoordinator; - this.privacyParameters = privacyParameters; - } - - static PantheonController init( - final StorageProvider storageProvider, - final GenesisConfigFile genesisConfig, - final SynchronizerConfiguration syncConfig, - final EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration, - final MiningParameters miningParams, - final int networkId, - final KeyPair nodeKeys, - final Path dataDirectory, - final MetricsSystem metricsSystem, - final Clock clock, - final int maxPendingTransactions, - final PrivacyParameters privacyParameters) { - final Address localAddress = Util.publicKeyToAddress(nodeKeys.getPublicKey()); - final CliqueConfigOptions cliqueConfig = - genesisConfig.getConfigOptions().getCliqueConfigOptions(); - final long blocksPerEpoch = cliqueConfig.getEpochLength(); - final long secondsBetweenBlocks = cliqueConfig.getBlockPeriodSeconds(); - - final EpochManager epochManager = new EpochManager(blocksPerEpoch); - final ProtocolSchedule protocolSchedule = - CliqueProtocolSchedule.create( - genesisConfig.getConfigOptions(), nodeKeys, privacyParameters); - final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); - - final ProtocolContext protocolContext = - ProtocolContext.init( - storageProvider, - genesisState, - protocolSchedule, - metricsSystem, - (blockchain, worldStateArchive) -> - new CliqueContext( - new VoteTallyCache( - blockchain, - new VoteTallyUpdater(epochManager, new CliqueBlockInterface()), - epochManager, - new CliqueBlockInterface()), - new VoteProposer(), - epochManager)); - final MutableBlockchain blockchain = protocolContext.getBlockchain(); - - final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST); - final EthProtocolManager ethProtocolManager = - new EthProtocolManager( - blockchain, - protocolContext.getWorldStateArchive(), - networkId, - fastSyncEnabled, - syncConfig.downloaderParallelism(), - syncConfig.transactionsParallelism(), - syncConfig.computationParallelism(), - metricsSystem, - ethereumWireProtocolConfiguration); - final SyncState syncState = - new SyncState(blockchain, ethProtocolManager.ethContext().getEthPeers()); - final Synchronizer synchronizer = - new DefaultSynchronizer<>( - syncConfig, - protocolSchedule, - protocolContext, - protocolContext.getWorldStateArchive().getStorage(), - ethProtocolManager.ethContext(), - syncState, - dataDirectory, - clock, - metricsSystem); - - final TransactionPool transactionPool = - TransactionPoolFactory.createTransactionPool( - protocolSchedule, - protocolContext, - ethProtocolManager.ethContext(), - clock, - maxPendingTransactions, - metricsSystem, - syncState); - - final ExecutorService minerThreadPool = Executors.newCachedThreadPool(); - final CliqueMinerExecutor miningExecutor = - new CliqueMinerExecutor( - protocolContext, - minerThreadPool, - protocolSchedule, - transactionPool.getPendingTransactions(), - nodeKeys, - miningParams, - new CliqueBlockScheduler( - clock, - protocolContext.getConsensusState().getVoteTallyCache(), - localAddress, - secondsBetweenBlocks), - epochManager); - final CliqueMiningCoordinator miningCoordinator = - new CliqueMiningCoordinator( - blockchain, - miningExecutor, - syncState, - new CliqueMiningTracker(localAddress, protocolContext)); - miningCoordinator.addMinedBlockObserver(ethProtocolManager); - - // Clique mining is implicitly enabled. - miningCoordinator.enable(); - - return new CliquePantheonController( - protocolSchedule, - protocolContext, - genesisConfig.getConfigOptions(), - ethProtocolManager, - synchronizer, - nodeKeys, - transactionPool, - miningCoordinator, - privacyParameters, - () -> { - miningCoordinator.disable(); - minerThreadPool.shutdownNow(); - try { - minerThreadPool.awaitTermination(5, TimeUnit.SECONDS); - } catch (final InterruptedException e) { - LOG.error("Failed to shutdown miner executor"); - } - try { - storageProvider.close(); - if (privacyParameters.isEnabled()) { - privacyParameters.getPrivateStorageProvider().close(); - } - } catch (final IOException e) { - LOG.error("Failed to close storage provider", e); - } - }); - } - - @Override - public ProtocolContext getProtocolContext() { - return context; - } - - @Override - public ProtocolSchedule getProtocolSchedule() { - return protocolSchedule; - } - - @Override - public GenesisConfigOptions getGenesisConfigOptions() { - return genesisConfigOptions; - } - - @Override - public Synchronizer getSynchronizer() { - return synchronizer; - } - - @Override - public SubProtocolConfiguration subProtocolConfiguration() { - return new SubProtocolConfiguration().withSubProtocol(EthProtocol.get(), ethProtocolManager); - } - - @Override - public KeyPair getLocalNodeKeyPair() { - return keyPair; - } - - @Override - public TransactionPool getTransactionPool() { - return transactionPool; - } - - @Override - public MiningCoordinator getMiningCoordinator() { - return miningCoordinator; - } - - @Override - public PrivacyParameters getPrivacyParameters() { - return privacyParameters; - } - - @Override - public Map getAdditionalJsonRpcMethods( - final Collection enabledRpcApis) { - return new CliqueJsonRpcMethodsFactory().methods(context, enabledRpcApis); - } - - @Override - public void close() { - closer.run(); - } -} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java new file mode 100644 index 0000000000..bdd068e933 --- /dev/null +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java @@ -0,0 +1,136 @@ +/* + * Copyright 2019 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 tech.pegasys.pantheon.config.CliqueConfigOptions; +import tech.pegasys.pantheon.consensus.clique.CliqueBlockInterface; +import tech.pegasys.pantheon.consensus.clique.CliqueContext; +import tech.pegasys.pantheon.consensus.clique.CliqueMiningTracker; +import tech.pegasys.pantheon.consensus.clique.CliqueProtocolSchedule; +import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueBlockScheduler; +import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueMinerExecutor; +import tech.pegasys.pantheon.consensus.clique.blockcreation.CliqueMiningCoordinator; +import tech.pegasys.pantheon.consensus.clique.jsonrpc.CliqueJsonRpcMethodsFactory; +import tech.pegasys.pantheon.consensus.common.EpochManager; +import tech.pegasys.pantheon.consensus.common.VoteProposer; +import tech.pegasys.pantheon.consensus.common.VoteTallyCache; +import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater; +import tech.pegasys.pantheon.ethereum.ProtocolContext; +import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; +import tech.pegasys.pantheon.ethereum.chain.Blockchain; +import tech.pegasys.pantheon.ethereum.core.Address; +import tech.pegasys.pantheon.ethereum.core.MiningParameters; +import tech.pegasys.pantheon.ethereum.core.Util; +import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; +import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState; +import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPool; +import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethodFactory; +import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; +import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class CliquePantheonControllerBuilder extends PantheonControllerBuilder { + private static final Logger LOG = LogManager.getLogger(); + + private Address localAddress; + private EpochManager epochManager; + private long secondsBetweenBlocks; + + @Override + protected void prepForBuild() { + localAddress = Util.publicKeyToAddress(nodeKeys.getPublicKey()); + final CliqueConfigOptions cliqueConfig = + genesisConfig.getConfigOptions().getCliqueConfigOptions(); + final long blocksPerEpoch = cliqueConfig.getEpochLength(); + secondsBetweenBlocks = cliqueConfig.getBlockPeriodSeconds(); + + epochManager = new EpochManager(blocksPerEpoch); + } + + @Override + protected JsonRpcMethodFactory createAdditionalJsonRpcMethodFactory( + final ProtocolContext protocolContext) { + return new CliqueJsonRpcMethodsFactory(protocolContext); + } + + @Override + protected MiningCoordinator createMiningCoordinator( + final ProtocolSchedule protocolSchedule, + final ProtocolContext protocolContext, + final TransactionPool transactionPool, + final MiningParameters miningParameters, + final SyncState syncState, + final EthProtocolManager ethProtocolManager) { + final ExecutorService minerThreadPool = Executors.newCachedThreadPool(); + final CliqueMinerExecutor miningExecutor = + new CliqueMinerExecutor( + protocolContext, + minerThreadPool, + protocolSchedule, + transactionPool.getPendingTransactions(), + nodeKeys, + miningParameters, + new CliqueBlockScheduler( + clock, + protocolContext.getConsensusState().getVoteTallyCache(), + localAddress, + secondsBetweenBlocks), + epochManager); + final CliqueMiningCoordinator miningCoordinator = + new CliqueMiningCoordinator( + protocolContext.getBlockchain(), + miningExecutor, + syncState, + new CliqueMiningTracker(localAddress, protocolContext)); + miningCoordinator.addMinedBlockObserver(ethProtocolManager); + + // Clique mining is implicitly enabled. + miningCoordinator.enable(); + addShutdownAction( + () -> { + miningCoordinator.disable(); + minerThreadPool.shutdownNow(); + try { + minerThreadPool.awaitTermination(5, TimeUnit.SECONDS); + } catch (final InterruptedException e) { + LOG.error("Failed to shutdown miner executor"); + } + }); + return miningCoordinator; + } + + @Override + protected ProtocolSchedule createProtocolSchedule() { + return CliqueProtocolSchedule.create( + genesisConfig.getConfigOptions(), nodeKeys, privacyParameters); + } + + @Override + protected CliqueContext createConsensusContext( + final Blockchain blockchain, final WorldStateArchive worldStateArchive) { + return new CliqueContext( + new VoteTallyCache( + blockchain, + new VoteTallyUpdater(epochManager, new CliqueBlockInterface()), + epochManager, + new CliqueBlockInterface()), + new VoteProposer(), + epochManager); + } +} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonController.java deleted file mode 100644 index 63a984857e..0000000000 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonController.java +++ /dev/null @@ -1,260 +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.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.VoteTallyCache; -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.PrivacyParameters; -import tech.pegasys.pantheon.ethereum.core.Synchronizer; -import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; -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.TransactionPool; -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.metrics.MetricsSystem; - -import java.io.IOException; -import java.nio.file.Path; -import java.time.Clock; -import java.util.Collection; -import java.util.Map; - -import org.apache.logging.log4j.Logger; - -public class IbftLegacyPantheonController implements PantheonController { - - private static final Logger LOG = getLogger(); - private final ProtocolSchedule protocolSchedule; - private final ProtocolContext context; - private final GenesisConfigOptions genesisConfigOptions; - private final Synchronizer synchronizer; - private final SubProtocol istanbulSubProtocol; - private final ProtocolManager istanbulProtocolManager; - private final KeyPair keyPair; - private final TransactionPool transactionPool; - private final Runnable closer; - private final PrivacyParameters privacyParameters; - - private IbftLegacyPantheonController( - final ProtocolSchedule protocolSchedule, - final ProtocolContext context, - final GenesisConfigOptions genesisConfigOptions, - final SubProtocol istanbulSubProtocol, - final ProtocolManager istanbulProtocolManager, - final Synchronizer synchronizer, - final KeyPair keyPair, - final TransactionPool transactionPool, - final PrivacyParameters privacyParameters, - final Runnable closer) { - - this.protocolSchedule = protocolSchedule; - this.context = context; - this.genesisConfigOptions = genesisConfigOptions; - this.istanbulSubProtocol = istanbulSubProtocol; - this.istanbulProtocolManager = istanbulProtocolManager; - this.synchronizer = synchronizer; - this.keyPair = keyPair; - this.transactionPool = transactionPool; - this.privacyParameters = privacyParameters; - this.closer = closer; - } - - static PantheonController init( - final StorageProvider storageProvider, - final GenesisConfigFile genesisConfig, - final SynchronizerConfiguration syncConfig, - final EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration, - final int networkId, - final KeyPair nodeKeys, - final Path dataDirectory, - final MetricsSystem metricsSystem, - final Clock clock, - final int maxPendingTransactions, - final PrivacyParameters privacyParameters) { - final ProtocolSchedule protocolSchedule = - IbftProtocolSchedule.create(genesisConfig.getConfigOptions(), privacyParameters); - final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); - final IbftConfigOptions ibftConfig = - genesisConfig.getConfigOptions().getIbftLegacyConfigOptions(); - - final ProtocolContext protocolContext = - ProtocolContext.init( - storageProvider, - genesisState, - protocolSchedule, - metricsSystem, - (blockchain, worldStateArchive) -> { - final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength()); - final VoteTallyCache voteTallyCache = - new VoteTallyCache( - blockchain, - new VoteTallyUpdater(epochManager, new IbftLegacyBlockInterface()), - epochManager, - new IbftLegacyBlockInterface()); - - final VoteProposer voteProposer = new VoteProposer(); - return new IbftContext(voteTallyCache, voteProposer); - }); - final MutableBlockchain blockchain = protocolContext.getBlockchain(); - - final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST); - final EthProtocolManager istanbul64ProtocolManager; - final SubProtocol istanbul64SubProtocol; - LOG.info("Operating on IBFT-1.0 network."); - istanbul64SubProtocol = Istanbul64Protocol.get(); - istanbul64ProtocolManager = - new Istanbul64ProtocolManager( - blockchain, - protocolContext.getWorldStateArchive(), - networkId, - fastSyncEnabled, - syncConfig.downloaderParallelism(), - syncConfig.transactionsParallelism(), - syncConfig.computationParallelism(), - metricsSystem, - ethereumWireProtocolConfiguration); - - final SyncState syncState = - new SyncState(blockchain, istanbul64ProtocolManager.ethContext().getEthPeers()); - final Synchronizer synchronizer = - new DefaultSynchronizer<>( - syncConfig, - protocolSchedule, - protocolContext, - protocolContext.getWorldStateArchive().getStorage(), - istanbul64ProtocolManager.ethContext(), - syncState, - dataDirectory, - clock, - metricsSystem); - - final Runnable closer = - () -> { - try { - storageProvider.close(); - if (privacyParameters.isEnabled()) { - privacyParameters.getPrivateStorageProvider().close(); - } - } catch (final IOException e) { - LOG.error("Failed to close storage provider", e); - } - }; - - final TransactionPool transactionPool = - TransactionPoolFactory.createTransactionPool( - protocolSchedule, - protocolContext, - istanbul64ProtocolManager.ethContext(), - clock, - maxPendingTransactions, - metricsSystem, - syncState); - - return new IbftLegacyPantheonController( - protocolSchedule, - protocolContext, - genesisConfig.getConfigOptions(), - istanbul64SubProtocol, - istanbul64ProtocolManager, - synchronizer, - nodeKeys, - transactionPool, - privacyParameters, - closer); - } - - @Override - public ProtocolContext getProtocolContext() { - return context; - } - - @Override - public ProtocolSchedule getProtocolSchedule() { - return protocolSchedule; - } - - @Override - public GenesisConfigOptions getGenesisConfigOptions() { - return genesisConfigOptions; - } - - @Override - public Synchronizer getSynchronizer() { - return synchronizer; - } - - @Override - public SubProtocolConfiguration subProtocolConfiguration() { - return new SubProtocolConfiguration() - .withSubProtocol(istanbulSubProtocol, istanbulProtocolManager); - } - - @Override - public KeyPair getLocalNodeKeyPair() { - return keyPair; - } - - @Override - public TransactionPool getTransactionPool() { - return transactionPool; - } - - @Override - public MiningCoordinator getMiningCoordinator() { - return null; - } - - @Override - public PrivacyParameters getPrivacyParameters() { - return privacyParameters; - } - - @Override - public Map getAdditionalJsonRpcMethods( - final Collection enabledRpcApis) { - return new IbftJsonRpcMethodsFactory().methods(context, enabledRpcApis); - } - - @Override - public void close() { - closer.run(); - } -} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java new file mode 100644 index 0000000000..ded1abfb9c --- /dev/null +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019 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 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.VoteTallyCache; +import tech.pegasys.pantheon.consensus.common.VoteTallyUpdater; +import tech.pegasys.pantheon.consensus.ibft.IbftContext; +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.ethereum.ProtocolContext; +import tech.pegasys.pantheon.ethereum.blockcreation.MiningCoordinator; +import tech.pegasys.pantheon.ethereum.chain.Blockchain; +import tech.pegasys.pantheon.ethereum.core.MiningParameters; +import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; +import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState; +import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPool; +import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; +import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration; +import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class IbftLegacyPantheonControllerBuilder extends PantheonControllerBuilder { + + private static final Logger LOG = LogManager.getLogger(); + + @Override + protected SubProtocolConfiguration createSubProtocolConfiguration( + final EthProtocolManager ethProtocolManager) { + return new SubProtocolConfiguration() + .withSubProtocol(Istanbul64Protocol.get(), ethProtocolManager); + } + + @Override + protected MiningCoordinator createMiningCoordinator( + final ProtocolSchedule protocolSchedule, + final ProtocolContext protocolContext, + final TransactionPool transactionPool, + final MiningParameters miningParameters, + final SyncState syncState, + final EthProtocolManager ethProtocolManager) { + return null; + } + + @Override + protected ProtocolSchedule createProtocolSchedule() { + return IbftProtocolSchedule.create(genesisConfig.getConfigOptions(), privacyParameters); + } + + @Override + protected IbftContext createConsensusContext( + final Blockchain blockchain, final WorldStateArchive worldStateArchive) { + final IbftConfigOptions ibftConfig = + genesisConfig.getConfigOptions().getIbftLegacyConfigOptions(); + final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength()); + final VoteTallyCache voteTallyCache = + new VoteTallyCache( + blockchain, + new VoteTallyUpdater(epochManager, new IbftLegacyBlockInterface()), + epochManager, + new IbftLegacyBlockInterface()); + + final VoteProposer voteProposer = new VoteProposer(); + return new IbftContext(voteTallyCache, voteProposer); + } + + @Override + protected EthProtocolManager createEthProtocolManager( + final ProtocolContext protocolContext, final boolean fastSyncEnabled) { + LOG.info("Operating on IBFT-1.0 network."); + return new Istanbul64ProtocolManager( + protocolContext.getBlockchain(), + protocolContext.getWorldStateArchive(), + networkId, + fastSyncEnabled, + syncConfig.downloaderParallelism(), + syncConfig.transactionsParallelism(), + syncConfig.computationParallelism(), + metricsSystem, + ethereumWireProtocolConfiguration); + } +} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java similarity index 51% rename from pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java rename to pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java index 82a1742625..33f3d79641 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 ConsenSys AG. + * Copyright 2019 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 @@ -12,11 +12,8 @@ */ package tech.pegasys.pantheon.controller; -import static org.apache.logging.log4j.LogManager.getLogger; import static tech.pegasys.pantheon.ethereum.eth.manager.MonitoredExecutors.newScheduledThreadPool; -import tech.pegasys.pantheon.config.GenesisConfigFile; -import tech.pegasys.pantheon.config.GenesisConfigOptions; import tech.pegasys.pantheon.config.IbftConfigOptions; import tech.pegasys.pantheon.consensus.common.BlockInterface; import tech.pegasys.pantheon.consensus.common.EpochManager; @@ -49,188 +46,84 @@ import tech.pegasys.pantheon.consensus.ibft.statemachine.IbftFinalState; import tech.pegasys.pantheon.consensus.ibft.statemachine.IbftRoundFactory; import tech.pegasys.pantheon.consensus.ibft.validation.MessageValidatorFactory; -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.Blockchain; import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver; import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; import tech.pegasys.pantheon.ethereum.core.MiningParameters; -import tech.pegasys.pantheon.ethereum.core.PrivacyParameters; -import tech.pegasys.pantheon.ethereum.core.Synchronizer; import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.eth.EthProtocol; -import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; -import tech.pegasys.pantheon.ethereum.eth.manager.EthContext; 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.TransactionPool; -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.jsonrpc.internal.methods.JsonRpcMethodFactory; 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.metrics.MetricsSystem; +import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.util.Subscribers; -import java.io.IOException; -import java.nio.file.Path; -import java.time.Clock; -import java.util.Collection; -import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -public class IbftPantheonController implements PantheonController { +public class IbftPantheonControllerBuilder extends PantheonControllerBuilder { + private static final Logger LOG = LogManager.getLogger(); + private IbftEventQueue ibftEventQueue; + private IbftConfigOptions ibftConfig; + private ValidatorPeers peers; - private static final Logger LOG = getLogger(); - private final ProtocolSchedule protocolSchedule; - private final ProtocolContext context; - private final GenesisConfigOptions genesisConfigOptions; - private final Synchronizer synchronizer; - private final SubProtocol ethSubProtocol; - private final ProtocolManager ethProtocolManager; - private final IbftProtocolManager ibftProtocolManager; - private final KeyPair keyPair; - private final TransactionPool transactionPool; - private final MiningCoordinator ibftMiningCoordinator; - private final Runnable closer; - private final PrivacyParameters privacyParameters; - - private IbftPantheonController( - final ProtocolSchedule protocolSchedule, - final ProtocolContext context, - final GenesisConfigOptions genesisConfigOptions, - final SubProtocol ethSubProtocol, - final ProtocolManager ethProtocolManager, - final IbftProtocolManager ibftProtocolManager, - final Synchronizer synchronizer, - final KeyPair keyPair, - final TransactionPool transactionPool, - final MiningCoordinator ibftMiningCoordinator, - final PrivacyParameters privacyParameters, - final Runnable closer) { - this.protocolSchedule = protocolSchedule; - this.context = context; - this.genesisConfigOptions = genesisConfigOptions; - this.ethSubProtocol = ethSubProtocol; - this.ethProtocolManager = ethProtocolManager; - this.ibftProtocolManager = ibftProtocolManager; - this.synchronizer = synchronizer; - this.keyPair = keyPair; - this.transactionPool = transactionPool; - this.ibftMiningCoordinator = ibftMiningCoordinator; - this.privacyParameters = privacyParameters; - this.closer = closer; + @Override + protected void prepForBuild() { + ibftConfig = genesisConfig.getConfigOptions().getIbft2ConfigOptions(); + ibftEventQueue = new IbftEventQueue(ibftConfig.getMessageQueueLimit()); } - static PantheonController init( - final StorageProvider storageProvider, - final GenesisConfigFile genesisConfig, - final SynchronizerConfiguration syncConfig, - final EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration, - final MiningParameters miningParams, - final int networkId, - final KeyPair nodeKeys, - final Path dataDirectory, - final MetricsSystem metricsSystem, - final Clock clock, - final int maxPendingTransactions, - final PrivacyParameters privacyParameters) { - final ProtocolSchedule protocolSchedule = - IbftProtocolSchedule.create(genesisConfig.getConfigOptions(), privacyParameters); - final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); - - final BlockInterface blockInterface = new IbftBlockInterface(); + @Override + protected JsonRpcMethodFactory createAdditionalJsonRpcMethodFactory( + final ProtocolContext protocolContext) { + return new IbftJsonRpcMethodsFactory(protocolContext); + } - final IbftConfigOptions ibftConfig = genesisConfig.getConfigOptions().getIbft2ConfigOptions(); + @Override + protected SubProtocolConfiguration createSubProtocolConfiguration( + final EthProtocolManager ethProtocolManager) { + return new SubProtocolConfiguration() + .withSubProtocol(EthProtocol.get(), ethProtocolManager) + .withSubProtocol(IbftSubProtocol.get(), new IbftProtocolManager(ibftEventQueue, peers)); + } - final ProtocolContext protocolContext = - ProtocolContext.init( - storageProvider, - genesisState, - protocolSchedule, - metricsSystem, - (blockchain, worldStateArchive) -> { - final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength()); - return new IbftContext( - new VoteTallyCache( - blockchain, - new VoteTallyUpdater(epochManager, new IbftBlockInterface()), - epochManager, - new IbftBlockInterface()), - new VoteProposer()); - }); + @Override + protected MiningCoordinator createMiningCoordinator( + final ProtocolSchedule protocolSchedule, + final ProtocolContext protocolContext, + final TransactionPool transactionPool, + final MiningParameters miningParameters, + final SyncState syncState, + final EthProtocolManager ethProtocolManager) { final MutableBlockchain blockchain = protocolContext.getBlockchain(); - final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST); - final EthProtocolManager ethProtocolManager = - new EthProtocolManager( - protocolContext.getBlockchain(), - protocolContext.getWorldStateArchive(), - networkId, - fastSyncEnabled, - syncConfig.downloaderParallelism(), - syncConfig.transactionsParallelism(), - syncConfig.computationParallelism(), - metricsSystem, - ethereumWireProtocolConfiguration); - final SubProtocol ethSubProtocol = EthProtocol.get(); - - final EthContext ethContext = ethProtocolManager.ethContext(); - - final SyncState syncState = - new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers()); - final Synchronizer synchronizer = - new DefaultSynchronizer<>( - syncConfig, - protocolSchedule, - protocolContext, - protocolContext.getWorldStateArchive().getStorage(), - ethProtocolManager.ethContext(), - syncState, - dataDirectory, - clock, - metricsSystem); - - final TransactionPool transactionPool = - TransactionPoolFactory.createTransactionPool( - protocolSchedule, - protocolContext, - ethContext, - clock, - maxPendingTransactions, - metricsSystem, - syncState); - - final IbftEventQueue ibftEventQueue = new IbftEventQueue(ibftConfig.getMessageQueueLimit()); - final IbftBlockCreatorFactory blockCreatorFactory = new IbftBlockCreatorFactory( (gasLimit) -> gasLimit, transactionPool.getPendingTransactions(), protocolContext, protocolSchedule, - miningParams, + miningParameters, Util.publicKeyToAddress(nodeKeys.getPublicKey())); + final BlockInterface blockInterface = new IbftBlockInterface(); final ProposerSelector proposerSelector = new ProposerSelector(blockchain, blockInterface, true); // NOTE: peers should not be used for accessing the network as it does not enforce the // "only send once" filter applied by the UniqueMessageMulticaster. final VoteTallyCache voteTallyCache = protocolContext.getConsensusState().getVoteTallyCache(); - final ValidatorPeers peers = new ValidatorPeers(voteTallyCache); + peers = new ValidatorPeers(voteTallyCache); final UniqueMessageMulticaster uniqueMessageMulticaster = new UniqueMessageMulticaster(peers, ibftConfig.getGossipedHistoryLimit()); @@ -284,7 +177,7 @@ static PantheonController init( gossiper, duplicateMessageTracker, futureMessageBuffer, - new EthSynchronizerUpdater(ethContext.getEthPeers())); + new EthSynchronizerUpdater(ethProtocolManager.ethContext().getEthPeers())); final EventMultiplexer eventMultiplexer = new EventMultiplexer(ibftController); final IbftProcessor ibftProcessor = new IbftProcessor(ibftEventQueue, eventMultiplexer); @@ -294,8 +187,7 @@ static PantheonController init( final MiningCoordinator ibftMiningCoordinator = new IbftMiningCoordinator(ibftProcessor, blockCreatorFactory, blockchain, ibftEventQueue); ibftMiningCoordinator.enable(); - - final Runnable closer = + addShutdownAction( () -> { ibftProcessor.stop(); ibftMiningCoordinator.disable(); @@ -311,86 +203,26 @@ static PantheonController init( } catch (final InterruptedException e) { LOG.error("Failed to shutdown timer executor"); } - try { - storageProvider.close(); - if (privacyParameters.isEnabled()) { - privacyParameters.getPrivateStorageProvider().close(); - } - } catch (final IOException e) { - LOG.error("Failed to close storage provider", e); - } - }; - - return new IbftPantheonController( - protocolSchedule, - protocolContext, - genesisConfig.getConfigOptions(), - ethSubProtocol, - ethProtocolManager, - new IbftProtocolManager(ibftEventQueue, peers), - synchronizer, - nodeKeys, - transactionPool, - ibftMiningCoordinator, - privacyParameters, - closer); - } - - @Override - public ProtocolContext getProtocolContext() { - return context; - } - - @Override - public ProtocolSchedule getProtocolSchedule() { - return protocolSchedule; - } - - @Override - public GenesisConfigOptions getGenesisConfigOptions() { - return genesisConfigOptions; - } - - @Override - public Synchronizer getSynchronizer() { - return synchronizer; - } - - @Override - public SubProtocolConfiguration subProtocolConfiguration() { - return new SubProtocolConfiguration() - .withSubProtocol(ethSubProtocol, ethProtocolManager) - .withSubProtocol(IbftSubProtocol.get(), ibftProtocolManager); - } - - @Override - public KeyPair getLocalNodeKeyPair() { - return keyPair; - } - - @Override - public TransactionPool getTransactionPool() { - return transactionPool; - } - - @Override - public MiningCoordinator getMiningCoordinator() { + }); return ibftMiningCoordinator; } @Override - public PrivacyParameters getPrivacyParameters() { - return privacyParameters; + protected ProtocolSchedule createProtocolSchedule() { + return IbftProtocolSchedule.create(genesisConfig.getConfigOptions(), privacyParameters); } @Override - public Map getAdditionalJsonRpcMethods( - final Collection enabledRpcApis) { - return new IbftJsonRpcMethodsFactory().methods(context, enabledRpcApis); - } - - @Override - public void close() { - closer.run(); + protected IbftContext createConsensusContext( + final Blockchain blockchain, final WorldStateArchive worldStateArchive) { + final IbftConfigOptions ibftConfig = genesisConfig.getConfigOptions().getIbft2ConfigOptions(); + final EpochManager epochManager = new EpochManager(ibftConfig.getEpochLength()); + return new IbftContext( + new VoteTallyCache( + blockchain, + new VoteTallyUpdater(epochManager, new IbftBlockInterface()), + epochManager, + new IbftBlockInterface()), + new VoteProposer()); } } diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java deleted file mode 100644 index a17031fc3e..0000000000 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java +++ /dev/null @@ -1,262 +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.controller; - -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.GenesisState; -import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; -import tech.pegasys.pantheon.ethereum.core.MiningParameters; -import tech.pegasys.pantheon.ethereum.core.PrivacyParameters; -import tech.pegasys.pantheon.ethereum.core.Synchronizer; -import tech.pegasys.pantheon.ethereum.eth.EthProtocol; -import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; -import tech.pegasys.pantheon.ethereum.eth.manager.EthContext; -import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; -import tech.pegasys.pantheon.ethereum.eth.peervalidation.DaoForkPeerValidator; -import tech.pegasys.pantheon.ethereum.eth.peervalidation.PeerValidatorRunner; -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.TransactionPool; -import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory; -import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHeaderValidator; -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.storage.StorageProvider; -import tech.pegasys.pantheon.metrics.MetricsSystem; - -import java.io.IOException; -import java.nio.file.Path; -import java.time.Clock; -import java.util.OptionalLong; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class MainnetPantheonController implements PantheonController { - - private static final Logger LOG = LogManager.getLogger(); - - private final ProtocolSchedule protocolSchedule; - private final ProtocolContext protocolContext; - private final GenesisConfigOptions genesisConfigOptions; - private final ProtocolManager ethProtocolManager; - private final KeyPair keyPair; - private final Synchronizer synchronizer; - - private final TransactionPool transactionPool; - private final MiningCoordinator miningCoordinator; - private final PrivacyParameters privacyParameters; - private final Runnable close; - - private MainnetPantheonController( - final ProtocolSchedule protocolSchedule, - final ProtocolContext protocolContext, - final GenesisConfigOptions genesisConfigOptions, - final ProtocolManager ethProtocolManager, - final Synchronizer synchronizer, - final KeyPair keyPair, - final TransactionPool transactionPool, - final MiningCoordinator miningCoordinator, - final PrivacyParameters privacyParameters, - final Runnable close) { - this.protocolSchedule = protocolSchedule; - this.protocolContext = protocolContext; - this.genesisConfigOptions = genesisConfigOptions; - this.ethProtocolManager = ethProtocolManager; - this.synchronizer = synchronizer; - this.keyPair = keyPair; - this.transactionPool = transactionPool; - this.miningCoordinator = miningCoordinator; - this.privacyParameters = privacyParameters; - this.close = close; - } - - public static PantheonController init( - final StorageProvider storageProvider, - final GenesisConfigFile genesisConfig, - final ProtocolSchedule protocolSchedule, - final SynchronizerConfiguration syncConfig, - final EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration, - final MiningParameters miningParams, - final int networkId, - final KeyPair nodeKeys, - final PrivacyParameters privacyParameters, - final Path dataDirectory, - final MetricsSystem metricsSystem, - final Clock clock, - final int maxPendingTransactions) { - - final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); - final ProtocolContext protocolContext = - ProtocolContext.init( - storageProvider, genesisState, protocolSchedule, metricsSystem, (a, b) -> null); - final MutableBlockchain blockchain = protocolContext.getBlockchain(); - - final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST); - final EthProtocolManager ethProtocolManager = - new EthProtocolManager( - blockchain, - protocolContext.getWorldStateArchive(), - networkId, - fastSyncEnabled, - syncConfig.downloaderParallelism(), - syncConfig.transactionsParallelism(), - syncConfig.computationParallelism(), - metricsSystem, - ethereumWireProtocolConfiguration); - final SyncState syncState = - new SyncState(blockchain, ethProtocolManager.ethContext().getEthPeers()); - final Synchronizer synchronizer = - new DefaultSynchronizer<>( - syncConfig, - protocolSchedule, - protocolContext, - protocolContext.getWorldStateArchive().getStorage(), - ethProtocolManager.ethContext(), - syncState, - dataDirectory, - clock, - metricsSystem); - - final OptionalLong daoBlock = genesisConfig.getConfigOptions().getDaoForkBlock(); - if (daoBlock.isPresent()) { - // Setup dao validator - final EthContext ethContext = ethProtocolManager.ethContext(); - final DaoForkPeerValidator daoForkPeerValidator = - new DaoForkPeerValidator( - ethContext, protocolSchedule, metricsSystem, daoBlock.getAsLong()); - PeerValidatorRunner.runValidator(ethContext, daoForkPeerValidator); - } - - final TransactionPool transactionPool = - TransactionPoolFactory.createTransactionPool( - protocolSchedule, - protocolContext, - ethProtocolManager.ethContext(), - clock, - maxPendingTransactions, - metricsSystem, - syncState); - - final ExecutorService minerThreadPool = Executors.newCachedThreadPool(); - final EthHashMinerExecutor executor = - new EthHashMinerExecutor( - protocolContext, - minerThreadPool, - protocolSchedule, - transactionPool.getPendingTransactions(), - miningParams, - new DefaultBlockScheduler( - MainnetBlockHeaderValidator.MINIMUM_SECONDS_SINCE_PARENT, - MainnetBlockHeaderValidator.TIMESTAMP_TOLERANCE_S, - clock)); - - final EthHashMiningCoordinator miningCoordinator = - new EthHashMiningCoordinator(blockchain, executor, syncState); - miningCoordinator.addMinedBlockObserver(ethProtocolManager); - if (miningParams.isMiningEnabled()) { - miningCoordinator.enable(); - } - - return new MainnetPantheonController( - protocolSchedule, - protocolContext, - genesisConfig.getConfigOptions(), - ethProtocolManager, - synchronizer, - nodeKeys, - transactionPool, - miningCoordinator, - privacyParameters, - () -> { - miningCoordinator.disable(); - minerThreadPool.shutdownNow(); - try { - minerThreadPool.awaitTermination(5, TimeUnit.SECONDS); - } catch (final InterruptedException e) { - LOG.error("Failed to shutdown miner executor"); - } - try { - storageProvider.close(); - if (privacyParameters.getPrivateStorageProvider() != null) { - privacyParameters.getPrivateStorageProvider().close(); - } - } catch (final IOException e) { - LOG.error("Failed to close storage provider", e); - } - }); - } - - @Override - public ProtocolContext getProtocolContext() { - return protocolContext; - } - - @Override - public ProtocolSchedule getProtocolSchedule() { - return protocolSchedule; - } - - @Override - public GenesisConfigOptions getGenesisConfigOptions() { - return genesisConfigOptions; - } - - @Override - public Synchronizer getSynchronizer() { - return synchronizer; - } - - @Override - public SubProtocolConfiguration subProtocolConfiguration() { - return new SubProtocolConfiguration().withSubProtocol(EthProtocol.get(), ethProtocolManager); - } - - @Override - public KeyPair getLocalNodeKeyPair() { - return keyPair; - } - - @Override - public TransactionPool getTransactionPool() { - return transactionPool; - } - - @Override - public MiningCoordinator getMiningCoordinator() { - return miningCoordinator; - } - - @Override - public void close() { - close.run(); - } - - @Override - public PrivacyParameters getPrivacyParameters() { - return privacyParameters; - } -} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java new file mode 100644 index 0000000000..ecfb9b9235 --- /dev/null +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java @@ -0,0 +1,90 @@ +/* + * Copyright 2019 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 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.Blockchain; +import tech.pegasys.pantheon.ethereum.core.MiningParameters; +import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; +import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState; +import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPool; +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.worldstate.WorldStateArchive; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class MainnetPantheonControllerBuilder extends PantheonControllerBuilder { + private static final Logger LOG = LogManager.getLogger(); + + @Override + protected MiningCoordinator createMiningCoordinator( + final ProtocolSchedule protocolSchedule, + final ProtocolContext protocolContext, + final TransactionPool transactionPool, + final MiningParameters miningParameters, + final SyncState syncState, + final EthProtocolManager ethProtocolManager) { + final ExecutorService minerThreadPool = Executors.newCachedThreadPool(); + final EthHashMinerExecutor executor = + new EthHashMinerExecutor( + protocolContext, + minerThreadPool, + protocolSchedule, + transactionPool.getPendingTransactions(), + miningParameters, + new DefaultBlockScheduler( + MainnetBlockHeaderValidator.MINIMUM_SECONDS_SINCE_PARENT, + MainnetBlockHeaderValidator.TIMESTAMP_TOLERANCE_S, + clock)); + + final EthHashMiningCoordinator miningCoordinator = + new EthHashMiningCoordinator(protocolContext.getBlockchain(), executor, syncState); + miningCoordinator.addMinedBlockObserver(ethProtocolManager); + if (miningParameters.isMiningEnabled()) { + miningCoordinator.enable(); + } + addShutdownAction( + () -> { + miningCoordinator.disable(); + minerThreadPool.shutdownNow(); + try { + minerThreadPool.awaitTermination(5, TimeUnit.SECONDS); + } catch (final InterruptedException e) { + LOG.error("Failed to shutdown miner executor"); + } + }); + return miningCoordinator; + } + + @Override + protected Void createConsensusContext( + final Blockchain blockchain, final WorldStateArchive worldStateArchive) { + return null; + } + + @Override + protected ProtocolSchedule createProtocolSchedule() { + return MainnetProtocolSchedule.fromConfig(genesisConfig.getConfigOptions(), privacyParameters); + } +} diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java index e54cbc967c..53df5dfdae 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 ConsenSys AG. + * Copyright 2019 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 @@ -12,134 +12,135 @@ */ package tech.pegasys.pantheon.controller; -import static java.util.Collections.emptyMap; - +import tech.pegasys.pantheon.cli.EthNetworkConfig; 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.MiningCoordinator; -import tech.pegasys.pantheon.ethereum.core.MiningParameters; import tech.pegasys.pantheon.ethereum.core.PrivacyParameters; import tech.pegasys.pantheon.ethereum.core.Synchronizer; -import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; -import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPool; import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApi; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod; -import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule; +import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethodFactory; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration; -import tech.pegasys.pantheon.ethereum.storage.StorageProvider; -import tech.pegasys.pantheon.metrics.MetricsSystem; -import java.io.Closeable; -import java.nio.file.Path; -import java.time.Clock; import java.util.Collection; import java.util.Map; -public interface PantheonController extends Closeable { - - String DATABASE_PATH = "database"; - - static PantheonController fromConfig( - final GenesisConfigFile genesisConfigFile, - final SynchronizerConfiguration syncConfig, - final EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration, - final StorageProvider storageProvider, - final int networkId, - final MiningParameters miningParameters, - final KeyPair nodeKeys, - final MetricsSystem metricsSystem, +public class PantheonController implements java.io.Closeable { + + public static final String DATABASE_PATH = "database"; + private final ProtocolSchedule protocolSchedule; + private final ProtocolContext protocolContext; + private final GenesisConfigOptions genesisConfigOptions; + private final SubProtocolConfiguration subProtocolConfiguration; + private final KeyPair keyPair; + private final Synchronizer synchronizer; + private final JsonRpcMethodFactory additionalJsonRpcMethodsFactory; + + private final TransactionPool transactionPool; + private final MiningCoordinator miningCoordinator; + private final PrivacyParameters privacyParameters; + private final Runnable close; + + PantheonController( + final ProtocolSchedule protocolSchedule, + final ProtocolContext protocolContext, + final GenesisConfigOptions genesisConfigOptions, + final SubProtocolConfiguration subProtocolConfiguration, + final Synchronizer synchronizer, + final JsonRpcMethodFactory additionalJsonRpcMethodsFactory, + final KeyPair keyPair, + final TransactionPool transactionPool, + final MiningCoordinator miningCoordinator, final PrivacyParameters privacyParameters, - final Path dataDirectory, - final Clock clock, - final int maxPendingTransactions) { - - final GenesisConfigOptions configOptions = genesisConfigFile.getConfigOptions(); - - if (configOptions.isEthHash()) { - return MainnetPantheonController.init( - storageProvider, - genesisConfigFile, - MainnetProtocolSchedule.fromConfig(configOptions, privacyParameters), - syncConfig, - ethereumWireProtocolConfiguration, - miningParameters, - networkId, - nodeKeys, - privacyParameters, - dataDirectory, - metricsSystem, - clock, - maxPendingTransactions); - } else if (configOptions.isIbft2()) { - return IbftPantheonController.init( - storageProvider, - genesisConfigFile, - syncConfig, - ethereumWireProtocolConfiguration, - miningParameters, - networkId, - nodeKeys, - dataDirectory, - metricsSystem, - clock, - maxPendingTransactions, - privacyParameters); - } else if (configOptions.isIbftLegacy()) { - return IbftLegacyPantheonController.init( - storageProvider, - genesisConfigFile, - syncConfig, - ethereumWireProtocolConfiguration, - networkId, - nodeKeys, - dataDirectory, - metricsSystem, - clock, - maxPendingTransactions, - privacyParameters); - } else if (configOptions.isClique()) { - return CliquePantheonController.init( - storageProvider, - genesisConfigFile, - syncConfig, - ethereumWireProtocolConfiguration, - miningParameters, - networkId, - nodeKeys, - dataDirectory, - metricsSystem, - clock, - maxPendingTransactions, - privacyParameters); - } else { - throw new IllegalArgumentException("Unknown consensus mechanism defined"); - } + final Runnable close) { + this.protocolSchedule = protocolSchedule; + this.protocolContext = protocolContext; + this.genesisConfigOptions = genesisConfigOptions; + this.subProtocolConfiguration = subProtocolConfiguration; + this.synchronizer = synchronizer; + this.additionalJsonRpcMethodsFactory = additionalJsonRpcMethodsFactory; + this.keyPair = keyPair; + this.transactionPool = transactionPool; + this.miningCoordinator = miningCoordinator; + this.privacyParameters = privacyParameters; + this.close = close; } - ProtocolContext getProtocolContext(); + public ProtocolContext getProtocolContext() { + return protocolContext; + } - ProtocolSchedule getProtocolSchedule(); + public ProtocolSchedule getProtocolSchedule() { + return protocolSchedule; + } - GenesisConfigOptions getGenesisConfigOptions(); + public GenesisConfigOptions getGenesisConfigOptions() { + return genesisConfigOptions; + } - Synchronizer getSynchronizer(); + public Synchronizer getSynchronizer() { + return synchronizer; + } - SubProtocolConfiguration subProtocolConfiguration(); + public SubProtocolConfiguration getSubProtocolConfiguration() { + return subProtocolConfiguration; + } - KeyPair getLocalNodeKeyPair(); + public KeyPair getLocalNodeKeyPair() { + return keyPair; + } - TransactionPool getTransactionPool(); + public TransactionPool getTransactionPool() { + return transactionPool; + } - MiningCoordinator getMiningCoordinator(); + public MiningCoordinator getMiningCoordinator() { + return miningCoordinator; + } - PrivacyParameters getPrivacyParameters(); + @Override + public void close() { + close.run(); + } - default Map getAdditionalJsonRpcMethods( + public PrivacyParameters getPrivacyParameters() { + return privacyParameters; + } + + public Map getAdditionalJsonRpcMethods( final Collection enabledRpcApis) { - return emptyMap(); + return additionalJsonRpcMethodsFactory.createJsonRpcMethods(enabledRpcApis); + } + + public static class Builder { + + public PantheonControllerBuilder fromEthNetworkConfig( + final EthNetworkConfig ethNetworkConfig) { + return fromGenesisConfig(GenesisConfigFile.fromConfig(ethNetworkConfig.getGenesisConfig())) + .networkId(ethNetworkConfig.getNetworkId()); + } + + public PantheonControllerBuilder fromGenesisConfig(final GenesisConfigFile genesisConfig) { + final GenesisConfigOptions configOptions = genesisConfig.getConfigOptions(); + final PantheonControllerBuilder builder; + + if (configOptions.isEthHash()) { + builder = new MainnetPantheonControllerBuilder(); + } else if (configOptions.isIbft2()) { + builder = new IbftPantheonControllerBuilder(); + } else if (configOptions.isIbftLegacy()) { + builder = new IbftLegacyPantheonControllerBuilder(); + } else if (configOptions.isClique()) { + builder = new CliquePantheonControllerBuilder(); + } else { + throw new IllegalArgumentException("Unknown consensus mechanism defined"); + } + return builder.genesisConfigFile(genesisConfig); + } } } diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonControllerBuilder.java new file mode 100644 index 0000000000..26eb99f8a3 --- /dev/null +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonControllerBuilder.java @@ -0,0 +1,308 @@ +/* + * Copyright 2019 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 com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair; + +import tech.pegasys.pantheon.config.GenesisConfigFile; +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.Blockchain; +import tech.pegasys.pantheon.ethereum.chain.GenesisState; +import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain; +import tech.pegasys.pantheon.ethereum.core.MiningParameters; +import tech.pegasys.pantheon.ethereum.core.PrivacyParameters; +import tech.pegasys.pantheon.ethereum.core.Synchronizer; +import tech.pegasys.pantheon.ethereum.eth.EthProtocol; +import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; +import tech.pegasys.pantheon.ethereum.eth.manager.EthContext; +import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager; +import tech.pegasys.pantheon.ethereum.eth.peervalidation.DaoForkPeerValidator; +import tech.pegasys.pantheon.ethereum.eth.peervalidation.PeerValidatorRunner; +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.TransactionPool; +import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory; +import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethodFactory; +import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; +import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration; +import tech.pegasys.pantheon.ethereum.storage.StorageProvider; +import tech.pegasys.pantheon.ethereum.storage.keyvalue.RocksDbStorageProvider; +import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; +import tech.pegasys.pantheon.metrics.MetricsSystem; +import tech.pegasys.pantheon.services.kvstore.RocksDbConfiguration; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.time.Clock; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.OptionalLong; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public abstract class PantheonControllerBuilder { + private static final Logger LOG = LogManager.getLogger(); + + protected GenesisConfigFile genesisConfig; + protected SynchronizerConfiguration syncConfig; + protected EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration; + protected Integer networkId; + protected MiningParameters miningParameters; + protected MetricsSystem metricsSystem; + protected PrivacyParameters privacyParameters; + protected Path dataDirectory; + protected Clock clock; + protected Integer maxPendingTransactions; + protected KeyPair nodeKeys; + private StorageProvider storageProvider; + private final List shutdownActions = new ArrayList<>(); + private RocksDbConfiguration rocksdDbConfiguration; + + public PantheonControllerBuilder rocksdDbConfiguration( + final RocksDbConfiguration rocksDbConfiguration) { + this.rocksdDbConfiguration = rocksDbConfiguration; + return this; + } + + public PantheonControllerBuilder storageProvider(final StorageProvider storageProvider) { + this.storageProvider = storageProvider; + return this; + } + + public PantheonControllerBuilder genesisConfigFile(final GenesisConfigFile genesisConfig) { + this.genesisConfig = genesisConfig; + return this; + } + + public PantheonControllerBuilder synchronizerConfiguration( + final SynchronizerConfiguration synchronizerConfig) { + this.syncConfig = synchronizerConfig; + return this; + } + + public PantheonControllerBuilder ethereumWireProtocolConfiguration( + final EthereumWireProtocolConfiguration ethereumWireProtocolConfiguration) { + this.ethereumWireProtocolConfiguration = ethereumWireProtocolConfiguration; + return this; + } + + public PantheonControllerBuilder networkId(final int networkId) { + this.networkId = networkId; + return this; + } + + public PantheonControllerBuilder miningParameters(final MiningParameters miningParameters) { + this.miningParameters = miningParameters; + return this; + } + + public PantheonControllerBuilder nodePrivateKeyFile(final File nodePrivateKeyFile) + throws IOException { + this.nodeKeys = loadKeyPair(nodePrivateKeyFile); + return this; + } + + public PantheonControllerBuilder nodeKeys(final KeyPair nodeKeys) { + this.nodeKeys = nodeKeys; + return this; + } + + public PantheonControllerBuilder metricsSystem(final MetricsSystem metricsSystem) { + this.metricsSystem = metricsSystem; + return this; + } + + public PantheonControllerBuilder privacyParameters(final PrivacyParameters privacyParameters) { + this.privacyParameters = privacyParameters; + return this; + } + + public PantheonControllerBuilder dataDirectory(final Path dataDirectory) { + this.dataDirectory = dataDirectory; + return this; + } + + public PantheonControllerBuilder clock(final Clock clock) { + this.clock = clock; + return this; + } + + public PantheonControllerBuilder maxPendingTransactions(final int maxPendingTransactions) { + this.maxPendingTransactions = maxPendingTransactions; + return this; + } + + public PantheonController build() throws IOException { + checkNotNull(genesisConfig, "Missing genesis config"); + checkNotNull(syncConfig, "Missing sync config"); + checkNotNull(ethereumWireProtocolConfiguration, "Missing ethereum protocol configuration"); + checkNotNull(networkId, "Missing network ID"); + checkNotNull(miningParameters, "Missing mining parameters"); + checkNotNull(metricsSystem, "Missing metrics system"); + checkNotNull(privacyParameters, "Missing privacy parameters"); + checkNotNull(dataDirectory, "Missing data directory"); // Why do we need this? + checkNotNull(clock, "Mising clock"); + checkNotNull(maxPendingTransactions, "Missing max pending transactions"); + checkNotNull(nodeKeys, "Missing node keys"); + checkArgument( + storageProvider != null || rocksdDbConfiguration != null, + "Must supply either a storage provider or RocksDB configuration"); + checkArgument( + storageProvider == null || rocksdDbConfiguration == null, + "Must supply either storage provider or RocksDB confguration, but not both"); + privacyParameters.setSigningKeyPair(nodeKeys); + + if (storageProvider == null && rocksdDbConfiguration != null) { + storageProvider = RocksDbStorageProvider.create(rocksdDbConfiguration, metricsSystem); + } + + prepForBuild(); + + final ProtocolSchedule protocolSchedule = createProtocolSchedule(); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); + final ProtocolContext protocolContext = + ProtocolContext.init( + storageProvider, + genesisState, + protocolSchedule, + metricsSystem, + this::createConsensusContext); + final MutableBlockchain blockchain = protocolContext.getBlockchain(); + + final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST); + final EthProtocolManager ethProtocolManager = + createEthProtocolManager(protocolContext, fastSyncEnabled); + final SyncState syncState = + new SyncState(blockchain, ethProtocolManager.ethContext().getEthPeers()); + final Synchronizer synchronizer = + new DefaultSynchronizer<>( + syncConfig, + protocolSchedule, + protocolContext, + protocolContext.getWorldStateArchive().getStorage(), + ethProtocolManager.ethContext(), + syncState, + dataDirectory, + clock, + metricsSystem); + + final OptionalLong daoBlock = genesisConfig.getConfigOptions().getDaoForkBlock(); + if (daoBlock.isPresent()) { + // Setup dao validator + final EthContext ethContext = ethProtocolManager.ethContext(); + final DaoForkPeerValidator daoForkPeerValidator = + new DaoForkPeerValidator( + ethContext, protocolSchedule, metricsSystem, daoBlock.getAsLong()); + PeerValidatorRunner.runValidator(ethContext, daoForkPeerValidator); + } + + final TransactionPool transactionPool = + TransactionPoolFactory.createTransactionPool( + protocolSchedule, + protocolContext, + ethProtocolManager.ethContext(), + clock, + maxPendingTransactions, + metricsSystem, + syncState); + + final MiningCoordinator miningCoordinator = + createMiningCoordinator( + protocolSchedule, + protocolContext, + transactionPool, + miningParameters, + syncState, + ethProtocolManager); + + final SubProtocolConfiguration subProtocolConfiguration = + createSubProtocolConfiguration(ethProtocolManager); + + final JsonRpcMethodFactory additionalJsonRpcMethodFactory = + createAdditionalJsonRpcMethodFactory(protocolContext); + return new PantheonController<>( + protocolSchedule, + protocolContext, + genesisConfig.getConfigOptions(), + subProtocolConfiguration, + synchronizer, + additionalJsonRpcMethodFactory, + nodeKeys, + transactionPool, + miningCoordinator, + privacyParameters, + () -> { + shutdownActions.forEach(Runnable::run); + try { + storageProvider.close(); + if (privacyParameters.getPrivateStorageProvider() != null) { + privacyParameters.getPrivateStorageProvider().close(); + } + } catch (final IOException e) { + LOG.error("Failed to close storage provider", e); + } + }); + } + + protected void prepForBuild() {} + + protected JsonRpcMethodFactory createAdditionalJsonRpcMethodFactory( + final ProtocolContext protocolContext) { + return apis -> Collections.emptyMap(); + } + + protected SubProtocolConfiguration createSubProtocolConfiguration( + final EthProtocolManager ethProtocolManager) { + return new SubProtocolConfiguration().withSubProtocol(EthProtocol.get(), ethProtocolManager); + } + + protected final void addShutdownAction(final Runnable action) { + shutdownActions.add(action); + } + + protected abstract MiningCoordinator createMiningCoordinator( + ProtocolSchedule protocolSchedule, + ProtocolContext protocolContext, + TransactionPool transactionPool, + MiningParameters miningParameters, + SyncState syncState, + EthProtocolManager ethProtocolManager); + + protected abstract ProtocolSchedule createProtocolSchedule(); + + protected abstract C createConsensusContext( + Blockchain blockchain, WorldStateArchive worldStateArchive); + + protected EthProtocolManager createEthProtocolManager( + final ProtocolContext protocolContext, final boolean fastSyncEnabled) { + return new EthProtocolManager( + protocolContext.getBlockchain(), + protocolContext.getWorldStateArchive(), + networkId, + fastSyncEnabled, + syncConfig.downloaderParallelism(), + syncConfig.transactionsParallelism(), + syncConfig.computationParallelism(), + metricsSystem, + ethereumWireProtocolConfiguration); + } +} diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java index b5f02cd970..d326bc0fe3 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/PrivacyTest.java @@ -15,9 +15,8 @@ import static org.assertj.core.api.Assertions.assertThat; import tech.pegasys.pantheon.config.GenesisConfigFile; -import tech.pegasys.pantheon.controller.MainnetPantheonController; import tech.pegasys.pantheon.controller.PantheonController; -import tech.pegasys.pantheon.crypto.SECP256K1; +import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.core.Address; import tech.pegasys.pantheon.ethereum.core.InMemoryStorageProvider; import tech.pegasys.pantheon.ethereum.core.MiningParametersTestBuilder; @@ -44,32 +43,32 @@ public class PrivacyTest { @Test public void privacyPrecompiled() throws IOException { final Path dataDir = folder.newFolder().toPath(); - PrivacyParameters privacyParameters = + final PrivacyParameters privacyParameters = new PrivacyParameters.Builder() .setPrivacyAddress(ADDRESS) .setEnabled(true) .setDataDir(dataDir) .build(); - MainnetPantheonController mainnetPantheonController = - (MainnetPantheonController) - PantheonController.fromConfig( - GenesisConfigFile.mainnet(), - SynchronizerConfiguration.builder().build(), - EthereumWireProtocolConfiguration.defaultConfig(), - new InMemoryStorageProvider(), - 1, - new MiningParametersTestBuilder().enabled(false).build(), - SECP256K1.KeyPair.generate(), - new NoOpMetricsSystem(), - privacyParameters, - dataDir, - TestClock.fixed(), - PendingTransactions.MAX_PENDING_TRANSACTIONS); + final PantheonController pantheonController = + new PantheonController.Builder() + .fromGenesisConfig(GenesisConfigFile.mainnet()) + .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) + .ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig()) + .storageProvider(new InMemoryStorageProvider()) + .networkId(1) + .miningParameters(new MiningParametersTestBuilder().enabled(false).build()) + .nodeKeys(KeyPair.generate()) + .metricsSystem(new NoOpMetricsSystem()) + .dataDirectory(dataDir) + .clock(TestClock.fixed()) + .privacyParameters(privacyParameters) + .maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS) + .build(); - Address privacyContractAddress = Address.privacyPrecompiled(ADDRESS); - PrecompiledContract precompiledContract = - mainnetPantheonController + final Address privacyContractAddress = Address.privacyPrecompiled(ADDRESS); + final PrecompiledContract precompiledContract = + pantheonController .getProtocolSchedule() .getByBlockNumber(1) .getPrecompileContractRegistry() diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java index f8aa822f02..ff87eea409 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java @@ -20,7 +20,7 @@ import tech.pegasys.pantheon.cli.EthNetworkConfig; import tech.pegasys.pantheon.config.GenesisConfigFile; -import tech.pegasys.pantheon.controller.MainnetPantheonController; +import tech.pegasys.pantheon.controller.MainnetPantheonControllerBuilder; import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.ProtocolContext; @@ -37,7 +37,6 @@ 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.storage.StorageProvider; @@ -101,39 +100,39 @@ private void syncFromGenesis(final SyncMode mode) throws Exception { // Setup state with block data try (final PantheonController controller = - MainnetPantheonController.init( - createKeyValueStorageProvider(dbAhead), - GenesisConfigFile.mainnet(), - MainnetProtocolSchedule.create(), - syncConfigAhead, - EthereumWireProtocolConfiguration.defaultConfig(), - new MiningParametersTestBuilder().enabled(false).build(), - networkId, - aheadDbNodeKeys, - PrivacyParameters.DEFAULT, - dataDirAhead, - noOpMetricsSystem, - TestClock.fixed(), - PendingTransactions.MAX_PENDING_TRANSACTIONS)) { + new MainnetPantheonControllerBuilder() + .genesisConfigFile(GenesisConfigFile.mainnet()) + .synchronizerConfiguration(syncConfigAhead) + .ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig()) + .dataDirectory(dataDirAhead) + .networkId(networkId) + .miningParameters(new MiningParametersTestBuilder().enabled(false).build()) + .nodeKeys(aheadDbNodeKeys) + .metricsSystem(noOpMetricsSystem) + .privacyParameters(PrivacyParameters.DEFAULT) + .clock(TestClock.fixed()) + .maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS) + .storageProvider(createKeyValueStorageProvider(dbAhead)) + .build()) { setupState(blockCount, controller.getProtocolSchedule(), controller.getProtocolContext()); } // Setup Runner with blocks final PantheonController controllerAhead = - MainnetPantheonController.init( - createKeyValueStorageProvider(dbAhead), - GenesisConfigFile.mainnet(), - MainnetProtocolSchedule.create(), - syncConfigAhead, - EthereumWireProtocolConfiguration.defaultConfig(), - new MiningParametersTestBuilder().enabled(false).build(), - networkId, - aheadDbNodeKeys, - PrivacyParameters.DEFAULT, - dataDirAhead, - noOpMetricsSystem, - TestClock.fixed(), - PendingTransactions.MAX_PENDING_TRANSACTIONS); + new MainnetPantheonControllerBuilder() + .genesisConfigFile(GenesisConfigFile.mainnet()) + .synchronizerConfiguration(syncConfigAhead) + .ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig()) + .dataDirectory(dataDirAhead) + .networkId(networkId) + .miningParameters(new MiningParametersTestBuilder().enabled(false).build()) + .nodeKeys(aheadDbNodeKeys) + .metricsSystem(noOpMetricsSystem) + .privacyParameters(PrivacyParameters.DEFAULT) + .clock(TestClock.fixed()) + .maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS) + .storageProvider(createKeyValueStorageProvider(dbAhead)) + .build(); final String listenHost = InetAddress.getLoopbackAddress().getHostAddress(); final JsonRpcConfiguration aheadJsonRpcConfiguration = jsonRpcConfiguration(); final WebSocketConfiguration aheadWebSocketConfiguration = wsRpcConfiguration(); @@ -176,20 +175,20 @@ private void syncFromGenesis(final SyncMode mode) throws Exception { // Setup runner with no block data final PantheonController controllerBehind = - MainnetPantheonController.init( - new InMemoryStorageProvider(), - GenesisConfigFile.mainnet(), - MainnetProtocolSchedule.create(), - syncConfigBehind, - EthereumWireProtocolConfiguration.defaultConfig(), - new MiningParametersTestBuilder().enabled(false).build(), - networkId, - KeyPair.generate(), - PrivacyParameters.DEFAULT, - dataDirBehind, - noOpMetricsSystem, - TestClock.fixed(), - PendingTransactions.MAX_PENDING_TRANSACTIONS); + new MainnetPantheonControllerBuilder() + .genesisConfigFile(GenesisConfigFile.mainnet()) + .synchronizerConfiguration(syncConfigBehind) + .ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig()) + .dataDirectory(dataDirBehind) + .networkId(networkId) + .miningParameters(new MiningParametersTestBuilder().enabled(false).build()) + .nodeKeys(KeyPair.generate()) + .storageProvider(new InMemoryStorageProvider()) + .metricsSystem(noOpMetricsSystem) + .privacyParameters(PrivacyParameters.DEFAULT) + .clock(TestClock.fixed()) + .maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS) + .build(); final EnodeURL enode = runnerAhead.getLocalEnode().get(); final EthNetworkConfig behindEthNetworkConfiguration = new EthNetworkConfig( @@ -251,7 +250,6 @@ private void syncFromGenesis(final SyncMode mode) throws Exception { UInt256.fromHexString( new JsonObject(resp.body().string()).getString("result")) .toInt(); - System.out.println("******current block " + currentBlock); if (currentBlock < blockCount) { // if not yet at blockCount, we should get a sync result from eth_syncing final int syncResultCurrentBlock = diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java b/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java index 2f83c2acb9..bddab2ce9f 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java @@ -16,12 +16,14 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import tech.pegasys.pantheon.Runner; import tech.pegasys.pantheon.RunnerBuilder; import tech.pegasys.pantheon.cli.PublicKeySubCommand.KeyLoader; import tech.pegasys.pantheon.controller.PantheonController; +import tech.pegasys.pantheon.controller.PantheonControllerBuilder; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.eth.EthereumWireProtocolConfiguration; import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration; @@ -69,13 +71,16 @@ public abstract class CommandTestAbstract { @Mock RunnerBuilder mockRunnerBuilder; @Mock Runner mockRunner; - @Mock PantheonControllerBuilder mockControllerBuilder; + + @Mock PantheonController.Builder mockControllerBuilderFactory; + + @Mock PantheonControllerBuilder mockControllerBuilder; @Mock SynchronizerConfiguration.Builder mockSyncConfBuilder; @Mock EthereumWireProtocolConfiguration.Builder mockEthereumWireProtocolConfigurationBuilder; @Mock SynchronizerConfiguration mockSyncConf; @Mock RocksDbConfiguration.Builder mockRocksDbConfBuilder; @Mock RocksDbConfiguration mockRocksDbConf; - @Mock PantheonController mockController; + @Mock PantheonController mockController; @Mock BlockImporter mockBlockImporter; @Mock Logger mockLogger; @@ -101,19 +106,20 @@ public void resetSystemProps() { @Before public void initMocks() throws Exception { + doReturn(mockControllerBuilder).when(mockControllerBuilderFactory).fromEthNetworkConfig(any()); // doReturn used because of generic PantheonController Mockito.doReturn(mockController).when(mockControllerBuilder).build(); when(mockControllerBuilder.synchronizerConfiguration(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.ethereumWireProtocolConfiguration(any())) .thenReturn(mockControllerBuilder); - when(mockControllerBuilder.rocksDbConfiguration(any())).thenReturn(mockControllerBuilder); - when(mockControllerBuilder.homePath(any())).thenReturn(mockControllerBuilder); - when(mockControllerBuilder.ethNetworkConfig(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.rocksdDbConfiguration(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.dataDirectory(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.miningParameters(any())).thenReturn(mockControllerBuilder); - when(mockControllerBuilder.maxPendingTransactions(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.maxPendingTransactions(anyInt())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.nodePrivateKeyFile(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.metricsSystem(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.privacyParameters(any())).thenReturn(mockControllerBuilder); + when(mockControllerBuilder.clock(any())).thenReturn(mockControllerBuilder); when(mockSyncConfBuilder.syncMode(any())).thenReturn(mockSyncConfBuilder); when(mockSyncConfBuilder.maxTrailingPeers(anyInt())).thenReturn(mockSyncConfBuilder); @@ -180,7 +186,7 @@ private CommandLine.Model.CommandSpec parseCommand( mockLogger, mockBlockImporter, mockRunnerBuilder, - mockControllerBuilder, + mockControllerBuilderFactory, mockSyncConfBuilder, mockEthereumWireProtocolConfigurationBuilder, mockRocksDbConfBuilder, @@ -209,7 +215,7 @@ protected KeyLoader getKeyLoader() { final Logger mockLogger, final BlockImporter mockBlockImporter, final RunnerBuilder mockRunnerBuilder, - final PantheonControllerBuilder mockControllerBuilder, + final PantheonController.Builder controllerBuilderFactory, final SynchronizerConfiguration.Builder mockSyncConfBuilder, final EthereumWireProtocolConfiguration.Builder mockEthereumConfigurationMockBuilder, final RocksDbConfiguration.Builder mockRocksDbConfBuilder, @@ -218,7 +224,7 @@ protected KeyLoader getKeyLoader() { mockLogger, mockBlockImporter, mockRunnerBuilder, - mockControllerBuilder, + controllerBuilderFactory, mockSyncConfBuilder, mockEthereumConfigurationMockBuilder, mockRocksDbConfBuilder); diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java index bc1f6d3325..7cb97baa71 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java @@ -138,6 +138,8 @@ public void callingVersionDisplayPantheonInfoVersion() { public void callingPantheonCommandWithoutOptionsMustSyncWithDefaultValues() throws Exception { parseCommand(); + final ArgumentCaptor ethNetworkArg = + ArgumentCaptor.forClass(EthNetworkConfig.class); verify(mockRunnerBuilder).discovery(eq(true)); verify(mockRunnerBuilder) .ethNetworkConfig( @@ -151,15 +153,14 @@ public void callingPantheonCommandWithoutOptionsMustSyncWithDefaultValues() thro verify(mockRunnerBuilder).jsonRpcConfiguration(eq(defaultJsonRpcConfiguration)); verify(mockRunnerBuilder).webSocketConfiguration(eq(defaultWebSocketConfiguration)); verify(mockRunnerBuilder).metricsConfiguration(eq(defaultMetricsConfiguration)); + verify(mockRunnerBuilder).ethNetworkConfig(ethNetworkArg.capture()); verify(mockRunnerBuilder).build(); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(ethNetworkArg.capture()); final ArgumentCaptor miningArg = ArgumentCaptor.forClass(MiningParameters.class); - final ArgumentCaptor networkArg = - ArgumentCaptor.forClass(EthNetworkConfig.class); verify(mockControllerBuilder).synchronizerConfiguration(isNotNull()); - verify(mockControllerBuilder).homePath(isNotNull()); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilder).dataDirectory(isNotNull()); verify(mockControllerBuilder).miningParameters(miningArg.capture()); verify(mockControllerBuilder).nodePrivateKeyFile(isNotNull()); verify(mockControllerBuilder).build(); @@ -170,8 +171,8 @@ public void callingPantheonCommandWithoutOptionsMustSyncWithDefaultValues() thro assertThat(miningArg.getValue().getCoinbase()).isEqualTo(Optional.empty()); assertThat(miningArg.getValue().getMinTransactionGasPrice()).isEqualTo(Wei.of(1000)); assertThat(miningArg.getValue().getExtraData()).isEqualTo(BytesValue.EMPTY); - assertThat(networkArg.getValue().getNetworkId()).isEqualTo(1); - assertThat(networkArg.getValue().getBootNodes()).isEqualTo(MAINNET_BOOTSTRAP_NODES); + assertThat(ethNetworkArg.getValue().getNetworkId()).isEqualTo(1); + assertThat(ethNetworkArg.getValue().getBootNodes()).isEqualTo(MAINNET_BOOTSTRAP_NODES); } // Testing each option @@ -300,8 +301,8 @@ public void overrideDefaultValuesIfKeyIsPresentInConfigFile() throws IOException .setGenesisConfig(encodeJsonGenesis(GENESIS_VALID_JSON)) .setBootNodes(nodes) .build(); - verify(mockControllerBuilder).homePath(eq(Paths.get("~/pantheondata").toAbsolutePath())); - verify(mockControllerBuilder).ethNetworkConfig(eq(networkConfig)); + verify(mockControllerBuilder).dataDirectory(eq(Paths.get("~/pantheondata").toAbsolutePath())); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(eq(networkConfig)); verify(mockSyncConfBuilder).syncMode(eq(SyncMode.FAST)); verify(mockSyncConfBuilder).fastSyncMinimumPeerCount(eq(13)); @@ -636,7 +637,7 @@ public void nodekeyOptionMustBeUsed() throws Exception { parseCommand("--node-private-key-file", file.getPath()); - verify(mockControllerBuilder).homePath(isNotNull()); + verify(mockControllerBuilder).dataDirectory(isNotNull()); verify(mockControllerBuilder).nodePrivateKeyFile(fileArgumentCaptor.capture()); verify(mockControllerBuilder).build(); @@ -663,7 +664,7 @@ public void nodekeyOptionDisabledUnderDocker() { } @Test - public void nodekeyDefaultedUnderDocker() { + public void nodekeyDefaultedUnderDocker() throws Exception { System.setProperty("pantheon.docker", "true"); assumeFalse(isFullInstantiation()); @@ -682,7 +683,7 @@ public void dataDirOptionMustBeUsed() throws Exception { parseCommand("--data-path", path.toString()); - verify(mockControllerBuilder).homePath(pathArgumentCaptor.capture()); + verify(mockControllerBuilder).dataDirectory(pathArgumentCaptor.capture()); verify(mockControllerBuilder) .nodePrivateKeyFile(eq(path.resolve("key").toAbsolutePath().toFile())); verify(mockControllerBuilder).build(); @@ -714,7 +715,7 @@ public void dataDirDefaultedUnderDocker() { parseCommand(); - verify(mockControllerBuilder).homePath(pathArgumentCaptor.capture()); + verify(mockControllerBuilder).dataDirectory(pathArgumentCaptor.capture()); assertThat(pathArgumentCaptor.getValue()).isEqualByComparingTo(Paths.get("/var/lib/pantheon")); } @@ -728,7 +729,7 @@ public void genesisPathOptionMustBeUsed() throws Exception { parseCommand("--genesis-file", genesisFile.toString()); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue().getGenesisConfig()) @@ -764,7 +765,7 @@ public void defaultNetworkIdAndBootnodesForCustomNetworkOptions() throws Excepti final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue().getGenesisConfig()) @@ -787,7 +788,7 @@ public void defaultNetworkIdForInvalidGenesisMustBeMainnetNetworkId() throws Exc final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue().getGenesisConfig()) @@ -2000,7 +2001,7 @@ public void devModeOptionMustBeUsed() throws Exception { final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(DEV)); @@ -2016,7 +2017,7 @@ public void rinkebyValuesAreUsed() throws Exception { final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(RINKEBY)); @@ -2032,7 +2033,7 @@ public void ropstenValuesAreUsed() throws Exception { final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(ROPSTEN)); @@ -2048,7 +2049,7 @@ public void goerliValuesAreUsed() throws Exception { final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(GOERLI)); @@ -2089,7 +2090,7 @@ private void networkValuesCanBeOverridden(final String network) throws Exception final ArgumentCaptor networkArg = ArgumentCaptor.forClass(EthNetworkConfig.class); - verify(mockControllerBuilder).ethNetworkConfig(networkArg.capture()); + verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture()); verify(mockControllerBuilder).build(); assertThat(networkArg.getValue().getBootNodes()) diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/util/BlockImporterTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/util/BlockImporterTest.java index 0227beea44..34ea3441c6 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/util/BlockImporterTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/util/BlockImporterTest.java @@ -52,19 +52,20 @@ public void blockImport() throws IOException { final Path source = dataDir.resolve("1000.blocks"); BlockTestUtil.write1000Blocks(source); final PantheonController targetController = - PantheonController.fromConfig( - GenesisConfigFile.mainnet(), - SynchronizerConfiguration.builder().build(), - EthereumWireProtocolConfiguration.defaultConfig(), - new InMemoryStorageProvider(), - 1, - new MiningParametersTestBuilder().enabled(false).build(), - KeyPair.generate(), - new NoOpMetricsSystem(), - PrivacyParameters.DEFAULT, - dataDir, - TestClock.fixed(), - PendingTransactions.MAX_PENDING_TRANSACTIONS); + new PantheonController.Builder() + .fromGenesisConfig(GenesisConfigFile.mainnet()) + .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) + .ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig()) + .storageProvider(new InMemoryStorageProvider()) + .networkId(1) + .miningParameters(new MiningParametersTestBuilder().enabled(false).build()) + .nodeKeys(KeyPair.generate()) + .metricsSystem(new NoOpMetricsSystem()) + .privacyParameters(PrivacyParameters.DEFAULT) + .dataDirectory(dataDir) + .clock(TestClock.fixed()) + .maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS) + .build(); final BlockImporter.ImportResult result = blockImporter.importBlockchain(source, targetController); // Don't count the Genesis block @@ -90,19 +91,20 @@ public void ibftImport() throws IOException { } final PantheonController controller = - PantheonController.fromConfig( - GenesisConfigFile.fromConfig(config), - SynchronizerConfiguration.builder().build(), - EthereumWireProtocolConfiguration.defaultConfig(), - new InMemoryStorageProvider(), - 10, - new MiningParametersTestBuilder().enabled(false).build(), - KeyPair.generate(), - new NoOpMetricsSystem(), - PrivacyParameters.DEFAULT, - dataDir, - TestClock.fixed(), - PendingTransactions.MAX_PENDING_TRANSACTIONS); + new PantheonController.Builder() + .fromGenesisConfig(GenesisConfigFile.fromConfig(config)) + .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) + .ethereumWireProtocolConfiguration(EthereumWireProtocolConfiguration.defaultConfig()) + .storageProvider(new InMemoryStorageProvider()) + .networkId(10) + .miningParameters(new MiningParametersTestBuilder().enabled(false).build()) + .nodeKeys(KeyPair.generate()) + .metricsSystem(new NoOpMetricsSystem()) + .privacyParameters(PrivacyParameters.DEFAULT) + .dataDirectory(dataDir) + .clock(TestClock.fixed()) + .maxPendingTransactions(PendingTransactions.MAX_PENDING_TRANSACTIONS) + .build(); final BlockImporter.ImportResult result = blockImporter.importBlockchain(source, controller); // Don't count the Genesis block