[PAN-2950] Use java.time.Clock instead of System.currentTimeMillis() (#1747)

To allow us to reset the timestamp in the blockchain for Retesteth support 
we need to pass a Clock to affected APIs and use that instead of the static method
System.currentTimeMillis().  The most consistent way to do this that will ensure
that the API does not sneak back in is to ban the method via ErrorProne.

TestClock.fixed() was altered to return the "now" time of the first time the fixed clock was requested, needed for many header validation tasks validating headers are not from the future.

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Danno Ferrin 5 years ago committed by GitHub
parent 6185129dc7
commit ec5dc85403
  1. 14
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java
  2. 7
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/BlockHeaderValidationRulesetFactory.java
  3. 27
      consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java
  4. 5
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java
  5. 5
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java
  6. 9
      consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java
  7. 5
      consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextBuilder.java
  8. 7
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java
  9. 24
      consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java
  10. 23
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java
  11. 5
      consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java
  12. 16
      consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java
  13. 19
      consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java
  14. 5
      consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java
  15. 12
      consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java
  16. 9
      errorprone-checks/src/main/java/tech/pegasys/errorpronechecks/BannedMethod.java
  17. 6
      errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodNegativeCases.java
  18. 6
      errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodPositiveCases.java
  19. 3
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java
  20. 4
      ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java
  21. 6
      ethereum/core/src/jmh/java/tech/pegasys/pantheon/ethereum/vm/operations/OperationBenchmarkHelper.java
  22. 17
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java
  23. 16
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidator.java
  24. 31
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java
  25. 62
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java
  26. 50
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleBuilder.java
  27. 11
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampBoundedByFutureParameter.java
  28. 17
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java
  29. 7
      ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java
  30. 15
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java
  31. 4
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java
  32. 13
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidatorTest.java
  33. 14
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java
  34. 4
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRuleTest.java
  35. 23
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java
  36. 8
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java
  37. 4
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java
  38. 4
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ConstantinopleSStoreOperationGasCostTest.java
  39. 2
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/EthPeer.java
  40. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTest.java
  41. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java
  42. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java
  43. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java
  44. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java
  45. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/NewBlockMessageTest.java
  46. 11
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java
  47. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java
  48. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java
  49. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java
  50. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java
  51. 5
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/worldstate/WorldStateDownloaderTest.java
  52. 3
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java
  53. 3
      ethereum/graphql/src/test/java/tech/pegasys/pantheon/ethereum/graphql/AbstractEthGraphQLHttpServiceTest.java
  54. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java
  55. 3
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java
  56. 5
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java
  57. 4
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java
  58. 3
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceLoginTest.java
  59. 6
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java
  60. 4
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java
  61. 18
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgent.java
  62. 6
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/VertxPeerDiscoveryAgent.java
  63. 6
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketData.java
  64. 6
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketData.java
  65. 34
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryController.java
  66. 7
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketData.java
  67. 7
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketData.java
  68. 16
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java
  69. 25
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgent.java
  70. 22
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnection.java
  71. 5
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/netty/NettyConnectionInitializer.java
  72. 13
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgentTest.java
  73. 4
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBondingTest.java
  74. 5
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBootstrappingTest.java
  75. 3
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryObserversTest.java
  76. 18
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryPacketSedesTest.java
  77. 44
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTestHelper.java
  78. 15
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTimestampsTest.java
  79. 10
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketDataTest.java
  80. 10
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPacketDataFactory.java
  81. 6
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPeerDiscoveryAgent.java
  82. 9
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketDataTest.java
  83. 76
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java
  84. 7
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryTableRefreshTest.java
  85. 11
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketDataTest.java
  86. 9
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketDataTest.java
  87. 9
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java
  88. 2
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/NetworkingServiceLifecycleTest.java
  89. 2
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java
  90. 2
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgentTest.java
  91. 58
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnectionTest.java
  92. 4
      ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java
  93. 4
      ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java
  94. 3
      pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java
  95. 15
      pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java
  96. 6
      pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java
  97. 6
      pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java
  98. 2
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java
  99. 2
      pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java
  100. 2
      pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -63,14 +63,16 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
private final Map<Node, PantheonPluginContextImpl> pantheonPluginContextMap = new HashMap<>(); private final Map<Node, PantheonPluginContextImpl> pantheonPluginContextMap = new HashMap<>();
private PantheonPluginContextImpl buildPluginContext(final PantheonNode node) { private PantheonPluginContextImpl buildPluginContext(
PantheonPluginContextImpl pantheonPluginContext = new PantheonPluginContextImpl(); final PantheonNode node, final CommandLine commandLine) {
final PantheonPluginContextImpl pantheonPluginContext = new PantheonPluginContextImpl();
final Path pluginsPath = node.homeDirectory().resolve("plugins"); final Path pluginsPath = node.homeDirectory().resolve("plugins");
final File pluginsDirFile = pluginsPath.toFile(); final File pluginsDirFile = pluginsPath.toFile();
if (!pluginsDirFile.isDirectory()) { if (!pluginsDirFile.isDirectory()) {
pluginsDirFile.mkdirs(); pluginsDirFile.mkdirs();
pluginsDirFile.deleteOnExit(); pluginsDirFile.deleteOnExit();
} }
pantheonPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
System.setProperty("pantheon.plugins.dir", pluginsPath.toString()); System.setProperty("pantheon.plugins.dir", pluginsPath.toString());
pantheonPluginContext.registerPlugins(pluginsPath); pantheonPluginContext.registerPlugins(pluginsPath);
return pantheonPluginContext; return pantheonPluginContext;
@ -85,8 +87,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
final CommandLine commandLine = new CommandLine(CommandSpec.create()); final CommandLine commandLine = new CommandLine(CommandSpec.create());
final PantheonPluginContextImpl pantheonPluginContext = final PantheonPluginContextImpl pantheonPluginContext =
pantheonPluginContextMap.computeIfAbsent(node, n -> buildPluginContext(node)); pantheonPluginContextMap.computeIfAbsent(node, n -> buildPluginContext(node, commandLine));
pantheonPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0])); commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0]));
@ -126,7 +127,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
final RunnerBuilder runnerBuilder = new RunnerBuilder(); final RunnerBuilder runnerBuilder = new RunnerBuilder();
if (node.getPermissioningConfiguration().isPresent()) { if (node.getPermissioningConfiguration().isPresent()) {
PermissioningConfiguration permissioningConfiguration = final PermissioningConfiguration permissioningConfiguration =
node.getPermissioningConfiguration().get(); node.getPermissioningConfiguration().get();
runnerBuilder.permissioningConfiguration(permissioningConfiguration); runnerBuilder.permissioningConfiguration(permissioningConfiguration);
@ -151,6 +152,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
.webSocketConfiguration(node.webSocketConfiguration()) .webSocketConfiguration(node.webSocketConfiguration())
.dataDir(node.homeDirectory()) .dataDir(node.homeDirectory())
.metricsSystem(noOpMetricsSystem) .metricsSystem(noOpMetricsSystem)
.clock(Clock.systemUTC())
.metricsConfiguration(node.metricsConfiguration()) .metricsConfiguration(node.metricsConfiguration())
.p2pEnabled(node.isP2pEnabled()) .p2pEnabled(node.isP2pEnabled())
.graphQLConfiguration(GraphQLConfiguration.createDefault()) .graphQLConfiguration(GraphQLConfiguration.createDefault())
@ -167,7 +169,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
@Override @Override
public void stopNode(final PantheonNode node) { public void stopNode(final PantheonNode node) {
PantheonPluginContextImpl pluginContext = pantheonPluginContextMap.remove(node); final PantheonPluginContextImpl pluginContext = pantheonPluginContextMap.remove(node);
if (pluginContext != null) { if (pluginContext != null) {
pluginContext.stopPlugins(); pluginContext.stopPlugins();
} }

@ -28,6 +28,8 @@ import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.GasUsageVali
import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampBoundedByFutureParameter; import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampBoundedByFutureParameter;
import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent; import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent;
import java.time.Clock;
public class BlockHeaderValidationRulesetFactory { public class BlockHeaderValidationRulesetFactory {
/** /**
@ -38,16 +40,17 @@ public class BlockHeaderValidationRulesetFactory {
* *
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks. * @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param epochManager an object which determines if a given block is an epoch block. * @param epochManager an object which determines if a given block is an epoch block.
* @param clock System clock
* @return the header validator. * @return the header validator.
*/ */
public static BlockHeaderValidator<CliqueContext> cliqueBlockHeaderValidator( public static BlockHeaderValidator<CliqueContext> cliqueBlockHeaderValidator(
final long secondsBetweenBlocks, final EpochManager epochManager) { final long secondsBetweenBlocks, final EpochManager epochManager, final Clock clock) {
return new BlockHeaderValidator.Builder<CliqueContext>() return new BlockHeaderValidator.Builder<CliqueContext>()
.addRule(new AncestryValidationRule()) .addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule()) .addRule(new GasUsageValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL)) .addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL))
.addRule(new TimestampBoundedByFutureParameter(10)) .addRule(new TimestampBoundedByFutureParameter(10, clock))
.addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks)) .addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks))
.addRule(new ConstantFieldValidationRule<>("MixHash", BlockHeader::getMixHash, Hash.ZERO)) .addRule(new ConstantFieldValidationRule<>("MixHash", BlockHeader::getMixHash, Hash.ZERO))
.addRule( .addRule(

@ -30,6 +30,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
/** Defines the protocol behaviours for a blockchain using Clique. */ /** Defines the protocol behaviours for a blockchain using Clique. */
public class CliqueProtocolSchedule { public class CliqueProtocolSchedule {
@ -40,7 +41,8 @@ public class CliqueProtocolSchedule {
final GenesisConfigOptions config, final GenesisConfigOptions config,
final KeyPair nodeKeys, final KeyPair nodeKeys,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
final Clock clock) {
final CliqueConfigOptions cliqueConfig = config.getCliqueConfigOptions(); final CliqueConfigOptions cliqueConfig = config.getCliqueConfigOptions();
@ -52,28 +54,37 @@ public class CliqueProtocolSchedule {
DEFAULT_CHAIN_ID, DEFAULT_CHAIN_ID,
builder -> builder ->
applyCliqueSpecificModifications( applyCliqueSpecificModifications(
epochManager, cliqueConfig.getBlockPeriodSeconds(), localNodeAddress, builder), epochManager,
cliqueConfig.getBlockPeriodSeconds(),
localNodeAddress,
builder,
clock),
privacyParameters, privacyParameters,
isRevertReasonEnabled) isRevertReasonEnabled,
clock)
.createProtocolSchedule(); .createProtocolSchedule();
} }
public static ProtocolSchedule<CliqueContext> create( public static ProtocolSchedule<CliqueContext> create(
final GenesisConfigOptions config, final GenesisConfigOptions config,
final KeyPair nodeKeys, final KeyPair nodeKeys,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
return create(config, nodeKeys, PrivacyParameters.DEFAULT, isRevertReasonEnabled); final Clock clock) {
return create(config, nodeKeys, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
} }
private static ProtocolSpecBuilder<CliqueContext> applyCliqueSpecificModifications( private static ProtocolSpecBuilder<CliqueContext> applyCliqueSpecificModifications(
final EpochManager epochManager, final EpochManager epochManager,
final long secondsBetweenBlocks, final long secondsBetweenBlocks,
final Address localNodeAddress, final Address localNodeAddress,
final ProtocolSpecBuilder<Void> specBuilder) { final ProtocolSpecBuilder<Void> specBuilder,
final Clock clock) {
return specBuilder return specBuilder
.changeConsensusContextType( .changeConsensusContextType(
difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager), difficultyCalculator ->
difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager), cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager, clock),
difficultyCalculator ->
cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager, clock),
MainnetBlockBodyValidator::new, MainnetBlockBodyValidator::new,
MainnetBlockValidator::new, MainnetBlockValidator::new,
MainnetBlockImporter::new, MainnetBlockImporter::new,

@ -20,6 +20,7 @@ import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.core.Wei; import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.testutil.TestClock;
import org.junit.Test; import org.junit.Test;
@ -41,7 +42,7 @@ public class CliqueProtocolScheduleTest {
final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions(); final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions();
final ProtocolSchedule<CliqueContext> protocolSchedule = final ProtocolSchedule<CliqueContext> protocolSchedule =
CliqueProtocolSchedule.create(config, NODE_KEYS, false); CliqueProtocolSchedule.create(config, NODE_KEYS, false, TestClock.fixed());
final ProtocolSpec<CliqueContext> homesteadSpec = protocolSchedule.getByBlockNumber(1); final ProtocolSpec<CliqueContext> homesteadSpec = protocolSchedule.getByBlockNumber(1);
final ProtocolSpec<CliqueContext> tangerineWhistleSpec = protocolSchedule.getByBlockNumber(2); final ProtocolSpec<CliqueContext> tangerineWhistleSpec = protocolSchedule.getByBlockNumber(2);
@ -57,7 +58,7 @@ public class CliqueProtocolScheduleTest {
public void parametersAlignWithMainnetWithAdjustments() { public void parametersAlignWithMainnetWithAdjustments() {
final ProtocolSpec<CliqueContext> homestead = final ProtocolSpec<CliqueContext> homestead =
CliqueProtocolSchedule.create( CliqueProtocolSchedule.create(
GenesisConfigFile.DEFAULT.getConfigOptions(), NODE_KEYS, false) GenesisConfigFile.DEFAULT.getConfigOptions(), NODE_KEYS, false, TestClock.fixed())
.getByBlockNumber(0); .getByBlockNumber(0);
assertThat(homestead.getName()).isEqualTo("Frontier"); assertThat(homestead.getName()).isEqualTo("Frontier");

@ -76,7 +76,10 @@ public class CliqueBlockCreatorTest {
public void setup() { public void setup() {
protocolSchedule = protocolSchedule =
CliqueProtocolSchedule.create( CliqueProtocolSchedule.create(
GenesisConfigFile.DEFAULT.getConfigOptions(), proposerKeyPair, false); GenesisConfigFile.DEFAULT.getConfigOptions(),
proposerKeyPair,
false,
TestClock.fixed());
final Address otherAddress = Util.publicKeyToAddress(otherKeyPair.getPublicKey()); final Address otherAddress = Util.publicKeyToAddress(otherKeyPair.getPublicKey());
validatorList.add(otherAddress); validatorList.add(otherAddress);

@ -90,7 +90,8 @@ public class CliqueMinerExecutorTest {
new CliqueMinerExecutor( new CliqueMinerExecutor(
cliqueProtocolContext, cliqueProtocolContext,
Executors.newSingleThreadExecutor(), Executors.newSingleThreadExecutor(),
CliqueProtocolSchedule.create(GENESIS_CONFIG_OPTIONS, proposerKeyPair, false), CliqueProtocolSchedule.create(
GENESIS_CONFIG_OPTIONS, proposerKeyPair, false, TestClock.fixed()),
new PendingTransactions( new PendingTransactions(
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS, TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS,
1, 1,
@ -127,7 +128,8 @@ public class CliqueMinerExecutorTest {
new CliqueMinerExecutor( new CliqueMinerExecutor(
cliqueProtocolContext, cliqueProtocolContext,
Executors.newSingleThreadExecutor(), Executors.newSingleThreadExecutor(),
CliqueProtocolSchedule.create(GENESIS_CONFIG_OPTIONS, proposerKeyPair, false), CliqueProtocolSchedule.create(
GENESIS_CONFIG_OPTIONS, proposerKeyPair, false, TestClock.fixed()),
new PendingTransactions( new PendingTransactions(
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS, TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS,
1, 1,
@ -164,7 +166,8 @@ public class CliqueMinerExecutorTest {
new CliqueMinerExecutor( new CliqueMinerExecutor(
cliqueProtocolContext, cliqueProtocolContext,
Executors.newSingleThreadExecutor(), Executors.newSingleThreadExecutor(),
CliqueProtocolSchedule.create(GENESIS_CONFIG_OPTIONS, proposerKeyPair, false), CliqueProtocolSchedule.create(
GENESIS_CONFIG_OPTIONS, proposerKeyPair, false, TestClock.fixed()),
new PendingTransactions( new PendingTransactions(
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS, TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS,
1, 1,

@ -12,6 +12,7 @@
*/ */
package tech.pegasys.pantheon.consensus.ibft.support; package tech.pegasys.pantheon.consensus.ibft.support;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static tech.pegasys.pantheon.ethereum.core.InMemoryStorageProvider.createInMemoryBlockchain; import static tech.pegasys.pantheon.ethereum.core.InMemoryStorageProvider.createInMemoryBlockchain;
@ -159,6 +160,8 @@ public class TestContextBuilder {
} }
public TestContext build() { public TestContext build() {
checkNotNull(clock);
final NetworkLayout networkNodes = final NetworkLayout networkNodes =
NetworkLayout.createNetworkLayout(validatorCount, indexOfFirstLocallyProposedBlock); NetworkLayout.createNetworkLayout(validatorCount, indexOfFirstLocallyProposedBlock);
@ -263,7 +266,7 @@ public class TestContextBuilder {
genesisConfigOptions.byzantiumBlock(0); genesisConfigOptions.byzantiumBlock(0);
final ProtocolSchedule<IbftContext> protocolSchedule = final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create(genesisConfigOptions); IbftProtocolSchedule.create(genesisConfigOptions, Clock.systemUTC());
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// From here down is BASICALLY taken from IbftPantheonController // From here down is BASICALLY taken from IbftPantheonController

@ -26,6 +26,8 @@ import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampBou
import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent; import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import java.time.Clock;
public class IbftBlockHeaderValidationRulesetFactory { public class IbftBlockHeaderValidationRulesetFactory {
/** /**
@ -33,15 +35,16 @@ public class IbftBlockHeaderValidationRulesetFactory {
* part of the BlockChain (i.e. not proposed blocks, which do not contain commit seals) * part of the BlockChain (i.e. not proposed blocks, which do not contain commit seals)
* *
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks. * @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param clock System clock
* @return BlockHeaderValidator configured for assessing ibft block headers * @return BlockHeaderValidator configured for assessing ibft block headers
*/ */
public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator( public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator(
final long secondsBetweenBlocks) { final long secondsBetweenBlocks, final Clock clock) {
return new BlockHeaderValidator.Builder<IbftContext>() return new BlockHeaderValidator.Builder<IbftContext>()
.addRule(new AncestryValidationRule()) .addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule()) .addRule(new GasUsageValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL)) .addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL))
.addRule(new TimestampBoundedByFutureParameter(1)) .addRule(new TimestampBoundedByFutureParameter(1, clock))
.addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks)) .addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks))
.addRule( .addRule(
new ConstantFieldValidationRule<>( new ConstantFieldValidationRule<>(

@ -26,6 +26,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
/** Defines the protocol behaviours for a blockchain using IBFT. */ /** Defines the protocol behaviours for a blockchain using IBFT. */
public class IbftProtocolSchedule { public class IbftProtocolSchedule {
@ -35,34 +36,37 @@ public class IbftProtocolSchedule {
public static ProtocolSchedule<IbftContext> create( public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final GenesisConfigOptions config,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
final Clock clock) {
final IbftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions(); final IbftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions();
final long blockPeriod = ibftConfig.getBlockPeriodSeconds(); final long blockPeriod = ibftConfig.getBlockPeriodSeconds();
return new ProtocolScheduleBuilder<>( return new ProtocolScheduleBuilder<>(
config, config,
DEFAULT_CHAIN_ID, DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(blockPeriod, builder), builder -> applyIbftChanges(blockPeriod, builder, clock),
privacyParameters, privacyParameters,
isRevertReasonEnabled) isRevertReasonEnabled,
clock)
.createProtocolSchedule(); .createProtocolSchedule();
} }
public static ProtocolSchedule<IbftContext> create( public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) { final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled); return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
} }
public static ProtocolSchedule<IbftContext> create(final GenesisConfigOptions config) { public static ProtocolSchedule<IbftContext> create(
return create(config, PrivacyParameters.DEFAULT, false); final GenesisConfigOptions config, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, false, clock);
} }
private static ProtocolSpecBuilder<IbftContext> applyIbftChanges( private static ProtocolSpecBuilder<IbftContext> applyIbftChanges(
final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder) { final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder, final Clock clock) {
return builder return builder
.<IbftContext>changeConsensusContextType( .<IbftContext>changeConsensusContextType(
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
MainnetBlockBodyValidator::new, MainnetBlockBodyValidator::new,
MainnetBlockValidator::new, MainnetBlockValidator::new,
MainnetBlockImporter::new, MainnetBlockImporter::new,

@ -26,6 +26,7 @@ import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.core.Util; import tech.pegasys.pantheon.ethereum.core.Util;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode; import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
@ -54,7 +55,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, validators, parentHeader).buildHeader(); getPresetHeaderBuilder(2, proposerKeyPair, validators, parentHeader).buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -75,7 +76,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, emptyList(), parentHeader).buildHeader(); getPresetHeaderBuilder(2, proposerKeyPair, emptyList(), parentHeader).buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -100,7 +101,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader(); .buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -121,7 +122,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, validators, parentHeader).nonce(3).buildHeader(); getPresetHeaderBuilder(2, proposerKeyPair, validators, parentHeader).nonce(3).buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -144,7 +145,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader(); .buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -167,7 +168,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader(); .buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -190,7 +191,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader(); .buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -213,7 +214,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader(); .buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -234,7 +235,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, validators, null).buildHeader(); getPresetHeaderBuilder(2, proposerKeyPair, validators, null).buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -258,7 +259,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader(); .buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -281,7 +282,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader(); .buildHeader();
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(

@ -75,7 +75,8 @@ public class IbftBlockCreatorTest {
final ProtocolSchedule<IbftContext> protocolSchedule = final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create( IbftProtocolSchedule.create(
GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}") GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}")
.getConfigOptions()); .getConfigOptions(),
TestClock.fixed());
final ProtocolContext<IbftContext> protContext = final ProtocolContext<IbftContext> protContext =
new ProtocolContext<>( new ProtocolContext<>(
blockchain, blockchain,
@ -110,7 +111,7 @@ public class IbftBlockCreatorTest {
final Block block = blockCreator.createBlock(Instant.now().getEpochSecond()); final Block block = blockCreator.createBlock(Instant.now().getEpochSecond());
final BlockHeaderValidator<IbftContext> rules = final BlockHeaderValidator<IbftContext> rules =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(0); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(0, TestClock.fixed());
// NOTE: The header will not contain commit seals, so can only do light validation on header. // NOTE: The header will not contain commit seals, so can only do light validation on header.
final boolean validationResult = final boolean validationResult =

@ -26,6 +26,8 @@ import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampBou
import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent; import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import java.time.Clock;
public class IbftBlockHeaderValidationRulesetFactory { public class IbftBlockHeaderValidationRulesetFactory {
/** /**
@ -33,11 +35,12 @@ public class IbftBlockHeaderValidationRulesetFactory {
* part of the BlockChain (i.e. not proposed blocks, which do not contain commit seals) * part of the BlockChain (i.e. not proposed blocks, which do not contain commit seals)
* *
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks. * @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param clock System clock
* @return BlockHeaderValidator configured for assessing ibft block headers * @return BlockHeaderValidator configured for assessing ibft block headers
*/ */
public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator( public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator(
final long secondsBetweenBlocks) { final long secondsBetweenBlocks, final Clock clock) {
return createValidator(secondsBetweenBlocks, true); return createValidator(secondsBetweenBlocks, true, clock);
} }
/** /**
@ -45,20 +48,21 @@ public class IbftBlockHeaderValidationRulesetFactory {
* which need to be vetted by the validators, and do not contain commit seals). * which need to be vetted by the validators, and do not contain commit seals).
* *
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks. * @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param clock System clock
* @return BlockHeaderValidator configured for assessing ibft block headers * @return BlockHeaderValidator configured for assessing ibft block headers
*/ */
public static BlockHeaderValidator<IbftContext> ibftProposedBlockValidator( public static BlockHeaderValidator<IbftContext> ibftProposedBlockValidator(
final long secondsBetweenBlocks) { final long secondsBetweenBlocks, final Clock clock) {
return createValidator(secondsBetweenBlocks, false); return createValidator(secondsBetweenBlocks, false, clock);
} }
private static BlockHeaderValidator<IbftContext> createValidator( private static BlockHeaderValidator<IbftContext> createValidator(
final long secondsBetweenBlocks, final boolean validateCommitSeals) { final long secondsBetweenBlocks, final boolean validateCommitSeals, final Clock clock) {
return new BlockHeaderValidator.Builder<IbftContext>() return new BlockHeaderValidator.Builder<IbftContext>()
.addRule(new AncestryValidationRule()) .addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule()) .addRule(new GasUsageValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL)) .addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL))
.addRule(new TimestampBoundedByFutureParameter(1)) .addRule(new TimestampBoundedByFutureParameter(1, clock))
.addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks)) .addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks))
.addRule( .addRule(
new ConstantFieldValidationRule<>( new ConstantFieldValidationRule<>(

@ -27,6 +27,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
/** Defines the protocol behaviours for a blockchain using IBFT. */ /** Defines the protocol behaviours for a blockchain using IBFT. */
public class IbftProtocolSchedule { public class IbftProtocolSchedule {
@ -36,30 +37,32 @@ public class IbftProtocolSchedule {
public static ProtocolSchedule<IbftContext> create( public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final GenesisConfigOptions config,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
final Clock clock) {
final IbftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions(); final IbftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions();
final long blockPeriod = ibftConfig.getBlockPeriodSeconds(); final long blockPeriod = ibftConfig.getBlockPeriodSeconds();
return new ProtocolScheduleBuilder<>( return new ProtocolScheduleBuilder<>(
config, config,
DEFAULT_CHAIN_ID, DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(blockPeriod, builder), builder -> applyIbftChanges(blockPeriod, builder, clock),
privacyParameters, privacyParameters,
isRevertReasonEnabled) isRevertReasonEnabled,
clock)
.createProtocolSchedule(); .createProtocolSchedule();
} }
public static ProtocolSchedule<IbftContext> create( public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) { final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled); return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
} }
private static ProtocolSpecBuilder<IbftContext> applyIbftChanges( private static ProtocolSpecBuilder<IbftContext> applyIbftChanges(
final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder) { final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder, final Clock clock) {
return builder return builder
.<IbftContext>changeConsensusContextType( .<IbftContext>changeConsensusContextType(
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
MainnetBlockBodyValidator::new, MainnetBlockBodyValidator::new,
MainnetBlockValidator::new, MainnetBlockValidator::new,
MainnetBlockImporter::new, MainnetBlockImporter::new,

@ -32,6 +32,7 @@ import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.core.Hash;
import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator; import tech.pegasys.pantheon.ethereum.mainnet.BlockHeaderValidator;
import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode; import tech.pegasys.pantheon.ethereum.mainnet.HeaderValidationMode;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
@ -67,7 +68,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, parentHeader); final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, parentHeader);
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(
@ -90,7 +91,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, null); final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, null);
final BlockHeaderValidator<IbftContext> validator = final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat( assertThat(
validator.validateHeader( validator.validateHeader(

@ -43,7 +43,7 @@ import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock; import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Instant; import java.time.Clock;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -78,11 +78,13 @@ public class IbftBlockCreatorTest {
Address.fromHexString(String.format("%020d", 4)), Address.fromHexString(String.format("%020d", 4)),
localAddr); localAddr);
Clock testClock = TestClock.fixed();
final ProtocolSchedule<IbftContext> protocolSchedule = final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create( IbftProtocolSchedule.create(
GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}") GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}")
.getConfigOptions(), .getConfigOptions(),
false); false,
testClock);
final ProtocolContext<IbftContext> protContext = final ProtocolContext<IbftContext> protContext =
new ProtocolContext<>( new ProtocolContext<>(
blockchain, blockchain,
@ -102,7 +104,7 @@ public class IbftBlockCreatorTest {
new PendingTransactions( new PendingTransactions(
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS, TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS,
1, 1,
TestClock.fixed(), testClock,
metricsSystem), metricsSystem),
protContext, protContext,
protocolSchedule, protocolSchedule,
@ -111,10 +113,10 @@ public class IbftBlockCreatorTest {
Wei.ZERO, Wei.ZERO,
parentHeader); parentHeader);
final Block block = blockCreator.createBlock(Instant.now().getEpochSecond()); final Block block = blockCreator.createBlock(testClock.instant().getEpochSecond());
final BlockHeaderValidator<IbftContext> rules = final BlockHeaderValidator<IbftContext> rules =
IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator(0); IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator(0, testClock);
final boolean validationResult = final boolean validationResult =
rules.validateHeader( rules.validateHeader(

@ -15,7 +15,6 @@ package tech.pegasys.errorpronechecks;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING; import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher; import static com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import static com.google.errorprone.matchers.Description.NO_MATCH; import static com.google.errorprone.matchers.Description.NO_MATCH;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod; import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
import java.util.Map; import java.util.Map;
@ -23,6 +22,7 @@ import java.util.Map;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.errorprone.BugPattern; import com.google.errorprone.BugPattern;
import com.google.errorprone.BugPattern.LinkType;
import com.google.errorprone.VisitorState; import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker; import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.matchers.Description; import com.google.errorprone.matchers.Description;
@ -34,12 +34,15 @@ import com.sun.source.tree.MethodInvocationTree;
@BugPattern( @BugPattern(
name = "BannedMethod", name = "BannedMethod",
summary = "Some methods should not be used, make sure that doesn't happen.", summary = "Some methods should not be used, make sure that doesn't happen.",
severity = WARNING) severity = WARNING,
linkType = LinkType.NONE)
public class BannedMethod extends BugChecker implements MethodInvocationTreeMatcher { public class BannedMethod extends BugChecker implements MethodInvocationTreeMatcher {
private static final ImmutableMap<Matcher<ExpressionTree>, String> BANNED_METHOD_LIST = private static final ImmutableMap<Matcher<ExpressionTree>, String> BANNED_METHOD_LIST =
ImmutableMap.of( ImmutableMap.of(
allOf(staticMethod().onClass("com.google.common.base.Objects").withAnyName()), staticMethod().onClass("java.lang.System").named("currentTimeMillis"),
"Do not use System.currentTimeMillis(), use a java.time.Clock passed into a constructor or as a static method parameter.",
staticMethod().onClass("com.google.common.base.Objects").withAnyName(),
"Do not use com.google.common.base.Objects methods, use java.util.Objects methods instead."); "Do not use com.google.common.base.Objects methods, use java.util.Objects methods instead.");
@Override @Override

@ -13,6 +13,7 @@
package tech.pegasys.errorpronechecks; package tech.pegasys.errorpronechecks;
import java.util.Objects; import java.util.Objects;
import java.time.Clock;
public class BannedMethodNegativeCases { public class BannedMethodNegativeCases {
@ -23,4 +24,9 @@ public class BannedMethodNegativeCases {
public void callsObjectsHashCode() throws Exception { public void callsObjectsHashCode() throws Exception {
Objects.hash("1", "1"); Objects.hash("1", "1");
} }
public void callsClockMillis(final Clock clock) throws Exception {
clock.millis();
}
} }

@ -27,4 +27,10 @@ public class BannedMethodPositiveCases {
// java.util.Objects methods instead. // java.util.Objects methods instead.
Objects.hashCode("1", "1"); Objects.hashCode("1", "1");
} }
public void callsSystemCurrentTimeMillis() throws Exception {
// BUG: Diagnostic contains: Do not use System.currentTimeMillis(), use a java.time.Clock
// passed into a constructor or as a static method parameter.
System.currentTimeMillis();
}
} }

@ -93,7 +93,8 @@ public class BlockTransactionSelectorTest {
@Test @Test
public void emptyPendingTransactionsResultsInEmptyVettingResult() { public void emptyPendingTransactionsResultsInEmptyVettingResult() {
final ProtocolSchedule<Void> protocolSchedule = final ProtocolSchedule<Void> protocolSchedule =
FixedDifficultyProtocolSchedule.create(GenesisConfigFile.development().getConfigOptions()); FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), TestClock.fixed());
final TransactionProcessor mainnetTransactionProcessor = final TransactionProcessor mainnetTransactionProcessor =
protocolSchedule.getByBlockNumber(0).getTransactionProcessor(); protocolSchedule.getByBlockNumber(0).getTransactionProcessor();

@ -58,8 +58,10 @@ public class EthHashBlockCreatorTest {
BigInteger.valueOf(42), BigInteger.valueOf(42),
Function.identity(), Function.identity(),
PrivacyParameters.DEFAULT, PrivacyParameters.DEFAULT,
false) false,
TestClock.fixed())
.createProtocolSchedule()) .createProtocolSchedule())
.clock(TestClock.fixed())
.build(); .build();
@Test @Test

@ -30,6 +30,7 @@ import tech.pegasys.pantheon.util.uint.UInt256;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Clock;
import com.google.common.io.MoreFiles; import com.google.common.io.MoreFiles;
import com.google.common.io.RecursiveDeleteOption; import com.google.common.io.RecursiveDeleteOption;
@ -57,7 +58,10 @@ public class OperationBenchmarkHelper {
new NoOpMetricsSystem()); new NoOpMetricsSystem());
final ExecutionContextTestFixture executionContext = final ExecutionContextTestFixture executionContext =
ExecutionContextTestFixture.builder().keyValueStorage(keyValueStorage).build(); ExecutionContextTestFixture.builder()
.keyValueStorage(keyValueStorage)
.clock(Clock.systemUTC())
.build();
final MutableBlockchain blockchain = executionContext.getBlockchain(); final MutableBlockchain blockchain = executionContext.getBlockchain();
for (int i = 1; i < 256; i++) { for (int i = 1; i < 256; i++) {

@ -17,27 +17,32 @@ import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import java.time.Clock;
/** A ProtocolSchedule which behaves similarly to MainNet, but with a much reduced difficulty. */ /** A ProtocolSchedule which behaves similarly to MainNet, but with a much reduced difficulty. */
public class FixedDifficultyProtocolSchedule { public class FixedDifficultyProtocolSchedule {
public static ProtocolSchedule<Void> create( public static ProtocolSchedule<Void> create(
final GenesisConfigOptions config, final GenesisConfigOptions config,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
final Clock clock) {
return new ProtocolScheduleBuilder<>( return new ProtocolScheduleBuilder<>(
config, config,
builder -> builder.difficultyCalculator(FixedDifficultyCalculators.calculator(config)), builder -> builder.difficultyCalculator(FixedDifficultyCalculators.calculator(config)),
privacyParameters, privacyParameters,
isRevertReasonEnabled) isRevertReasonEnabled,
clock)
.createProtocolSchedule(); .createProtocolSchedule();
} }
public static ProtocolSchedule<Void> create( public static ProtocolSchedule<Void> create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) { final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled); return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
} }
public static ProtocolSchedule<Void> create(final GenesisConfigOptions config) { public static ProtocolSchedule<Void> create(
return create(config, PrivacyParameters.DEFAULT, false); final GenesisConfigOptions config, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, false, clock);
} }
} }

@ -24,6 +24,8 @@ import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampBou
import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent; import tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
public final class MainnetBlockHeaderValidator { public final class MainnetBlockHeaderValidator {
public static final BytesValue DAO_EXTRA_DATA = public static final BytesValue DAO_EXTRA_DATA =
@ -34,13 +36,13 @@ public final class MainnetBlockHeaderValidator {
public static final int MINIMUM_SECONDS_SINCE_PARENT = 1; public static final int MINIMUM_SECONDS_SINCE_PARENT = 1;
public static BlockHeaderValidator<Void> create( public static BlockHeaderValidator<Void> create(
final DifficultyCalculator<Void> difficultyCalculator) { final DifficultyCalculator<Void> difficultyCalculator, final Clock clock) {
return createValidator(difficultyCalculator).build(); return createValidator(difficultyCalculator, clock).build();
} }
public static BlockHeaderValidator<Void> createDaoValidator( static BlockHeaderValidator<Void> createDaoValidator(
final DifficultyCalculator<Void> difficultyCalculator) { final DifficultyCalculator<Void> difficultyCalculator, final Clock clock) {
return createValidator(difficultyCalculator) return createValidator(difficultyCalculator, clock)
.addRule( .addRule(
new ConstantFieldValidationRule<>( new ConstantFieldValidationRule<>(
"extraData", BlockHeader::getExtraData, DAO_EXTRA_DATA)) "extraData", BlockHeader::getExtraData, DAO_EXTRA_DATA))
@ -65,14 +67,14 @@ public final class MainnetBlockHeaderValidator {
} }
private static BlockHeaderValidator.Builder<Void> createValidator( private static BlockHeaderValidator.Builder<Void> createValidator(
final DifficultyCalculator<Void> difficultyCalculator) { final DifficultyCalculator<Void> difficultyCalculator, final Clock clock) {
return new BlockHeaderValidator.Builder<Void>() return new BlockHeaderValidator.Builder<Void>()
.addRule(new CalculatedDifficultyValidationRule<>(difficultyCalculator)) .addRule(new CalculatedDifficultyValidationRule<>(difficultyCalculator))
.addRule(new AncestryValidationRule()) .addRule(new AncestryValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(MIN_GAS_LIMIT, MAX_GAS_LIMIT)) .addRule(new GasLimitRangeAndDeltaValidationRule(MIN_GAS_LIMIT, MAX_GAS_LIMIT))
.addRule(new GasUsageValidationRule()) .addRule(new GasUsageValidationRule())
.addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT)) .addRule(new TimestampMoreRecentThanParent(MINIMUM_SECONDS_SINCE_PARENT))
.addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S)) .addRule(new TimestampBoundedByFutureParameter(TIMESTAMP_TOLERANCE_S, clock))
.addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES)) .addRule(new ExtraDataMaxLengthValidationRule(BlockHeader.MAX_EXTRA_DATA_BYTES))
.addRule(new ProofOfWorkValidationRule()); .addRule(new ProofOfWorkValidationRule());
} }

@ -19,6 +19,7 @@ import tech.pegasys.pantheon.ethereum.difficulty.fixed.FixedDifficultyCalculator
import tech.pegasys.pantheon.ethereum.difficulty.fixed.FixedDifficultyProtocolSchedule; import tech.pegasys.pantheon.ethereum.difficulty.fixed.FixedDifficultyProtocolSchedule;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
import java.util.function.Function; import java.util.function.Function;
/** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */ /** Provides {@link ProtocolSpec} lookups for mainnet hard forks. */
@ -26,9 +27,9 @@ public class MainnetProtocolSchedule {
public static final BigInteger DEFAULT_CHAIN_ID = BigInteger.ONE; public static final BigInteger DEFAULT_CHAIN_ID = BigInteger.ONE;
public static ProtocolSchedule<Void> create() { public static ProtocolSchedule<Void> create(final Clock clock) {
return fromConfig( return fromConfig(
GenesisConfigFile.mainnet().getConfigOptions(), PrivacyParameters.DEFAULT, false); GenesisConfigFile.mainnet().getConfigOptions(), PrivacyParameters.DEFAULT, false, clock);
} }
/** /**
@ -38,18 +39,25 @@ public class MainnetProtocolSchedule {
* starting points * starting points
* @param privacyParameters the parameters set for private transactions * @param privacyParameters the parameters set for private transactions
* @param isRevertReasonEnabled whether storing the revert reason is for failed transactions * @param isRevertReasonEnabled whether storing the revert reason is for failed transactions
* @param clock System clock
* @return A configured mainnet protocol schedule * @return A configured mainnet protocol schedule
*/ */
public static ProtocolSchedule<Void> fromConfig( public static ProtocolSchedule<Void> fromConfig(
final GenesisConfigOptions config, final GenesisConfigOptions config,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
final Clock clock) {
if (FixedDifficultyCalculators.isFixedDifficultyInConfig(config)) { if (FixedDifficultyCalculators.isFixedDifficultyInConfig(config)) {
return FixedDifficultyProtocolSchedule.create( return FixedDifficultyProtocolSchedule.create(
config, privacyParameters, isRevertReasonEnabled); config, privacyParameters, isRevertReasonEnabled, clock);
} }
return new ProtocolScheduleBuilder<>( return new ProtocolScheduleBuilder<Void>(
config, DEFAULT_CHAIN_ID, Function.identity(), privacyParameters, isRevertReasonEnabled) config,
DEFAULT_CHAIN_ID,
Function.identity(),
privacyParameters,
isRevertReasonEnabled,
clock)
.createProtocolSchedule(); .createProtocolSchedule();
} }
@ -59,11 +67,12 @@ public class MainnetProtocolSchedule {
* @param config {@link GenesisConfigOptions} containing the config options for the milestone * @param config {@link GenesisConfigOptions} containing the config options for the milestone
* starting points * starting points
* @param isRevertReasonEnabled whether storing the revert reason is for failed transactions * @param isRevertReasonEnabled whether storing the revert reason is for failed transactions
* @param clock System clock
* @return A configured mainnet protocol schedule * @return A configured mainnet protocol schedule
*/ */
public static ProtocolSchedule<Void> fromConfig( public static ProtocolSchedule<Void> fromConfig(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) { final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
return fromConfig(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled); return fromConfig(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
} }
/** /**
@ -71,9 +80,11 @@ public class MainnetProtocolSchedule {
* *
* @param config {@link GenesisConfigOptions} containing the config options for the milestone * @param config {@link GenesisConfigOptions} containing the config options for the milestone
* starting points * starting points
* @param clock System clock
* @return A configured mainnet protocol schedule * @return A configured mainnet protocol schedule
*/ */
public static ProtocolSchedule<Void> fromConfig(final GenesisConfigOptions config) { public static ProtocolSchedule<Void> fromConfig(
return fromConfig(config, PrivacyParameters.DEFAULT, false); final GenesisConfigOptions config, final Clock clock) {
return fromConfig(config, PrivacyParameters.DEFAULT, false, clock);
} }
} }

@ -34,6 +34,7 @@ import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -72,7 +73,9 @@ public abstract class MainnetProtocolSpecs {
private MainnetProtocolSpecs() {} private MainnetProtocolSpecs() {}
public static ProtocolSpecBuilder<Void> frontierDefinition( public static ProtocolSpecBuilder<Void> frontierDefinition(
final OptionalInt configContractSizeLimit, final OptionalInt configStackSizeLimit) { final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final Clock clock) {
final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT); final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE); final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return new ProtocolSpecBuilder<Void>() return new ProtocolSpecBuilder<Void>()
@ -120,7 +123,8 @@ public abstract class MainnetProtocolSpecs {
Account.DEFAULT_VERSION, Account.DEFAULT_VERSION,
new PrivateTransactionValidator(Optional.empty()))) new PrivateTransactionValidator(Optional.empty())))
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER) .difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::create) .blockHeaderValidatorBuilder(
difficultyCalculator -> MainnetBlockHeaderValidator.create(difficultyCalculator, clock))
.ommerHeaderValidatorBuilder(MainnetBlockHeaderValidator::createOmmerValidator) .ommerHeaderValidatorBuilder(MainnetBlockHeaderValidator::createOmmerValidator)
.blockBodyValidatorBuilder(MainnetBlockBodyValidator::new) .blockBodyValidatorBuilder(MainnetBlockBodyValidator::new)
.transactionReceiptFactory(MainnetProtocolSpecs::frontierTransactionReceiptFactory) .transactionReceiptFactory(MainnetProtocolSpecs::frontierTransactionReceiptFactory)
@ -135,9 +139,11 @@ public abstract class MainnetProtocolSpecs {
} }
public static ProtocolSpecBuilder<Void> homesteadDefinition( public static ProtocolSpecBuilder<Void> homesteadDefinition(
final OptionalInt configContractSizeLimit, final OptionalInt configStackSizeLimit) { final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final Clock clock) {
final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT); final int contractSizeLimit = configContractSizeLimit.orElse(FRONTIER_CONTRACT_SIZE_LIMIT);
return frontierDefinition(configContractSizeLimit, configStackSizeLimit) return frontierDefinition(configContractSizeLimit, configStackSizeLimit, clock)
.gasCalculator(HomesteadGasCalculator::new) .gasCalculator(HomesteadGasCalculator::new)
.evmBuilder(MainnetEvmRegistries::homestead) .evmBuilder(MainnetEvmRegistries::homestead)
.contractCreationProcessorBuilder( .contractCreationProcessorBuilder(
@ -155,9 +161,13 @@ public abstract class MainnetProtocolSpecs {
} }
public static ProtocolSpecBuilder<Void> daoRecoveryInitDefinition( public static ProtocolSpecBuilder<Void> daoRecoveryInitDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) { final OptionalInt contractSizeLimit,
return homesteadDefinition(contractSizeLimit, configStackSizeLimit) final OptionalInt configStackSizeLimit,
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::createDaoValidator) final Clock clock) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, clock)
.blockHeaderValidatorBuilder(
difficultyCalculator ->
MainnetBlockHeaderValidator.createDaoValidator(difficultyCalculator, clock))
.blockProcessorBuilder( .blockProcessorBuilder(
(transactionProcessor, (transactionProcessor,
transactionReceiptFactory, transactionReceiptFactory,
@ -173,15 +183,19 @@ public abstract class MainnetProtocolSpecs {
} }
public static ProtocolSpecBuilder<Void> daoRecoveryTransitionDefinition( public static ProtocolSpecBuilder<Void> daoRecoveryTransitionDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) { final OptionalInt contractSizeLimit,
return daoRecoveryInitDefinition(contractSizeLimit, configStackSizeLimit) final OptionalInt configStackSizeLimit,
final Clock clock) {
return daoRecoveryInitDefinition(contractSizeLimit, configStackSizeLimit, clock)
.blockProcessorBuilder(MainnetBlockProcessor::new) .blockProcessorBuilder(MainnetBlockProcessor::new)
.name("DaoRecoveryTransition"); .name("DaoRecoveryTransition");
} }
public static ProtocolSpecBuilder<Void> tangerineWhistleDefinition( public static ProtocolSpecBuilder<Void> tangerineWhistleDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) { final OptionalInt contractSizeLimit,
return homesteadDefinition(contractSizeLimit, configStackSizeLimit) final OptionalInt configStackSizeLimit,
final Clock clock) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, clock)
.gasCalculator(TangerineWhistleGasCalculator::new) .gasCalculator(TangerineWhistleGasCalculator::new)
.name("TangerineWhistle"); .name("TangerineWhistle");
} }
@ -189,12 +203,13 @@ public abstract class MainnetProtocolSpecs {
public static ProtocolSpecBuilder<Void> spuriousDragonDefinition( public static ProtocolSpecBuilder<Void> spuriousDragonDefinition(
final Optional<BigInteger> chainId, final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit, final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit) { final OptionalInt configStackSizeLimit,
final Clock clock) {
final int contractSizeLimit = final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT); configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE); final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return tangerineWhistleDefinition(OptionalInt.empty(), configStackSizeLimit) return tangerineWhistleDefinition(OptionalInt.empty(), configStackSizeLimit, clock)
.gasCalculator(SpuriousDragonGasCalculator::new) .gasCalculator(SpuriousDragonGasCalculator::new)
.messageCallProcessorBuilder( .messageCallProcessorBuilder(
(evm, precompileContractRegistry) -> (evm, precompileContractRegistry) ->
@ -249,8 +264,9 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId, final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit, final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit, final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) { final boolean enableRevertReason,
return spuriousDragonDefinition(chainId, contractSizeLimit, configStackSizeLimit) final Clock clock) {
return spuriousDragonDefinition(chainId, contractSizeLimit, configStackSizeLimit, clock)
.evmBuilder(MainnetEvmRegistries::byzantium) .evmBuilder(MainnetEvmRegistries::byzantium)
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium) .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium)
.difficultyCalculator(MainnetDifficultyCalculators.BYZANTIUM) .difficultyCalculator(MainnetDifficultyCalculators.BYZANTIUM)
@ -267,8 +283,10 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId, final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit, final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit, final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) { final boolean enableRevertReason,
return byzantiumDefinition(chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason) final Clock clock) {
return byzantiumDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, clock)
.difficultyCalculator(MainnetDifficultyCalculators.CONSTANTINOPLE) .difficultyCalculator(MainnetDifficultyCalculators.CONSTANTINOPLE)
.gasCalculator(ConstantinopleGasCalculator::new) .gasCalculator(ConstantinopleGasCalculator::new)
.evmBuilder(MainnetEvmRegistries::constantinople) .evmBuilder(MainnetEvmRegistries::constantinople)
@ -280,9 +298,10 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId, final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit, final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit, final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) { final boolean enableRevertReason,
final Clock clock) {
return constantinopleDefinition( return constantinopleDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason) chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, clock)
.gasCalculator(ConstantinopleFixGasCalculator::new) .gasCalculator(ConstantinopleFixGasCalculator::new)
.name("ConstantinopleFix"); .name("ConstantinopleFix");
} }
@ -291,13 +310,14 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId, final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit, final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit, final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) { final boolean enableRevertReason,
final Clock clock) {
checkArgument(chainId.isPresent(), "Istanbul requires the use of chainId"); checkArgument(chainId.isPresent(), "Istanbul requires the use of chainId");
final int contractSizeLimit = final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT); configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE); final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return constantinopleFixDefinition( return constantinopleFixDefinition(
chainId, configContractSizeLimit, configStackSizeLimit, enableRevertReason) chainId, configContractSizeLimit, configStackSizeLimit, enableRevertReason, clock)
.gasCalculator(IstanbulGasCalculator::new) .gasCalculator(IstanbulGasCalculator::new)
.evmBuilder(gasCalculator -> MainnetEvmRegistries.istanbul(gasCalculator, chainId.get())) .evmBuilder(gasCalculator -> MainnetEvmRegistries.istanbul(gasCalculator, chainId.get()))
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::istanbul) .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::istanbul)

@ -17,6 +17,7 @@ import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator; import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalLong; import java.util.OptionalLong;
import java.util.function.Function; import java.util.function.Function;
@ -32,27 +33,37 @@ public class ProtocolScheduleBuilder<C> {
private final Optional<BigInteger> defaultChainId; private final Optional<BigInteger> defaultChainId;
private final PrivacyParameters privacyParameters; private final PrivacyParameters privacyParameters;
private final boolean isRevertReasonEnabled; private final boolean isRevertReasonEnabled;
private final Clock clock;
public ProtocolScheduleBuilder( public ProtocolScheduleBuilder(
final GenesisConfigOptions config, final GenesisConfigOptions config,
final BigInteger defaultChainId, final BigInteger defaultChainId,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter, final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
final Clock clock) {
this( this(
config, config,
Optional.of(defaultChainId), Optional.of(defaultChainId),
protocolSpecAdapter, protocolSpecAdapter,
privacyParameters, privacyParameters,
isRevertReasonEnabled); isRevertReasonEnabled,
clock);
} }
public ProtocolScheduleBuilder( public ProtocolScheduleBuilder(
final GenesisConfigOptions config, final GenesisConfigOptions config,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter, final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
this(config, Optional.empty(), protocolSpecAdapter, privacyParameters, isRevertReasonEnabled); final Clock clock) {
this(
config,
Optional.empty(),
protocolSpecAdapter,
privacyParameters,
isRevertReasonEnabled,
clock);
} }
private ProtocolScheduleBuilder( private ProtocolScheduleBuilder(
@ -60,17 +71,18 @@ public class ProtocolScheduleBuilder<C> {
final Optional<BigInteger> defaultChainId, final Optional<BigInteger> defaultChainId,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter, final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters, final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) { final boolean isRevertReasonEnabled,
final Clock clock) {
this.config = config; this.config = config;
this.defaultChainId = defaultChainId; this.defaultChainId = defaultChainId;
this.protocolSpecAdapter = protocolSpecAdapter; this.protocolSpecAdapter = protocolSpecAdapter;
this.privacyParameters = privacyParameters; this.privacyParameters = privacyParameters;
this.isRevertReasonEnabled = isRevertReasonEnabled; this.isRevertReasonEnabled = isRevertReasonEnabled;
this.clock = clock;
} }
public ProtocolSchedule<C> createProtocolSchedule() { public ProtocolSchedule<C> createProtocolSchedule() {
final Optional<BigInteger> chainId = final Optional<BigInteger> chainId = config.getChainId().or(() -> defaultChainId);
config.getChainId().map(Optional::of).orElse(defaultChainId);
final MutableProtocolSchedule<C> protocolSchedule = new MutableProtocolSchedule<>(chainId); final MutableProtocolSchedule<C> protocolSchedule = new MutableProtocolSchedule<>(chainId);
validateForkOrdering(); validateForkOrdering();
@ -79,12 +91,12 @@ public class ProtocolScheduleBuilder<C> {
protocolSchedule, protocolSchedule,
OptionalLong.of(0), OptionalLong.of(0),
MainnetProtocolSpecs.frontierDefinition( MainnetProtocolSpecs.frontierDefinition(
config.getContractSizeLimit(), config.getEvmStackSize())); config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec( addProtocolSpec(
protocolSchedule, protocolSchedule,
config.getHomesteadBlockNumber(), config.getHomesteadBlockNumber(),
MainnetProtocolSpecs.homesteadDefinition( MainnetProtocolSpecs.homesteadDefinition(
config.getContractSizeLimit(), config.getEvmStackSize())); config.getContractSizeLimit(), config.getEvmStackSize(), clock));
config config
.getDaoForkBlock() .getDaoForkBlock()
@ -96,12 +108,12 @@ public class ProtocolScheduleBuilder<C> {
protocolSchedule, protocolSchedule,
OptionalLong.of(daoBlockNumber), OptionalLong.of(daoBlockNumber),
MainnetProtocolSpecs.daoRecoveryInitDefinition( MainnetProtocolSpecs.daoRecoveryInitDefinition(
config.getContractSizeLimit(), config.getEvmStackSize())); config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec( addProtocolSpec(
protocolSchedule, protocolSchedule,
OptionalLong.of(daoBlockNumber + 1), OptionalLong.of(daoBlockNumber + 1),
MainnetProtocolSpecs.daoRecoveryTransitionDefinition( MainnetProtocolSpecs.daoRecoveryTransitionDefinition(
config.getContractSizeLimit(), config.getEvmStackSize())); config.getContractSizeLimit(), config.getEvmStackSize(), clock));
// Return to the previous protocol spec after the dao fork has completed. // Return to the previous protocol spec after the dao fork has completed.
protocolSchedule.putMilestone(daoBlockNumber + 10, originalProtocolSpec); protocolSchedule.putMilestone(daoBlockNumber + 10, originalProtocolSpec);
@ -111,12 +123,12 @@ public class ProtocolScheduleBuilder<C> {
protocolSchedule, protocolSchedule,
config.getTangerineWhistleBlockNumber(), config.getTangerineWhistleBlockNumber(),
MainnetProtocolSpecs.tangerineWhistleDefinition( MainnetProtocolSpecs.tangerineWhistleDefinition(
config.getContractSizeLimit(), config.getEvmStackSize())); config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec( addProtocolSpec(
protocolSchedule, protocolSchedule,
config.getSpuriousDragonBlockNumber(), config.getSpuriousDragonBlockNumber(),
MainnetProtocolSpecs.spuriousDragonDefinition( MainnetProtocolSpecs.spuriousDragonDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize())); chainId, config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec( addProtocolSpec(
protocolSchedule, protocolSchedule,
config.getByzantiumBlockNumber(), config.getByzantiumBlockNumber(),
@ -124,7 +136,8 @@ public class ProtocolScheduleBuilder<C> {
chainId, chainId,
config.getContractSizeLimit(), config.getContractSizeLimit(),
config.getEvmStackSize(), config.getEvmStackSize(),
isRevertReasonEnabled)); isRevertReasonEnabled,
clock));
addProtocolSpec( addProtocolSpec(
protocolSchedule, protocolSchedule,
config.getConstantinopleBlockNumber(), config.getConstantinopleBlockNumber(),
@ -132,7 +145,8 @@ public class ProtocolScheduleBuilder<C> {
chainId, chainId,
config.getContractSizeLimit(), config.getContractSizeLimit(),
config.getEvmStackSize(), config.getEvmStackSize(),
isRevertReasonEnabled)); isRevertReasonEnabled,
clock));
addProtocolSpec( addProtocolSpec(
protocolSchedule, protocolSchedule,
config.getConstantinopleFixBlockNumber(), config.getConstantinopleFixBlockNumber(),
@ -140,7 +154,8 @@ public class ProtocolScheduleBuilder<C> {
chainId, chainId,
config.getContractSizeLimit(), config.getContractSizeLimit(),
config.getEvmStackSize(), config.getEvmStackSize(),
isRevertReasonEnabled)); isRevertReasonEnabled,
clock));
addProtocolSpec( addProtocolSpec(
protocolSchedule, protocolSchedule,
config.getIstanbulBlockNumber(), config.getIstanbulBlockNumber(),
@ -148,7 +163,8 @@ public class ProtocolScheduleBuilder<C> {
chainId, chainId,
config.getContractSizeLimit(), config.getContractSizeLimit(),
config.getEvmStackSize(), config.getEvmStackSize(),
isRevertReasonEnabled)); isRevertReasonEnabled,
clock));
LOG.info("Protocol schedule created with milestones: {}", protocolSchedule.listMilestones()); LOG.info("Protocol schedule created with milestones: {}", protocolSchedule.listMilestones());
return protocolSchedule; return protocolSchedule;

@ -15,7 +15,7 @@ package tech.pegasys.pantheon.ethereum.mainnet.headervalidationrules;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.mainnet.DetachedBlockHeaderValidationRule; import tech.pegasys.pantheon.ethereum.mainnet.DetachedBlockHeaderValidationRule;
import java.util.concurrent.TimeUnit; import java.time.Clock;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -28,9 +28,12 @@ public class TimestampBoundedByFutureParameter implements DetachedBlockHeaderVal
private final Logger LOG = LogManager.getLogger(); private final Logger LOG = LogManager.getLogger();
private final long acceptableClockDriftSeconds; private final long acceptableClockDriftSeconds;
private final Clock clock;
public TimestampBoundedByFutureParameter(final long acceptableClockDriftSeconds) { public TimestampBoundedByFutureParameter(
final long acceptableClockDriftSeconds, final Clock clock) {
this.acceptableClockDriftSeconds = acceptableClockDriftSeconds; this.acceptableClockDriftSeconds = acceptableClockDriftSeconds;
this.clock = clock;
} }
@Override @Override
@ -43,9 +46,7 @@ public class TimestampBoundedByFutureParameter implements DetachedBlockHeaderVal
} }
private boolean validateHeaderNotAheadOfCurrentSystemTime(final long timestamp) { private boolean validateHeaderNotAheadOfCurrentSystemTime(final long timestamp) {
final long timestampMargin = final long timestampMargin = clock.instant().getEpochSecond() + acceptableClockDriftSeconds;
TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
+ acceptableClockDriftSeconds;
if (Long.compareUnsigned(timestamp, timestampMargin) > 0) { if (Long.compareUnsigned(timestamp, timestampMargin) > 0) {
LOG.trace( LOG.trace(
"Invalid block header: timestamp {} is greater than the timestamp margin {}", "Invalid block header: timestamp {} is greater than the timestamp margin {}",

@ -12,6 +12,8 @@
*/ */
package tech.pegasys.pantheon.ethereum.core; package tech.pegasys.pantheon.ethereum.core;
import static com.google.common.base.Preconditions.checkNotNull;
import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.config.StubGenesisConfigOptions; import tech.pegasys.pantheon.config.StubGenesisConfigOptions;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
@ -27,8 +29,10 @@ import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage; import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage;
import tech.pegasys.pantheon.services.kvstore.KeyValueStorage; import tech.pegasys.pantheon.services.kvstore.KeyValueStorage;
import tech.pegasys.pantheon.testutil.TestClock;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
import java.util.function.Function; import java.util.function.Function;
public class ExecutionContextTestFixture { public class ExecutionContextTestFixture {
@ -60,7 +64,7 @@ public class ExecutionContextTestFixture {
} }
public static ExecutionContextTestFixture create() { public static ExecutionContextTestFixture create() {
return new Builder().build(); return new Builder().clock(TestClock.fixed()).build();
} }
public static Builder builder() { public static Builder builder() {
@ -95,6 +99,7 @@ public class ExecutionContextTestFixture {
private KeyValueStorage keyValueStorage; private KeyValueStorage keyValueStorage;
private ProtocolSchedule<Void> protocolSchedule; private ProtocolSchedule<Void> protocolSchedule;
private Clock clock;
public Builder keyValueStorage(final KeyValueStorage keyValueStorage) { public Builder keyValueStorage(final KeyValueStorage keyValueStorage) {
this.keyValueStorage = keyValueStorage; this.keyValueStorage = keyValueStorage;
@ -106,7 +111,14 @@ public class ExecutionContextTestFixture {
return this; return this;
} }
public Builder clock(final Clock clock) {
this.clock = clock;
return this;
}
public ExecutionContextTestFixture build() { public ExecutionContextTestFixture build() {
checkNotNull(clock);
if (protocolSchedule == null) { if (protocolSchedule == null) {
protocolSchedule = protocolSchedule =
new ProtocolScheduleBuilder<>( new ProtocolScheduleBuilder<>(
@ -114,7 +126,8 @@ public class ExecutionContextTestFixture {
BigInteger.valueOf(42), BigInteger.valueOf(42),
Function.identity(), Function.identity(),
new PrivacyParameters(), new PrivacyParameters(),
false) false,
clock)
.createProtocolSchedule(); .createProtocolSchedule();
} }
if (keyValueStorage == null) { if (keyValueStorage == null) {

@ -21,6 +21,7 @@ import tech.pegasys.pantheon.ethereum.vm.Code;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame; import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
import tech.pegasys.pantheon.ethereum.vm.OperationTracer; import tech.pegasys.pantheon.ethereum.vm.OperationTracer;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger; import java.math.BigInteger;
@ -35,7 +36,11 @@ public class TestCodeExecutor {
private static final Address SENDER_ADDRESS = AddressHelpers.ofValue(244259721); private static final Address SENDER_ADDRESS = AddressHelpers.ofValue(244259721);
public TestCodeExecutor(final ProtocolSchedule<Void> protocolSchedule) { public TestCodeExecutor(final ProtocolSchedule<Void> protocolSchedule) {
fixture = ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build(); fixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(protocolSchedule)
.clock(TestClock.fixed())
.build();
} }
public MessageFrame executeCode( public MessageFrame executeCode(

@ -23,9 +23,12 @@ import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.storage.keyvalue.WorldStateKeyValueStorage; import tech.pegasys.pantheon.ethereum.storage.keyvalue.WorldStateKeyValueStorage;
import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState; import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState;
import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage; import tech.pegasys.pantheon.services.kvstore.InMemoryKeyValueStorage;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import java.time.Clock;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.encoders.Hex;
@ -33,6 +36,8 @@ import org.junit.Test;
public final class GenesisStateTest { public final class GenesisStateTest {
final Clock testClock = new TestClock();
/** Known RLP encoded bytes of the Olympic Genesis Block. */ /** Known RLP encoded bytes of the Olympic Genesis Block. */
private static final String OLYMPIC_RLP = private static final String OLYMPIC_RLP =
"f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0"; "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0";
@ -49,7 +54,7 @@ public final class GenesisStateTest {
final GenesisState genesisState = final GenesisState genesisState =
GenesisState.fromJson( GenesisState.fromJson(
Resources.toString(GenesisStateTest.class.getResource("genesis1.json"), Charsets.UTF_8), Resources.toString(GenesisStateTest.class.getResource("genesis1.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader(); final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getStateRoot()) assertThat(header.getStateRoot())
.isEqualTo( .isEqualTo(
@ -78,7 +83,7 @@ public final class GenesisStateTest {
final GenesisState genesisState = final GenesisState genesisState =
GenesisState.fromJson( GenesisState.fromJson(
Resources.toString(GenesisStateTest.class.getResource("genesis2.json"), Charsets.UTF_8), Resources.toString(GenesisStateTest.class.getResource("genesis2.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader(); final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getStateRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); assertThat(header.getStateRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH);
assertThat(header.getTransactionsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH); assertThat(header.getTransactionsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH);
@ -93,7 +98,7 @@ public final class GenesisStateTest {
final GenesisState genesisState = final GenesisState genesisState =
GenesisState.fromJson( GenesisState.fromJson(
Resources.toString(GenesisStateTest.class.getResource(sourceFile), Charsets.UTF_8), Resources.toString(GenesisStateTest.class.getResource(sourceFile), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader(); final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getHash()).isEqualTo(Hash.fromHexString(blockHash)); assertThat(header.getHash()).isEqualTo(Hash.fromHexString(blockHash));
@ -132,7 +137,7 @@ public final class GenesisStateTest {
GenesisState.fromJson( GenesisState.fromJson(
Resources.toString( Resources.toString(
GenesisStateTest.class.getResource("genesisNonce.json"), Charsets.UTF_8), GenesisStateTest.class.getResource("genesisNonce.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader(); final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getHash()) assertThat(header.getHash())
.isEqualTo( .isEqualTo(
@ -146,7 +151,7 @@ public final class GenesisStateTest {
GenesisState.fromJson( GenesisState.fromJson(
Resources.toString( Resources.toString(
GenesisStateTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8), GenesisStateTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create()); MainnetProtocolSchedule.create(testClock));
final BytesValueRLPOutput tmp = new BytesValueRLPOutput(); final BytesValueRLPOutput tmp = new BytesValueRLPOutput();
genesisState.getBlock().writeTo(tmp); genesisState.getBlock().writeTo(tmp);
assertThat(Hex.toHexString(genesisState.getBlock().getHeader().getHash().extractArray())) assertThat(Hex.toHexString(genesisState.getBlock().getHeader().getHash().extractArray()))

@ -18,6 +18,7 @@ import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.testutil.TestClock;
import org.junit.Test; import org.junit.Test;
@ -27,7 +28,8 @@ public class FixedProtocolScheduleTest {
public void reportedDifficultyForAllBlocksIsAFixedValue() { public void reportedDifficultyForAllBlocksIsAFixedValue() {
final ProtocolSchedule<Void> schedule = final ProtocolSchedule<Void> schedule =
FixedDifficultyProtocolSchedule.create(GenesisConfigFile.development().getConfigOptions()); FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), TestClock.fixed());
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();

@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import tech.pegasys.pantheon.ethereum.ProtocolContext; import tech.pegasys.pantheon.ethereum.ProtocolContext;
import tech.pegasys.pantheon.testutil.TestClock;
import org.junit.Test; import org.junit.Test;
@ -28,7 +29,8 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void validHeaderFrontier() throws Exception { public void validHeaderFrontier() throws Exception {
final BlockHeaderValidator<Void> headerValidator = final BlockHeaderValidator<Void> headerValidator =
MainnetBlockHeaderValidator.create(MainnetDifficultyCalculators.FRONTIER); MainnetBlockHeaderValidator.create(
MainnetDifficultyCalculators.FRONTIER, TestClock.fixed());
assertThat( assertThat(
headerValidator.validateHeader( headerValidator.validateHeader(
ValidationTestUtils.readHeader(300006), ValidationTestUtils.readHeader(300006),
@ -41,7 +43,8 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void validHeaderHomestead() throws Exception { public void validHeaderHomestead() throws Exception {
final BlockHeaderValidator<Void> headerValidator = final BlockHeaderValidator<Void> headerValidator =
MainnetBlockHeaderValidator.create(MainnetDifficultyCalculators.HOMESTEAD); MainnetBlockHeaderValidator.create(
MainnetDifficultyCalculators.HOMESTEAD, TestClock.fixed());
assertThat( assertThat(
headerValidator.validateHeader( headerValidator.validateHeader(
ValidationTestUtils.readHeader(1200001), ValidationTestUtils.readHeader(1200001),
@ -54,7 +57,8 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void invalidParentHash() throws Exception { public void invalidParentHash() throws Exception {
final BlockHeaderValidator<Void> headerValidator = final BlockHeaderValidator<Void> headerValidator =
MainnetBlockHeaderValidator.create(MainnetDifficultyCalculators.HOMESTEAD); MainnetBlockHeaderValidator.create(
MainnetDifficultyCalculators.HOMESTEAD, TestClock.fixed());
assertThat( assertThat(
headerValidator.validateHeader( headerValidator.validateHeader(
ValidationTestUtils.readHeader(1200001), ValidationTestUtils.readHeader(1200001),
@ -67,7 +71,8 @@ public final class MainnetBlockHeaderValidatorTest {
@Test @Test
public void validHeaderByzantium() throws Exception { public void validHeaderByzantium() throws Exception {
final BlockHeaderValidator<Void> headerValidator = final BlockHeaderValidator<Void> headerValidator =
MainnetBlockHeaderValidator.create(MainnetDifficultyCalculators.BYZANTIUM); MainnetBlockHeaderValidator.create(
MainnetDifficultyCalculators.BYZANTIUM, TestClock.fixed());
assertThat( assertThat(
headerValidator.validateHeader( headerValidator.validateHeader(
ValidationTestUtils.readHeader(4400001), ValidationTestUtils.readHeader(4400001),

@ -13,6 +13,7 @@
package tech.pegasys.pantheon.ethereum.mainnet; package tech.pegasys.pantheon.ethereum.mainnet;
import tech.pegasys.pantheon.config.GenesisConfigFile; import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.testutil.TestClock;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -25,7 +26,7 @@ public class MainnetProtocolScheduleTest {
@Test @Test
public void shouldReturnDefaultProtocolSpecsWhenCustomNumbersAreNotUsed() { public void shouldReturnDefaultProtocolSpecsWhenCustomNumbersAreNotUsed() {
final ProtocolSchedule<Void> sched = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> sched = MainnetProtocolSchedule.create(TestClock.fixed());
Assertions.assertThat(sched.getByBlockNumber(1L).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(1L).getName()).isEqualTo("Frontier");
Assertions.assertThat(sched.getByBlockNumber(1_150_000L).getName()).isEqualTo("Homestead"); Assertions.assertThat(sched.getByBlockNumber(1_150_000L).getName()).isEqualTo("Homestead");
Assertions.assertThat(sched.getByBlockNumber(1_920_000L).getName()) Assertions.assertThat(sched.getByBlockNumber(1_920_000L).getName())
@ -49,7 +50,8 @@ public class MainnetProtocolScheduleTest {
public void shouldOnlyUseFrontierWhenEmptyJsonConfigIsUsed() { public void shouldOnlyUseFrontierWhenEmptyJsonConfigIsUsed() {
final JsonObject json = new JsonObject("{}"); final JsonObject json = new JsonObject("{}");
final ProtocolSchedule<Void> sched = final ProtocolSchedule<Void> sched =
MainnetProtocolSchedule.fromConfig(GenesisConfigFile.fromConfig(json).getConfigOptions()); MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(json).getConfigOptions(), TestClock.fixed());
Assertions.assertThat(sched.getByBlockNumber(1L).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(1L).getName()).isEqualTo("Frontier");
Assertions.assertThat(sched.getByBlockNumber(Long.MAX_VALUE).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(Long.MAX_VALUE).getName()).isEqualTo("Frontier");
} }
@ -60,7 +62,8 @@ public class MainnetProtocolScheduleTest {
new JsonObject( new JsonObject(
"{\"config\": {\"homesteadBlock\": 2, \"daoForkBlock\": 3, \"eip150Block\": 14, \"eip158Block\": 15, \"byzantiumBlock\": 16, \"constantinopleBlock\": 18, \"constantinopleFixBlock\": 19, \"chainId\":1234}}"); "{\"config\": {\"homesteadBlock\": 2, \"daoForkBlock\": 3, \"eip150Block\": 14, \"eip158Block\": 15, \"byzantiumBlock\": 16, \"constantinopleBlock\": 18, \"constantinopleFixBlock\": 19, \"chainId\":1234}}");
final ProtocolSchedule<Void> sched = final ProtocolSchedule<Void> sched =
MainnetProtocolSchedule.fromConfig(GenesisConfigFile.fromConfig(json).getConfigOptions()); MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(json).getConfigOptions(), TestClock.fixed());
Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("Frontier"); Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("Frontier");
Assertions.assertThat(sched.getByBlockNumber(2).getName()).isEqualTo("Homestead"); Assertions.assertThat(sched.getByBlockNumber(2).getName()).isEqualTo("Homestead");
Assertions.assertThat(sched.getByBlockNumber(3).getName()).isEqualTo("DaoRecoveryInit"); Assertions.assertThat(sched.getByBlockNumber(3).getName()).isEqualTo("DaoRecoveryInit");
@ -84,7 +87,7 @@ public class MainnetProtocolScheduleTest {
.isThrownBy( .isThrownBy(
() -> () ->
MainnetProtocolSchedule.fromConfig( MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(json).getConfigOptions())); GenesisConfigFile.fromConfig(json).getConfigOptions(), TestClock.fixed()));
} }
@Test @Test
@ -94,7 +97,8 @@ public class MainnetProtocolScheduleTest {
GenesisConfigFile.fromConfig( GenesisConfigFile.fromConfig(
Resources.toString( Resources.toString(
this.getClass().getResource("/ropsten.json"), StandardCharsets.UTF_8)) this.getClass().getResource("/ropsten.json"), StandardCharsets.UTF_8))
.getConfigOptions()); .getConfigOptions(),
TestClock.fixed());
Assertions.assertThat(sched.getByBlockNumber(0).getName()).isEqualTo("TangerineWhistle"); Assertions.assertThat(sched.getByBlockNumber(0).getName()).isEqualTo("TangerineWhistle");
Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("TangerineWhistle"); Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("TangerineWhistle");
Assertions.assertThat(sched.getByBlockNumber(10).getName()).isEqualTo("SpuriousDragon"); Assertions.assertThat(sched.getByBlockNumber(10).getName()).isEqualTo("SpuriousDragon");

@ -22,6 +22,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import tech.pegasys.pantheon.ethereum.mainnet.ValidationTestUtils; import tech.pegasys.pantheon.ethereum.mainnet.ValidationTestUtils;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import java.io.IOException; import java.io.IOException;
@ -109,7 +110,8 @@ public class ProofOfWorkValidationRuleTest {
} }
private BlockHeaderFunctions mainnetBlockHashFunction() { private BlockHeaderFunctions mainnetBlockHashFunction() {
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
return ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); return ScheduleBasedBlockHeaderFunctions.create(protocolSchedule);
} }
} }

@ -16,8 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture; import tech.pegasys.pantheon.ethereum.core.BlockHeaderTestFixture;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.Test; import org.junit.Test;
@ -26,7 +25,8 @@ public class TimestampValidationRuleTest {
@Test @Test
public void headerTimestampSufficientlyFarIntoFutureVadidatesSuccessfully() { public void headerTimestampSufficientlyFarIntoFutureVadidatesSuccessfully() {
final TimestampBoundedByFutureParameter uut00 = new TimestampBoundedByFutureParameter(0); final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(0, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10); final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
@ -50,7 +50,8 @@ public class TimestampValidationRuleTest {
@Test @Test
public void headerTimestampTooCloseToParentFailsValidation() { public void headerTimestampTooCloseToParentFailsValidation() {
final TimestampBoundedByFutureParameter uut00 = new TimestampBoundedByFutureParameter(0); final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(0, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10); final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
@ -68,7 +69,8 @@ public class TimestampValidationRuleTest {
@Test @Test
public void headerTimestampIsBehindParentFailsValidation() { public void headerTimestampIsBehindParentFailsValidation() {
final TimestampBoundedByFutureParameter uut00 = new TimestampBoundedByFutureParameter(0); final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(0, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10); final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
@ -89,14 +91,13 @@ public class TimestampValidationRuleTest {
final long acceptableClockDrift = 5; final long acceptableClockDrift = 5;
final TimestampBoundedByFutureParameter uut00 = final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(acceptableClockDrift); new TimestampBoundedByFutureParameter(acceptableClockDrift, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10); final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
// Create Parent Header @ 'now' // Create Parent Header @ 'now'
headerBuilder.timestamp( headerBuilder.timestamp(TestClock.fixed().instant().getEpochSecond());
TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS));
final BlockHeader parent = headerBuilder.buildHeader(); final BlockHeader parent = headerBuilder.buildHeader();
// Create header for validation with a timestamp in the future (1 second too far away) // Create header for validation with a timestamp in the future (1 second too far away)
@ -112,14 +113,12 @@ public class TimestampValidationRuleTest {
final long acceptableClockDrift = 5; final long acceptableClockDrift = 5;
final TimestampBoundedByFutureParameter uut00 = final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(acceptableClockDrift); new TimestampBoundedByFutureParameter(acceptableClockDrift, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10); final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
// Create Parent Header @ 'now' headerBuilder.timestamp(TestClock.fixed().instant().getEpochSecond());
headerBuilder.timestamp(
TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS));
final BlockHeader parent = headerBuilder.buildHeader(); final BlockHeader parent = headerBuilder.buildHeader();
// Create header for validation with a timestamp in the future (1 second too far away) // Create header for validation with a timestamp in the future (1 second too far away)

@ -19,6 +19,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -67,7 +68,12 @@ public class ReferenceTestProtocolSchedules {
private static ProtocolSchedule<Void> createSchedule(final GenesisConfigOptions options) { private static ProtocolSchedule<Void> createSchedule(final GenesisConfigOptions options) {
return new ProtocolScheduleBuilder<>( return new ProtocolScheduleBuilder<>(
options, CHAIN_ID, Function.identity(), PrivacyParameters.DEFAULT, false) options,
CHAIN_ID,
Function.identity(),
PrivacyParameters.DEFAULT,
false,
Clock.systemUTC())
.createProtocolSchedule(); .createProtocolSchedule();
} }
} }

@ -31,6 +31,7 @@ import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState;
import tech.pegasys.pantheon.testutil.JsonTestParameters; import tech.pegasys.pantheon.testutil.JsonTestParameters;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
@ -121,7 +122,8 @@ public class VMReferenceTest extends AbstractRetryingTest {
final EnvironmentInformation execEnv = spec.getExec(); final EnvironmentInformation execEnv = spec.getExec();
final ProtocolSpec<Void> protocolSpec = final ProtocolSpec<Void> protocolSpec =
MainnetProtocolSpecs.frontierDefinition(OptionalInt.empty(), OptionalInt.empty()) MainnetProtocolSpecs.frontierDefinition(
OptionalInt.empty(), OptionalInt.empty(), Clock.systemUTC())
.privacyParameters(PrivacyParameters.DEFAULT) .privacyParameters(PrivacyParameters.DEFAULT)
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(CHAIN_ID)) .privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(CHAIN_ID))
.build(new MutableProtocolSchedule<>(CHAIN_ID)); .build(new MutableProtocolSchedule<>(CHAIN_ID));

@ -22,6 +22,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame; import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame.State; import tech.pegasys.pantheon.ethereum.vm.MessageFrame.State;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import org.junit.Before; import org.junit.Before;
@ -35,7 +36,8 @@ import org.junit.runners.Parameterized.Parameters;
public class ConstantinopleSStoreOperationGasCostTest { public class ConstantinopleSStoreOperationGasCostTest {
private static final ProtocolSchedule<Void> protocolSchedule = private static final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.fromConfig(new StubGenesisConfigOptions().constantinopleBlock(0)); MainnetProtocolSchedule.fromConfig(
new StubGenesisConfigOptions().constantinopleBlock(0), TestClock.fixed());
@Parameters(name = "Code: {0}, Original: {1}") @Parameters(name = "Code: {0}, Original: {1}")
public static Object[][] scenarios() { public static Object[][] scenarios() {

@ -109,7 +109,7 @@ public class EthPeer {
public void recordUselessResponse(final String requestType) { public void recordUselessResponse(final String requestType) {
LOG.debug("Received useless response for {} from peer {}", requestType, this); LOG.debug("Received useless response for {} from peer {}", requestType, this);
reputation.recordUselessResponse(System.currentTimeMillis()).ifPresent(this::disconnect); reputation.recordUselessResponse(clock.millis()).ifPresent(this::disconnect);
} }
public void disconnect(final DisconnectReason reason) { public void disconnect(final DisconnectReason reason) {

@ -967,7 +967,8 @@ public final class EthProtocolManagerTest {
.isEqualTo(Collections.singletonList(EthProtocol.ETH63)); .isEqualTo(Collections.singletonList(EthProtocol.ETH63));
// assert that all messages transmitted contain the expected block & total difficulty. // assert that all messages transmitted contain the expected block & total difficulty.
final ProtocolSchedule<Void> protocolSchdeule = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> protocolSchdeule =
MainnetProtocolSchedule.create(TestClock.fixed());
for (final NewBlockMessage msg : messageSentCaptor.getAllValues()) { for (final NewBlockMessage msg : messageSentCaptor.getAllValues()) {
assertThat(msg.block(protocolSchdeule)).isEqualTo(minedBlock); assertThat(msg.block(protocolSchdeule)).isEqualTo(minedBlock);
assertThat(msg.totalDifficulty(protocolSchdeule)).isEqualTo(expectedTotalDifficulty); assertThat(msg.totalDifficulty(protocolSchdeule)).isEqualTo(expectedTotalDifficulty);

@ -65,7 +65,8 @@ public class EthProtocolManagerTestUtil {
} }
public static EthProtocolManager create(final EthScheduler ethScheduler) { public static EthProtocolManager create(final EthScheduler ethScheduler) {
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
final GenesisConfigFile config = GenesisConfigFile.mainnet(); final GenesisConfigFile config = GenesisConfigFile.mainnet();
final GenesisState genesisState = GenesisState.fromConfig(config, protocolSchedule); final GenesisState genesisState = GenesisState.fromConfig(config, protocolSchedule);
final Blockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final Blockchain blockchain = createInMemoryBlockchain(genesisState.getBlock());

@ -32,6 +32,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import tech.pegasys.pantheon.ethereum.util.RawBlockIterator; import tech.pegasys.pantheon.ethereum.util.RawBlockIterator;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.testutil.BlockTestUtil; import tech.pegasys.pantheon.testutil.BlockTestUtil;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
@ -91,7 +92,8 @@ public class BlockchainSetupUtil<C> {
} }
public static BlockchainSetupUtil<Void> forTesting() { public static BlockchainSetupUtil<Void> forTesting() {
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
final TemporaryFolder temp = new TemporaryFolder(); final TemporaryFolder temp = new TemporaryFolder();
try { try {
temp.create(); temp.create();

@ -23,6 +23,7 @@ import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.RawMessage;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput; import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException; import java.io.IOException;
@ -66,7 +67,7 @@ public final class BlockBodiesMessageTest {
message message
.bodies( .bodies(
FixedDifficultyProtocolSchedule.create( FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false)) GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed()))
.iterator(); .iterator();
for (int i = 0; i < 50; ++i) { for (int i = 0; i < 50; ++i) {
Assertions.assertThat(readBodies.next()).isEqualTo(bodies.get(i)); Assertions.assertThat(readBodies.next()).isEqualTo(bodies.get(i));

@ -21,6 +21,7 @@ import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.RawMessage;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput; import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException; import java.io.IOException;
@ -58,7 +59,7 @@ public final class BlockHeadersMessageTest {
final List<BlockHeader> readHeaders = final List<BlockHeader> readHeaders =
message.getHeaders( message.getHeaders(
FixedDifficultyProtocolSchedule.create( FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false)); GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed()));
for (int i = 0; i < 50; ++i) { for (int i = 0; i < 50; ++i) {
Assertions.assertThat(readHeaders.get(i)).isEqualTo(headers.get(i)); Assertions.assertThat(readHeaders.get(i)).isEqualTo(headers.get(i));

@ -21,13 +21,15 @@ import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.RawMessage; import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.RawMessage;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput; import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import org.junit.Test; import org.junit.Test;
public class NewBlockMessageTest { public class NewBlockMessageTest {
private static final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); private static final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
@Test @Test
public void roundTripNewBlockMessage() { public void roundTripNewBlockMessage() {

@ -29,6 +29,7 @@ import tech.pegasys.pantheon.ethereum.eth.messages.GetBlockHeadersMessage;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHeaderValidator; import tech.pegasys.pantheon.ethereum.mainnet.MainnetBlockHeaderValidator;
import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List; import java.util.List;
@ -55,7 +56,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator = PeerValidator validator =
new DaoForkPeerValidator( new DaoForkPeerValidator(
ethProtocolManager.ethContext(), ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
daoBlockNumber, daoBlockNumber,
0); 0);
@ -87,7 +88,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator = PeerValidator validator =
new DaoForkPeerValidator( new DaoForkPeerValidator(
ethProtocolManager.ethContext(), ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
daoBlockNumber, daoBlockNumber,
0); 0);
@ -115,7 +116,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator = PeerValidator validator =
new DaoForkPeerValidator( new DaoForkPeerValidator(
ethProtocolManager.ethContext(), ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
daoBlockNumber, daoBlockNumber,
0); 0);
@ -144,7 +145,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator = PeerValidator validator =
new DaoForkPeerValidator( new DaoForkPeerValidator(
ethProtocolManager.ethContext(), ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
daoBlockNumber, daoBlockNumber,
0); 0);
@ -183,7 +184,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator = PeerValidator validator =
new DaoForkPeerValidator( new DaoForkPeerValidator(
ethProtocolManager.ethContext(), ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
daoBlockNumber, daoBlockNumber,
buffer); buffer);

@ -27,6 +27,7 @@ import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer.Responder;
import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.BlockchainSetupUtil; import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.BlockchainSetupUtil;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import org.junit.Test; import org.junit.Test;
@ -45,7 +46,7 @@ public class ChainHeadTrackerTest {
0); 0);
private final ProtocolSchedule<Void> protocolSchedule = private final ProtocolSchedule<Void> protocolSchedule =
FixedDifficultyProtocolSchedule.create( FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false); GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed());
private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class); private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class);
private final ChainHeadTracker chainHeadTracker = private final ChainHeadTracker chainHeadTracker =

@ -32,6 +32,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -58,7 +59,8 @@ public class FullSyncTargetManagerTest {
final BlockchainSetupUtil<Void> localBlockchainSetup = BlockchainSetupUtil.forTesting(); final BlockchainSetupUtil<Void> localBlockchainSetup = BlockchainSetupUtil.forTesting();
localBlockchain = localBlockchainSetup.getBlockchain(); localBlockchain = localBlockchainSetup.getBlockchain();
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
final ProtocolContext<Void> protocolContext = final ProtocolContext<Void> protocolContext =
new ProtocolContext<>(localBlockchain, localWorldState, null); new ProtocolContext<>(localBlockchain, localWorldState, null);
ethProtocolManager = ethProtocolManager =

@ -34,6 +34,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.MetricsSystem; import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import java.io.IOException; import java.io.IOException;
@ -53,7 +54,8 @@ import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
public class DetermineCommonAncestorTaskParameterizedTest { public class DetermineCommonAncestorTaskParameterizedTest {
private final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); private final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
private static final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); private static final BlockDataGenerator blockDataGenerator = new BlockDataGenerator();
private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); private final MetricsSystem metricsSystem = new NoOpMetricsSystem();

@ -46,6 +46,7 @@ import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.D
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.MetricsSystem; import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.ExceptionUtils; import tech.pegasys.pantheon.util.ExceptionUtils;
import java.util.List; import java.util.List;
@ -58,7 +59,8 @@ import org.junit.Test;
public class DetermineCommonAncestorTaskTest { public class DetermineCommonAncestorTaskTest {
private final ProtocolSchedule<?> protocolSchedule = MainnetProtocolSchedule.create(); private final ProtocolSchedule<?> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
private final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); private final BlockDataGenerator blockDataGenerator = new BlockDataGenerator();
private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); private final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private final int defaultHeaderRequestSize = 10; private final int defaultHeaderRequestSize = 10;

@ -892,7 +892,10 @@ public class WorldStateDownloaderTest {
RespondingEthPeer.blockchainResponder(mock(Blockchain.class), remoteWorldStateArchive); RespondingEthPeer.blockchainResponder(mock(Blockchain.class), remoteWorldStateArchive);
final Responder partialResponder = final Responder partialResponder =
RespondingEthPeer.partialResponder( RespondingEthPeer.partialResponder(
mock(Blockchain.class), remoteWorldStateArchive, MainnetProtocolSchedule.create(), .5f); mock(Blockchain.class),
remoteWorldStateArchive,
MainnetProtocolSchedule.create(TestClock.fixed()),
.5f);
final Responder emptyResponder = RespondingEthPeer.emptyResponder(); final Responder emptyResponder = RespondingEthPeer.emptyResponder();
// Send a few partial responses // Send a few partial responses

@ -95,7 +95,7 @@ public class TestNode implements Closeable {
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.development(); final GenesisConfigFile genesisConfigFile = GenesisConfigFile.development();
final ProtocolSchedule<Void> protocolSchedule = final ProtocolSchedule<Void> protocolSchedule =
FixedDifficultyProtocolSchedule.create( FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false); GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed());
final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule); final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule);
final BlockHeaderFunctions blockHeaderFunctions = final BlockHeaderFunctions blockHeaderFunctions =
@ -130,6 +130,7 @@ public class TestNode implements Closeable {
.keyPair(this.kp) .keyPair(this.kp)
.config(networkingConfiguration) .config(networkingConfiguration)
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.supportedCapabilities(capabilities) .supportedCapabilities(capabilities)
.build()) .build())
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())

@ -44,6 +44,7 @@ import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.Capability;
import tech.pegasys.pantheon.ethereum.util.RawBlockIterator; import tech.pegasys.pantheon.ethereum.util.RawBlockIterator;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.testutil.BlockTestUtil; import tech.pegasys.pantheon.testutil.BlockTestUtil;
import tech.pegasys.pantheon.testutil.TestClock;
import java.net.URL; import java.net.URL;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -97,7 +98,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
@BeforeClass @BeforeClass
public static void setupConstants() throws Exception { public static void setupConstants() throws Exception {
PROTOCOL_SCHEDULE = MainnetProtocolSchedule.create(); PROTOCOL_SCHEDULE = MainnetProtocolSchedule.create(TestClock.fixed());
final URL blocksUrl = BlockTestUtil.getTestBlockchainUrl(); final URL blocksUrl = BlockTestUtil.getTestBlockchainUrl();

@ -23,6 +23,7 @@ import tech.pegasys.pantheon.ethereum.util.RawBlockIterator;
import java.net.URL; import java.net.URL;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.time.Clock;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -40,7 +41,7 @@ public class BlockchainImporter {
public BlockchainImporter(final URL blocksUrl, final String genesisJson) throws Exception { public BlockchainImporter(final URL blocksUrl, final String genesisJson) throws Exception {
protocolSchedule = protocolSchedule =
MainnetProtocolSchedule.fromConfig( MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(genesisJson).getConfigOptions()); GenesisConfigFile.fromConfig(genesisJson).getConfigOptions(), Clock.systemUTC());
blocks = new ArrayList<>(); blocks = new ArrayList<>();
try (final RawBlockIterator iterator = try (final RawBlockIterator iterator =

@ -43,6 +43,7 @@ import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration; import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import java.time.Clock;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -102,7 +103,7 @@ public class JsonRpcTestMethodsFactory {
peerDiscovery, peerDiscovery,
blockchainQueries, blockchainQueries,
synchronizer, synchronizer,
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(Clock.systemUTC()),
filterManager, filterManager,
transactionPool, transactionPool,
miningCoordinator, miningCoordinator,

@ -54,6 +54,7 @@ import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration; import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.BlockTestUtil; import tech.pegasys.pantheon.testutil.BlockTestUtil;
import tech.pegasys.pantheon.testutil.TestClock;
import java.net.URL; import java.net.URL;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -115,7 +116,7 @@ public abstract class AbstractEthJsonRpcHttpServiceTest {
@BeforeClass @BeforeClass
public static void setupConstants() throws Exception { public static void setupConstants() throws Exception {
PROTOCOL_SCHEDULE = MainnetProtocolSchedule.create(); PROTOCOL_SCHEDULE = MainnetProtocolSchedule.create(TestClock.fixed());
final URL blocksUrl = BlockTestUtil.getTestBlockchainUrl(); final URL blocksUrl = BlockTestUtil.getTestBlockchainUrl();
@ -179,7 +180,7 @@ public abstract class AbstractEthJsonRpcHttpServiceTest {
peerDiscoveryMock, peerDiscoveryMock,
blockchainQueries, blockchainQueries,
synchronizerMock, synchronizerMock,
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
filterManager, filterManager,
transactionPoolMock, transactionPoolMock,
miningCoordinatorMock, miningCoordinatorMock,

@ -34,6 +34,7 @@ import tech.pegasys.pantheon.ethereum.permissioning.AccountLocalConfigPermission
import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController; import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration; import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
@ -99,7 +100,8 @@ public class JsonRpcHttpServiceHostWhitelistTest {
MainnetProtocolSchedule.fromConfig( MainnetProtocolSchedule.fromConfig(
new StubGenesisConfigOptions() new StubGenesisConfigOptions()
.constantinopleBlock(0) .constantinopleBlock(0)
.chainId(BigInteger.valueOf(CHAIN_ID))), .chainId(BigInteger.valueOf(CHAIN_ID)),
TestClock.fixed()),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(EthHashMiningCoordinator.class),

@ -38,6 +38,7 @@ import tech.pegasys.pantheon.ethereum.p2p.network.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.Capability;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration; import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -127,7 +128,7 @@ public class JsonRpcHttpServiceLoginTest {
peerDiscoveryMock, peerDiscoveryMock,
blockchainQueries, blockchainQueries,
synchronizer, synchronizer,
MainnetProtocolSchedule.fromConfig(genesisConfigOptions), MainnetProtocolSchedule.fromConfig(genesisConfigOptions, TestClock.fixed()),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(EthHashMiningCoordinator.class),

@ -43,6 +43,7 @@ import tech.pegasys.pantheon.ethereum.permissioning.AccountLocalConfigPermission
import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController; import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration; import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -193,7 +194,7 @@ public class JsonRpcHttpServiceRpcApisTest {
mock(P2PNetwork.class), mock(P2PNetwork.class),
blockchainQueries, blockchainQueries,
mock(Synchronizer.class), mock(Synchronizer.class),
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(EthHashMiningCoordinator.class),
@ -251,6 +252,7 @@ public class JsonRpcHttpServiceRpcApisTest {
.vertx(vertx) .vertx(vertx)
.config(config) .config(config)
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.build(); .build();
p2pNetwork.start(); p2pNetwork.start();
@ -283,7 +285,7 @@ public class JsonRpcHttpServiceRpcApisTest {
p2pNetwork, p2pNetwork,
blockchainQueries, blockchainQueries,
mock(Synchronizer.class), mock(Synchronizer.class),
MainnetProtocolSchedule.create(), MainnetProtocolSchedule.create(TestClock.fixed()),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(EthHashMiningCoordinator.class),

@ -49,6 +49,7 @@ import tech.pegasys.pantheon.ethereum.permissioning.AccountLocalConfigPermission
import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController; import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration; import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues; import tech.pegasys.pantheon.util.bytes.BytesValues;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
@ -126,7 +127,8 @@ public class JsonRpcHttpServiceTest {
MainnetProtocolSchedule.fromConfig( MainnetProtocolSchedule.fromConfig(
new StubGenesisConfigOptions() new StubGenesisConfigOptions()
.constantinopleBlock(0) .constantinopleBlock(0)
.chainId(BigInteger.valueOf(CHAIN_ID))), .chainId(BigInteger.valueOf(CHAIN_ID)),
TestClock.fixed()),
mock(FilterManager.class), mock(FilterManager.class),
mock(TransactionPool.class), mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class), mock(EthHashMiningCoordinator.class),

@ -35,6 +35,7 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketException; import java.net.SocketException;
import java.time.Clock;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt; import java.util.OptionalInt;
@ -64,6 +65,7 @@ public abstract class PeerDiscoveryAgent {
private final List<PeerRequirement> peerRequirements = new CopyOnWriteArrayList<>(); private final List<PeerRequirement> peerRequirements = new CopyOnWriteArrayList<>();
private final PeerPermissions peerPermissions; private final PeerPermissions peerPermissions;
private final Optional<UpnpNatManager> natManager; private final Optional<UpnpNatManager> natManager;
private final Clock clock;
private final MetricsSystem metricsSystem; private final MetricsSystem metricsSystem;
/* The peer controller, which takes care of the state machine of peers. */ /* The peer controller, which takes care of the state machine of peers. */
protected Optional<PeerDiscoveryController> controller = Optional.empty(); protected Optional<PeerDiscoveryController> controller = Optional.empty();
@ -87,20 +89,23 @@ public abstract class PeerDiscoveryAgent {
final DiscoveryConfiguration config, final DiscoveryConfiguration config,
final PeerPermissions peerPermissions, final PeerPermissions peerPermissions,
final Optional<UpnpNatManager> natManager, final Optional<UpnpNatManager> natManager,
final MetricsSystem metricsSystem) { final MetricsSystem metricsSystem,
this.metricsSystem = metricsSystem; final Clock clock) {
checkArgument(keyPair != null, "keypair cannot be null"); checkArgument(keyPair != null, "keypair cannot be null");
checkArgument(config != null, "provided configuration cannot be null"); checkArgument(config != null, "provided configuration cannot be null");
checkArgument(clock != null, "provided clock cannot be null");
validateConfiguration(config); validateConfiguration(config);
this.keyPair = keyPair;
this.config = config;
this.peerPermissions = peerPermissions; this.peerPermissions = peerPermissions;
this.natManager = natManager; this.natManager = natManager;
this.bootstrapPeers = this.bootstrapPeers =
config.getBootnodes().stream().map(DiscoveryPeer::fromEnode).collect(Collectors.toList()); config.getBootnodes().stream().map(DiscoveryPeer::fromEnode).collect(Collectors.toList());
this.metricsSystem = metricsSystem;
this.config = config; this.clock = clock;
this.keyPair = keyPair;
id = keyPair.getPublicKey().getEncodedBytes(); id = keyPair.getPublicKey().getEncodedBytes();
} }
@ -188,6 +193,7 @@ public abstract class PeerDiscoveryAgent {
.peerPermissions(peerPermissions) .peerPermissions(peerPermissions)
.peerBondedObservers(peerBondedObservers) .peerBondedObservers(peerBondedObservers)
.metricsSystem(metricsSystem) .metricsSystem(metricsSystem)
.clock(clock)
.build(); .build();
} }
@ -242,7 +248,7 @@ public abstract class PeerDiscoveryAgent {
} }
return; return;
} }
peer.setLastContacted(System.currentTimeMillis()); peer.setLastContacted(clock.millis());
}); });
} }

@ -31,6 +31,7 @@ import java.io.IOException;
import java.net.BindException; import java.net.BindException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketException; import java.net.SocketException;
import java.time.Clock;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -61,8 +62,9 @@ public class VertxPeerDiscoveryAgent extends PeerDiscoveryAgent {
final DiscoveryConfiguration config, final DiscoveryConfiguration config,
final PeerPermissions peerPermissions, final PeerPermissions peerPermissions,
final Optional<UpnpNatManager> natManager, final Optional<UpnpNatManager> natManager,
final MetricsSystem metricsSystem) { final MetricsSystem metricsSystem,
super(keyPair, config, peerPermissions, natManager, metricsSystem); final Clock clock) {
super(keyPair, config, peerPermissions, natManager, metricsSystem, clock);
checkArgument(vertx != null, "vertx instance cannot be null"); checkArgument(vertx != null, "vertx instance cannot be null");
this.vertx = vertx; this.vertx = vertx;

@ -18,6 +18,8 @@ import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
public class FindNeighborsPacketData implements PacketData { public class FindNeighborsPacketData implements PacketData {
private static final int TARGET_SIZE = 64; private static final int TARGET_SIZE = 64;
@ -35,9 +37,9 @@ public class FindNeighborsPacketData implements PacketData {
this.expiration = expiration; this.expiration = expiration;
} }
public static FindNeighborsPacketData create(final BytesValue target) { public static FindNeighborsPacketData create(final BytesValue target, final Clock clock) {
return new FindNeighborsPacketData( return new FindNeighborsPacketData(
target, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS); target, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
} }
@Override @Override

@ -18,6 +18,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import java.time.Clock;
import java.util.List; import java.util.List;
public class NeighborsPacketData implements PacketData { public class NeighborsPacketData implements PacketData {
@ -36,9 +37,8 @@ public class NeighborsPacketData implements PacketData {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static NeighborsPacketData create(final List<DiscoveryPeer> peers) { public static NeighborsPacketData create(final List<DiscoveryPeer> peers, final Clock clock) {
return new NeighborsPacketData( return new NeighborsPacketData(peers, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
peers, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
} }
public static NeighborsPacketData readFrom(final RLPInput in) { public static NeighborsPacketData readFrom(final RLPInput in) {

@ -35,6 +35,7 @@ import tech.pegasys.pantheon.metrics.PantheonMetricCategory;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -142,6 +143,8 @@ public class PeerDiscoveryController {
private RecursivePeerRefreshState recursivePeerRefreshState; private RecursivePeerRefreshState recursivePeerRefreshState;
private final Clock clock;
private PeerDiscoveryController( private PeerDiscoveryController(
final KeyPair keypair, final KeyPair keypair,
final DiscoveryPeer localPeer, final DiscoveryPeer localPeer,
@ -155,7 +158,8 @@ public class PeerDiscoveryController {
final PeerRequirement peerRequirement, final PeerRequirement peerRequirement,
final PeerPermissions peerPermissions, final PeerPermissions peerPermissions,
final Subscribers<PeerBondedObserver> peerBondedObservers, final Subscribers<PeerBondedObserver> peerBondedObservers,
final MetricsSystem metricsSystem) { final MetricsSystem metricsSystem,
final Clock clock) {
this.timerUtil = timerUtil; this.timerUtil = timerUtil;
this.keypair = keypair; this.keypair = keypair;
this.localPeer = localPeer; this.localPeer = localPeer;
@ -167,6 +171,7 @@ public class PeerDiscoveryController {
this.peerRequirement = peerRequirement; this.peerRequirement = peerRequirement;
this.outboundMessageHandler = outboundMessageHandler; this.outboundMessageHandler = outboundMessageHandler;
this.peerBondedObservers = peerBondedObservers; this.peerBondedObservers = peerBondedObservers;
this.clock = clock;
this.discoveryProtocolLogger = new DiscoveryProtocolLogger(metricsSystem); this.discoveryProtocolLogger = new DiscoveryProtocolLogger(metricsSystem);
this.peerPermissions = new PeerDiscoveryPermissions(localPeer, peerPermissions); this.peerPermissions = new PeerDiscoveryPermissions(localPeer, peerPermissions);
@ -357,7 +362,7 @@ public class PeerDiscoveryController {
} }
// Reset the last seen timestamp. // Reset the last seen timestamp.
final long now = System.currentTimeMillis(); final long now = clock.millis();
if (peer.getFirstDiscovered() == 0) { if (peer.getFirstDiscovered() == 0) {
peer.setFirstDiscovered(now); peer.setFirstDiscovered(now);
} }
@ -396,7 +401,7 @@ public class PeerDiscoveryController {
} }
private void refreshTableIfRequired() { private void refreshTableIfRequired() {
final long now = System.currentTimeMillis(); final long now = clock.millis();
if (lastRefreshTime + tableRefreshIntervalMs <= now) { if (lastRefreshTime + tableRefreshIntervalMs <= now) {
LOG.debug("Peer table refresh triggered by timer expiry"); LOG.debug("Peer table refresh triggered by timer expiry");
refreshTable(); refreshTable();
@ -425,7 +430,7 @@ public class PeerDiscoveryController {
final BytesValue target = Peer.randomId(); final BytesValue target = Peer.randomId();
final List<DiscoveryPeer> initialPeers = peerTable.nearestPeers(Peer.randomId(), 16); final List<DiscoveryPeer> initialPeers = peerTable.nearestPeers(Peer.randomId(), 16);
recursivePeerRefreshState.start(initialPeers, target); recursivePeerRefreshState.start(initialPeers, target);
lastRefreshTime = System.currentTimeMillis(); lastRefreshTime = clock.millis();
} }
/** /**
@ -435,13 +440,13 @@ public class PeerDiscoveryController {
*/ */
@VisibleForTesting @VisibleForTesting
void bond(final DiscoveryPeer peer) { void bond(final DiscoveryPeer peer) {
peer.setFirstDiscovered(System.currentTimeMillis()); peer.setFirstDiscovered(clock.millis());
peer.setStatus(PeerDiscoveryStatus.BONDING); peer.setStatus(PeerDiscoveryStatus.BONDING);
final Consumer<PeerInteractionState> action = final Consumer<PeerInteractionState> action =
interaction -> { interaction -> {
final PingPacketData data = final PingPacketData data =
PingPacketData.create(localPeer.getEndpoint(), peer.getEndpoint()); PingPacketData.create(localPeer.getEndpoint(), peer.getEndpoint(), clock);
createPacket( createPacket(
PacketType.PING, PacketType.PING,
data, data,
@ -505,7 +510,7 @@ public class PeerDiscoveryController {
private void findNodes(final DiscoveryPeer peer, final BytesValue target) { private void findNodes(final DiscoveryPeer peer, final BytesValue target) {
final Consumer<PeerInteractionState> action = final Consumer<PeerInteractionState> action =
(interaction) -> { (interaction) -> {
final FindNeighborsPacketData data = FindNeighborsPacketData.create(target); final FindNeighborsPacketData data = FindNeighborsPacketData.create(target, clock);
sendPacket(peer, PacketType.FIND_NEIGHBORS, data); sendPacket(peer, PacketType.FIND_NEIGHBORS, data);
}; };
final PeerInteractionState interaction = final PeerInteractionState interaction =
@ -532,7 +537,7 @@ public class PeerDiscoveryController {
private void respondToPing( private void respondToPing(
final PingPacketData packetData, final BytesValue pingHash, final DiscoveryPeer sender) { final PingPacketData packetData, final BytesValue pingHash, final DiscoveryPeer sender) {
final PongPacketData data = PongPacketData.create(packetData.getFrom(), pingHash); final PongPacketData data = PongPacketData.create(packetData.getFrom(), pingHash, clock);
sendPacket(sender, PacketType.PONG, data); sendPacket(sender, PacketType.PONG, data);
} }
@ -541,7 +546,7 @@ public class PeerDiscoveryController {
// TODO: for now return 16 peers. Other implementations calculate how many // TODO: for now return 16 peers. Other implementations calculate how many
// peers they can fit in a 1280-byte payload. // peers they can fit in a 1280-byte payload.
final List<DiscoveryPeer> peers = peerTable.nearestPeers(packetData.getTarget(), 16); final List<DiscoveryPeer> peers = peerTable.nearestPeers(packetData.getTarget(), 16);
final PacketData data = NeighborsPacketData.create(peers); final PacketData data = NeighborsPacketData.create(peers, clock);
sendPacket(sender, PacketType.NEIGHBORS, data); sendPacket(sender, PacketType.NEIGHBORS, data);
} }
@ -662,6 +667,7 @@ public class PeerDiscoveryController {
private TimerUtil timerUtil; private TimerUtil timerUtil;
private AsyncExecutor workerExecutor; private AsyncExecutor workerExecutor;
private MetricsSystem metricsSystem; private MetricsSystem metricsSystem;
private Clock clock;
private Builder() {} private Builder() {}
@ -685,7 +691,8 @@ public class PeerDiscoveryController {
peerRequirement, peerRequirement,
peerPermissions, peerPermissions,
peerBondedObservers, peerBondedObservers,
metricsSystem); metricsSystem,
clock);
} }
private void validate() { private void validate() {
@ -695,6 +702,7 @@ public class PeerDiscoveryController {
validateRequiredDependency(workerExecutor, "AsyncExecutor"); validateRequiredDependency(workerExecutor, "AsyncExecutor");
validateRequiredDependency(metricsSystem, "MetricsSystem"); validateRequiredDependency(metricsSystem, "MetricsSystem");
validateRequiredDependency(peerBondedObservers, "PeerBondedObservers"); validateRequiredDependency(peerBondedObservers, "PeerBondedObservers");
validateRequiredDependency(clock, "Clock");
} }
private void validateRequiredDependency(final Object object, final String name) { private void validateRequiredDependency(final Object object, final String name) {
@ -777,5 +785,11 @@ public class PeerDiscoveryController {
this.metricsSystem = metricsSystem; this.metricsSystem = metricsSystem;
return this; return this;
} }
public Builder clock(final Clock clock) {
checkNotNull(clock);
this.clock = clock;
return this;
}
} }
} }

@ -18,6 +18,8 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.Endpoint;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput; import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import java.time.Clock;
public class PingPacketData implements PacketData { public class PingPacketData implements PacketData {
/* Fixed value that represents we're using v4 of the P2P discovery protocol. */ /* Fixed value that represents we're using v4 of the P2P discovery protocol. */
@ -42,9 +44,8 @@ public class PingPacketData implements PacketData {
this.expiration = expiration; this.expiration = expiration;
} }
public static PingPacketData create(final Endpoint from, final Endpoint to) { public static PingPacketData create(final Endpoint from, final Endpoint to, final Clock clock) {
return new PingPacketData( return new PingPacketData(from, to, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
from, to, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
} }
public static PingPacketData readFrom(final RLPInput in) { public static PingPacketData readFrom(final RLPInput in) {

@ -17,6 +17,8 @@ import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLPOutput;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
public class PongPacketData implements PacketData { public class PongPacketData implements PacketData {
/* Destination. */ /* Destination. */
@ -34,9 +36,10 @@ public class PongPacketData implements PacketData {
this.expiration = expiration; this.expiration = expiration;
} }
public static PongPacketData create(final Endpoint to, final BytesValue pingHash) { public static PongPacketData create(
final Endpoint to, final BytesValue pingHash, final Clock clock) {
return new PongPacketData( return new PongPacketData(
to, pingHash, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS); to, pingHash, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
} }
public static PongPacketData readFrom(final RLPInput in) { public static PongPacketData readFrom(final RLPInput in) {

@ -43,6 +43,7 @@ import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.nat.upnp.UpnpNatManager; import tech.pegasys.pantheon.nat.upnp.UpnpNatManager;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -409,6 +410,7 @@ public class DefaultP2PNetwork implements P2PNetwork {
private Optional<UpnpNatManager> natManager = Optional.empty(); private Optional<UpnpNatManager> natManager = Optional.empty();
private MetricsSystem metricsSystem; private MetricsSystem metricsSystem;
private Clock clock;
public P2PNetwork build() { public P2PNetwork build() {
validate(); validate();
@ -426,7 +428,7 @@ public class DefaultP2PNetwork implements P2PNetwork {
MutableLocalNode.create(config.getRlpx().getClientId(), 5, supportedCapabilities); MutableLocalNode.create(config.getRlpx().getClientId(), 5, supportedCapabilities);
final PeerPrivileges peerPrivileges = new DefaultPeerPrivileges(maintainedPeers); final PeerPrivileges peerPrivileges = new DefaultPeerPrivileges(maintainedPeers);
peerDiscoveryAgent = peerDiscoveryAgent == null ? createDiscoveryAgent() : peerDiscoveryAgent; peerDiscoveryAgent = peerDiscoveryAgent == null ? createDiscoveryAgent() : peerDiscoveryAgent;
rlpxAgent = rlpxAgent == null ? createRlpxAgent(localNode, peerPrivileges) : rlpxAgent; rlpxAgent = rlpxAgent == null ? createRlpxAgent(localNode, peerPrivileges, clock) : rlpxAgent;
return new DefaultP2PNetwork( return new DefaultP2PNetwork(
localNode, localNode,
@ -447,17 +449,18 @@ public class DefaultP2PNetwork implements P2PNetwork {
supportedCapabilities != null && supportedCapabilities.size() > 0, supportedCapabilities != null && supportedCapabilities.size() > 0,
"Supported capabilities must be set and non-empty."); "Supported capabilities must be set and non-empty.");
checkState(metricsSystem != null, "MetricsSystem must be set."); checkState(metricsSystem != null, "MetricsSystem must be set.");
checkState(clock != null, "Clock must be set.");
checkState(peerDiscoveryAgent != null || vertx != null, "Vertx must be set."); checkState(peerDiscoveryAgent != null || vertx != null, "Vertx must be set.");
} }
private PeerDiscoveryAgent createDiscoveryAgent() { private PeerDiscoveryAgent createDiscoveryAgent() {
return new VertxPeerDiscoveryAgent( return new VertxPeerDiscoveryAgent(
vertx, keyPair, config.getDiscovery(), peerPermissions, natManager, metricsSystem); vertx, keyPair, config.getDiscovery(), peerPermissions, natManager, metricsSystem, clock);
} }
private RlpxAgent createRlpxAgent( private RlpxAgent createRlpxAgent(
final LocalNode localNode, final PeerPrivileges peerPrivileges) { final LocalNode localNode, final PeerPrivileges peerPrivileges, final Clock clock) {
return RlpxAgent.builder() return RlpxAgent.builder()
.keyPair(keyPair) .keyPair(keyPair)
.config(config.getRlpx()) .config(config.getRlpx())
@ -465,6 +468,7 @@ public class DefaultP2PNetwork implements P2PNetwork {
.peerPrivileges(peerPrivileges) .peerPrivileges(peerPrivileges)
.localNode(localNode) .localNode(localNode)
.metricsSystem(metricsSystem) .metricsSystem(metricsSystem)
.clock(clock)
.build(); .build();
} }
@ -521,6 +525,12 @@ public class DefaultP2PNetwork implements P2PNetwork {
return this; return this;
} }
public Builder clock(final Clock clock) {
checkNotNull(clock);
this.clock = clock;
return this;
}
public Builder natManager(final UpnpNatManager natManager) { public Builder natManager(final UpnpNatManager natManager) {
this.natManager = Optional.ofNullable(natManager); this.natManager = Optional.ofNullable(natManager);
return this; return this;

@ -39,6 +39,7 @@ import tech.pegasys.pantheon.util.FutureUtils;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -67,6 +68,7 @@ public class RlpxAgent {
private final PeerPrivileges peerPrivileges; private final PeerPrivileges peerPrivileges;
private final int maxConnections; private final int maxConnections;
private final int maxRemotelyInitiatedConnections; private final int maxRemotelyInitiatedConnections;
private final Clock clock;
@VisibleForTesting @VisibleForTesting
final Map<BytesValue, RlpxConnection> connectionsById = new ConcurrentHashMap<>(); final Map<BytesValue, RlpxConnection> connectionsById = new ConcurrentHashMap<>();
@ -84,7 +86,8 @@ public class RlpxAgent {
final PeerPrivileges peerPrivileges, final PeerPrivileges peerPrivileges,
final int maxConnections, final int maxConnections,
final int maxRemotelyInitiatedConnections, final int maxRemotelyInitiatedConnections,
final MetricsSystem metricsSystem) { final MetricsSystem metricsSystem,
final Clock clock) {
this.localNode = localNode; this.localNode = localNode;
this.connectionEvents = connectionEvents; this.connectionEvents = connectionEvents;
this.connectionInitializer = connectionInitializer; this.connectionInitializer = connectionInitializer;
@ -93,6 +96,7 @@ public class RlpxAgent {
this.maxConnections = maxConnections; this.maxConnections = maxConnections;
this.maxRemotelyInitiatedConnections = this.maxRemotelyInitiatedConnections =
Math.min(maxConnections, maxRemotelyInitiatedConnections); Math.min(maxConnections, maxRemotelyInitiatedConnections);
this.clock = clock;
// Setup metrics // Setup metrics
connectedPeersCounter = connectedPeersCounter =
@ -231,7 +235,8 @@ public class RlpxAgent {
// We're initiating a new connection // We're initiating a new connection
final CompletableFuture<PeerConnection> future = initiateOutboundConnection(peer); final CompletableFuture<PeerConnection> future = initiateOutboundConnection(peer);
connectionFuture.set(future); connectionFuture.set(future);
RlpxConnection newConnection = RlpxConnection.outboundConnection(peer, future); RlpxConnection newConnection =
RlpxConnection.outboundConnection(peer, future, clock.millis());
newConnection.subscribeConnectionEstablished( newConnection.subscribeConnectionEstablished(
(conn) -> { (conn) -> {
this.dispatchConnect(conn.getPeerConnection()); this.dispatchConnect(conn.getPeerConnection());
@ -299,7 +304,7 @@ public class RlpxAgent {
private CompletableFuture<PeerConnection> initiateOutboundConnection(final Peer peer) { private CompletableFuture<PeerConnection> initiateOutboundConnection(final Peer peer) {
LOG.trace("Initiating connection to peer: {}", peer.getEnodeURL()); LOG.trace("Initiating connection to peer: {}", peer.getEnodeURL());
if (peer instanceof DiscoveryPeer) { if (peer instanceof DiscoveryPeer) {
((DiscoveryPeer) peer).setLastAttemptedConnection(System.currentTimeMillis()); ((DiscoveryPeer) peer).setLastAttemptedConnection(clock.millis());
} }
return connectionInitializer return connectionInitializer
@ -339,7 +344,8 @@ public class RlpxAgent {
// Track this new connection, deduplicating existing connection if necessary // Track this new connection, deduplicating existing connection if necessary
final AtomicBoolean newConnectionAccepted = new AtomicBoolean(false); final AtomicBoolean newConnectionAccepted = new AtomicBoolean(false);
final RlpxConnection inboundConnection = RlpxConnection.inboundConnection(peerConnection); final RlpxConnection inboundConnection =
RlpxConnection.inboundConnection(peerConnection, clock.millis());
// Our disconnect handler runs connectionsById.compute(), so don't actually execute the // Our disconnect handler runs connectionsById.compute(), so don't actually execute the
// disconnect command until we've returned from our compute() calculation // disconnect command until we've returned from our compute() calculation
final AtomicReference<Runnable> disconnectAction = new AtomicReference<>(); final AtomicReference<Runnable> disconnectAction = new AtomicReference<>();
@ -503,6 +509,7 @@ public class RlpxAgent {
private ConnectionInitializer connectionInitializer; private ConnectionInitializer connectionInitializer;
private PeerConnectionEvents connectionEvents; private PeerConnectionEvents connectionEvents;
private MetricsSystem metricsSystem; private MetricsSystem metricsSystem;
private Clock clock;
private Builder() {} private Builder() {}
@ -528,7 +535,8 @@ public class RlpxAgent {
peerPrivileges, peerPrivileges,
config.getMaxPeers(), config.getMaxPeers(),
config.getMaxRemotelyInitiatedConnections(), config.getMaxRemotelyInitiatedConnections(),
metricsSystem); metricsSystem,
clock);
} }
private void validate() { private void validate() {
@ -538,6 +546,7 @@ public class RlpxAgent {
checkState(peerPrivileges != null, "PeerPrivileges must be configured"); checkState(peerPrivileges != null, "PeerPrivileges must be configured");
checkState(peerPermissions != null, "PeerPermissions must be configured"); checkState(peerPermissions != null, "PeerPermissions must be configured");
checkState(metricsSystem != null, "MetricsSystem must be configured"); checkState(metricsSystem != null, "MetricsSystem must be configured");
checkState(clock != null, "Clock must be configured");
} }
public Builder keyPair(final KeyPair keyPair) { public Builder keyPair(final KeyPair keyPair) {
@ -587,5 +596,11 @@ public class RlpxAgent {
this.metricsSystem = metricsSystem; this.metricsSystem = metricsSystem;
return this; return this;
} }
public Builder clock(final Clock clock) {
checkNotNull(clock);
this.clock = clock;
return this;
}
} }
} }

@ -24,18 +24,19 @@ public abstract class RlpxConnection {
private final long initiatedAt; private final long initiatedAt;
protected final CompletableFuture<PeerConnection> future; protected final CompletableFuture<PeerConnection> future;
private RlpxConnection(final CompletableFuture<PeerConnection> future) { private RlpxConnection(final CompletableFuture<PeerConnection> future, final long initiatedAt) {
this.future = future; this.future = future;
this.initiatedAt = System.currentTimeMillis(); this.initiatedAt = initiatedAt;
} }
public static RlpxConnection inboundConnection(final PeerConnection peerConnection) { public static RlpxConnection inboundConnection(
return new RemotelyInitiatedRlpxConnection(peerConnection); final PeerConnection peerConnection, final long initiatedAt) {
return new RemotelyInitiatedRlpxConnection(peerConnection, initiatedAt);
} }
public static RlpxConnection outboundConnection( public static RlpxConnection outboundConnection(
final Peer peer, final CompletableFuture<PeerConnection> future) { final Peer peer, final CompletableFuture<PeerConnection> future, final long initiatedAt) {
return new LocallyInitiatedRlpxConnection(peer, future); return new LocallyInitiatedRlpxConnection(peer, future, initiatedAt);
} }
public abstract Peer getPeer(); public abstract Peer getPeer();
@ -84,8 +85,9 @@ public abstract class RlpxConnection {
private final PeerConnection peerConnection; private final PeerConnection peerConnection;
private RemotelyInitiatedRlpxConnection(final PeerConnection peerConnection) { private RemotelyInitiatedRlpxConnection(
super(CompletableFuture.completedFuture(peerConnection)); final PeerConnection peerConnection, final long initiatedAt) {
super(CompletableFuture.completedFuture(peerConnection), initiatedAt);
this.peerConnection = peerConnection; this.peerConnection = peerConnection;
} }
@ -147,8 +149,8 @@ public abstract class RlpxConnection {
private final Peer peer; private final Peer peer;
private LocallyInitiatedRlpxConnection( private LocallyInitiatedRlpxConnection(
final Peer peer, final CompletableFuture<PeerConnection> future) { final Peer peer, final CompletableFuture<PeerConnection> future, final long initiatedAt) {
super(future); super(future, initiatedAt);
this.peer = peer; this.peer = peer;
} }

@ -16,7 +16,6 @@ import static com.google.common.base.Preconditions.checkState;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
import tech.pegasys.pantheon.ethereum.p2p.config.RlpxConfiguration; import tech.pegasys.pantheon.ethereum.p2p.config.RlpxConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer;
import tech.pegasys.pantheon.ethereum.p2p.peers.EnodeURL; import tech.pegasys.pantheon.ethereum.p2p.peers.EnodeURL;
import tech.pegasys.pantheon.ethereum.p2p.peers.LocalNode; import tech.pegasys.pantheon.ethereum.p2p.peers.LocalNode;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
@ -164,10 +163,6 @@ public class NettyConnectionInitializer implements ConnectionInitializer {
public CompletableFuture<PeerConnection> connect(final Peer peer) { public CompletableFuture<PeerConnection> connect(final Peer peer) {
final CompletableFuture<PeerConnection> connectionFuture = new CompletableFuture<>(); final CompletableFuture<PeerConnection> connectionFuture = new CompletableFuture<>();
if (peer instanceof DiscoveryPeer) {
((DiscoveryPeer) peer).setLastAttemptedConnection(System.currentTimeMillis());
}
final EnodeURL enode = peer.getEnodeURL(); final EnodeURL enode = peer.getEnodeURL();
new Bootstrap() new Bootstrap()
.group(workers) .group(workers)

@ -32,6 +32,7 @@ import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions; import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions.Action; import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions.Action;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissionsBlacklist; import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissionsBlacklist;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -73,7 +74,7 @@ public class PeerDiscoveryAgentTest {
// Generate an out-of-band NEIGHBORS message. // Generate an out-of-band NEIGHBORS message.
final List<DiscoveryPeer> peers = helper.createDiscoveryPeers(5); final List<DiscoveryPeer> peers = helper.createDiscoveryPeers(5);
final NeighborsPacketData data = NeighborsPacketData.create(peers); final NeighborsPacketData data = NeighborsPacketData.create(peers, TestClock.fixed());
final Packet packet = Packet.create(PacketType.NEIGHBORS, data, otherNode.getKeyPair()); final Packet packet = Packet.create(PacketType.NEIGHBORS, data, otherNode.getKeyPair());
helper.sendMessageBetweenAgents(otherNode, agent, packet); helper.sendMessageBetweenAgents(otherNode, agent, packet);
@ -112,7 +113,8 @@ public class PeerDiscoveryAgentTest {
packet = packet =
Packet.create( Packet.create(
PacketType.FIND_NEIGHBORS, PacketType.FIND_NEIGHBORS,
FindNeighborsPacketData.create(otherAgents.get(0).getAdvertisedPeer().get().getId()), FindNeighborsPacketData.create(
otherAgents.get(0).getAdvertisedPeer().get().getId(), TestClock.fixed()),
testAgent.getKeyPair()); testAgent.getKeyPair());
helper.sendMessageBetweenAgents(testAgent, agent, packet); helper.sendMessageBetweenAgents(testAgent, agent, packet);
@ -204,7 +206,7 @@ public class PeerDiscoveryAgentTest {
// Start an agent with no bootstrap peers. // Start an agent with no bootstrap peers.
final PeerPermissions peerPermissions = mock(PeerPermissions.class); final PeerPermissions peerPermissions = mock(PeerPermissions.class);
final MockPeerDiscoveryAgent agent = final MockPeerDiscoveryAgent agent =
helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions); helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions, TestClock.fixed());
final Peer localNode = agent.getAdvertisedPeer().get(); final Peer localNode = agent.getAdvertisedPeer().get();
// Setup peer and permissions // Setup peer and permissions
@ -231,7 +233,7 @@ public class PeerDiscoveryAgentTest {
// Start an agent with no bootstrap peers. // Start an agent with no bootstrap peers.
final PeerPermissions peerPermissions = mock(PeerPermissions.class); final PeerPermissions peerPermissions = mock(PeerPermissions.class);
final MockPeerDiscoveryAgent agent = final MockPeerDiscoveryAgent agent =
helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions); helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions, TestClock.fixed());
final Peer localNode = agent.getAdvertisedPeer().get(); final Peer localNode = agent.getAdvertisedPeer().get();
// Setup peer and permissions // Setup peer and permissions
@ -472,7 +474,8 @@ public class PeerDiscoveryAgentTest {
protected void requestNeighbors( protected void requestNeighbors(
final MockPeerDiscoveryAgent fromAgent, final MockPeerDiscoveryAgent toAgent) { final MockPeerDiscoveryAgent fromAgent, final MockPeerDiscoveryAgent toAgent) {
final FindNeighborsPacketData data = FindNeighborsPacketData.create(Peer.randomId()); final FindNeighborsPacketData data =
FindNeighborsPacketData.create(Peer.randomId(), TestClock.fixed());
final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, data, fromAgent.getKeyPair()); final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, data, fromAgent.getKeyPair());
helper.sendMessageBetweenAgents(fromAgent, toAgent, packet); helper.sendMessageBetweenAgents(fromAgent, toAgent, packet);
} }

@ -21,6 +21,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.MockPeerDiscoveryAg
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.Packet; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.Packet;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PongPacketData; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PongPacketData;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -67,7 +68,8 @@ public class PeerDiscoveryBondingTest {
// ignored because // ignored because
// we haven't bonded. // we haven't bonded.
final MockPeerDiscoveryAgent otherNode = helper.startDiscoveryAgent(); final MockPeerDiscoveryAgent otherNode = helper.startDiscoveryAgent();
final FindNeighborsPacketData data = FindNeighborsPacketData.create(otherNode.getId()); final FindNeighborsPacketData data =
FindNeighborsPacketData.create(otherNode.getId(), TestClock.fixed());
final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, data, otherNode.getKeyPair()); final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, data, otherNode.getKeyPair());
helper.sendMessageBetweenAgents(otherNode, agent, packet); helper.sendMessageBetweenAgents(otherNode, agent, packet);

@ -23,6 +23,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.Packet;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PingPacketData; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PingPacketData;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List; import java.util.List;
@ -53,7 +54,7 @@ public class PeerDiscoveryBootstrappingTest {
final PingPacketData pingData = pingPacket.getPacketData(PingPacketData.class).get(); final PingPacketData pingData = pingPacket.getPacketData(PingPacketData.class).get();
assertThat(pingData.getExpiration()) assertThat(pingData.getExpiration())
.isGreaterThanOrEqualTo(System.currentTimeMillis() / 1000 - 10000); .isGreaterThanOrEqualTo(TestClock.fixed().millis() / 1000 - 10000);
assertThat(pingData.getFrom()).isEqualTo(agent.getAdvertisedPeer().get().getEndpoint()); assertThat(pingData.getFrom()).isEqualTo(agent.getAdvertisedPeer().get().getEndpoint());
assertThat(pingData.getTo()).isEqualTo(testAgent.getAdvertisedPeer().get().getEndpoint()); assertThat(pingData.getTo()).isEqualTo(testAgent.getAdvertisedPeer().get().getEndpoint());
} }
@ -100,7 +101,7 @@ public class PeerDiscoveryBootstrappingTest {
// Assert on the content of the packet data. // Assert on the content of the packet data.
final PingPacketData ping = packet.getPacketData(PingPacketData.class).get(); final PingPacketData ping = packet.getPacketData(PingPacketData.class).get();
assertThat(ping.getExpiration()) assertThat(ping.getExpiration())
.isGreaterThanOrEqualTo(System.currentTimeMillis() / 1000 - 10000); .isGreaterThanOrEqualTo(TestClock.fixed().millis() / 1000 - 10000);
assertThat(ping.getTo()).isEqualTo(bootstrapAgent.getAdvertisedPeer().get().getEndpoint()); assertThat(ping.getTo()).isEqualTo(bootstrapAgent.getAdvertisedPeer().get().getEndpoint());
} }
} }

@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryEvent.PeerBondedEvent; import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryEvent.PeerBondedEvent;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.MockPeerDiscoveryAgent; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.MockPeerDiscoveryAgent;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.ArrayList; import java.util.ArrayList;
@ -102,7 +103,7 @@ public class PeerDiscoveryObserversTest {
// Create a discovery agent (which we'll assert on), using the above two peers as bootstrap // Create a discovery agent (which we'll assert on), using the above two peers as bootstrap
// peers. // peers.
final MockPeerDiscoveryAgent agent = helper.createDiscoveryAgent(peers2); final MockPeerDiscoveryAgent agent = helper.createDiscoveryAgent(peers2, TestClock.fixed());
// A queue for storing peer bonded events. // A queue for storing peer bonded events.
final List<PeerBondedEvent> events = new ArrayList<>(10); final List<PeerBondedEvent> events = new ArrayList<>(10);
agent.observePeerBondedEvents(events::add); agent.observePeerBondedEvents(events::add);

@ -24,6 +24,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketData;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.ethereum.rlp.RLPException; import tech.pegasys.pantheon.ethereum.rlp.RLPException;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.MutableBytesValue; import tech.pegasys.pantheon.util.bytes.MutableBytesValue;
@ -43,7 +44,8 @@ public class PeerDiscoveryPacketSedesTest {
final BytesValue target = BytesValue.wrap(r); final BytesValue target = BytesValue.wrap(r);
final SECP256K1.KeyPair kp = SECP256K1.KeyPair.generate(); final SECP256K1.KeyPair kp = SECP256K1.KeyPair.generate();
final FindNeighborsPacketData packetData = FindNeighborsPacketData.create(target); final FindNeighborsPacketData packetData =
FindNeighborsPacketData.create(target, TestClock.fixed());
final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, packetData, kp); final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, packetData, kp);
final Buffer encoded = packet.encode(); final Buffer encoded = packet.encode();
assertNotNull(encoded); assertNotNull(encoded);
@ -61,7 +63,8 @@ public class PeerDiscoveryPacketSedesTest {
new Random().nextBytes(r); new Random().nextBytes(r);
final BytesValue target = BytesValue.wrap(r); final BytesValue target = BytesValue.wrap(r);
final FindNeighborsPacketData packet = FindNeighborsPacketData.create(target); final FindNeighborsPacketData packet =
FindNeighborsPacketData.create(target, TestClock.fixed());
final BytesValue serialized = RLP.encode(packet::writeTo); final BytesValue serialized = RLP.encode(packet::writeTo);
assertNotNull(serialized); assertNotNull(serialized);
@ -72,14 +75,14 @@ public class PeerDiscoveryPacketSedesTest {
// assertion. // assertion.
assertThat(deserialized.getExpiration()) assertThat(deserialized.getExpiration())
.isCloseTo( .isCloseTo(
System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L)); TestClock.fixed().millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L));
} }
@Test @Test
public void neighborsPacketData() { public void neighborsPacketData() {
final List<DiscoveryPeer> peers = helper.createDiscoveryPeers(5); final List<DiscoveryPeer> peers = helper.createDiscoveryPeers(5);
final NeighborsPacketData packet = NeighborsPacketData.create(peers); final NeighborsPacketData packet = NeighborsPacketData.create(peers, TestClock.fixed());
final BytesValue serialized = RLP.encode(packet::writeTo); final BytesValue serialized = RLP.encode(packet::writeTo);
assertNotNull(serialized); assertNotNull(serialized);
@ -89,7 +92,7 @@ public class PeerDiscoveryPacketSedesTest {
// assertion. // assertion.
assertThat(deserialized.getExpiration()) assertThat(deserialized.getExpiration())
.isCloseTo( .isCloseTo(
System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L)); TestClock.fixed().millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L));
} }
@Test(expected = RLPException.class) @Test(expected = RLPException.class)
@ -98,7 +101,8 @@ public class PeerDiscoveryPacketSedesTest {
new Random().nextBytes(r); new Random().nextBytes(r);
final BytesValue target = BytesValue.wrap(r); final BytesValue target = BytesValue.wrap(r);
final FindNeighborsPacketData packet = FindNeighborsPacketData.create(target); final FindNeighborsPacketData packet =
FindNeighborsPacketData.create(target, TestClock.fixed());
final BytesValue serialized = RLP.encode(packet::writeTo); final BytesValue serialized = RLP.encode(packet::writeTo);
assertNotNull(serialized); assertNotNull(serialized);
@ -113,7 +117,7 @@ public class PeerDiscoveryPacketSedesTest {
final SECP256K1.KeyPair kp = SECP256K1.KeyPair.generate(); final SECP256K1.KeyPair kp = SECP256K1.KeyPair.generate();
final FindNeighborsPacketData data = FindNeighborsPacketData.create(target); final FindNeighborsPacketData data = FindNeighborsPacketData.create(target, TestClock.fixed());
final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, data, kp); final Packet packet = Packet.create(PacketType.FIND_NEIGHBORS, data, kp);
final BytesValue encoded = BytesValue.wrapBuffer(packet.encode()); final BytesValue encoded = BytesValue.wrapBuffer(packet.encode());

@ -24,8 +24,10 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PingPacketData;
import tech.pegasys.pantheon.ethereum.p2p.peers.EnodeURL; import tech.pegasys.pantheon.ethereum.p2p.peers.EnodeURL;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions; import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -80,7 +82,8 @@ public class PeerDiscoveryTestHelper {
PacketType.PING, PacketType.PING,
PingPacketData.create( PingPacketData.create(
fromAgent.getAdvertisedPeer().get().getEndpoint(), fromAgent.getAdvertisedPeer().get().getEndpoint(),
toAgent.getAdvertisedPeer().get().getEndpoint()), toAgent.getAdvertisedPeer().get().getEndpoint(),
TestClock.fixed()),
fromAgent.getKeyPair()); fromAgent.getKeyPair());
} }
@ -122,7 +125,19 @@ public class PeerDiscoveryTestHelper {
* @return a list of discovery agents. * @return a list of discovery agents.
*/ */
public MockPeerDiscoveryAgent startDiscoveryAgent(final List<DiscoveryPeer> bootstrapPeers) { public MockPeerDiscoveryAgent startDiscoveryAgent(final List<DiscoveryPeer> bootstrapPeers) {
final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers); return startDiscoveryAgent(bootstrapPeers, TestClock.fixed());
}
/**
* Start a single discovery agent with the provided bootstrap peers.
*
* @param bootstrapPeers the list of bootstrap peers
* @param clock the clock to sample timestamps from
* @return a list of discovery agents.
*/
public MockPeerDiscoveryAgent startDiscoveryAgent(
final List<DiscoveryPeer> bootstrapPeers, final Clock clock) {
final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers).clock(clock);
return startDiscoveryAgent(agentBuilder); return startDiscoveryAgent(agentBuilder);
} }
@ -133,6 +148,12 @@ public class PeerDiscoveryTestHelper {
return startDiscoveryAgent(agentBuilder); return startDiscoveryAgent(agentBuilder);
} }
public MockPeerDiscoveryAgent startDiscoveryAgent(final Clock clock) {
final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(List.of()).clock(clock);
return startDiscoveryAgent(agentBuilder);
}
/** /**
* Start a single discovery agent with the provided bootstrap peers. * Start a single discovery agent with the provided bootstrap peers.
* *
@ -141,9 +162,11 @@ public class PeerDiscoveryTestHelper {
* @return a list of discovery agents. * @return a list of discovery agents.
*/ */
public MockPeerDiscoveryAgent startDiscoveryAgent( public MockPeerDiscoveryAgent startDiscoveryAgent(
final List<DiscoveryPeer> bootstrapPeers, final PeerPermissions peerPermissions) { final List<DiscoveryPeer> bootstrapPeers,
final PeerPermissions peerPermissions,
final Clock clock) {
final AgentBuilder agentBuilder = final AgentBuilder agentBuilder =
agentBuilder().bootstrapPeers(bootstrapPeers).peerPermissions(peerPermissions); agentBuilder().bootstrapPeers(bootstrapPeers).peerPermissions(peerPermissions).clock(clock);
return startDiscoveryAgent(agentBuilder); return startDiscoveryAgent(agentBuilder);
} }
@ -154,8 +177,9 @@ public class PeerDiscoveryTestHelper {
return agent; return agent;
} }
public MockPeerDiscoveryAgent createDiscoveryAgent(final List<DiscoveryPeer> bootstrapPeers) { public MockPeerDiscoveryAgent createDiscoveryAgent(
final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers); final List<DiscoveryPeer> bootstrapPeers, final Clock clock) {
final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers).clock(clock);
return createDiscoveryAgent(agentBuilder); return createDiscoveryAgent(agentBuilder);
} }
@ -179,6 +203,7 @@ public class PeerDiscoveryTestHelper {
private List<EnodeURL> bootnodes = Collections.emptyList(); private List<EnodeURL> bootnodes = Collections.emptyList();
private boolean active = true; private boolean active = true;
private PeerPermissions peerPermissions = PeerPermissions.noop(); private PeerPermissions peerPermissions = PeerPermissions.noop();
private Clock clock = TestClock.fixed();
private AgentBuilder( private AgentBuilder(
final Map<BytesValue, MockPeerDiscoveryAgent> agents, final Map<BytesValue, MockPeerDiscoveryAgent> agents,
@ -215,6 +240,11 @@ public class PeerDiscoveryTestHelper {
return this; return this;
} }
public AgentBuilder clock(final Clock clock) {
this.clock = clock;
return this;
}
public MockPeerDiscoveryAgent build() { public MockPeerDiscoveryAgent build() {
final DiscoveryConfiguration config = new DiscoveryConfiguration(); final DiscoveryConfiguration config = new DiscoveryConfiguration();
config.setBootnodes(bootnodes); config.setBootnodes(bootnodes);
@ -222,7 +252,7 @@ public class PeerDiscoveryTestHelper {
config.setActive(active); config.setActive(active);
return new MockPeerDiscoveryAgent( return new MockPeerDiscoveryAgent(
SECP256K1.KeyPair.generate(), config, peerPermissions, agents); SECP256K1.KeyPair.generate(), config, peerPermissions, agents, clock);
} }
} }
} }

@ -26,6 +26,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PeerDiscoveryContro
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PeerTable; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PeerTable;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PingPacketData; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PingPacketData;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import java.util.Collections; import java.util.Collections;
@ -38,6 +39,7 @@ import org.junit.Test;
public class PeerDiscoveryTimestampsTest { public class PeerDiscoveryTimestampsTest {
private final PeerDiscoveryTestHelper helper = new PeerDiscoveryTestHelper(); private final PeerDiscoveryTestHelper helper = new PeerDiscoveryTestHelper();
private final TestClock testClock = new TestClock();
@Test @Test
public void lastSeenAndFirstDiscoveredTimestampsUpdatedOnMessage() { public void lastSeenAndFirstDiscoveredTimestampsUpdatedOnMessage() {
@ -60,11 +62,14 @@ public class PeerDiscoveryTimestampsTest {
.tableRefreshIntervalMs(TimeUnit.HOURS.toMillis(1)) .tableRefreshIntervalMs(TimeUnit.HOURS.toMillis(1))
.peerBondedObservers(Subscribers.create()) .peerBondedObservers(Subscribers.create())
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())
.clock(testClock)
.build(); .build();
controller.start(); controller.start();
testClock.stepMillis(1_000);
final PingPacketData ping = final PingPacketData ping =
PingPacketData.create(peers.get(1).getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
peers.get(1).getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet packet = Packet.create(PacketType.PING, ping, keypairs.get(1)); final Packet packet = Packet.create(PacketType.PING, ping, keypairs.get(1));
controller.onMessage(packet, peers.get(1)); controller.onMessage(packet, peers.get(1));
@ -74,6 +79,7 @@ public class PeerDiscoveryTimestampsTest {
assertThat(controller.streamDiscoveredPeers()).hasSize(1); assertThat(controller.streamDiscoveredPeers()).hasSize(1);
testClock.stepMillis(1_000);
DiscoveryPeer p = controller.streamDiscoveredPeers().iterator().next(); DiscoveryPeer p = controller.streamDiscoveredPeers().iterator().next();
assertThat(p.getLastSeen()).isGreaterThan(0); assertThat(p.getLastSeen()).isGreaterThan(0);
assertThat(p.getFirstDiscovered()).isGreaterThan(0); assertThat(p.getFirstDiscovered()).isGreaterThan(0);
@ -81,6 +87,7 @@ public class PeerDiscoveryTimestampsTest {
lastSeen.set(p.getLastSeen()); lastSeen.set(p.getLastSeen());
firstDiscovered.set(p.getFirstDiscovered()); firstDiscovered.set(p.getFirstDiscovered());
testClock.stepMillis(1_000);
controller.onMessage(packet, peers.get(1)); controller.onMessage(packet, peers.get(1));
assertThat(controller.streamDiscoveredPeers()).hasSize(1); assertThat(controller.streamDiscoveredPeers()).hasSize(1);
@ -92,11 +99,12 @@ public class PeerDiscoveryTimestampsTest {
@Test @Test
public void lastContactedTimestampUpdatedOnOutboundMessage() { public void lastContactedTimestampUpdatedOnOutboundMessage() {
final MockPeerDiscoveryAgent agent = helper.startDiscoveryAgent(Collections.emptyList()); final MockPeerDiscoveryAgent agent =
helper.startDiscoveryAgent(Collections.emptyList(), testClock);
assertThat(agent.streamDiscoveredPeers()).hasSize(0); assertThat(agent.streamDiscoveredPeers()).hasSize(0);
// Start a test peer and send a PING packet to the agent under test. // Start a test peer and send a PING packet to the agent under test.
final MockPeerDiscoveryAgent testAgent = helper.startDiscoveryAgent(); final MockPeerDiscoveryAgent testAgent = helper.startDiscoveryAgent(testClock);
final Packet ping = helper.createPingPacket(testAgent, agent); final Packet ping = helper.createPingPacket(testAgent, agent);
helper.sendMessageBetweenAgents(testAgent, agent, ping); helper.sendMessageBetweenAgents(testAgent, agent, ping);
@ -120,6 +128,7 @@ public class PeerDiscoveryTimestampsTest {
firstDiscovered.set(fd); firstDiscovered.set(fd);
// Send another packet and ensure that timestamps are updated accordingly. // Send another packet and ensure that timestamps are updated accordingly.
testClock.stepMillis(1_000);
helper.sendMessageBetweenAgents(testAgent, agent, ping); helper.sendMessageBetweenAgents(testAgent, agent, ping);
peer = agent.streamDiscoveredPeers().iterator().next(); peer = agent.streamDiscoveredPeers().iterator().next();

@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput; import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import org.junit.Test; import org.junit.Test;
@ -24,10 +25,11 @@ import org.junit.Test;
public class FindNeighborsPacketDataTest { public class FindNeighborsPacketDataTest {
@Test @Test
public void serializeDeserialize() { public void serializeDeserialize() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final BytesValue target = Peer.randomId(); final BytesValue target = Peer.randomId();
final FindNeighborsPacketData packet = FindNeighborsPacketData.create(target); final FindNeighborsPacketData packet =
FindNeighborsPacketData.create(target, TestClock.fixed());
final BytesValue serialized = RLP.encode(packet::writeTo); final BytesValue serialized = RLP.encode(packet::writeTo);
final FindNeighborsPacketData deserialized = final FindNeighborsPacketData deserialized =
FindNeighborsPacketData.readFrom(RLP.input(serialized)); FindNeighborsPacketData.readFrom(RLP.input(serialized));
@ -38,7 +40,7 @@ public class FindNeighborsPacketDataTest {
@Test @Test
public void readFrom() { public void readFrom() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final BytesValue target = Peer.randomId(); final BytesValue target = Peer.randomId();
BytesValueRLPOutput out = new BytesValueRLPOutput(); BytesValueRLPOutput out = new BytesValueRLPOutput();
@ -56,7 +58,7 @@ public class FindNeighborsPacketDataTest {
@Test @Test
public void readFrom_withExtraFields() { public void readFrom_withExtraFields() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final BytesValue target = Peer.randomId(); final BytesValue target = Peer.randomId();
BytesValueRLPOutput out = new BytesValueRLPOutput(); BytesValueRLPOutput out = new BytesValueRLPOutput();

@ -18,6 +18,7 @@ import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer; import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.Bytes32; import tech.pegasys.pantheon.util.bytes.Bytes32;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -30,7 +31,8 @@ public class MockPacketDataFactory {
final DiscoveryPeer from, final DiscoveryPeer... neighbors) { final DiscoveryPeer from, final DiscoveryPeer... neighbors) {
final Packet packet = mock(Packet.class); final Packet packet = mock(Packet.class);
final NeighborsPacketData packetData = NeighborsPacketData.create(Arrays.asList(neighbors)); final NeighborsPacketData packetData =
NeighborsPacketData.create(Arrays.asList(neighbors), TestClock.fixed());
when(packet.getPacketData(any())).thenReturn(Optional.of(packetData)); when(packet.getPacketData(any())).thenReturn(Optional.of(packetData));
final BytesValue id = from.getId(); final BytesValue id = from.getId();
@ -44,7 +46,8 @@ public class MockPacketDataFactory {
public static Packet mockPongPacket(final DiscoveryPeer from, final BytesValue pingHash) { public static Packet mockPongPacket(final DiscoveryPeer from, final BytesValue pingHash) {
final Packet packet = mock(Packet.class); final Packet packet = mock(Packet.class);
final PongPacketData pongPacketData = PongPacketData.create(from.getEndpoint(), pingHash); final PongPacketData pongPacketData =
PongPacketData.create(from.getEndpoint(), pingHash, TestClock.fixed());
when(packet.getPacketData(any())).thenReturn(Optional.of(pongPacketData)); when(packet.getPacketData(any())).thenReturn(Optional.of(pongPacketData));
final BytesValue id = from.getId(); final BytesValue id = from.getId();
when(packet.getNodeId()).thenReturn(id); when(packet.getNodeId()).thenReturn(id);
@ -60,7 +63,8 @@ public class MockPacketDataFactory {
BytesValue.fromHexString( BytesValue.fromHexString(
"0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40"); "0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40");
final FindNeighborsPacketData packetData = FindNeighborsPacketData.create(target); final FindNeighborsPacketData packetData =
FindNeighborsPacketData.create(target, TestClock.fixed());
when(packet.getPacketData(any())).thenReturn(Optional.of(packetData)); when(packet.getPacketData(any())).thenReturn(Optional.of(packetData));
final BytesValue id = from.getId(); final BytesValue id = from.getId();
when(packet.getNodeId()).thenReturn(id); when(packet.getNodeId()).thenReturn(id);

@ -22,6 +22,7 @@ import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.time.Clock;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Arrays; import java.util.Arrays;
import java.util.Deque; import java.util.Deque;
@ -39,8 +40,9 @@ public class MockPeerDiscoveryAgent extends PeerDiscoveryAgent {
final KeyPair keyPair, final KeyPair keyPair,
final DiscoveryConfiguration config, final DiscoveryConfiguration config,
final PeerPermissions peerPermissions, final PeerPermissions peerPermissions,
final Map<BytesValue, MockPeerDiscoveryAgent> agentNetwork) { final Map<BytesValue, MockPeerDiscoveryAgent> agentNetwork,
super(keyPair, config, peerPermissions, Optional.empty(), new NoOpMetricsSystem()); final Clock clock) {
super(keyPair, config, peerPermissions, Optional.empty(), new NoOpMetricsSystem(), clock);
this.agentNetwork = agentNetwork; this.agentNetwork = agentNetwork;
} }

@ -18,6 +18,7 @@ import static tech.pegasys.pantheon.ethereum.p2p.peers.PeerTestHelper.enode;
import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer; import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput; import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Arrays; import java.util.Arrays;
@ -29,11 +30,11 @@ public class NeighborsPacketDataTest {
@Test @Test
public void serializeDeserialize() { public void serializeDeserialize() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final List<DiscoveryPeer> peers = final List<DiscoveryPeer> peers =
Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode())); Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode()));
final NeighborsPacketData packet = NeighborsPacketData.create(peers); final NeighborsPacketData packet = NeighborsPacketData.create(peers, TestClock.fixed());
final BytesValue serialized = RLP.encode(packet::writeTo); final BytesValue serialized = RLP.encode(packet::writeTo);
final NeighborsPacketData deserialized = NeighborsPacketData.readFrom(RLP.input(serialized)); final NeighborsPacketData deserialized = NeighborsPacketData.readFrom(RLP.input(serialized));
@ -43,7 +44,7 @@ public class NeighborsPacketDataTest {
@Test @Test
public void readFrom() { public void readFrom() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final List<DiscoveryPeer> peers = final List<DiscoveryPeer> peers =
Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode())); Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode()));
@ -61,7 +62,7 @@ public class NeighborsPacketDataTest {
@Test @Test
public void readFrom_extraFields() { public void readFrom_extraFields() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final List<DiscoveryPeer> peers = final List<DiscoveryPeer> peers =
Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode())); Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode()));

@ -41,6 +41,7 @@ import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions.Action; import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions.Action;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissionsBlacklist; import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissionsBlacklist;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.Bytes32; import tech.pegasys.pantheon.util.bytes.Bytes32;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -113,7 +114,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet, so that we can control the hash, // Mock the creation of the PING packet, so that we can control the hash,
// which gets validated when receiving the PONG. // which gets validated when receiving the PONG.
final PingPacketData mockPing = final PingPacketData mockPing =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0)); final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0));
mockPingPacketCreation(mockPacket); mockPingPacketCreation(mockPacket);
@ -183,7 +185,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet, so that we can control the hash, // Mock the creation of the PING packet, so that we can control the hash,
// which gets validated when receiving the PONG. // which gets validated when receiving the PONG.
final PingPacketData mockPing = final PingPacketData mockPing =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0)); final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0));
mockPingPacketCreation(mockPacket); mockPingPacketCreation(mockPacket);
@ -201,7 +204,7 @@ public class PeerDiscoveryControllerTest {
// Simulate a PONG message from peer 0. // Simulate a PONG message from peer 0.
final PongPacketData packetData = final PongPacketData packetData =
PongPacketData.create(localPeer.getEndpoint(), mockPacket.getHash()); PongPacketData.create(localPeer.getEndpoint(), mockPacket.getHash(), TestClock.fixed());
final Packet packet = Packet.create(PacketType.PONG, packetData, keyPairs.get(0)); final Packet packet = Packet.create(PacketType.PONG, packetData, keyPairs.get(0));
controller.onMessage(packet, peers.get(0)); controller.onMessage(packet, peers.get(0));
@ -237,7 +240,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet, so that we can control the hash, // Mock the creation of the PING packet, so that we can control the hash,
// which gets validated when receiving the PONG. // which gets validated when receiving the PONG.
final PingPacketData mockPing = final PingPacketData mockPing =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0)); final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0));
mockPingPacketCreation(mockPacket); mockPingPacketCreation(mockPacket);
@ -272,7 +276,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet, so that we can control the hash, which gets validated // Mock the creation of the PING packet, so that we can control the hash, which gets validated
// when receiving the PONG. // when receiving the PONG.
final PingPacketData mockPing = final PingPacketData mockPing =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0)); final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0));
mockPingPacketCreation(mockPacket); mockPingPacketCreation(mockPacket);
@ -287,7 +292,7 @@ public class PeerDiscoveryControllerTest {
// Simulate PONG messages from all peers // Simulate PONG messages from all peers
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
final PongPacketData packetData = final PongPacketData packetData =
PongPacketData.create(localPeer.getEndpoint(), mockPacket.getHash()); PongPacketData.create(localPeer.getEndpoint(), mockPacket.getHash(), TestClock.fixed());
final Packet packet0 = Packet.create(PacketType.PONG, packetData, keyPairs.get(i)); final Packet packet0 = Packet.create(PacketType.PONG, packetData, keyPairs.get(i));
controller.onMessage(packet0, peers.get(i)); controller.onMessage(packet0, peers.get(i));
} }
@ -332,7 +337,8 @@ public class PeerDiscoveryControllerTest {
// when // when
// processing the PONG. // processing the PONG.
final PingPacketData mockPing = final PingPacketData mockPing =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0)); final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0));
mockPingPacketCreation(mockPacket); mockPingPacketCreation(mockPacket);
@ -346,7 +352,8 @@ public class PeerDiscoveryControllerTest {
// Send a PONG packet from peer 1, with an incorrect hash. // Send a PONG packet from peer 1, with an incorrect hash.
final PongPacketData packetData = final PongPacketData packetData =
PongPacketData.create(localPeer.getEndpoint(), BytesValue.fromHexString("1212")); PongPacketData.create(
localPeer.getEndpoint(), BytesValue.fromHexString("1212"), TestClock.fixed());
final Packet packet = Packet.create(PacketType.PONG, packetData, keyPairs.get(1)); final Packet packet = Packet.create(PacketType.PONG, packetData, keyPairs.get(1));
controller.onMessage(packet, peers.get(1)); controller.onMessage(packet, peers.get(1));
@ -381,7 +388,8 @@ public class PeerDiscoveryControllerTest {
// when // when
// processing the PONG. // processing the PONG.
final PingPacketData mockPing = final PingPacketData mockPing =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0)); final Packet mockPacket = Packet.create(PacketType.PING, mockPing, keyPairs.get(0));
mockPingPacketCreation(mockPacket); mockPingPacketCreation(mockPacket);
controller.setRetryDelayFunction((prev) -> 999999999L); controller.setRetryDelayFunction((prev) -> 999999999L);
@ -423,7 +431,8 @@ public class PeerDiscoveryControllerTest {
private void respondWithPong( private void respondWithPong(
final DiscoveryPeer discoveryPeer, final KeyPair keyPair, final BytesValue hash) { final DiscoveryPeer discoveryPeer, final KeyPair keyPair, final BytesValue hash) {
final PongPacketData packetData0 = PongPacketData.create(localPeer.getEndpoint(), hash); final PongPacketData packetData0 =
PongPacketData.create(localPeer.getEndpoint(), hash, TestClock.fixed());
final Packet pongPacket0 = Packet.create(PacketType.PONG, packetData0, keyPair); final Packet pongPacket0 = Packet.create(PacketType.PONG, packetData0, keyPair);
controller.onMessage(pongPacket0, discoveryPeer); controller.onMessage(pongPacket0, discoveryPeer);
} }
@ -445,7 +454,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet, so that we can control the hash, which gets validated // Mock the creation of the PING packet, so that we can control the hash, which gets validated
// when processing the PONG. // when processing the PONG.
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPingPacketCreation(pingPacket); mockPingPacketCreation(pingPacket);
@ -471,7 +481,7 @@ public class PeerDiscoveryControllerTest {
.hasSize(1); .hasSize(1);
final PongPacketData pongPacketData = final PongPacketData pongPacketData =
PongPacketData.create(localPeer.getEndpoint(), pingPacket.getHash()); PongPacketData.create(localPeer.getEndpoint(), pingPacket.getHash(), TestClock.fixed());
final Packet pongPacket = Packet.create(PacketType.PONG, pongPacketData, keyPairs.get(1)); final Packet pongPacket = Packet.create(PacketType.PONG, pongPacketData, keyPairs.get(1));
controller.onMessage(pongPacket, peers.get(1)); controller.onMessage(pongPacket, peers.get(1));
@ -481,7 +491,7 @@ public class PeerDiscoveryControllerTest {
// Simulate a NEIGHBORS message from peer[0] listing peer[2]. // Simulate a NEIGHBORS message from peer[0] listing peer[2].
final NeighborsPacketData neighbors0 = final NeighborsPacketData neighbors0 =
NeighborsPacketData.create(Collections.singletonList(peers.get(2))); NeighborsPacketData.create(Collections.singletonList(peers.get(2)), TestClock.fixed());
final Packet neighborsPacket0 = final Packet neighborsPacket0 =
Packet.create(PacketType.NEIGHBORS, neighbors0, keyPairs.get(0)); Packet.create(PacketType.NEIGHBORS, neighbors0, keyPairs.get(0));
controller.onMessage(neighborsPacket0, peers.get(0)); controller.onMessage(neighborsPacket0, peers.get(0));
@ -495,7 +505,7 @@ public class PeerDiscoveryControllerTest {
// Simulate bonding and neighbors packet from the second bootstrap peer, with peer[2] reported // Simulate bonding and neighbors packet from the second bootstrap peer, with peer[2] reported
// in the peer list. // in the peer list.
final NeighborsPacketData neighbors1 = final NeighborsPacketData neighbors1 =
NeighborsPacketData.create(Collections.singletonList(peers.get(2))); NeighborsPacketData.create(Collections.singletonList(peers.get(2)), TestClock.fixed());
final Packet neighborsPacket1 = final Packet neighborsPacket1 =
Packet.create(PacketType.NEIGHBORS, neighbors1, keyPairs.get(1)); Packet.create(PacketType.NEIGHBORS, neighbors1, keyPairs.get(1));
controller.onMessage(neighborsPacket1, peers.get(1)); controller.onMessage(neighborsPacket1, peers.get(1));
@ -505,7 +515,7 @@ public class PeerDiscoveryControllerTest {
// Send a PONG packet from peer[2], to transition it to the BONDED state. // Send a PONG packet from peer[2], to transition it to the BONDED state.
final PongPacketData packetData2 = final PongPacketData packetData2 =
PongPacketData.create(localPeer.getEndpoint(), pingPacket.getHash()); PongPacketData.create(localPeer.getEndpoint(), pingPacket.getHash(), TestClock.fixed());
final Packet pongPacket2 = Packet.create(PacketType.PONG, packetData2, keyPairs.get(2)); final Packet pongPacket2 = Packet.create(PacketType.PONG, packetData2, keyPairs.get(2));
controller.onMessage(pongPacket2, peers.get(2)); controller.onMessage(pongPacket2, peers.get(2));
@ -605,7 +615,8 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer // Setup ping to be sent to discoPeer
List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
PingPacketData pingPacketData = PingPacketData.create(localEndpoint, discoPeer.getEndpoint()); PingPacketData pingPacketData =
PingPacketData.create(localEndpoint, discoPeer.getEndpoint(), TestClock.fixed());
final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing); mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -622,13 +633,15 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to otherPeer after neighbors packet is received // Setup ping to be sent to otherPeer after neighbors packet is received
keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
pingPacketData = PingPacketData.create(localEndpoint, otherPeer.getEndpoint()); pingPacketData =
PingPacketData.create(localEndpoint, otherPeer.getEndpoint(), TestClock.fixed());
final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, otherPeer, pingPacket); mockPacketCreation(PacketType.PING, otherPeer, pingPacket);
// Setup ping to be sent to otherPeer2 after neighbors packet is received // Setup ping to be sent to otherPeer2 after neighbors packet is received
keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
pingPacketData = PingPacketData.create(localEndpoint, otherPeer2.getEndpoint()); pingPacketData =
PingPacketData.create(localEndpoint, otherPeer2.getEndpoint(), TestClock.fixed());
final Packet pingPacket2 = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket2 = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, otherPeer2, pingPacket2); mockPacketCreation(PacketType.PING, otherPeer2, pingPacket2);
@ -683,7 +696,8 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer // Setup ping to be sent to discoPeer
List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
PingPacketData pingPacketData = PingPacketData.create(localEndpoint, discoPeer.getEndpoint()); PingPacketData pingPacketData =
PingPacketData.create(localEndpoint, discoPeer.getEndpoint(), TestClock.fixed());
final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing); mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -699,13 +713,15 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to otherPeer after neighbors packet is received // Setup ping to be sent to otherPeer after neighbors packet is received
keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
pingPacketData = PingPacketData.create(localEndpoint, otherPeer.getEndpoint()); pingPacketData =
PingPacketData.create(localEndpoint, otherPeer.getEndpoint(), TestClock.fixed());
final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, otherPeer, pingPacket); mockPacketCreation(PacketType.PING, otherPeer, pingPacket);
// Setup ping to be sent to otherPeer2 after neighbors packet is received // Setup ping to be sent to otherPeer2 after neighbors packet is received
keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
pingPacketData = PingPacketData.create(localEndpoint, otherPeer2.getEndpoint()); pingPacketData =
PingPacketData.create(localEndpoint, otherPeer2.getEndpoint(), TestClock.fixed());
final Packet pingPacket2 = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket2 = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, otherPeer2, pingPacket2); mockPacketCreation(PacketType.PING, otherPeer2, pingPacket2);
@ -738,7 +754,7 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer // Setup ping to be sent to discoPeer
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(localEndpoint, discoPeer.getEndpoint()); PingPacketData.create(localEndpoint, discoPeer.getEndpoint(), TestClock.fixed());
final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing); mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -778,7 +794,7 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer // Setup ping to be sent to discoPeer
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(localEndpoint, discoPeer.getEndpoint()); PingPacketData.create(localEndpoint, discoPeer.getEndpoint(), TestClock.fixed());
final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing); mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -819,7 +835,7 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer // Setup ping to be sent to discoPeer
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(localEndpoint, discoPeer.getEndpoint()); PingPacketData.create(localEndpoint, discoPeer.getEndpoint(), TestClock.fixed());
final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet discoPeerPing = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing); mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -848,7 +864,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet to control hash for PONG. // Mock the creation of the PING packet to control hash for PONG.
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
final OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class); final OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class);
@ -887,7 +904,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of PING packets to control hash PONG packets. // Mock the creation of PING packets to control hash PONG packets.
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
mockPingPacketCreation(pingPacket); mockPingPacketCreation(pingPacket);
@ -946,7 +964,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet to control hash for PONG. // Mock the creation of the PING packet to control hash for PONG.
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1); final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(localPeer.getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
localPeer.getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0)); final Packet pingPacket = Packet.create(PacketType.PING, pingPacketData, keyPairs.get(0));
final OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class); final OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class);
@ -1177,7 +1196,7 @@ public class PeerDiscoveryControllerTest {
final Packet packet = mock(Packet.class); final Packet packet = mock(Packet.class);
final PingPacketData pingPacketData = final PingPacketData pingPacketData =
PingPacketData.create(from.getEndpoint(), to.getEndpoint()); PingPacketData.create(from.getEndpoint(), to.getEndpoint(), TestClock.fixed());
when(packet.getPacketData(any())).thenReturn(Optional.of(pingPacketData)); when(packet.getPacketData(any())).thenReturn(Optional.of(pingPacketData));
final BytesValue id = from.getId(); final BytesValue id = from.getId();
when(packet.getNodeId()).thenReturn(id); when(packet.getNodeId()).thenReturn(id);
@ -1309,6 +1328,7 @@ public class PeerDiscoveryControllerTest {
.peerPermissions(peerPermissions) .peerPermissions(peerPermissions)
.peerBondedObservers(peerBondedObservers) .peerBondedObservers(peerBondedObservers)
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.build()); .build());
} }
} }

@ -25,6 +25,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer;
import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryStatus; import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryStatus;
import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryTestHelper; import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryTestHelper;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -62,12 +63,14 @@ public class PeerDiscoveryTableRefreshTest {
.tableRefreshIntervalMs(0) .tableRefreshIntervalMs(0)
.peerBondedObservers(Subscribers.create()) .peerBondedObservers(Subscribers.create())
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.build()); .build());
controller.start(); controller.start();
// Send a PING, so as to add a Peer in the controller. // Send a PING, so as to add a Peer in the controller.
final PingPacketData ping = final PingPacketData ping =
PingPacketData.create(peers.get(1).getEndpoint(), peers.get(0).getEndpoint()); PingPacketData.create(
peers.get(1).getEndpoint(), peers.get(0).getEndpoint(), TestClock.fixed());
final Packet pingPacket = Packet.create(PacketType.PING, ping, keypairs.get(1)); final Packet pingPacket = Packet.create(PacketType.PING, ping, keypairs.get(1));
controller.onMessage(pingPacket, peers.get(1)); controller.onMessage(pingPacket, peers.get(1));
@ -76,7 +79,7 @@ public class PeerDiscoveryTableRefreshTest {
// Simulate a PONG message from peer 0. // Simulate a PONG message from peer 0.
final PongPacketData pongPacketData = final PongPacketData pongPacketData =
PongPacketData.create(localPeer.getEndpoint(), pingPacket.getHash()); PongPacketData.create(localPeer.getEndpoint(), pingPacket.getHash(), TestClock.fixed());
final Packet pongPacket = Packet.create(PacketType.PONG, pongPacketData, keypairs.get(0)); final Packet pongPacket = Packet.create(PacketType.PONG, pongPacketData, keypairs.get(0));
final ArgumentCaptor<Packet> captor = ArgumentCaptor.forClass(Packet.class); final ArgumentCaptor<Packet> captor = ArgumentCaptor.forClass(Packet.class);

@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.p2p.discovery.Endpoint; import tech.pegasys.pantheon.ethereum.p2p.discovery.Endpoint;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput; import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.OptionalInt; import java.util.OptionalInt;
@ -27,11 +28,11 @@ public class PingPacketDataTest {
@Test @Test
public void serializeDeserialize() { public void serializeDeserialize() {
final long currentTime = System.currentTimeMillis(); final long currentTime = TestClock.fixed().millis();
final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303)); final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303));
final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty()); final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty());
final PingPacketData packet = PingPacketData.create(from, to); final PingPacketData packet = PingPacketData.create(from, to, TestClock.fixed());
final BytesValue serialized = RLP.encode(packet::writeTo); final BytesValue serialized = RLP.encode(packet::writeTo);
final PingPacketData deserialized = PingPacketData.readFrom(RLP.input(serialized)); final PingPacketData deserialized = PingPacketData.readFrom(RLP.input(serialized));
@ -45,7 +46,7 @@ public class PingPacketDataTest {
final int version = 4; final int version = 4;
final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303)); final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303));
final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty()); final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty());
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final BytesValueRLPOutput out = new BytesValueRLPOutput(); final BytesValueRLPOutput out = new BytesValueRLPOutput();
out.startList(); out.startList();
@ -68,7 +69,7 @@ public class PingPacketDataTest {
final int version = 4; final int version = 4;
final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303)); final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303));
final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty()); final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty());
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final BytesValueRLPOutput out = new BytesValueRLPOutput(); final BytesValueRLPOutput out = new BytesValueRLPOutput();
out.startList(); out.startList();
@ -93,7 +94,7 @@ public class PingPacketDataTest {
final int version = 99; final int version = 99;
final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303)); final Endpoint from = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303));
final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty()); final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty());
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final BytesValueRLPOutput out = new BytesValueRLPOutput(); final BytesValueRLPOutput out = new BytesValueRLPOutput();
out.startList(); out.startList();

@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.p2p.discovery.Endpoint; import tech.pegasys.pantheon.ethereum.p2p.discovery.Endpoint;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput; import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.Bytes32; import tech.pegasys.pantheon.util.bytes.Bytes32;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -28,11 +29,11 @@ public class PongPacketDataTest {
@Test @Test
public void serializeDeserialize() { public void serializeDeserialize() {
final long currentTime = System.currentTimeMillis(); final long currentTime = TestClock.fixed().millis();
final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty()); final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty());
final Bytes32 hash = Bytes32.fromHexStringLenient("0x1234"); final Bytes32 hash = Bytes32.fromHexStringLenient("0x1234");
final PongPacketData packet = PongPacketData.create(to, hash); final PongPacketData packet = PongPacketData.create(to, hash, TestClock.fixed());
final BytesValue serialized = RLP.encode(packet::writeTo); final BytesValue serialized = RLP.encode(packet::writeTo);
final PongPacketData deserialized = PongPacketData.readFrom(RLP.input(serialized)); final PongPacketData deserialized = PongPacketData.readFrom(RLP.input(serialized));
@ -43,7 +44,7 @@ public class PongPacketDataTest {
@Test @Test
public void readFrom() { public void readFrom() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty()); final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty());
final Bytes32 hash = Bytes32.fromHexStringLenient("0x1234"); final Bytes32 hash = Bytes32.fromHexStringLenient("0x1234");
@ -63,7 +64,7 @@ public class PongPacketDataTest {
@Test @Test
public void readFrom_withExtraFields() { public void readFrom_withExtraFields() {
final long time = System.currentTimeMillis(); final long time = TestClock.fixed().millis();
final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty()); final Endpoint to = new Endpoint("127.0.0.2", 30303, OptionalInt.empty());
final Bytes32 hash = Bytes32.fromHexStringLenient("0x1234"); final Bytes32 hash = Bytes32.fromHexStringLenient("0x1234");

@ -44,6 +44,7 @@ import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.D
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.nat.upnp.UpnpNatManager; import tech.pegasys.pantheon.nat.upnp.UpnpNatManager;
import tech.pegasys.pantheon.nat.upnp.UpnpNatManager.Protocol; import tech.pegasys.pantheon.nat.upnp.UpnpNatManager.Protocol;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -215,7 +216,7 @@ public final class DefaultP2PNetworkTest {
when(natManager.queryExternalIPAddress()) when(natManager.queryExternalIPAddress())
.thenReturn(CompletableFuture.completedFuture(externalIp)); .thenReturn(CompletableFuture.completedFuture(externalIp));
final P2PNetwork network = builder().natManager(natManager).build(); final P2PNetwork network = builder().natManager(natManager).clock(TestClock.fixed()).build();
network.start(); network.start();
verify(natManager) verify(natManager)
@ -231,7 +232,7 @@ public final class DefaultP2PNetworkTest {
final DefaultP2PNetwork network = network(); final DefaultP2PNetwork network = network();
network.start(); network.start();
final DiscoveryPeer peer = DiscoveryPeer.fromEnode(enode()); final DiscoveryPeer peer = DiscoveryPeer.fromEnode(enode());
final PeerBondedEvent peerBondedEvent = new PeerBondedEvent(peer, System.currentTimeMillis()); final PeerBondedEvent peerBondedEvent = new PeerBondedEvent(peer, TestClock.fixed().millis());
discoverySubscriberCaptor.getValue().onPeerBonded(peerBondedEvent); discoverySubscriberCaptor.getValue().onPeerBonded(peerBondedEvent);
verify(rlpxAgent, times(1)).connect(peer); verify(rlpxAgent, times(1)).connect(peer);
@ -244,7 +245,7 @@ public final class DefaultP2PNetworkTest {
final DiscoveryPeer peer = final DiscoveryPeer peer =
DiscoveryPeer.fromIdAndEndpoint( DiscoveryPeer.fromIdAndEndpoint(
Peer.randomId(), new Endpoint("127.0.0.1", 999, OptionalInt.empty())); Peer.randomId(), new Endpoint("127.0.0.1", 999, OptionalInt.empty()));
final PeerBondedEvent peerBondedEvent = new PeerBondedEvent(peer, System.currentTimeMillis()); final PeerBondedEvent peerBondedEvent = new PeerBondedEvent(peer, TestClock.fixed().millis());
discoverySubscriberCaptor.getValue().onPeerBonded(peerBondedEvent); discoverySubscriberCaptor.getValue().onPeerBonded(peerBondedEvent);
verify(rlpxAgent, times(1)).connect(peer); verify(rlpxAgent, times(1)).connect(peer);
@ -305,7 +306,7 @@ public final class DefaultP2PNetworkTest {
} }
private DefaultP2PNetwork network() { private DefaultP2PNetwork network() {
return (DefaultP2PNetwork) builder().build(); return (DefaultP2PNetwork) builder().clock(TestClock.fixed()).build();
} }
private DefaultP2PNetwork.Builder builder() { private DefaultP2PNetwork.Builder builder() {

@ -25,6 +25,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryServiceExceptio
import tech.pegasys.pantheon.ethereum.p2p.peers.EnodeURL; import tech.pegasys.pantheon.ethereum.p2p.peers.EnodeURL;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.Capability;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
@ -157,6 +158,7 @@ public class NetworkingServiceLifecycleTest {
.keyPair(keyPair) .keyPair(keyPair)
.config(config) .config(config)
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.supportedCapabilities(Arrays.asList(Capability.create("eth", 63))); .supportedCapabilities(Arrays.asList(Capability.create("eth", 63)));
} }
} }

@ -36,6 +36,7 @@ import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.SubProtocol; import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.SubProtocol;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetAddress; import java.net.InetAddress;
@ -326,6 +327,7 @@ public class P2PNetworkTest {
.config(config) .config(config)
.keyPair(KeyPair.generate()) .keyPair(KeyPair.generate())
.metricsSystem(new NoOpMetricsSystem()) .metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.supportedCapabilities(Arrays.asList(Capability.create("eth", 63))); .supportedCapabilities(Arrays.asList(Capability.create("eth", 63)));
} }
} }

@ -49,6 +49,7 @@ import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.D
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.PingMessage; import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.PingMessage;
import tech.pegasys.pantheon.metrics.MetricsSystem; import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Arrays; import java.util.Arrays;
@ -971,6 +972,7 @@ public class RlpxAgentTest {
.peerPrivileges(peerPrivileges) .peerPrivileges(peerPrivileges)
.localNode(localNode) .localNode(localNode)
.metricsSystem(metrics) .metricsSystem(metrics)
.clock(TestClock.fixed())
.connectionInitializer(connectionInitializer) .connectionInitializer(connectionInitializer)
.connectionEvents(peerConnectionEvents) .connectionEvents(peerConnectionEvents)
.build(); .build();

@ -21,6 +21,7 @@ import static tech.pegasys.pantheon.ethereum.p2p.peers.PeerTestHelper.createPeer
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.connections.RlpxConnection.ConnectionNotEstablishedException; import tech.pegasys.pantheon.ethereum.p2p.rlpx.connections.RlpxConnection.ConnectionNotEstablishedException;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -32,7 +33,8 @@ public class RlpxConnectionTest {
public void getPeer_pendingOutboundConnection() { public void getPeer_pendingOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
assertThat(conn.getPeer()).isEqualTo(peer); assertThat(conn.getPeer()).isEqualTo(peer);
} }
@ -41,7 +43,8 @@ public class RlpxConnectionTest {
public void getPeer_establishedOutboundConnection() { public void getPeer_establishedOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
future.complete(peerConnection(peer)); future.complete(peerConnection(peer));
assertThat(conn.getPeer()).isEqualTo(peer); assertThat(conn.getPeer()).isEqualTo(peer);
@ -51,7 +54,8 @@ public class RlpxConnectionTest {
public void getPeer_inboundConnection() { public void getPeer_inboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
assertThat(conn.getPeer()).isEqualTo(peer); assertThat(conn.getPeer()).isEqualTo(peer);
} }
@ -60,7 +64,8 @@ public class RlpxConnectionTest {
public void disconnect_pendingOutboundConnection() { public void disconnect_pendingOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
final DisconnectReason reason = DisconnectReason.REQUESTED; final DisconnectReason reason = DisconnectReason.REQUESTED;
conn.disconnect(reason); conn.disconnect(reason);
@ -79,7 +84,8 @@ public class RlpxConnectionTest {
public void disconnect_activeOutboundConnection() { public void disconnect_activeOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
future.complete(peerConnection); future.complete(peerConnection);
@ -95,7 +101,8 @@ public class RlpxConnectionTest {
public void disconnect_failedOutboundConnection() { public void disconnect_failedOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
future.completeExceptionally(new IllegalStateException("whoops")); future.completeExceptionally(new IllegalStateException("whoops"));
assertThat(conn.isFailedOrDisconnected()).isTrue(); assertThat(conn.isFailedOrDisconnected()).isTrue();
@ -108,7 +115,8 @@ public class RlpxConnectionTest {
public void disconnect_inboundConnection() { public void disconnect_inboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
assertThat(conn.isFailedOrDisconnected()).isFalse(); assertThat(conn.isFailedOrDisconnected()).isFalse();
final DisconnectReason reason = DisconnectReason.REQUESTED; final DisconnectReason reason = DisconnectReason.REQUESTED;
@ -123,7 +131,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_pendingOutboundConnection() { public void getPeerConnection_pendingOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
assertThatThrownBy(conn::getPeerConnection) assertThatThrownBy(conn::getPeerConnection)
.isInstanceOf(ConnectionNotEstablishedException.class); .isInstanceOf(ConnectionNotEstablishedException.class);
@ -133,7 +142,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_activeOutboundConnection() { public void getPeerConnection_activeOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
future.complete(peerConnection); future.complete(peerConnection);
@ -144,7 +154,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_failedOutboundConnection() { public void getPeerConnection_failedOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
future.completeExceptionally(new IllegalStateException("whoops")); future.completeExceptionally(new IllegalStateException("whoops"));
assertThatThrownBy(conn::getPeerConnection) assertThatThrownBy(conn::getPeerConnection)
@ -155,7 +166,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_disconnectedOutboundConnection() { public void getPeerConnection_disconnectedOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
future.complete(peerConnection); future.complete(peerConnection);
conn.disconnect(DisconnectReason.REQUESTED); conn.disconnect(DisconnectReason.REQUESTED);
@ -167,7 +179,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_activeInboundConnection() { public void getPeerConnection_activeInboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
assertThat(conn.getPeerConnection()).isEqualTo(peerConnection); assertThat(conn.getPeerConnection()).isEqualTo(peerConnection);
} }
@ -176,7 +189,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_disconnectedInboundConnection() { public void getPeerConnection_disconnectedInboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
conn.disconnect(DisconnectReason.REQUESTED); conn.disconnect(DisconnectReason.REQUESTED);
assertThat(conn.getPeerConnection()).isEqualTo(peerConnection); assertThat(conn.getPeerConnection()).isEqualTo(peerConnection);
@ -186,7 +200,8 @@ public class RlpxConnectionTest {
public void checkState_pendingOutboundConnection() { public void checkState_pendingOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
assertThat(conn.initiatedRemotely()).isFalse(); assertThat(conn.initiatedRemotely()).isFalse();
assertThat(conn.isActive()).isFalse(); assertThat(conn.isActive()).isFalse();
@ -198,7 +213,8 @@ public class RlpxConnectionTest {
public void checkState_activeOutboundConnection() { public void checkState_activeOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
future.complete(peerConnection); future.complete(peerConnection);
@ -212,7 +228,8 @@ public class RlpxConnectionTest {
public void checkState_failedOutboundConnection() { public void checkState_failedOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
future.completeExceptionally(new IllegalStateException("whoops")); future.completeExceptionally(new IllegalStateException("whoops"));
assertThat(conn.initiatedRemotely()).isFalse(); assertThat(conn.initiatedRemotely()).isFalse();
@ -225,7 +242,8 @@ public class RlpxConnectionTest {
public void checkState_disconnectedOutboundConnection() { public void checkState_disconnectedOutboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final CompletableFuture<PeerConnection> future = new CompletableFuture<>(); final CompletableFuture<PeerConnection> future = new CompletableFuture<>();
final RlpxConnection conn = RlpxConnection.outboundConnection(peer, future); final RlpxConnection conn =
RlpxConnection.outboundConnection(peer, future, TestClock.fixed().millis());
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
future.complete(peerConnection); future.complete(peerConnection);
conn.disconnect(DisconnectReason.UNKNOWN); conn.disconnect(DisconnectReason.UNKNOWN);
@ -240,7 +258,8 @@ public class RlpxConnectionTest {
public void checkState_activeInboundConnection() { public void checkState_activeInboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
assertThat(conn.initiatedRemotely()).isTrue(); assertThat(conn.initiatedRemotely()).isTrue();
assertThat(conn.isActive()).isTrue(); assertThat(conn.isActive()).isTrue();
@ -252,7 +271,8 @@ public class RlpxConnectionTest {
public void checkState_disconnectedInboundConnection() { public void checkState_disconnectedInboundConnection() {
final Peer peer = createPeer(); final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer); final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection); final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
conn.disconnect(DisconnectReason.UNKNOWN); conn.disconnect(DisconnectReason.UNKNOWN);
assertThat(conn.initiatedRemotely()).isTrue(); assertThat(conn.initiatedRemotely()).isTrue();

@ -35,6 +35,7 @@ import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.PantheonMetricCategory; import tech.pegasys.pantheon.metrics.PantheonMetricCategory;
import java.io.IOException; import java.io.IOException;
import java.time.Clock;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import org.junit.Test; import org.junit.Test;
@ -51,7 +52,8 @@ public class NodeSmartContractPermissioningControllerTest {
private NodeSmartContractPermissioningController setupController( private NodeSmartContractPermissioningController setupController(
final String resourceName, final String contractAddressString) throws IOException { final String resourceName, final String contractAddressString) throws IOException {
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(Clock.systemUTC());
final String emptyContractFile = final String emptyContractFile =
Resources.toString(this.getClass().getResource(resourceName), UTF_8); Resources.toString(this.getClass().getResource(resourceName), UTF_8);

@ -39,6 +39,7 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Clock;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import org.junit.Test; import org.junit.Test;
@ -55,7 +56,8 @@ public class TransactionSmartContractPermissioningControllerTest {
private TransactionSmartContractPermissioningController setupController( private TransactionSmartContractPermissioningController setupController(
final String resourceName, final String contractAddressString) throws IOException { final String resourceName, final String contractAddressString) throws IOException {
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create(); final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(Clock.systemUTC());
final String emptyContractFile = final String emptyContractFile =
Resources.toString(this.getClass().getResource(resourceName), UTF_8); Resources.toString(this.getClass().getResource(resourceName), UTF_8);

@ -20,6 +20,8 @@ import tech.pegasys.pantheon.services.PantheonPluginContextImpl;
import tech.pegasys.pantheon.util.BlockExporter; import tech.pegasys.pantheon.util.BlockExporter;
import tech.pegasys.pantheon.util.BlockImporter; import tech.pegasys.pantheon.util.BlockImporter;
import java.time.Clock;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import picocli.CommandLine.RunLast; import picocli.CommandLine.RunLast;
@ -40,6 +42,7 @@ public final class Pantheon {
new RunnerBuilder(), new RunnerBuilder(),
new PantheonController.Builder(), new PantheonController.Builder(),
new PantheonPluginContextImpl(), new PantheonPluginContextImpl(),
Clock.systemUTC(),
System.getenv()); System.getenv());
pantheonCommand.parse( pantheonCommand.parse(

@ -12,6 +12,8 @@
*/ */
package tech.pegasys.pantheon; package tech.pegasys.pantheon;
import static com.google.common.base.Preconditions.checkNotNull;
import tech.pegasys.pantheon.cli.config.EthNetworkConfig; import tech.pegasys.pantheon.cli.config.EthNetworkConfig;
import tech.pegasys.pantheon.controller.PantheonController; import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
@ -85,6 +87,7 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Clock;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -95,7 +98,6 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import graphql.GraphQL; import graphql.GraphQL;
import io.vertx.core.Vertx; import io.vertx.core.Vertx;
@ -124,6 +126,7 @@ public class RunnerBuilder {
private MetricsSystem metricsSystem; private MetricsSystem metricsSystem;
private Optional<PermissioningConfiguration> permissioningConfiguration = Optional.empty(); private Optional<PermissioningConfiguration> permissioningConfiguration = Optional.empty();
private Collection<EnodeURL> staticNodes = Collections.emptyList(); private Collection<EnodeURL> staticNodes = Collections.emptyList();
private Clock clock;
public RunnerBuilder vertx(final Vertx vertx) { public RunnerBuilder vertx(final Vertx vertx) {
this.vertx = vertx; this.vertx = vertx;
@ -234,9 +237,14 @@ public class RunnerBuilder {
return this; return this;
} }
public Runner build() { public RunnerBuilder clock(final Clock clock) {
this.clock = clock;
return this;
}
Preconditions.checkNotNull(pantheonController); public Runner build() {
checkNotNull(pantheonController);
checkNotNull(clock);
final DiscoveryConfiguration discoveryConfiguration; final DiscoveryConfiguration discoveryConfiguration;
if (discovery) { if (discovery) {
@ -313,6 +321,7 @@ public class RunnerBuilder {
.config(networkingConfiguration) .config(networkingConfiguration)
.peerPermissions(peerPermissions) .peerPermissions(peerPermissions)
.metricsSystem(metricsSystem) .metricsSystem(metricsSystem)
.clock(clock)
.supportedCapabilities(caps) .supportedCapabilities(caps)
.natManager(natManager) .natManager(natManager)
.build(); .build();

@ -622,6 +622,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
private Optional<PermissioningConfiguration> permissioningConfiguration; private Optional<PermissioningConfiguration> permissioningConfiguration;
private Collection<EnodeURL> staticNodes; private Collection<EnodeURL> staticNodes;
private PantheonController<?> pantheonController; private PantheonController<?> pantheonController;
private Clock clock;
private final Supplier<MetricsSystem> metricsSystem = private final Supplier<MetricsSystem> metricsSystem =
Suppliers.memoize(() -> PrometheusMetricsSystem.init(metricsConfiguration())); Suppliers.memoize(() -> PrometheusMetricsSystem.init(metricsConfiguration()));
@ -633,6 +634,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
final RunnerBuilder runnerBuilder, final RunnerBuilder runnerBuilder,
final PantheonController.Builder controllerBuilderFactory, final PantheonController.Builder controllerBuilderFactory,
final PantheonPluginContextImpl pantheonPluginContext, final PantheonPluginContextImpl pantheonPluginContext,
final Clock clock,
final Map<String, String> environment) { final Map<String, String> environment) {
this.logger = logger; this.logger = logger;
this.blockImporter = blockImporter; this.blockImporter = blockImporter;
@ -640,6 +642,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
this.runnerBuilder = runnerBuilder; this.runnerBuilder = runnerBuilder;
this.controllerBuilderFactory = controllerBuilderFactory; this.controllerBuilderFactory = controllerBuilderFactory;
this.pantheonPluginContext = pantheonPluginContext; this.pantheonPluginContext = pantheonPluginContext;
this.clock = clock;
this.environment = environment; this.environment = environment;
} }
@ -883,7 +886,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
.nodePrivateKeyFile(nodePrivateKeyFile()) .nodePrivateKeyFile(nodePrivateKeyFile())
.metricsSystem(metricsSystem.get()) .metricsSystem(metricsSystem.get())
.privacyParameters(privacyParameters()) .privacyParameters(privacyParameters())
.clock(Clock.systemUTC()) .clock(clock)
.isRevertReasonEnabled(isRevertReasonEnabled) .isRevertReasonEnabled(isRevertReasonEnabled)
.build(); .build();
} catch (final InvalidConfigurationException e) { } catch (final InvalidConfigurationException e) {
@ -1199,6 +1202,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
.metricsSystem(metricsSystem) .metricsSystem(metricsSystem)
.metricsConfiguration(metricsConfiguration) .metricsConfiguration(metricsConfiguration)
.staticNodes(staticNodes) .staticNodes(staticNodes)
.clock(clock)
.build(); .build();
addShutdownHook(runner); addShutdownHook(runner);

@ -121,7 +121,11 @@ public class CliquePantheonControllerBuilder extends PantheonControllerBuilder<C
@Override @Override
protected ProtocolSchedule<CliqueContext> createProtocolSchedule() { protected ProtocolSchedule<CliqueContext> createProtocolSchedule() {
return CliqueProtocolSchedule.create( return CliqueProtocolSchedule.create(
genesisConfig.getConfigOptions(), nodeKeys, privacyParameters, isRevertReasonEnabled); genesisConfig.getConfigOptions(),
nodeKeys,
privacyParameters,
isRevertReasonEnabled,
clock);
} }
@Override @Override

@ -64,7 +64,7 @@ public class IbftLegacyPantheonControllerBuilder extends PantheonControllerBuild
@Override @Override
protected ProtocolSchedule<IbftContext> createProtocolSchedule() { protected ProtocolSchedule<IbftContext> createProtocolSchedule() {
return IbftProtocolSchedule.create( return IbftProtocolSchedule.create(
genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled); genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled, clock);
} }
@Override @Override

@ -211,7 +211,7 @@ public class IbftPantheonControllerBuilder extends PantheonControllerBuilder<Ibf
@Override @Override
protected ProtocolSchedule<IbftContext> createProtocolSchedule() { protected ProtocolSchedule<IbftContext> createProtocolSchedule() {
return IbftProtocolSchedule.create( return IbftProtocolSchedule.create(
genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled); genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled, clock);
} }
@Override @Override

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

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save