[NC-1384] Disable mining while catching up to chain head (#125)

Adrian Sutton 6 years ago committed by GitHub
parent ba18fcf163
commit d2583e3ef2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      acceptance-tests/build.gradle
  2. 2
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java
  3. 2
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNodeConfig.java
  4. 1
      consensus/clique/build.gradle
  5. 2
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockMiner.java
  6. 4
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutor.java
  7. 14
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMiningCoordinator.java
  8. 2
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java
  9. 1
      consensus/ibft/build.gradle
  10. 2
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockMiner.java
  11. 1
      consensus/ibftlegacy/build.gradle
  12. 27
      ethereum/blockcreation/build.gradle
  13. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/AbstractBlockCreator.java
  14. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/AbstractBlockScheduler.java
  15. 3
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/AbstractMinerExecutor.java
  16. 65
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/AbstractMiningCoordinator.java
  17. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/AsyncBlockCreator.java
  18. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockCreator.java
  19. 2
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMiner.java
  20. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelector.java
  21. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/CoinbaseNotSetException.java
  22. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/DefaultBlockScheduler.java
  23. 9
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreator.java
  24. 3
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockMiner.java
  25. 4
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashMinerExecutor.java
  26. 6
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashMiningCoordinator.java
  27. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/IncrementingNonceGenerator.java
  28. 0
      ethereum/blockcreation/src/main/java/tech/pegasys/pantheon/ethereum/blockcreation/RandomNonceGenerator.java
  29. 138
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/AbstractMiningCoordinatorTest.java
  30. 3
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockMinerTest.java
  31. 0
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java
  32. 0
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/DefaultBlockSchedulerTest.java
  33. 8
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java
  34. 1
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashMinerExecutorTest.java
  35. 21
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashMiningCoordinatorTest.java
  36. 0
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/IncrementingNonceGeneratorTest.java
  37. 4
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/BlockAddedEvent.java
  38. 19
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/chain/MinedBlockObserver.java
  39. 4
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/core/MiningParameters.java
  40. 1
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/MiningParametersTestBuilder.java
  41. 19
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/ChainState.java
  42. 9
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/EthPeer.java
  43. 2
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManager.java
  44. 5
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/BlockPropagationManager.java
  45. 13
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/DefaultSynchronizer.java
  46. 10
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/Downloader.java
  47. 3
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/TrailingPeerLimiter.java
  48. 84
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/state/SyncState.java
  49. 17
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/state/SyncTarget.java
  50. 59
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ChainStateTest.java
  51. 15
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/BlockPropagationManagerTest.java
  52. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/DownloaderTest.java
  53. 114
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/state/SyncStateTest.java
  54. 1
      ethereum/jsonrpc/build.gradle
  55. 1
      pantheon/build.gradle
  56. 2
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java
  57. 3
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonControllerBuilder.java
  58. 18
      pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonController.java
  59. 14
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonController.java
  60. 16
      pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonController.java
  61. 3
      pantheon/src/main/java/tech/pegasys/pantheon/controller/PantheonController.java
  62. 3
      pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java
  63. 2
      pantheon/src/test/java/tech/pegasys/pantheon/cli/PantheonCommandTest.java
  64. 3
      pantheon/src/test/java/tech/pegasys/pantheon/util/BlockchainImporterTest.java
  65. 1
      settings.gradle

@ -19,6 +19,7 @@ dependencies {
testImplementation project(':crypto')
testImplementation project(':ethereum:eth')
testImplementation project(':ethereum:core')
testImplementation project(':ethereum:blockcreation')
testImplementation project(':ethereum:jsonrpc')
testImplementation project(':pantheon')
testImplementation project(':util')

@ -19,7 +19,7 @@ import static org.web3j.protocol.core.DefaultBlockParameterName.LATEST;
import tech.pegasys.pantheon.controller.KeyPairUtil;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account;

@ -12,7 +12,7 @@
*/
package tech.pegasys.pantheon.tests.acceptance.dsl.node;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.MiningParametersTestBuilder;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApi;

@ -26,6 +26,7 @@ repositories { mavenCentral() }
dependencies {
implementation project(':crypto')
implementation project(':ethereum:core')
implementation project(':ethereum:blockcreation')
implementation project(':ethereum:eth')
implementation project(':ethereum:jsonrpc')
implementation project(':ethereum:rlp')

@ -16,8 +16,8 @@ import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.consensus.clique.CliqueHelpers;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockScheduler;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.blockcreation.BlockMiner;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;

@ -20,10 +20,10 @@ import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockScheduler;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMinerExecutor;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;

@ -15,19 +15,13 @@ package tech.pegasys.pantheon.consensus.clique.blockcreation;
import tech.pegasys.pantheon.consensus.clique.CliqueContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import java.util.Optional;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
public class CliqueMiningCoordinator
extends AbstractMiningCoordinator<CliqueContext, CliqueBlockMiner> {
public CliqueMiningCoordinator(final Blockchain blockchain, final CliqueMinerExecutor executor) {
super(blockchain, executor);
}
@Override
protected void haltCurrentMiningOperation() {
currentRunningMiner.ifPresent(CliqueBlockMiner::cancel);
currentRunningMiner = Optional.empty();
public CliqueMiningCoordinator(
final Blockchain blockchain, final CliqueMinerExecutor executor, final SyncState syncState) {
super(blockchain, executor, syncState);
}
}

@ -26,11 +26,11 @@ import tech.pegasys.pantheon.consensus.common.VoteProposer;
import tech.pegasys.pantheon.consensus.common.VoteTally;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.AddressHelpers;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.core.Wei;

@ -25,6 +25,7 @@ dependencies {
implementation project(':consensus:common')
implementation project(':crypto')
implementation project(':ethereum:core')
implementation project(':ethereum:blockcreation')
implementation project(':ethereum:eth')
implementation project(':ethereum:jsonrpc')
implementation project(':ethereum:rlp')

@ -15,8 +15,8 @@ package tech.pegasys.pantheon.consensus.ibft.blockcreation;
import tech.pegasys.pantheon.consensus.ibft.IbftContext;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockScheduler;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.blockcreation.BlockMiner;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.util.Subscribers;

@ -13,6 +13,7 @@ dependencies {
implementation project(':consensus:ibft')
implementation project(':crypto')
implementation project(':ethereum:core')
implementation project(':ethereum:blockcreation')
implementation project(':ethereum:eth')
implementation project(':ethereum:jsonrpc')
implementation project(':ethereum:rlp')

@ -0,0 +1,27 @@
apply plugin: 'java-library'
jar {
baseName 'pantheon-blockcreation'
manifest {
attributes('Implementation-Title': baseName,
'Implementation-Version': project.version)
}
}
dependencies {
implementation project(':ethereum:core')
implementation project(':ethereum:eth')
implementation project(':util')
implementation project(':crypto')
implementation project(':services:kvstore')
implementation 'io.vertx:vertx-core'
implementation 'com.google.guava:guava'
testImplementation 'junit:junit'
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.awaitility:awaitility'
testImplementation 'org.mockito:mockito-core'
testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
testImplementation project(path: ':ethereum:core', configuration: 'testArtifacts')
}

@ -13,8 +13,9 @@
package tech.pegasys.pantheon.ethereum.blockcreation;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;

@ -12,14 +12,16 @@
*/
package tech.pegasys.pantheon.ethereum.blockcreation;
import static org.apache.logging.log4j.LogManager.getLogger;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent.EventType;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedObserver;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolution;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolverInputs;
import tech.pegasys.pantheon.util.Subscribers;
@ -27,22 +29,29 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Optional;
import org.apache.logging.log4j.Logger;
public abstract class AbstractMiningCoordinator<
C, M extends BlockMiner<C, ? extends AbstractBlockCreator<C>>>
implements BlockAddedObserver {
private static final Logger LOG = getLogger();
protected boolean isEnabled = false;
protected volatile Optional<M> currentRunningMiner = Optional.empty();
private final Subscribers<MinedBlockObserver> minedBlockObservers = new Subscribers<>();
private final AbstractMinerExecutor<C, M> executor;
protected final Blockchain blockchain;
private final SyncState syncState;
public AbstractMiningCoordinator(
final Blockchain blockchain, final AbstractMinerExecutor<C, M> executor) {
final Blockchain blockchain,
final AbstractMinerExecutor<C, M> executor,
final SyncState syncState) {
this.executor = executor;
this.blockchain = blockchain;
this.syncState = syncState;
this.blockchain.observeBlockAdded(this);
syncState.addInSyncListener(this::inSyncChanged);
}
public void enable() {
@ -50,7 +59,9 @@ public abstract class AbstractMiningCoordinator<
if (isEnabled) {
return;
}
startAsyncMiningOperation();
if (syncState.isInSync()) {
startAsyncMiningOperation();
}
isEnabled = true;
}
}
@ -67,7 +78,7 @@ public abstract class AbstractMiningCoordinator<
public boolean isRunning() {
synchronized (this) {
return isEnabled;
return currentRunningMiner.isPresent();
}
}
@ -78,28 +89,35 @@ public abstract class AbstractMiningCoordinator<
protected void haltCurrentMiningOperation() {
currentRunningMiner.ifPresent(M::cancel);
currentRunningMiner = Optional.empty();
}
@Override
public void onBlockAdded(final BlockAddedEvent event, final Blockchain blockchain) {
synchronized (this) {
if (isEnabled && shouldStartNewMiner(event)) {
if (isEnabled && event.isNewCanonicalHead()) {
haltCurrentMiningOperation();
startAsyncMiningOperation();
if (syncState.isInSync()) {
startAsyncMiningOperation();
}
}
}
}
private boolean shouldStartNewMiner(final BlockAddedEvent event) {
return event.getEventType() != EventType.FORK;
}
public void removeMinedBlockObserver(final long id) {
minedBlockObservers.unsubscribe(id);
public void inSyncChanged(final boolean inSync) {
synchronized (this) {
if (isEnabled && inSync) {
LOG.info("Resuming mining operations");
startAsyncMiningOperation();
} else if (!inSync) {
LOG.info("Pausing mining while behind chain head");
haltCurrentMiningOperation();
}
}
}
public long addMinedBlockObserver(final MinedBlockObserver obs) {
return minedBlockObservers.subscribe(obs);
public void addMinedBlockObserver(final MinedBlockObserver obs) {
minedBlockObservers.subscribe(obs);
}
// Required for JSON RPC, and are deemed to be valid for all mining mechanisms
@ -117,31 +135,26 @@ public abstract class AbstractMiningCoordinator<
public void setCoinbase(final Address coinbase) {
throw new UnsupportedOperationException(
"Current consensus mechanism prevents" + " setting coinbase.");
"Current consensus mechanism prevents setting coinbase.");
}
public Optional<Address> getCoinbase() {
throw new UnsupportedOperationException(
"Current consensus mechanism prevents" + " querying of coinbase.");
"Current consensus mechanism prevents querying of coinbase.");
}
public Optional<Long> hashesPerSecond() {
throw new UnsupportedOperationException(
"Current consensus mechanism prevents querying " + "of hashrate.");
"Current consensus mechanism prevents querying of hashrate.");
}
public Optional<EthHashSolverInputs> getWorkDefinition() {
throw new UnsupportedOperationException(
"Current consensus mechanism prevents querying " + "work definition.");
"Current consensus mechanism prevents querying work definition.");
}
public boolean submitWork(final EthHashSolution solution) {
throw new UnsupportedOperationException(
"Current consensus mechanism prevents submission of work" + " solutions.");
}
public interface MinedBlockObserver {
void blockMined(Block block);
"Current consensus mechanism prevents submission of work solutions.");
}
}

@ -13,7 +13,7 @@
package tech.pegasys.pantheon.ethereum.blockcreation;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockImporter;

@ -10,17 +10,22 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.ethereum.mainnet;
package tech.pegasys.pantheon.ethereum.blockcreation;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderBuilder;
import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.ethereum.core.SealableBlockHeader;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.mainnet.EthHash;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolution;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolver;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolver.EthHashSolverJob;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolverInputs;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHashFunction;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import tech.pegasys.pantheon.util.uint.UInt256;

@ -13,9 +13,8 @@
package tech.pegasys.pantheon.ethereum.blockcreation;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashBlockCreator;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolution;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolverInputs;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;

@ -13,11 +13,11 @@
package tech.pegasys.pantheon.ethereum.blockcreation;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashBlockCreator;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolver;
import tech.pegasys.pantheon.ethereum.mainnet.EthHasher;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;

@ -15,6 +15,7 @@ package tech.pegasys.pantheon.ethereum.blockcreation;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedObserver;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolution;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolverInputs;
@ -31,8 +32,8 @@ public class EthHashMiningCoordinator extends AbstractMiningCoordinator<Void, Et
private volatile Optional<Long> cachedHashesPerSecond = Optional.empty();
public EthHashMiningCoordinator(
final Blockchain blockchain, final EthHashMinerExecutor executor) {
super(blockchain, executor);
final Blockchain blockchain, final EthHashMinerExecutor executor, final SyncState syncState) {
super(blockchain, executor, syncState);
this.executor = executor;
}
@ -78,5 +79,6 @@ public class EthHashMiningCoordinator extends AbstractMiningCoordinator<Void, Et
miner.cancel();
miner.getHashesPerSecond().ifPresent(val -> cachedHashesPerSecond = Optional.of(val));
});
currentRunningMiner = Optional.empty();
}
}

@ -0,0 +1,138 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.ethereum.blockcreation;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockBody;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
public class AbstractMiningCoordinatorTest {
private static final Block BLOCK =
new Block(
new BlockHeaderTestFixture().buildHeader(),
new BlockBody(Collections.emptyList(), Collections.emptyList()));
private final Blockchain blockchain = mock(Blockchain.class);
private final EthHashMinerExecutor minerExecutor = mock(EthHashMinerExecutor.class);
private final SyncState syncState = mock(SyncState.class);
private final EthHashBlockMiner blockMiner = mock(EthHashBlockMiner.class);
private final TestMiningCoordinator miningCoordinator =
new TestMiningCoordinator(blockchain, minerExecutor, syncState);
@Before
public void setUp() {
when(minerExecutor.startAsyncMining(any(), any())).thenReturn(blockMiner);
}
@Test
public void shouldNotStartMiningWhenEnabledAndOutOfSync() {
when(syncState.isInSync()).thenReturn(false);
miningCoordinator.enable();
verifyZeroInteractions(minerExecutor, blockMiner);
}
@Test
public void shouldStartMiningWhenEnabledAndInSync() {
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.enable();
verify(minerExecutor).startAsyncMining(any(), any());
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@Test
public void shouldStartMiningWhenEnabledAndBecomeInSync() {
when(syncState.isInSync()).thenReturn(false);
miningCoordinator.enable();
miningCoordinator.inSyncChanged(true);
verify(minerExecutor).startAsyncMining(any(), any());
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@Test
public void shouldHaltMiningWhenBecomingOutOfSync() {
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.enable();
verify(minerExecutor).startAsyncMining(any(), any());
miningCoordinator.inSyncChanged(false);
verify(blockMiner).cancel();
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@Test
public void shouldNotStartWhenBlockAddedAndOutOfSync() {
when(syncState.isInSync()).thenReturn(false);
miningCoordinator.enable();
miningCoordinator.onBlockAdded(BlockAddedEvent.createForHeadAdvancement(BLOCK), blockchain);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@Test
public void shouldRestartMiningWhenBlockAddedAndInSync() {
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.enable();
miningCoordinator.onBlockAdded(BlockAddedEvent.createForHeadAdvancement(BLOCK), blockchain);
verify(blockMiner).cancel();
verify(minerExecutor, times(2)).startAsyncMining(any(), any());
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@Test
public void shouldNotStartMiningWhenBecomingInSyncIfMinerNotEnabled() {
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.inSyncChanged(true);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
@Test
public void shouldNotStartMiningWhenBlockAddedAndInSyncIfMinerNotEnabled() {
when(syncState.isInSync()).thenReturn(true);
miningCoordinator.onBlockAdded(BlockAddedEvent.createForHeadAdvancement(BLOCK), blockchain);
verifyNoMoreInteractions(minerExecutor, blockMiner);
}
public static class TestMiningCoordinator
extends AbstractMiningCoordinator<Void, EthHashBlockMiner> {
public TestMiningCoordinator(
final Blockchain blockchain,
final AbstractMinerExecutor<Void, EthHashBlockMiner> executor,
final SyncState syncState) {
super(blockchain, executor, syncState);
}
}
}

@ -20,12 +20,11 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockBody;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.core.BlockImporter;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashBlockCreator;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode;
import tech.pegasys.pantheon.ethereum.mainnet.MutableProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;

@ -10,13 +10,16 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.ethereum.mainnet;
package tech.pegasys.pantheon.ethereum.blockcreation;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture;
import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolver;
import tech.pegasys.pantheon.ethereum.mainnet.EthHasher.Light;
import tech.pegasys.pantheon.ethereum.mainnet.ValidationTestUtils;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException;
@ -42,8 +45,7 @@ public class EthHashBlockCreatorTest {
@Test
public void createMainnetBlock1() throws IOException {
final EthHashSolver solver =
new EthHashSolver(Lists.newArrayList(BLOCK_1_NONCE), new EthHasher.Light());
final EthHashSolver solver = new EthHashSolver(Lists.newArrayList(BLOCK_1_NONCE), new Light());
final EthHashBlockCreator blockCreator =
new EthHashBlockCreator(
BLOCK_1_COINBASE,

@ -14,6 +14,7 @@ package tech.pegasys.pantheon.ethereum.blockcreation;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.MiningParametersTestBuilder;
import tech.pegasys.pantheon.ethereum.core.PendingTransactions;
import tech.pegasys.pantheon.util.Subscribers;

@ -19,22 +19,31 @@ import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.ethereum.core.ExecutionContextTestFixture;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.mainnet.EthHashSolution;
import tech.pegasys.pantheon.util.bytes.Bytes32;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class EthHashMiningCoordinatorTest {
private final ExecutionContextTestFixture executionContext = new ExecutionContextTestFixture();
private final SyncState syncState = mock(SyncState.class);
private final EthHashMinerExecutor executor = mock(EthHashMinerExecutor.class);
private final EthHashBlockMiner miner = mock(EthHashBlockMiner.class);
@Before
public void setUp() {
when(syncState.isInSync()).thenReturn(true);
}
@Test
public void miningCoordinatorIsCreatedDisabledWithNoReportableMiningStatistics() {
final EthHashMinerExecutor executor = mock(EthHashMinerExecutor.class);
final EthHashMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(executionContext.getBlockchain(), executor);
new EthHashMiningCoordinator(executionContext.getBlockchain(), executor, syncState);
final EthHashSolution solution = new EthHashSolution(1L, Hash.EMPTY, new byte[Bytes32.SIZE]);
assertThat(miningCoordinator.isRunning()).isFalse();
@ -45,21 +54,17 @@ public class EthHashMiningCoordinatorTest {
@Test
@SuppressWarnings("unchecked")
public void reportedHashRateIsCachedIfNoCurrentDataInMiner() throws InterruptedException {
final EthHashBlockMiner miner = mock(EthHashBlockMiner.class);
public void reportedHashRateIsCachedIfNoCurrentDataInMiner() {
final Optional<Long> hashRate1 = Optional.of(10L);
final Optional<Long> hashRate2 = Optional.empty();
final Optional<Long> hashRate3 = Optional.of(20L);
when(miner.getHashesPerSecond()).thenReturn(hashRate1, hashRate2, hashRate3);
final EthHashMinerExecutor executor = mock(EthHashMinerExecutor.class);
when(executor.startAsyncMining(any(), any())).thenReturn(miner);
final EthHashMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(executionContext.getBlockchain(), executor);
new EthHashMiningCoordinator(executionContext.getBlockchain(), executor, syncState);
miningCoordinator.enable(); // Must enable prior returning data
assertThat(miningCoordinator.hashesPerSecond()).isEqualTo(hashRate1);

@ -64,6 +64,10 @@ public class BlockAddedEvent {
return block;
}
public boolean isNewCanonicalHead() {
return eventType != EventType.FORK;
}
public EventType getEventType() {
return eventType;
}

@ -0,0 +1,19 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.ethereum.chain;
import tech.pegasys.pantheon.ethereum.core.Block;
public interface MinedBlockObserver {
void blockMined(Block block);
}

@ -10,10 +10,8 @@
* 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.blockcreation;
package tech.pegasys.pantheon.ethereum.core;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Optional;

@ -12,7 +12,6 @@
*/
package tech.pegasys.pantheon.ethereum.core;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.util.bytes.BytesValue;
public class MiningParametersTestBuilder {

@ -14,6 +14,7 @@ package tech.pegasys.pantheon.ethereum.eth.manager;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.uint.UInt256;
import com.google.common.base.MoreObjects;
@ -25,6 +26,16 @@ public class ChainState {
private volatile long estimatedHeight = 0L;
private volatile boolean estimatedHeightKnown = false;
private final Subscribers<EstimatedHeightListener> estimatedHeightListeners = new Subscribers<>();
public long addEstimatedHeightListener(final EstimatedHeightListener listener) {
return estimatedHeightListeners.subscribe(listener);
}
public void removeEstimatedHeightListener(final long listenerId) {
estimatedHeightListeners.unsubscribe(listenerId);
}
public boolean hasEstimatedHeight() {
return estimatedHeightKnown;
}
@ -55,7 +66,7 @@ public class ChainState {
public void update(final BlockHeader header) {
synchronized (this) {
if (bestBlock.hash.equals(header.getHash())) {
if (header.getHash().equals(bestBlock.hash)) {
bestBlock.number = header.getNumber();
}
updateHeightEstimate(header.getNumber());
@ -77,6 +88,7 @@ public class ChainState {
estimatedHeightKnown = true;
if (blockNumber > estimatedHeight) {
estimatedHeight = blockNumber;
estimatedHeightListeners.forEach(e -> e.onEstimatedHeightChanged(estimatedHeight));
}
}
@ -115,4 +127,9 @@ public class ChainState {
.toString();
}
}
@FunctionalInterface
public interface EstimatedHeightListener {
void onEstimatedHeightChanged(long estimatedHeight);
}
}

@ -15,6 +15,7 @@ package tech.pegasys.pantheon.ethereum.eth.manager;
import static com.google.common.base.Preconditions.checkArgument;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.eth.manager.ChainState.EstimatedHeightListener;
import tech.pegasys.pantheon.ethereum.eth.manager.RequestManager.ResponseStream;
import tech.pegasys.pantheon.ethereum.eth.messages.EthPV62;
import tech.pegasys.pantheon.ethereum.eth.messages.EthPV63;
@ -81,6 +82,14 @@ public class EthPeer {
this.onStatusesExchanged.set(onStatusesExchanged);
}
public long addChainEstimatedHeightListener(final EstimatedHeightListener listener) {
return chainHeadState.addEstimatedHeightListener(listener);
}
public void removeChainEstimatedHeightListener(final long listenerId) {
chainHeadState.removeEstimatedHeightListener(listenerId);
}
public void recordRequestTimeout(final int requestCode) {
LOG.debug("Timed out while waiting for response from peer {}", this);
reputation.recordRequestTimeout(requestCode).ifPresent(this::disconnect);

@ -14,8 +14,8 @@ package tech.pegasys.pantheon.ethereum.eth.manager;
import static com.google.common.base.Preconditions.checkArgument;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.chain.MinedBlockObserver;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.eth.EthProtocol;

@ -70,14 +70,15 @@ public class BlockPropagationManager<C> {
final ProtocolSchedule<C> protocolSchedule,
final ProtocolContext<C> protocolContext,
final EthContext ethContext,
final SyncState syncState) {
final SyncState syncState,
final PendingBlocks pendingBlocks) {
this.config = config;
this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext;
this.ethContext = ethContext;
this.syncState = syncState;
pendingBlocks = syncState.pendingBlocks();
this.pendingBlocks = pendingBlocks;
}
public void start() {

@ -39,12 +39,17 @@ public class DefaultSynchronizer<C> implements Synchronizer {
final SynchronizerConfiguration syncConfig,
final ProtocolSchedule<C> protocolSchedule,
final ProtocolContext<C> protocolContext,
final EthContext ethContext) {
this.syncState =
new SyncState(protocolContext.getBlockchain(), ethContext, new PendingBlocks());
final EthContext ethContext,
final SyncState syncState) {
this.syncState = syncState;
this.blockPropagationManager =
new BlockPropagationManager<>(
syncConfig, protocolSchedule, protocolContext, ethContext, syncState);
syncConfig,
protocolSchedule,
protocolContext,
ethContext,
syncState,
new PendingBlocks());
this.downloader =
new Downloader<>(syncConfig, protocolSchedule, protocolContext, ethContext, syncState);

@ -327,7 +327,7 @@ public class Downloader<C> {
return CompletableFuture.completedFuture(Collections.emptyList());
}
CompletableFuture<List<Block>> importedBlocks;
final CompletableFuture<List<Block>> importedBlocks;
if (checkpointHeaders.size() < 2) {
// Download blocks without constraining the end block
final ImportBlocksTask<C> importTask =
@ -382,9 +382,7 @@ public class Downloader<C> {
chainSegmentTimeouts = 0;
final BlockHeader lastImportedCheckpoint = checkpointHeaders.getLast();
checkpointHeaders.clear();
syncState
.syncTarget()
.ifPresent(target -> target.setCommonAncestor(lastImportedCheckpoint));
syncState.setCommonAncestor(lastImportedCheckpoint);
}
});
}
@ -400,9 +398,7 @@ public class Downloader<C> {
final BlockHeader lastImportedCheckpointHeader = imported.get(imported.size() - 1);
// The first checkpoint header is always present in the blockchain.
checkpointHeaders.addFirst(lastImportedCheckpointHeader);
syncState
.syncTarget()
.ifPresent(target -> target.setCommonAncestor(lastImportedCheckpointHeader));
syncState.setCommonAncestor(lastImportedCheckpointHeader);
return imported.size() > 1;
}
}

@ -15,7 +15,6 @@ package tech.pegasys.pantheon.ethereum.eth.sync;
import static org.apache.logging.log4j.LogManager.getLogger;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent.EventType;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedObserver;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeer;
@ -74,7 +73,7 @@ public class TrailingPeerLimiter implements BlockAddedObserver {
@Override
public void onBlockAdded(final BlockAddedEvent event, final Blockchain blockchain) {
if (event.getEventType() != EventType.FORK
if (event.isNewCanonicalHead()
&& event.getBlock().getHeader().getNumber() % RECHECK_PEERS_WHEN_BLOCK_NUMBER_MULTIPLE_OF
== 0) {
enforceTrailingPeerLimit();

@ -15,26 +15,38 @@ package tech.pegasys.pantheon.ethereum.eth.sync.state;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.SyncStatus;
import tech.pegasys.pantheon.ethereum.eth.manager.EthContext;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeer;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeers;
import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.util.Optional;
public class SyncState {
private static final long SYNC_TOLERANCE = 5;
private final Blockchain blockchain;
private final EthContext ethContext;
private final EthPeers ethPeers;
private final long startingBlock;
private final PendingBlocks pendingBlocks;
private boolean lastInSync = true;
private final Subscribers<InSyncListener> inSyncListeners = new Subscribers<>();
private Optional<SyncTarget> syncTarget = Optional.empty();
private long chainHeightListenerId;
public SyncState(
final Blockchain blockchain, final EthContext ethContext, final PendingBlocks pendingBlocks) {
public SyncState(final Blockchain blockchain, final EthPeers ethPeers) {
this.blockchain = blockchain;
this.ethContext = ethContext;
this.ethPeers = ethPeers;
this.startingBlock = chainHeadNumber();
this.pendingBlocks = pendingBlocks;
blockchain.observeBlockAdded(
(event, chain) -> {
if (event.isNewCanonicalHead()) {
checkInSync();
}
});
}
public void addInSyncListener(final InSyncListener observer) {
inSyncListeners.subscribe(observer);
}
public SyncStatus syncStatus() {
@ -53,22 +65,45 @@ public class SyncState {
return blockchain.getChainHead().getTotalDifficulty();
}
public PendingBlocks pendingBlocks() {
return pendingBlocks;
}
public Optional<SyncTarget> syncTarget() {
return syncTarget;
}
public SyncTarget setSyncTarget(final EthPeer peer, final BlockHeader commonAncestor) {
final SyncTarget target = new SyncTarget(peer, commonAncestor);
this.syncTarget = Optional.of(target);
return target;
final SyncTarget syncTarget = new SyncTarget(peer, commonAncestor);
replaceSyncTarget(Optional.of(syncTarget));
return syncTarget;
}
public boolean isInSync() {
return syncTarget
.map(
t -> t.estimatedTargetHeight() - blockchain.getChainHeadBlockNumber() <= SYNC_TOLERANCE)
.orElse(true);
}
public void setCommonAncestor(final BlockHeader commonAncestor) {
syncTarget.ifPresent(target -> target.setCommonAncestor(commonAncestor));
}
public void clearSyncTarget() {
this.syncTarget = Optional.empty();
replaceSyncTarget(Optional.empty());
}
private void replaceSyncTarget(final Optional<SyncTarget> newTarget) {
syncTarget.ifPresent(this::removeEstimatedHeightListener);
syncTarget = newTarget;
newTarget.ifPresent(this::addEstimatedHeightListener);
checkInSync();
}
private void removeEstimatedHeightListener(final SyncTarget target) {
target.removePeerChainEstimatedHeightListener(chainHeightListenerId);
}
private void addEstimatedHeightListener(final SyncTarget target) {
chainHeightListenerId =
target.addPeerChainEstimatedHeightListener(estimatedHeight -> checkInSync());
}
public long bestChainHeight() {
@ -79,10 +114,19 @@ public class SyncState {
public long bestChainHeight(final long localChainHeight) {
return Math.max(
localChainHeight,
ethContext
.getEthPeers()
.bestPeer()
.map(p -> p.chainState().getEstimatedHeight())
.orElse(localChainHeight));
ethPeers.bestPeer().map(p -> p.chainState().getEstimatedHeight()).orElse(localChainHeight));
}
private synchronized void checkInSync() {
final boolean currentSyncStatus = isInSync();
if (lastInSync != currentSyncStatus) {
lastInSync = currentSyncStatus;
inSyncListeners.forEach(c -> c.onSyncStatusChanged(currentSyncStatus));
}
}
@FunctionalInterface
public interface InSyncListener {
void onSyncStatusChanged(boolean newSyncStatus);
}
}

@ -14,6 +14,7 @@ package tech.pegasys.pantheon.ethereum.eth.sync.state;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.eth.manager.ChainState;
import tech.pegasys.pantheon.ethereum.eth.manager.ChainState.EstimatedHeightListener;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeer;
import com.google.common.base.MoreObjects;
@ -23,7 +24,7 @@ public class SyncTarget {
private final EthPeer peer;
private BlockHeader commonAncestor;
public SyncTarget(final EthPeer peer, final BlockHeader commonAncestor) {
SyncTarget(final EthPeer peer, final BlockHeader commonAncestor) {
this.peer = peer;
this.commonAncestor = commonAncestor;
}
@ -36,10 +37,22 @@ public class SyncTarget {
return commonAncestor;
}
public void setCommonAncestor(final BlockHeader commonAncestor) {
void setCommonAncestor(final BlockHeader commonAncestor) {
this.commonAncestor = commonAncestor;
}
public long addPeerChainEstimatedHeightListener(final EstimatedHeightListener listener) {
return peer.addChainEstimatedHeightListener(listener);
}
public void removePeerChainEstimatedHeightListener(final long listenerId) {
peer.removeChainEstimatedHeightListener(listenerId);
}
public long estimatedTargetHeight() {
return peer.chainState().getEstimatedHeight();
}
@Override
public String toString() {
final ChainState chainState = peer.chainState();

@ -13,10 +13,14 @@
package tech.pegasys.pantheon.ethereum.eth.manager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.eth.manager.ChainState.EstimatedHeightListener;
import tech.pegasys.pantheon.ethereum.testutil.BlockDataGenerator;
import tech.pegasys.pantheon.util.uint.UInt256;
@ -228,4 +232,59 @@ public class ChainStateTest {
assertThat(chainState.hasEstimatedHeight()).isTrue();
}
@Test
public void observersInformedWhenHeightUpdatedViaHashAndNumber() {
final long blockNumber = 12;
final BlockHeader bestBlockHeader =
new BlockHeaderTestFixture().number(blockNumber).buildHeader();
chainState.statusReceived(bestBlockHeader.getHash(), INITIAL_TOTAL_DIFFICULTY);
final EstimatedHeightListener listener = mock(EstimatedHeightListener.class);
chainState.addEstimatedHeightListener(listener);
chainState.update(bestBlockHeader.getHash(), blockNumber);
verify(listener).onEstimatedHeightChanged(blockNumber);
}
@Test
public void observersInformedWhenHeightUpdatedViaHeader() {
final long blockNumber = 12;
final BlockHeader bestBlockHeader =
new BlockHeaderTestFixture().number(blockNumber).buildHeader();
chainState.statusReceived(bestBlockHeader.getHash(), INITIAL_TOTAL_DIFFICULTY);
final EstimatedHeightListener listener = mock(EstimatedHeightListener.class);
chainState.addEstimatedHeightListener(listener);
chainState.update(bestBlockHeader);
verify(listener).onEstimatedHeightChanged(blockNumber);
}
@Test
public void observersInformedWhenHeightUpdatedViaHeaderAndTD() {
final long blockNumber = 12;
final BlockHeader bestBlockHeader =
new BlockHeaderTestFixture().number(blockNumber).buildHeader();
chainState.statusReceived(bestBlockHeader.getHash(), INITIAL_TOTAL_DIFFICULTY);
final EstimatedHeightListener listener = mock(EstimatedHeightListener.class);
chainState.addEstimatedHeightListener(listener);
chainState.update(bestBlockHeader, INITIAL_TOTAL_DIFFICULTY);
verify(listener).onEstimatedHeightChanged(blockNumber);
}
@Test
public void observersNotInformedWhenHeightLowers() {
final long blockNumber = 12;
final BlockHeader bestBlockHeader =
new BlockHeaderTestFixture().number(blockNumber).buildHeader();
chainState.statusReceived(bestBlockHeader.getHash(), INITIAL_TOTAL_DIFFICULTY);
final EstimatedHeightListener listener = mock(EstimatedHeightListener.class);
chainState.addEstimatedHeightListener(listener);
chainState.update(bestBlockHeader);
verify(listener).onEstimatedHeightChanged(blockNumber);
final long lowerBlockNumber = 12;
final BlockHeader lowerBlockHeader =
new BlockHeaderTestFixture().number(lowerBlockNumber).buildHeader();
chainState.update(lowerBlockHeader);
verifyNoMoreInteractions(listener);
}
}

@ -54,6 +54,7 @@ public class BlockPropagationManagerTest {
private EthProtocolManager ethProtocolManager;
private BlockPropagationManager<Void> blockPropagationManager;
private SynchronizerConfiguration syncConfig;
private final PendingBlocks pendingBlocks = new PendingBlocks();
private SyncState syncState;
@BeforeClass
@ -78,14 +79,15 @@ public class BlockPropagationManagerTest {
.blockPropagationRange(-3, 5)
.build()
.validated(blockchain);
syncState = new SyncState(blockchain, ethProtocolManager.ethContext(), new PendingBlocks());
syncState = new SyncState(blockchain, ethProtocolManager.ethContext().getEthPeers());
blockPropagationManager =
new BlockPropagationManager<>(
syncConfig,
protocolSchedule,
protocolContext,
ethProtocolManager.ethContext(),
syncState);
syncState,
pendingBlocks);
}
@Test
@ -459,7 +461,8 @@ public class BlockPropagationManagerTest {
protocolSchedule,
protocolContext,
ethProtocolManager.ethContext(),
syncState);
syncState,
pendingBlocks);
final BlockDataGenerator gen = new BlockDataGenerator();
// Import some blocks
@ -479,20 +482,20 @@ public class BlockPropagationManagerTest {
// Check that we pushed our block into the pending collection
assertThat(blockchain.contains(blockToPurge.getHash())).isFalse();
assertThat(syncState.pendingBlocks().contains(blockToPurge.getHash())).isTrue();
assertThat(pendingBlocks.contains(blockToPurge.getHash())).isTrue();
// Import blocks until we bury the target block far enough to be cleaned up
for (int i = 0; i < oldBlocksToImport; i++) {
blockchainUtil.importBlockAtIndex((int) blockchain.getChainHeadBlockNumber() + 1);
assertThat(blockchain.contains(blockToPurge.getHash())).isFalse();
assertThat(syncState.pendingBlocks().contains(blockToPurge.getHash())).isTrue();
assertThat(pendingBlocks.contains(blockToPurge.getHash())).isTrue();
}
// Import again to trigger cleanup
blockchainUtil.importBlockAtIndex((int) blockchain.getChainHeadBlockNumber() + 1);
assertThat(blockchain.contains(blockToPurge.getHash())).isFalse();
assertThat(syncState.pendingBlocks().contains(blockToPurge.getHash())).isFalse();
assertThat(pendingBlocks.contains(blockToPurge.getHash())).isFalse();
}
@Test

@ -35,7 +35,6 @@ import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer.Responder;
import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.BlockchainSetupUtil;
import tech.pegasys.pantheon.ethereum.eth.messages.EthPV62;
import tech.pegasys.pantheon.ethereum.eth.messages.GetBlockHeadersMessage;
import tech.pegasys.pantheon.ethereum.eth.sync.state.PendingBlocks;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction;
@ -81,7 +80,7 @@ public class DownloaderTest {
protocolContext = localBlockchainSetup.getProtocolContext();
ethProtocolManager = EthProtocolManagerTestUtil.create(localBlockchain);
ethContext = ethProtocolManager.ethContext();
syncState = new SyncState(protocolContext.getBlockchain(), ethContext, new PendingBlocks());
syncState = new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers());
}
private Downloader<?> downloader(final SynchronizerConfiguration syncConfig) {

@ -0,0 +1,114 @@
/*
* Copyright 2018 ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package tech.pegasys.pantheon.ethereum.eth.sync.state;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent;
import tech.pegasys.pantheon.ethereum.chain.BlockAddedObserver;
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockBody;
import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.eth.manager.ChainState;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeer;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeers;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
public class SyncStateTest {
private static final long OUR_CHAIN_HEAD_NUMBER = 500;
private static final long TARGET_SYNC_NUMBER = OUR_CHAIN_HEAD_NUMBER + 100;
private final Blockchain blockchain = mock(Blockchain.class);
private final EthPeers ethPeers = mock(EthPeers.class);
private final SyncState.InSyncListener inSyncListener = mock(SyncState.InSyncListener.class);
private final EthPeer peer = mock(EthPeer.class);
private final ChainState peerChainHead = new ChainState();
private SyncState syncState;
private BlockAddedObserver blockAddedObserver;
@Before
public void setUp() {
final ArgumentCaptor<BlockAddedObserver> captor =
ArgumentCaptor.forClass(BlockAddedObserver.class);
when(blockchain.observeBlockAdded(captor.capture())).thenReturn(1L);
when(peer.chainState()).thenReturn(peerChainHead);
when(blockchain.getChainHeadBlockNumber()).thenReturn(OUR_CHAIN_HEAD_NUMBER);
syncState = new SyncState(blockchain, ethPeers);
blockAddedObserver = captor.getValue();
syncState.addInSyncListener(inSyncListener);
}
@Test
public void shouldBeInSyncWhenNoSyncTargetHasBeenSet() {
assertThat(syncState.isInSync()).isTrue();
}
@Test
public void shouldSwitchToNotInSyncWhenSyncTargetWithBetterChainSet() {
final BlockHeader bestBlockHeader = targetBlockHeader();
peerChainHead.update(bestBlockHeader);
syncState.setSyncTarget(peer, bestBlockHeader);
assertThat(syncState.isInSync()).isFalse();
verify(inSyncListener).onSyncStatusChanged(false);
verifyNoMoreInteractions(inSyncListener);
}
@Test
public void shouldSwitchToInSyncWhenSyncTargetCleared() {
setupOutOfSyncState();
syncState.clearSyncTarget();
verify(inSyncListener).onSyncStatusChanged(true);
verifyNoMoreInteractions(inSyncListener);
}
@Test
public void shouldBecomeInSyncWhenOurBlockchainCatchesUp() {
setupOutOfSyncState();
when(blockchain.getChainHeadBlockNumber()).thenReturn(TARGET_SYNC_NUMBER);
blockAddedObserver.onBlockAdded(
BlockAddedEvent.createForHeadAdvancement(
new Block(
targetBlockHeader(),
new BlockBody(Collections.emptyList(), Collections.emptyList()))),
blockchain);
assertThat(syncState.isInSync()).isTrue();
verify(inSyncListener).onSyncStatusChanged(true);
}
private void setupOutOfSyncState() {
final BlockHeader bestBlockHeader = targetBlockHeader();
peerChainHead.update(bestBlockHeader);
syncState.setSyncTarget(peer, bestBlockHeader);
assertThat(syncState.isInSync()).isFalse();
verify(inSyncListener).onSyncStatusChanged(false);
}
private BlockHeader targetBlockHeader() {
return new BlockHeaderTestFixture().number(TARGET_SYNC_NUMBER).buildHeader();
}
}

@ -24,6 +24,7 @@ jar {
dependencies {
implementation project(':crypto')
implementation project(':ethereum:core')
implementation project(':ethereum:blockcreation')
implementation project(':ethereum:eth')
implementation project(':ethereum:p2p')
implementation project(':ethereum:rlp')

@ -30,6 +30,7 @@ dependencies {
implementation project(':consensus:clique')
implementation project(':ethereum:eth')
implementation project(':ethereum:core')
implementation project(':ethereum:blockcreation')
implementation project(':ethereum:rlp')
implementation project(':ethereum:p2p')
implementation project(':ethereum:jsonrpc')

@ -20,8 +20,8 @@ import tech.pegasys.pantheon.cli.custom.CorsAllowedOriginsProperty;
import tech.pegasys.pantheon.consensus.clique.jsonrpc.CliqueRpcApis;
import tech.pegasys.pantheon.consensus.ibft.jsonrpc.IbftRpcApis;
import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.eth.sync.SyncMode;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;

@ -18,8 +18,8 @@ import static tech.pegasys.pantheon.controller.KeyPairUtil.loadKeyPair;
import tech.pegasys.pantheon.controller.MainnetPantheonController;
import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;
import java.io.IOException;
@ -46,7 +46,6 @@ public class PantheonControllerBuilder {
GenesisConfig.development(),
synchronizerConfiguration,
miningParameters,
ethNetworkConfig.getNetworkId(),
nodeKeys);
} else {
final String genesisConfig =

@ -26,11 +26,11 @@ import tech.pegasys.pantheon.consensus.common.VoteProposer;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.BlockHashFunction;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Synchronizer;
import tech.pegasys.pantheon.ethereum.core.TransactionPool;
import tech.pegasys.pantheon.ethereum.core.Util;
@ -41,6 +41,7 @@ import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager;
import tech.pegasys.pantheon.ethereum.eth.sync.DefaultSynchronizer;
import tech.pegasys.pantheon.ethereum.eth.sync.SyncMode;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction;
@ -140,16 +141,23 @@ public class CliquePantheonController
genesisConfig.getChainId(),
fastSyncEnabled,
networkId);
final SyncState syncState =
new SyncState(
protocolContext.getBlockchain(), ethProtocolManager.ethContext().getEthPeers());
final Synchronizer synchronizer =
new DefaultSynchronizer<>(
syncConfig, protocolSchedule, protocolContext, ethProtocolManager.ethContext());
syncConfig,
protocolSchedule,
protocolContext,
ethProtocolManager.ethContext(),
syncState);
final TransactionPool transactionPool =
TransactionPoolFactory.createTransactionPool(
protocolSchedule, protocolContext, ethProtocolManager.ethContext());
final ExecutorService minerThreadPool = Executors.newCachedThreadPool();
CliqueMinerExecutor miningExecutor =
final CliqueMinerExecutor miningExecutor =
new CliqueMinerExecutor(
protocolContext,
minerThreadPool,
@ -163,8 +171,8 @@ public class CliquePantheonController
Util.publicKeyToAddress(nodeKeys.getPublicKey()),
secondsBetweenBlocks),
epochManger);
CliqueMiningCoordinator miningCoordinator =
new CliqueMiningCoordinator(blockchain, miningExecutor);
final CliqueMiningCoordinator miningCoordinator =
new CliqueMiningCoordinator(blockchain, miningExecutor, syncState);
miningCoordinator.addMinedBlockObserver(ethProtocolManager);
// Clique mining is implicitly enabled.

@ -46,6 +46,7 @@ import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager;
import tech.pegasys.pantheon.ethereum.eth.sync.DefaultSynchronizer;
import tech.pegasys.pantheon.ethereum.eth.sync.SyncMode;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHashFunction;
@ -140,8 +141,8 @@ public class IbftPantheonController implements PantheonController<IbftContext, I
final SynchronizerConfiguration syncConfig = taintedSyncConfig.validated(blockchain);
final boolean fastSyncEnabled = syncConfig.syncMode().equals(SyncMode.FAST);
EthProtocolManager ethProtocolManager;
SubProtocol ethSubProtocol;
final EthProtocolManager ethProtocolManager;
final SubProtocol ethSubProtocol;
if (ottomanTestnetOperation) {
LOG.info("Operating on Ottoman testnet.");
ethSubProtocol = Istanbul64Protocol.get();
@ -153,9 +154,16 @@ public class IbftPantheonController implements PantheonController<IbftContext, I
ethProtocolManager =
new EthProtocolManager(protocolContext.getBlockchain(), networkId, fastSyncEnabled, 1);
}
final SyncState syncState =
new SyncState(
protocolContext.getBlockchain(), ethProtocolManager.ethContext().getEthPeers());
final Synchronizer synchronizer =
new DefaultSynchronizer<>(
syncConfig, protocolSchedule, protocolContext, ethProtocolManager.ethContext());
syncConfig,
protocolSchedule,
protocolContext,
ethProtocolManager.ethContext(),
syncState);
final IbftEventQueue ibftEventQueue = new IbftEventQueue();

@ -20,11 +20,11 @@ import tech.pegasys.pantheon.ethereum.blockcreation.DefaultBlockScheduler;
import tech.pegasys.pantheon.ethereum.blockcreation.EthHashBlockMiner;
import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMinerExecutor;
import tech.pegasys.pantheon.ethereum.blockcreation.EthHashMiningCoordinator;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig;
import tech.pegasys.pantheon.ethereum.chain.MutableBlockchain;
import tech.pegasys.pantheon.ethereum.core.BlockHashFunction;
import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Synchronizer;
import tech.pegasys.pantheon.ethereum.core.TransactionPool;
import tech.pegasys.pantheon.ethereum.db.DefaultMutableBlockchain;
@ -34,6 +34,7 @@ import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManager;
import tech.pegasys.pantheon.ethereum.eth.sync.DefaultSynchronizer;
import tech.pegasys.pantheon.ethereum.eth.sync.SyncMode;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;
import tech.pegasys.pantheon.ethereum.eth.sync.state.SyncState;
import tech.pegasys.pantheon.ethereum.eth.transactions.TransactionPoolFactory;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHeaderValidator;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
@ -97,7 +98,6 @@ public class MainnetPantheonController implements PantheonController<Void, EthHa
GenesisConfig.mainnet(),
SynchronizerConfiguration.builder().build(),
miningParams,
MAINNET_NETWORK_ID,
nodeKeys);
}
@ -106,7 +106,6 @@ public class MainnetPantheonController implements PantheonController<Void, EthHa
final GenesisConfig<Void> genesisConfig,
final SynchronizerConfiguration taintedSyncConfig,
final MiningParameters miningParams,
final int networkId,
final KeyPair nodeKeys)
throws IOException {
final RocksDbKeyValueStorage kv =
@ -131,9 +130,16 @@ public class MainnetPantheonController implements PantheonController<Void, EthHa
genesisConfig.getChainId(),
fastSyncEnabled,
syncConfig.downloaderParallelism());
final SyncState syncState =
new SyncState(
protocolContext.getBlockchain(), ethProtocolManager.ethContext().getEthPeers());
final Synchronizer synchronizer =
new DefaultSynchronizer<>(
syncConfig, protocolSchedule, protocolContext, ethProtocolManager.ethContext());
syncConfig,
protocolSchedule,
protocolContext,
ethProtocolManager.ethContext(),
syncState);
final TransactionPool transactionPool =
TransactionPoolFactory.createTransactionPool(
@ -153,7 +159,7 @@ public class MainnetPantheonController implements PantheonController<Void, EthHa
new SystemClock()));
final EthHashMiningCoordinator miningCoordinator =
new EthHashMiningCoordinator(protocolContext.getBlockchain(), executor);
new EthHashMiningCoordinator(protocolContext.getBlockchain(), executor, syncState);
miningCoordinator.addMinedBlockObserver(ethProtocolManager);
if (miningParams.isMiningEnabled()) {
miningCoordinator.enable();

@ -19,8 +19,8 @@ import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractBlockCreator;
import tech.pegasys.pantheon.ethereum.blockcreation.AbstractMiningCoordinator;
import tech.pegasys.pantheon.ethereum.blockcreation.BlockMiner;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Synchronizer;
import tech.pegasys.pantheon.ethereum.core.TransactionPool;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;
@ -58,7 +58,6 @@ public interface PantheonController<C, M extends BlockMiner<C, ? extends Abstrac
GenesisConfig.fromConfig(config, MainnetProtocolSchedule.fromConfig(configOptions)),
syncConfig,
miningParameters,
networkId,
nodeKeys);
} else if (configOptions.containsKey("ibft")) {
return IbftPantheonController.init(

@ -97,7 +97,6 @@ public final class RunnerTest {
GenesisConfig.mainnet(),
fastSyncConfig,
new MiningParametersTestBuilder().enabled(false).build(),
NETWORK_ID,
aheadDbNodeKeys)) {
setupState(blockCount, controller.getProtocolSchedule(), controller.getProtocolContext());
}
@ -109,7 +108,6 @@ public final class RunnerTest {
GenesisConfig.mainnet(),
fastSyncConfig,
new MiningParametersTestBuilder().enabled(false).build(),
NETWORK_ID,
aheadDbNodeKeys);
final String listenHost = InetAddress.getLoopbackAddress().getHostAddress();
final ExecutorService executorService = Executors.newFixedThreadPool(2);
@ -143,7 +141,6 @@ public final class RunnerTest {
GenesisConfig.mainnet(),
fastSyncConfig,
new MiningParametersTestBuilder().enabled(false).build(),
NETWORK_ID,
behindDbNodeKeys);
final Runner runnerBehind =
runnerBuilder.build(

@ -30,8 +30,8 @@ import tech.pegasys.pantheon.PantheonInfo;
import tech.pegasys.pantheon.cli.EthNetworkConfig.Builder;
import tech.pegasys.pantheon.consensus.clique.jsonrpc.CliqueRpcApis;
import tech.pegasys.pantheon.consensus.ibft.jsonrpc.IbftRpcApis;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.eth.sync.SyncMode;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;

@ -19,8 +19,8 @@ import tech.pegasys.pantheon.controller.MainnetPantheonController;
import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.blockcreation.EthHashBlockMiner;
import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters;
import tech.pegasys.pantheon.ethereum.chain.GenesisConfig;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.MiningParametersTestBuilder;
import tech.pegasys.pantheon.ethereum.eth.sync.SynchronizerConfiguration;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
@ -72,7 +72,6 @@ public final class BlockchainImporterTest {
genesisConfig,
SynchronizerConfiguration.builder().build(),
miningParams,
10,
keyPair);
final BlockchainImporter.ImportResult result =
blockImporter.importBlockchain(source, ctrl, true, 1, 1, false, false, null);

@ -24,6 +24,7 @@ include 'ethereum:mock-p2p'
include 'ethereum:jsonrpc'
include 'ethereum:referencetests'
include 'ethereum:core'
include 'ethereum:blockcreation'
include 'ethereum:rlp'
include 'ethereum:eth'
include 'ethereum:trie'

Loading…
Cancel
Save