[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 PantheonPluginContextImpl buildPluginContext(final PantheonNode node) {
PantheonPluginContextImpl pantheonPluginContext = new PantheonPluginContextImpl();
private PantheonPluginContextImpl buildPluginContext(
final PantheonNode node, final CommandLine commandLine) {
final PantheonPluginContextImpl pantheonPluginContext = new PantheonPluginContextImpl();
final Path pluginsPath = node.homeDirectory().resolve("plugins");
final File pluginsDirFile = pluginsPath.toFile();
if (!pluginsDirFile.isDirectory()) {
pluginsDirFile.mkdirs();
pluginsDirFile.deleteOnExit();
}
pantheonPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
System.setProperty("pantheon.plugins.dir", pluginsPath.toString());
pantheonPluginContext.registerPlugins(pluginsPath);
return pantheonPluginContext;
@ -85,8 +87,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
final CommandLine commandLine = new CommandLine(CommandSpec.create());
final PantheonPluginContextImpl pantheonPluginContext =
pantheonPluginContextMap.computeIfAbsent(node, n -> buildPluginContext(node));
pantheonPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
pantheonPluginContextMap.computeIfAbsent(node, n -> buildPluginContext(node, commandLine));
commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0]));
@ -126,7 +127,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
final RunnerBuilder runnerBuilder = new RunnerBuilder();
if (node.getPermissioningConfiguration().isPresent()) {
PermissioningConfiguration permissioningConfiguration =
final PermissioningConfiguration permissioningConfiguration =
node.getPermissioningConfiguration().get();
runnerBuilder.permissioningConfiguration(permissioningConfiguration);
@ -151,6 +152,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
.webSocketConfiguration(node.webSocketConfiguration())
.dataDir(node.homeDirectory())
.metricsSystem(noOpMetricsSystem)
.clock(Clock.systemUTC())
.metricsConfiguration(node.metricsConfiguration())
.p2pEnabled(node.isP2pEnabled())
.graphQLConfiguration(GraphQLConfiguration.createDefault())
@ -167,7 +169,7 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner {
@Override
public void stopNode(final PantheonNode node) {
PantheonPluginContextImpl pluginContext = pantheonPluginContextMap.remove(node);
final PantheonPluginContextImpl pluginContext = pantheonPluginContextMap.remove(node);
if (pluginContext != null) {
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.TimestampMoreRecentThanParent;
import java.time.Clock;
public class BlockHeaderValidationRulesetFactory {
/**
@ -38,16 +40,17 @@ public class BlockHeaderValidationRulesetFactory {
*
* @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 clock System clock
* @return the header validator.
*/
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>()
.addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL))
.addRule(new TimestampBoundedByFutureParameter(10))
.addRule(new TimestampBoundedByFutureParameter(10, clock))
.addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks))
.addRule(new ConstantFieldValidationRule<>("MixHash", BlockHeader::getMixHash, Hash.ZERO))
.addRule(

@ -30,6 +30,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder;
import java.math.BigInteger;
import java.time.Clock;
/** Defines the protocol behaviours for a blockchain using Clique. */
public class CliqueProtocolSchedule {
@ -40,7 +41,8 @@ public class CliqueProtocolSchedule {
final GenesisConfigOptions config,
final KeyPair nodeKeys,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isRevertReasonEnabled,
final Clock clock) {
final CliqueConfigOptions cliqueConfig = config.getCliqueConfigOptions();
@ -52,28 +54,37 @@ public class CliqueProtocolSchedule {
DEFAULT_CHAIN_ID,
builder ->
applyCliqueSpecificModifications(
epochManager, cliqueConfig.getBlockPeriodSeconds(), localNodeAddress, builder),
epochManager,
cliqueConfig.getBlockPeriodSeconds(),
localNodeAddress,
builder,
clock),
privacyParameters,
isRevertReasonEnabled)
isRevertReasonEnabled,
clock)
.createProtocolSchedule();
}
public static ProtocolSchedule<CliqueContext> create(
final GenesisConfigOptions config,
final KeyPair nodeKeys,
final boolean isRevertReasonEnabled) {
return create(config, nodeKeys, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final boolean isRevertReasonEnabled,
final Clock clock) {
return create(config, nodeKeys, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
}
private static ProtocolSpecBuilder<CliqueContext> applyCliqueSpecificModifications(
final EpochManager epochManager,
final long secondsBetweenBlocks,
final Address localNodeAddress,
final ProtocolSpecBuilder<Void> specBuilder) {
final ProtocolSpecBuilder<Void> specBuilder,
final Clock clock) {
return specBuilder
.changeConsensusContextType(
difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager),
difficultyCalculator -> cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager),
difficultyCalculator ->
cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager, clock),
difficultyCalculator ->
cliqueBlockHeaderValidator(secondsBetweenBlocks, epochManager, clock),
MainnetBlockBodyValidator::new,
MainnetBlockValidator::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.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.testutil.TestClock;
import org.junit.Test;
@ -41,7 +42,7 @@ public class CliqueProtocolScheduleTest {
final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions();
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> tangerineWhistleSpec = protocolSchedule.getByBlockNumber(2);
@ -57,7 +58,7 @@ public class CliqueProtocolScheduleTest {
public void parametersAlignWithMainnetWithAdjustments() {
final ProtocolSpec<CliqueContext> homestead =
CliqueProtocolSchedule.create(
GenesisConfigFile.DEFAULT.getConfigOptions(), NODE_KEYS, false)
GenesisConfigFile.DEFAULT.getConfigOptions(), NODE_KEYS, false, TestClock.fixed())
.getByBlockNumber(0);
assertThat(homestead.getName()).isEqualTo("Frontier");

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

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

@ -12,6 +12,7 @@
*/
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 org.mockito.Mockito.mock;
import static tech.pegasys.pantheon.ethereum.core.InMemoryStorageProvider.createInMemoryBlockchain;
@ -159,6 +160,8 @@ public class TestContextBuilder {
}
public TestContext build() {
checkNotNull(clock);
final NetworkLayout networkNodes =
NetworkLayout.createNetworkLayout(validatorCount, indexOfFirstLocallyProposedBlock);
@ -263,7 +266,7 @@ public class TestContextBuilder {
genesisConfigOptions.byzantiumBlock(0);
final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create(genesisConfigOptions);
IbftProtocolSchedule.create(genesisConfigOptions, Clock.systemUTC());
/////////////////////////////////////////////////////////////////////////////////////
// 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.util.uint.UInt256;
import java.time.Clock;
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)
*
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param clock System clock
* @return BlockHeaderValidator configured for assessing ibft block headers
*/
public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator(
final long secondsBetweenBlocks) {
final long secondsBetweenBlocks, final Clock clock) {
return new BlockHeaderValidator.Builder<IbftContext>()
.addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL))
.addRule(new TimestampBoundedByFutureParameter(1))
.addRule(new TimestampBoundedByFutureParameter(1, clock))
.addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks))
.addRule(
new ConstantFieldValidationRule<>(

@ -26,6 +26,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder;
import java.math.BigInteger;
import java.time.Clock;
/** Defines the protocol behaviours for a blockchain using IBFT. */
public class IbftProtocolSchedule {
@ -35,34 +36,37 @@ public class IbftProtocolSchedule {
public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isRevertReasonEnabled,
final Clock clock) {
final IbftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions();
final long blockPeriod = ibftConfig.getBlockPeriodSeconds();
return new ProtocolScheduleBuilder<>(
config,
DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(blockPeriod, builder),
builder -> applyIbftChanges(blockPeriod, builder, clock),
privacyParameters,
isRevertReasonEnabled)
isRevertReasonEnabled,
clock)
.createProtocolSchedule();
}
public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
}
public static ProtocolSchedule<IbftContext> create(final GenesisConfigOptions config) {
return create(config, PrivacyParameters.DEFAULT, false);
public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, false, clock);
}
private static ProtocolSpecBuilder<IbftContext> applyIbftChanges(
final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder) {
final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder, final Clock clock) {
return builder
.<IbftContext>changeConsensusContextType(
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
MainnetBlockBodyValidator::new,
MainnetBlockValidator::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.mainnet.BlockHeaderValidator;
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.uint.UInt256;
@ -54,7 +55,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, validators, parentHeader).buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -75,7 +76,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, emptyList(), parentHeader).buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -100,7 +101,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -121,7 +122,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, validators, parentHeader).nonce(3).buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -144,7 +145,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -167,7 +168,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -190,7 +191,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -213,7 +214,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -234,7 +235,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
getPresetHeaderBuilder(2, proposerKeyPair, validators, null).buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -258,7 +259,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -281,7 +282,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
.buildHeader();
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(

@ -75,7 +75,8 @@ public class IbftBlockCreatorTest {
final ProtocolSchedule<IbftContext> protocolSchedule =
IbftProtocolSchedule.create(
GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}")
.getConfigOptions());
.getConfigOptions(),
TestClock.fixed());
final ProtocolContext<IbftContext> protContext =
new ProtocolContext<>(
blockchain,
@ -110,7 +111,7 @@ public class IbftBlockCreatorTest {
final Block block = blockCreator.createBlock(Instant.now().getEpochSecond());
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.
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.util.uint.UInt256;
import java.time.Clock;
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)
*
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param clock System clock
* @return BlockHeaderValidator configured for assessing ibft block headers
*/
public static BlockHeaderValidator<IbftContext> ibftBlockHeaderValidator(
final long secondsBetweenBlocks) {
return createValidator(secondsBetweenBlocks, true);
final long secondsBetweenBlocks, final Clock clock) {
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).
*
* @param secondsBetweenBlocks the minimum number of seconds which must elapse between blocks.
* @param clock System clock
* @return BlockHeaderValidator configured for assessing ibft block headers
*/
public static BlockHeaderValidator<IbftContext> ibftProposedBlockValidator(
final long secondsBetweenBlocks) {
return createValidator(secondsBetweenBlocks, false);
final long secondsBetweenBlocks, final Clock clock) {
return createValidator(secondsBetweenBlocks, false, clock);
}
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>()
.addRule(new AncestryValidationRule())
.addRule(new GasUsageValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(5000, 0x7fffffffffffffffL))
.addRule(new TimestampBoundedByFutureParameter(1))
.addRule(new TimestampBoundedByFutureParameter(1, clock))
.addRule(new TimestampMoreRecentThanParent(secondsBetweenBlocks))
.addRule(
new ConstantFieldValidationRule<>(

@ -27,6 +27,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolScheduleBuilder;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpecBuilder;
import java.math.BigInteger;
import java.time.Clock;
/** Defines the protocol behaviours for a blockchain using IBFT. */
public class IbftProtocolSchedule {
@ -36,30 +37,32 @@ public class IbftProtocolSchedule {
public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isRevertReasonEnabled,
final Clock clock) {
final IbftConfigOptions ibftConfig = config.getIbftLegacyConfigOptions();
final long blockPeriod = ibftConfig.getBlockPeriodSeconds();
return new ProtocolScheduleBuilder<>(
config,
DEFAULT_CHAIN_ID,
builder -> applyIbftChanges(blockPeriod, builder),
builder -> applyIbftChanges(blockPeriod, builder, clock),
privacyParameters,
isRevertReasonEnabled)
isRevertReasonEnabled,
clock)
.createProtocolSchedule();
}
public static ProtocolSchedule<IbftContext> create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
}
private static ProtocolSpecBuilder<IbftContext> applyIbftChanges(
final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder) {
final long secondsBetweenBlocks, final ProtocolSpecBuilder<Void> builder, final Clock clock) {
return builder
.<IbftContext>changeConsensusContextType(
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock),
MainnetBlockBodyValidator::new,
MainnetBlockValidator::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.mainnet.BlockHeaderValidator;
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.uint.UInt256;
@ -67,7 +68,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, parentHeader);
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(
@ -90,7 +91,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest {
final BlockHeader blockHeader = buildBlockHeader(2, proposerKeyPair, validators, null);
final BlockHeaderValidator<IbftContext> validator =
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5);
IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed());
assertThat(
validator.validateHeader(

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

@ -15,7 +15,6 @@ package tech.pegasys.errorpronechecks;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
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 java.util.Map;
@ -23,6 +22,7 @@ import java.util.Map;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.BugPattern;
import com.google.errorprone.BugPattern.LinkType;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.matchers.Description;
@ -34,12 +34,15 @@ import com.sun.source.tree.MethodInvocationTree;
@BugPattern(
name = "BannedMethod",
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 {
private static final ImmutableMap<Matcher<ExpressionTree>, String> BANNED_METHOD_LIST =
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.");
@Override

@ -13,6 +13,7 @@
package tech.pegasys.errorpronechecks;
import java.util.Objects;
import java.time.Clock;
public class BannedMethodNegativeCases {
@ -23,4 +24,9 @@ public class BannedMethodNegativeCases {
public void callsObjectsHashCode() throws Exception {
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.
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
public void emptyPendingTransactionsResultsInEmptyVettingResult() {
final ProtocolSchedule<Void> protocolSchedule =
FixedDifficultyProtocolSchedule.create(GenesisConfigFile.development().getConfigOptions());
FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), TestClock.fixed());
final TransactionProcessor mainnetTransactionProcessor =
protocolSchedule.getByBlockNumber(0).getTransactionProcessor();

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

@ -30,6 +30,7 @@ import tech.pegasys.pantheon.util.uint.UInt256;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Clock;
import com.google.common.io.MoreFiles;
import com.google.common.io.RecursiveDeleteOption;
@ -57,7 +58,10 @@ public class OperationBenchmarkHelper {
new NoOpMetricsSystem());
final ExecutionContextTestFixture executionContext =
ExecutionContextTestFixture.builder().keyValueStorage(keyValueStorage).build();
ExecutionContextTestFixture.builder()
.keyValueStorage(keyValueStorage)
.clock(Clock.systemUTC())
.build();
final MutableBlockchain blockchain = executionContext.getBlockchain();
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.ProtocolScheduleBuilder;
import java.time.Clock;
/** A ProtocolSchedule which behaves similarly to MainNet, but with a much reduced difficulty. */
public class FixedDifficultyProtocolSchedule {
public static ProtocolSchedule<Void> create(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isRevertReasonEnabled,
final Clock clock) {
return new ProtocolScheduleBuilder<>(
config,
builder -> builder.difficultyCalculator(FixedDifficultyCalculators.calculator(config)),
privacyParameters,
isRevertReasonEnabled)
isRevertReasonEnabled,
clock)
.createProtocolSchedule();
}
public static ProtocolSchedule<Void> create(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
return create(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled, clock);
}
public static ProtocolSchedule<Void> create(final GenesisConfigOptions config) {
return create(config, PrivacyParameters.DEFAULT, false);
public static ProtocolSchedule<Void> create(
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.util.bytes.BytesValue;
import java.time.Clock;
public final class MainnetBlockHeaderValidator {
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 BlockHeaderValidator<Void> create(
final DifficultyCalculator<Void> difficultyCalculator) {
return createValidator(difficultyCalculator).build();
final DifficultyCalculator<Void> difficultyCalculator, final Clock clock) {
return createValidator(difficultyCalculator, clock).build();
}
public static BlockHeaderValidator<Void> createDaoValidator(
final DifficultyCalculator<Void> difficultyCalculator) {
return createValidator(difficultyCalculator)
static BlockHeaderValidator<Void> createDaoValidator(
final DifficultyCalculator<Void> difficultyCalculator, final Clock clock) {
return createValidator(difficultyCalculator, clock)
.addRule(
new ConstantFieldValidationRule<>(
"extraData", BlockHeader::getExtraData, DAO_EXTRA_DATA))
@ -65,14 +67,14 @@ public final class MainnetBlockHeaderValidator {
}
private static BlockHeaderValidator.Builder<Void> createValidator(
final DifficultyCalculator<Void> difficultyCalculator) {
final DifficultyCalculator<Void> difficultyCalculator, final Clock clock) {
return new BlockHeaderValidator.Builder<Void>()
.addRule(new CalculatedDifficultyValidationRule<>(difficultyCalculator))
.addRule(new AncestryValidationRule())
.addRule(new GasLimitRangeAndDeltaValidationRule(MIN_GAS_LIMIT, MAX_GAS_LIMIT))
.addRule(new GasUsageValidationRule())
.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 ProofOfWorkValidationRule());
}

@ -19,6 +19,7 @@ import tech.pegasys.pantheon.ethereum.difficulty.fixed.FixedDifficultyCalculator
import tech.pegasys.pantheon.ethereum.difficulty.fixed.FixedDifficultyProtocolSchedule;
import java.math.BigInteger;
import java.time.Clock;
import java.util.function.Function;
/** 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 ProtocolSchedule<Void> create() {
public static ProtocolSchedule<Void> create(final Clock clock) {
return fromConfig(
GenesisConfigFile.mainnet().getConfigOptions(), PrivacyParameters.DEFAULT, false);
GenesisConfigFile.mainnet().getConfigOptions(), PrivacyParameters.DEFAULT, false, clock);
}
/**
@ -38,18 +39,25 @@ public class MainnetProtocolSchedule {
* starting points
* @param privacyParameters the parameters set for private transactions
* @param isRevertReasonEnabled whether storing the revert reason is for failed transactions
* @param clock System clock
* @return A configured mainnet protocol schedule
*/
public static ProtocolSchedule<Void> fromConfig(
final GenesisConfigOptions config,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isRevertReasonEnabled,
final Clock clock) {
if (FixedDifficultyCalculators.isFixedDifficultyInConfig(config)) {
return FixedDifficultyProtocolSchedule.create(
config, privacyParameters, isRevertReasonEnabled);
config, privacyParameters, isRevertReasonEnabled, clock);
}
return new ProtocolScheduleBuilder<>(
config, DEFAULT_CHAIN_ID, Function.identity(), privacyParameters, isRevertReasonEnabled)
return new ProtocolScheduleBuilder<Void>(
config,
DEFAULT_CHAIN_ID,
Function.identity(),
privacyParameters,
isRevertReasonEnabled,
clock)
.createProtocolSchedule();
}
@ -59,11 +67,12 @@ public class MainnetProtocolSchedule {
* @param config {@link GenesisConfigOptions} containing the config options for the milestone
* starting points
* @param isRevertReasonEnabled whether storing the revert reason is for failed transactions
* @param clock System clock
* @return A configured mainnet protocol schedule
*/
public static ProtocolSchedule<Void> fromConfig(
final GenesisConfigOptions config, final boolean isRevertReasonEnabled) {
return fromConfig(config, PrivacyParameters.DEFAULT, isRevertReasonEnabled);
final GenesisConfigOptions config, final boolean isRevertReasonEnabled, final Clock clock) {
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
* starting points
* @param clock System clock
* @return A configured mainnet protocol schedule
*/
public static ProtocolSchedule<Void> fromConfig(final GenesisConfigOptions config) {
return fromConfig(config, PrivacyParameters.DEFAULT, false);
public static ProtocolSchedule<Void> fromConfig(
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.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@ -72,7 +73,9 @@ public abstract class MainnetProtocolSpecs {
private MainnetProtocolSpecs() {}
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 stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return new ProtocolSpecBuilder<Void>()
@ -120,7 +123,8 @@ public abstract class MainnetProtocolSpecs {
Account.DEFAULT_VERSION,
new PrivateTransactionValidator(Optional.empty())))
.difficultyCalculator(MainnetDifficultyCalculators.FRONTIER)
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::create)
.blockHeaderValidatorBuilder(
difficultyCalculator -> MainnetBlockHeaderValidator.create(difficultyCalculator, clock))
.ommerHeaderValidatorBuilder(MainnetBlockHeaderValidator::createOmmerValidator)
.blockBodyValidatorBuilder(MainnetBlockBodyValidator::new)
.transactionReceiptFactory(MainnetProtocolSpecs::frontierTransactionReceiptFactory)
@ -135,9 +139,11 @@ public abstract class MainnetProtocolSpecs {
}
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);
return frontierDefinition(configContractSizeLimit, configStackSizeLimit)
return frontierDefinition(configContractSizeLimit, configStackSizeLimit, clock)
.gasCalculator(HomesteadGasCalculator::new)
.evmBuilder(MainnetEvmRegistries::homestead)
.contractCreationProcessorBuilder(
@ -155,9 +161,13 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder<Void> daoRecoveryInitDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit)
.blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::createDaoValidator)
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final Clock clock) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, clock)
.blockHeaderValidatorBuilder(
difficultyCalculator ->
MainnetBlockHeaderValidator.createDaoValidator(difficultyCalculator, clock))
.blockProcessorBuilder(
(transactionProcessor,
transactionReceiptFactory,
@ -173,15 +183,19 @@ public abstract class MainnetProtocolSpecs {
}
public static ProtocolSpecBuilder<Void> daoRecoveryTransitionDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) {
return daoRecoveryInitDefinition(contractSizeLimit, configStackSizeLimit)
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final Clock clock) {
return daoRecoveryInitDefinition(contractSizeLimit, configStackSizeLimit, clock)
.blockProcessorBuilder(MainnetBlockProcessor::new)
.name("DaoRecoveryTransition");
}
public static ProtocolSpecBuilder<Void> tangerineWhistleDefinition(
final OptionalInt contractSizeLimit, final OptionalInt configStackSizeLimit) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit)
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final Clock clock) {
return homesteadDefinition(contractSizeLimit, configStackSizeLimit, clock)
.gasCalculator(TangerineWhistleGasCalculator::new)
.name("TangerineWhistle");
}
@ -189,12 +203,13 @@ public abstract class MainnetProtocolSpecs {
public static ProtocolSpecBuilder<Void> spuriousDragonDefinition(
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit) {
final OptionalInt configStackSizeLimit,
final Clock clock) {
final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return tangerineWhistleDefinition(OptionalInt.empty(), configStackSizeLimit)
return tangerineWhistleDefinition(OptionalInt.empty(), configStackSizeLimit, clock)
.gasCalculator(SpuriousDragonGasCalculator::new)
.messageCallProcessorBuilder(
(evm, precompileContractRegistry) ->
@ -249,8 +264,9 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
return spuriousDragonDefinition(chainId, contractSizeLimit, configStackSizeLimit)
final boolean enableRevertReason,
final Clock clock) {
return spuriousDragonDefinition(chainId, contractSizeLimit, configStackSizeLimit, clock)
.evmBuilder(MainnetEvmRegistries::byzantium)
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium)
.difficultyCalculator(MainnetDifficultyCalculators.BYZANTIUM)
@ -267,8 +283,10 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
return byzantiumDefinition(chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
final boolean enableRevertReason,
final Clock clock) {
return byzantiumDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, clock)
.difficultyCalculator(MainnetDifficultyCalculators.CONSTANTINOPLE)
.gasCalculator(ConstantinopleGasCalculator::new)
.evmBuilder(MainnetEvmRegistries::constantinople)
@ -280,9 +298,10 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final boolean enableRevertReason,
final Clock clock) {
return constantinopleDefinition(
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason)
chainId, contractSizeLimit, configStackSizeLimit, enableRevertReason, clock)
.gasCalculator(ConstantinopleFixGasCalculator::new)
.name("ConstantinopleFix");
}
@ -291,13 +310,14 @@ public abstract class MainnetProtocolSpecs {
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final boolean enableRevertReason,
final Clock clock) {
checkArgument(chainId.isPresent(), "Istanbul requires the use of chainId");
final int contractSizeLimit =
configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return constantinopleFixDefinition(
chainId, configContractSizeLimit, configStackSizeLimit, enableRevertReason)
chainId, configContractSizeLimit, configStackSizeLimit, enableRevertReason, clock)
.gasCalculator(IstanbulGasCalculator::new)
.evmBuilder(gasCalculator -> MainnetEvmRegistries.istanbul(gasCalculator, chainId.get()))
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::istanbul)

@ -17,6 +17,7 @@ import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionValidator;
import java.math.BigInteger;
import java.time.Clock;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Function;
@ -32,27 +33,37 @@ public class ProtocolScheduleBuilder<C> {
private final Optional<BigInteger> defaultChainId;
private final PrivacyParameters privacyParameters;
private final boolean isRevertReasonEnabled;
private final Clock clock;
public ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final BigInteger defaultChainId,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isRevertReasonEnabled,
final Clock clock) {
this(
config,
Optional.of(defaultChainId),
protocolSpecAdapter,
privacyParameters,
isRevertReasonEnabled);
isRevertReasonEnabled,
clock);
}
public ProtocolScheduleBuilder(
final GenesisConfigOptions config,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
this(config, Optional.empty(), protocolSpecAdapter, privacyParameters, isRevertReasonEnabled);
final boolean isRevertReasonEnabled,
final Clock clock) {
this(
config,
Optional.empty(),
protocolSpecAdapter,
privacyParameters,
isRevertReasonEnabled,
clock);
}
private ProtocolScheduleBuilder(
@ -60,17 +71,18 @@ public class ProtocolScheduleBuilder<C> {
final Optional<BigInteger> defaultChainId,
final Function<ProtocolSpecBuilder<Void>, ProtocolSpecBuilder<C>> protocolSpecAdapter,
final PrivacyParameters privacyParameters,
final boolean isRevertReasonEnabled) {
final boolean isRevertReasonEnabled,
final Clock clock) {
this.config = config;
this.defaultChainId = defaultChainId;
this.protocolSpecAdapter = protocolSpecAdapter;
this.privacyParameters = privacyParameters;
this.isRevertReasonEnabled = isRevertReasonEnabled;
this.clock = clock;
}
public ProtocolSchedule<C> createProtocolSchedule() {
final Optional<BigInteger> chainId =
config.getChainId().map(Optional::of).orElse(defaultChainId);
final Optional<BigInteger> chainId = config.getChainId().or(() -> defaultChainId);
final MutableProtocolSchedule<C> protocolSchedule = new MutableProtocolSchedule<>(chainId);
validateForkOrdering();
@ -79,12 +91,12 @@ public class ProtocolScheduleBuilder<C> {
protocolSchedule,
OptionalLong.of(0),
MainnetProtocolSpecs.frontierDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec(
protocolSchedule,
config.getHomesteadBlockNumber(),
MainnetProtocolSpecs.homesteadDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), clock));
config
.getDaoForkBlock()
@ -96,12 +108,12 @@ public class ProtocolScheduleBuilder<C> {
protocolSchedule,
OptionalLong.of(daoBlockNumber),
MainnetProtocolSpecs.daoRecoveryInitDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec(
protocolSchedule,
OptionalLong.of(daoBlockNumber + 1),
MainnetProtocolSpecs.daoRecoveryTransitionDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), clock));
// Return to the previous protocol spec after the dao fork has completed.
protocolSchedule.putMilestone(daoBlockNumber + 10, originalProtocolSpec);
@ -111,12 +123,12 @@ public class ProtocolScheduleBuilder<C> {
protocolSchedule,
config.getTangerineWhistleBlockNumber(),
MainnetProtocolSpecs.tangerineWhistleDefinition(
config.getContractSizeLimit(), config.getEvmStackSize()));
config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec(
protocolSchedule,
config.getSpuriousDragonBlockNumber(),
MainnetProtocolSpecs.spuriousDragonDefinition(
chainId, config.getContractSizeLimit(), config.getEvmStackSize()));
chainId, config.getContractSizeLimit(), config.getEvmStackSize(), clock));
addProtocolSpec(
protocolSchedule,
config.getByzantiumBlockNumber(),
@ -124,7 +136,8 @@ public class ProtocolScheduleBuilder<C> {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
isRevertReasonEnabled,
clock));
addProtocolSpec(
protocolSchedule,
config.getConstantinopleBlockNumber(),
@ -132,7 +145,8 @@ public class ProtocolScheduleBuilder<C> {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
isRevertReasonEnabled,
clock));
addProtocolSpec(
protocolSchedule,
config.getConstantinopleFixBlockNumber(),
@ -140,7 +154,8 @@ public class ProtocolScheduleBuilder<C> {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
isRevertReasonEnabled,
clock));
addProtocolSpec(
protocolSchedule,
config.getIstanbulBlockNumber(),
@ -148,7 +163,8 @@ public class ProtocolScheduleBuilder<C> {
chainId,
config.getContractSizeLimit(),
config.getEvmStackSize(),
isRevertReasonEnabled));
isRevertReasonEnabled,
clock));
LOG.info("Protocol schedule created with milestones: {}", protocolSchedule.listMilestones());
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.mainnet.DetachedBlockHeaderValidationRule;
import java.util.concurrent.TimeUnit;
import java.time.Clock;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -28,9 +28,12 @@ public class TimestampBoundedByFutureParameter implements DetachedBlockHeaderVal
private final Logger LOG = LogManager.getLogger();
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.clock = clock;
}
@Override
@ -43,9 +46,7 @@ public class TimestampBoundedByFutureParameter implements DetachedBlockHeaderVal
}
private boolean validateHeaderNotAheadOfCurrentSystemTime(final long timestamp) {
final long timestampMargin =
TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
+ acceptableClockDriftSeconds;
final long timestampMargin = clock.instant().getEpochSecond() + acceptableClockDriftSeconds;
if (Long.compareUnsigned(timestamp, timestampMargin) > 0) {
LOG.trace(
"Invalid block header: timestamp {} is greater than the timestamp margin {}",

@ -12,6 +12,8 @@
*/
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.StubGenesisConfigOptions;
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.services.kvstore.InMemoryKeyValueStorage;
import tech.pegasys.pantheon.services.kvstore.KeyValueStorage;
import tech.pegasys.pantheon.testutil.TestClock;
import java.math.BigInteger;
import java.time.Clock;
import java.util.function.Function;
public class ExecutionContextTestFixture {
@ -60,7 +64,7 @@ public class ExecutionContextTestFixture {
}
public static ExecutionContextTestFixture create() {
return new Builder().build();
return new Builder().clock(TestClock.fixed()).build();
}
public static Builder builder() {
@ -95,6 +99,7 @@ public class ExecutionContextTestFixture {
private KeyValueStorage keyValueStorage;
private ProtocolSchedule<Void> protocolSchedule;
private Clock clock;
public Builder keyValueStorage(final KeyValueStorage keyValueStorage) {
this.keyValueStorage = keyValueStorage;
@ -106,7 +111,14 @@ public class ExecutionContextTestFixture {
return this;
}
public Builder clock(final Clock clock) {
this.clock = clock;
return this;
}
public ExecutionContextTestFixture build() {
checkNotNull(clock);
if (protocolSchedule == null) {
protocolSchedule =
new ProtocolScheduleBuilder<>(
@ -114,7 +126,8 @@ public class ExecutionContextTestFixture {
BigInteger.valueOf(42),
Function.identity(),
new PrivacyParameters(),
false)
false,
clock)
.createProtocolSchedule();
}
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.OperationTracer;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger;
@ -35,7 +36,11 @@ public class TestCodeExecutor {
private static final Address SENDER_ADDRESS = AddressHelpers.ofValue(244259721);
public TestCodeExecutor(final ProtocolSchedule<Void> protocolSchedule) {
fixture = ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build();
fixture =
ExecutionContextTestFixture.builder()
.protocolSchedule(protocolSchedule)
.clock(TestClock.fixed())
.build();
}
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.worldstate.DefaultMutableWorldState;
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.uint.UInt256;
import java.time.Clock;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import org.bouncycastle.util.encoders.Hex;
@ -33,6 +36,8 @@ import org.junit.Test;
public final class GenesisStateTest {
final Clock testClock = new TestClock();
/** Known RLP encoded bytes of the Olympic Genesis Block. */
private static final String OLYMPIC_RLP =
"f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0";
@ -49,7 +54,7 @@ public final class GenesisStateTest {
final GenesisState genesisState =
GenesisState.fromJson(
Resources.toString(GenesisStateTest.class.getResource("genesis1.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create());
MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getStateRoot())
.isEqualTo(
@ -78,7 +83,7 @@ public final class GenesisStateTest {
final GenesisState genesisState =
GenesisState.fromJson(
Resources.toString(GenesisStateTest.class.getResource("genesis2.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create());
MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getStateRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH);
assertThat(header.getTransactionsRoot()).isEqualTo(Hash.EMPTY_TRIE_HASH);
@ -93,7 +98,7 @@ public final class GenesisStateTest {
final GenesisState genesisState =
GenesisState.fromJson(
Resources.toString(GenesisStateTest.class.getResource(sourceFile), Charsets.UTF_8),
MainnetProtocolSchedule.create());
MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getHash()).isEqualTo(Hash.fromHexString(blockHash));
@ -132,7 +137,7 @@ public final class GenesisStateTest {
GenesisState.fromJson(
Resources.toString(
GenesisStateTest.class.getResource("genesisNonce.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create());
MainnetProtocolSchedule.create(testClock));
final BlockHeader header = genesisState.getBlock().getHeader();
assertThat(header.getHash())
.isEqualTo(
@ -146,7 +151,7 @@ public final class GenesisStateTest {
GenesisState.fromJson(
Resources.toString(
GenesisStateTest.class.getResource("genesis-olympic.json"), Charsets.UTF_8),
MainnetProtocolSchedule.create());
MainnetProtocolSchedule.create(testClock));
final BytesValueRLPOutput tmp = new BytesValueRLPOutput();
genesisState.getBlock().writeTo(tmp);
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.BlockHeaderTestFixture;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.testutil.TestClock;
import org.junit.Test;
@ -27,7 +28,8 @@ public class FixedProtocolScheduleTest {
public void reportedDifficultyForAllBlocksIsAFixedValue() {
final ProtocolSchedule<Void> schedule =
FixedDifficultyProtocolSchedule.create(GenesisConfigFile.development().getConfigOptions());
FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), TestClock.fixed());
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();

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

@ -13,6 +13,7 @@
package tech.pegasys.pantheon.ethereum.mainnet;
import tech.pegasys.pantheon.config.GenesisConfigFile;
import tech.pegasys.pantheon.testutil.TestClock;
import java.nio.charset.StandardCharsets;
@ -25,7 +26,7 @@ public class MainnetProtocolScheduleTest {
@Test
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(1_150_000L).getName()).isEqualTo("Homestead");
Assertions.assertThat(sched.getByBlockNumber(1_920_000L).getName())
@ -49,7 +50,8 @@ public class MainnetProtocolScheduleTest {
public void shouldOnlyUseFrontierWhenEmptyJsonConfigIsUsed() {
final JsonObject json = new JsonObject("{}");
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(Long.MAX_VALUE).getName()).isEqualTo("Frontier");
}
@ -60,7 +62,8 @@ public class MainnetProtocolScheduleTest {
new JsonObject(
"{\"config\": {\"homesteadBlock\": 2, \"daoForkBlock\": 3, \"eip150Block\": 14, \"eip158Block\": 15, \"byzantiumBlock\": 16, \"constantinopleBlock\": 18, \"constantinopleFixBlock\": 19, \"chainId\":1234}}");
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(2).getName()).isEqualTo("Homestead");
Assertions.assertThat(sched.getByBlockNumber(3).getName()).isEqualTo("DaoRecoveryInit");
@ -84,7 +87,7 @@ public class MainnetProtocolScheduleTest {
.isThrownBy(
() ->
MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(json).getConfigOptions()));
GenesisConfigFile.fromConfig(json).getConfigOptions(), TestClock.fixed()));
}
@Test
@ -94,7 +97,8 @@ public class MainnetProtocolScheduleTest {
GenesisConfigFile.fromConfig(
Resources.toString(
this.getClass().getResource("/ropsten.json"), StandardCharsets.UTF_8))
.getConfigOptions());
.getConfigOptions(),
TestClock.fixed());
Assertions.assertThat(sched.getByBlockNumber(0).getName()).isEqualTo("TangerineWhistle");
Assertions.assertThat(sched.getByBlockNumber(1).getName()).isEqualTo("TangerineWhistle");
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.ScheduleBasedBlockHeaderFunctions;
import tech.pegasys.pantheon.ethereum.mainnet.ValidationTestUtils;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.io.IOException;
@ -109,7 +110,8 @@ public class ProofOfWorkValidationRuleTest {
}
private BlockHeaderFunctions mainnetBlockHashFunction() {
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create();
final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
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.BlockHeaderTestFixture;
import java.util.concurrent.TimeUnit;
import tech.pegasys.pantheon.testutil.TestClock;
import org.assertj.core.api.Assertions;
import org.junit.Test;
@ -26,7 +25,8 @@ public class TimestampValidationRuleTest {
@Test
public void headerTimestampSufficientlyFarIntoFutureVadidatesSuccessfully() {
final TimestampBoundedByFutureParameter uut00 = new TimestampBoundedByFutureParameter(0);
final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(0, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
@ -50,7 +50,8 @@ public class TimestampValidationRuleTest {
@Test
public void headerTimestampTooCloseToParentFailsValidation() {
final TimestampBoundedByFutureParameter uut00 = new TimestampBoundedByFutureParameter(0);
final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(0, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
@ -68,7 +69,8 @@ public class TimestampValidationRuleTest {
@Test
public void headerTimestampIsBehindParentFailsValidation() {
final TimestampBoundedByFutureParameter uut00 = new TimestampBoundedByFutureParameter(0);
final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(0, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
@ -89,14 +91,13 @@ public class TimestampValidationRuleTest {
final long acceptableClockDrift = 5;
final TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(acceptableClockDrift);
new TimestampBoundedByFutureParameter(acceptableClockDrift, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
// Create Parent Header @ 'now'
headerBuilder.timestamp(
TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS));
headerBuilder.timestamp(TestClock.fixed().instant().getEpochSecond());
final BlockHeader parent = headerBuilder.buildHeader();
// 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 TimestampBoundedByFutureParameter uut00 =
new TimestampBoundedByFutureParameter(acceptableClockDrift);
new TimestampBoundedByFutureParameter(acceptableClockDrift, TestClock.fixed());
final TimestampMoreRecentThanParent uut01 = new TimestampMoreRecentThanParent(10);
final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture();
// Create Parent Header @ 'now'
headerBuilder.timestamp(
TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS));
headerBuilder.timestamp(TestClock.fixed().instant().getEpochSecond());
final BlockHeader parent = headerBuilder.buildHeader();
// 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 java.math.BigInteger;
import java.time.Clock;
import java.util.Map;
import java.util.function.Function;
@ -67,7 +68,12 @@ public class ReferenceTestProtocolSchedules {
private static ProtocolSchedule<Void> createSchedule(final GenesisConfigOptions options) {
return new ProtocolScheduleBuilder<>(
options, CHAIN_ID, Function.identity(), PrivacyParameters.DEFAULT, false)
options,
CHAIN_ID,
Function.identity(),
PrivacyParameters.DEFAULT,
false,
Clock.systemUTC())
.createProtocolSchedule();
}
}

@ -31,6 +31,7 @@ import tech.pegasys.pantheon.ethereum.worldstate.DefaultMutableWorldState;
import tech.pegasys.pantheon.testutil.JsonTestParameters;
import java.math.BigInteger;
import java.time.Clock;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Optional;
@ -121,7 +122,8 @@ public class VMReferenceTest extends AbstractRetryingTest {
final EnvironmentInformation execEnv = spec.getExec();
final ProtocolSpec<Void> protocolSpec =
MainnetProtocolSpecs.frontierDefinition(OptionalInt.empty(), OptionalInt.empty())
MainnetProtocolSpecs.frontierDefinition(
OptionalInt.empty(), OptionalInt.empty(), Clock.systemUTC())
.privacyParameters(PrivacyParameters.DEFAULT)
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(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.vm.MessageFrame;
import tech.pegasys.pantheon.ethereum.vm.MessageFrame.State;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256;
import org.junit.Before;
@ -35,7 +36,8 @@ import org.junit.runners.Parameterized.Parameters;
public class ConstantinopleSStoreOperationGasCostTest {
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}")
public static Object[][] scenarios() {

@ -109,7 +109,7 @@ public class EthPeer {
public void recordUselessResponse(final String requestType) {
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) {

@ -967,7 +967,8 @@ public final class EthProtocolManagerTest {
.isEqualTo(Collections.singletonList(EthProtocol.ETH63));
// 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()) {
assertThat(msg.block(protocolSchdeule)).isEqualTo(minedBlock);
assertThat(msg.totalDifficulty(protocolSchdeule)).isEqualTo(expectedTotalDifficulty);

@ -65,7 +65,8 @@ public class EthProtocolManagerTestUtil {
}
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 GenesisState genesisState = GenesisState.fromConfig(config, protocolSchedule);
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.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.testutil.BlockTestUtil;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException;
import java.net.URISyntaxException;
@ -91,7 +92,8 @@ public class BlockchainSetupUtil<C> {
}
public static BlockchainSetupUtil<Void> forTesting() {
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create();
final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
final TemporaryFolder temp = new TemporaryFolder();
try {
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.RLP;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException;
@ -66,7 +67,7 @@ public final class BlockBodiesMessageTest {
message
.bodies(
FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false))
GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed()))
.iterator();
for (int i = 0; i < 50; ++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.RLP;
import tech.pegasys.pantheon.ethereum.rlp.RLPInput;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException;
@ -58,7 +59,7 @@ public final class BlockHeadersMessageTest {
final List<BlockHeader> readHeaders =
message.getHeaders(
FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false));
GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed()));
for (int i = 0; i < 50; ++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.p2p.rlpx.wire.RawMessage;
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.uint.UInt256;
import org.junit.Test;
public class NewBlockMessageTest {
private static final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create();
private static final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
@Test
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.MainnetProtocolSchedule;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List;
@ -55,7 +56,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator =
new DaoForkPeerValidator(
ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(),
daoBlockNumber,
0);
@ -87,7 +88,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator =
new DaoForkPeerValidator(
ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(),
daoBlockNumber,
0);
@ -115,7 +116,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator =
new DaoForkPeerValidator(
ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(),
daoBlockNumber,
0);
@ -144,7 +145,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator =
new DaoForkPeerValidator(
ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(),
daoBlockNumber,
0);
@ -183,7 +184,7 @@ public class DaoForkPeerValidatorTest {
PeerValidator validator =
new DaoForkPeerValidator(
ethProtocolManager.ethContext(),
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(TestClock.fixed()),
new NoOpMetricsSystem(),
daoBlockNumber,
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.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256;
import org.junit.Test;
@ -45,7 +46,7 @@ public class ChainHeadTrackerTest {
0);
private final ProtocolSchedule<Void> protocolSchedule =
FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false);
GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed());
private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class);
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.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@ -58,7 +59,8 @@ public class FullSyncTargetManagerTest {
final BlockchainSetupUtil<Void> localBlockchainSetup = BlockchainSetupUtil.forTesting();
localBlockchain = localBlockchainSetup.getBlockchain();
final ProtocolSchedule<Void> protocolSchedule = MainnetProtocolSchedule.create();
final ProtocolSchedule<Void> protocolSchedule =
MainnetProtocolSchedule.create(TestClock.fixed());
final ProtocolContext<Void> protocolContext =
new ProtocolContext<>(localBlockchain, localWorldState, null);
ethProtocolManager =

@ -34,6 +34,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.io.IOException;
@ -53,7 +54,8 @@ import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
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 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.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.ExceptionUtils;
import java.util.List;
@ -58,7 +59,8 @@ import org.junit.Test;
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 MetricsSystem metricsSystem = new NoOpMetricsSystem();
private final int defaultHeaderRequestSize = 10;

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

@ -95,7 +95,7 @@ public class TestNode implements Closeable {
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.development();
final ProtocolSchedule<Void> protocolSchedule =
FixedDifficultyProtocolSchedule.create(
GenesisConfigFile.development().getConfigOptions(), false);
GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed());
final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule);
final BlockHeaderFunctions blockHeaderFunctions =
@ -130,6 +130,7 @@ public class TestNode implements Closeable {
.keyPair(this.kp)
.config(networkingConfiguration)
.metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.supportedCapabilities(capabilities)
.build())
.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.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.testutil.BlockTestUtil;
import tech.pegasys.pantheon.testutil.TestClock;
import java.net.URL;
import java.nio.file.Paths;
@ -97,7 +98,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
@BeforeClass
public static void setupConstants() throws Exception {
PROTOCOL_SCHEDULE = MainnetProtocolSchedule.create();
PROTOCOL_SCHEDULE = MainnetProtocolSchedule.create(TestClock.fixed());
final URL blocksUrl = BlockTestUtil.getTestBlockchainUrl();

@ -23,6 +23,7 @@ import tech.pegasys.pantheon.ethereum.util.RawBlockIterator;
import java.net.URL;
import java.nio.file.Paths;
import java.time.Clock;
import java.util.ArrayList;
import java.util.List;
@ -40,7 +41,7 @@ public class BlockchainImporter {
public BlockchainImporter(final URL blocksUrl, final String genesisJson) throws Exception {
protocolSchedule =
MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(genesisJson).getConfigOptions());
GenesisConfigFile.fromConfig(genesisJson).getConfigOptions(), Clock.systemUTC());
blocks = new ArrayList<>();
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.prometheus.MetricsConfiguration;
import java.time.Clock;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
@ -102,7 +103,7 @@ public class JsonRpcTestMethodsFactory {
peerDiscovery,
blockchainQueries,
synchronizer,
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(Clock.systemUTC()),
filterManager,
transactionPool,
miningCoordinator,

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

@ -34,6 +34,7 @@ import tech.pegasys.pantheon.ethereum.permissioning.AccountLocalConfigPermission
import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException;
import java.math.BigInteger;
@ -99,7 +100,8 @@ public class JsonRpcHttpServiceHostWhitelistTest {
MainnetProtocolSchedule.fromConfig(
new StubGenesisConfigOptions()
.constantinopleBlock(0)
.chainId(BigInteger.valueOf(CHAIN_ID))),
.chainId(BigInteger.valueOf(CHAIN_ID)),
TestClock.fixed()),
mock(FilterManager.class),
mock(TransactionPool.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.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@ -127,7 +128,7 @@ public class JsonRpcHttpServiceLoginTest {
peerDiscoveryMock,
blockchainQueries,
synchronizer,
MainnetProtocolSchedule.fromConfig(genesisConfigOptions),
MainnetProtocolSchedule.fromConfig(genesisConfigOptions, TestClock.fixed()),
mock(FilterManager.class),
mock(TransactionPool.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.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException;
import java.util.ArrayList;
@ -193,7 +194,7 @@ public class JsonRpcHttpServiceRpcApisTest {
mock(P2PNetwork.class),
blockchainQueries,
mock(Synchronizer.class),
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(TestClock.fixed()),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),
@ -251,6 +252,7 @@ public class JsonRpcHttpServiceRpcApisTest {
.vertx(vertx)
.config(config)
.metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.build();
p2pNetwork.start();
@ -283,7 +285,7 @@ public class JsonRpcHttpServiceRpcApisTest {
p2pNetwork,
blockchainQueries,
mock(Synchronizer.class),
MainnetProtocolSchedule.create(),
MainnetProtocolSchedule.create(TestClock.fixed()),
mock(FilterManager.class),
mock(TransactionPool.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.metrics.noop.NoOpMetricsSystem;
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.BytesValues;
import tech.pegasys.pantheon.util.uint.UInt256;
@ -126,7 +127,8 @@ public class JsonRpcHttpServiceTest {
MainnetProtocolSchedule.fromConfig(
new StubGenesisConfigOptions()
.constantinopleBlock(0)
.chainId(BigInteger.valueOf(CHAIN_ID))),
.chainId(BigInteger.valueOf(CHAIN_ID)),
TestClock.fixed()),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(EthHashMiningCoordinator.class),

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

@ -31,6 +31,7 @@ import java.io.IOException;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.time.Clock;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.concurrent.CompletableFuture;
@ -61,8 +62,9 @@ public class VertxPeerDiscoveryAgent extends PeerDiscoveryAgent {
final DiscoveryConfiguration config,
final PeerPermissions peerPermissions,
final Optional<UpnpNatManager> natManager,
final MetricsSystem metricsSystem) {
super(keyPair, config, peerPermissions, natManager, metricsSystem);
final MetricsSystem metricsSystem,
final Clock clock) {
super(keyPair, config, peerPermissions, natManager, metricsSystem, clock);
checkArgument(vertx != null, "vertx instance cannot be null");
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.util.bytes.BytesValue;
import java.time.Clock;
public class FindNeighborsPacketData implements PacketData {
private static final int TARGET_SIZE = 64;
@ -35,9 +37,9 @@ public class FindNeighborsPacketData implements PacketData {
this.expiration = expiration;
}
public static FindNeighborsPacketData create(final BytesValue target) {
public static FindNeighborsPacketData create(final BytesValue target, final Clock clock) {
return new FindNeighborsPacketData(
target, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
target, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
}
@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.RLPOutput;
import java.time.Clock;
import java.util.List;
public class NeighborsPacketData implements PacketData {
@ -36,9 +37,8 @@ public class NeighborsPacketData implements PacketData {
}
@SuppressWarnings("unchecked")
public static NeighborsPacketData create(final List<DiscoveryPeer> peers) {
return new NeighborsPacketData(
peers, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
public static NeighborsPacketData create(final List<DiscoveryPeer> peers, final Clock clock) {
return new NeighborsPacketData(peers, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
}
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.bytes.BytesValue;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -142,6 +143,8 @@ public class PeerDiscoveryController {
private RecursivePeerRefreshState recursivePeerRefreshState;
private final Clock clock;
private PeerDiscoveryController(
final KeyPair keypair,
final DiscoveryPeer localPeer,
@ -155,7 +158,8 @@ public class PeerDiscoveryController {
final PeerRequirement peerRequirement,
final PeerPermissions peerPermissions,
final Subscribers<PeerBondedObserver> peerBondedObservers,
final MetricsSystem metricsSystem) {
final MetricsSystem metricsSystem,
final Clock clock) {
this.timerUtil = timerUtil;
this.keypair = keypair;
this.localPeer = localPeer;
@ -167,6 +171,7 @@ public class PeerDiscoveryController {
this.peerRequirement = peerRequirement;
this.outboundMessageHandler = outboundMessageHandler;
this.peerBondedObservers = peerBondedObservers;
this.clock = clock;
this.discoveryProtocolLogger = new DiscoveryProtocolLogger(metricsSystem);
this.peerPermissions = new PeerDiscoveryPermissions(localPeer, peerPermissions);
@ -357,7 +362,7 @@ public class PeerDiscoveryController {
}
// Reset the last seen timestamp.
final long now = System.currentTimeMillis();
final long now = clock.millis();
if (peer.getFirstDiscovered() == 0) {
peer.setFirstDiscovered(now);
}
@ -396,7 +401,7 @@ public class PeerDiscoveryController {
}
private void refreshTableIfRequired() {
final long now = System.currentTimeMillis();
final long now = clock.millis();
if (lastRefreshTime + tableRefreshIntervalMs <= now) {
LOG.debug("Peer table refresh triggered by timer expiry");
refreshTable();
@ -425,7 +430,7 @@ public class PeerDiscoveryController {
final BytesValue target = Peer.randomId();
final List<DiscoveryPeer> initialPeers = peerTable.nearestPeers(Peer.randomId(), 16);
recursivePeerRefreshState.start(initialPeers, target);
lastRefreshTime = System.currentTimeMillis();
lastRefreshTime = clock.millis();
}
/**
@ -435,13 +440,13 @@ public class PeerDiscoveryController {
*/
@VisibleForTesting
void bond(final DiscoveryPeer peer) {
peer.setFirstDiscovered(System.currentTimeMillis());
peer.setFirstDiscovered(clock.millis());
peer.setStatus(PeerDiscoveryStatus.BONDING);
final Consumer<PeerInteractionState> action =
interaction -> {
final PingPacketData data =
PingPacketData.create(localPeer.getEndpoint(), peer.getEndpoint());
PingPacketData.create(localPeer.getEndpoint(), peer.getEndpoint(), clock);
createPacket(
PacketType.PING,
data,
@ -505,7 +510,7 @@ public class PeerDiscoveryController {
private void findNodes(final DiscoveryPeer peer, final BytesValue target) {
final Consumer<PeerInteractionState> action =
(interaction) -> {
final FindNeighborsPacketData data = FindNeighborsPacketData.create(target);
final FindNeighborsPacketData data = FindNeighborsPacketData.create(target, clock);
sendPacket(peer, PacketType.FIND_NEIGHBORS, data);
};
final PeerInteractionState interaction =
@ -532,7 +537,7 @@ public class PeerDiscoveryController {
private void respondToPing(
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);
}
@ -541,7 +546,7 @@ public class PeerDiscoveryController {
// TODO: for now return 16 peers. Other implementations calculate how many
// peers they can fit in a 1280-byte payload.
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);
}
@ -662,6 +667,7 @@ public class PeerDiscoveryController {
private TimerUtil timerUtil;
private AsyncExecutor workerExecutor;
private MetricsSystem metricsSystem;
private Clock clock;
private Builder() {}
@ -685,7 +691,8 @@ public class PeerDiscoveryController {
peerRequirement,
peerPermissions,
peerBondedObservers,
metricsSystem);
metricsSystem,
clock);
}
private void validate() {
@ -695,6 +702,7 @@ public class PeerDiscoveryController {
validateRequiredDependency(workerExecutor, "AsyncExecutor");
validateRequiredDependency(metricsSystem, "MetricsSystem");
validateRequiredDependency(peerBondedObservers, "PeerBondedObservers");
validateRequiredDependency(clock, "Clock");
}
private void validateRequiredDependency(final Object object, final String name) {
@ -777,5 +785,11 @@ public class PeerDiscoveryController {
this.metricsSystem = metricsSystem;
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.RLPOutput;
import java.time.Clock;
public class PingPacketData implements PacketData {
/* 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;
}
public static PingPacketData create(final Endpoint from, final Endpoint to) {
return new PingPacketData(
from, to, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
public static PingPacketData create(final Endpoint from, final Endpoint to, final Clock clock) {
return new PingPacketData(from, to, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS);
}
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.util.bytes.BytesValue;
import java.time.Clock;
public class PongPacketData implements PacketData {
/* Destination. */
@ -34,9 +36,10 @@ public class PongPacketData implements PacketData {
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(
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) {

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

@ -39,6 +39,7 @@ import tech.pegasys.pantheon.util.FutureUtils;
import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -67,6 +68,7 @@ public class RlpxAgent {
private final PeerPrivileges peerPrivileges;
private final int maxConnections;
private final int maxRemotelyInitiatedConnections;
private final Clock clock;
@VisibleForTesting
final Map<BytesValue, RlpxConnection> connectionsById = new ConcurrentHashMap<>();
@ -84,7 +86,8 @@ public class RlpxAgent {
final PeerPrivileges peerPrivileges,
final int maxConnections,
final int maxRemotelyInitiatedConnections,
final MetricsSystem metricsSystem) {
final MetricsSystem metricsSystem,
final Clock clock) {
this.localNode = localNode;
this.connectionEvents = connectionEvents;
this.connectionInitializer = connectionInitializer;
@ -93,6 +96,7 @@ public class RlpxAgent {
this.maxConnections = maxConnections;
this.maxRemotelyInitiatedConnections =
Math.min(maxConnections, maxRemotelyInitiatedConnections);
this.clock = clock;
// Setup metrics
connectedPeersCounter =
@ -231,7 +235,8 @@ public class RlpxAgent {
// We're initiating a new connection
final CompletableFuture<PeerConnection> future = initiateOutboundConnection(peer);
connectionFuture.set(future);
RlpxConnection newConnection = RlpxConnection.outboundConnection(peer, future);
RlpxConnection newConnection =
RlpxConnection.outboundConnection(peer, future, clock.millis());
newConnection.subscribeConnectionEstablished(
(conn) -> {
this.dispatchConnect(conn.getPeerConnection());
@ -299,7 +304,7 @@ public class RlpxAgent {
private CompletableFuture<PeerConnection> initiateOutboundConnection(final Peer peer) {
LOG.trace("Initiating connection to peer: {}", peer.getEnodeURL());
if (peer instanceof DiscoveryPeer) {
((DiscoveryPeer) peer).setLastAttemptedConnection(System.currentTimeMillis());
((DiscoveryPeer) peer).setLastAttemptedConnection(clock.millis());
}
return connectionInitializer
@ -339,7 +344,8 @@ public class RlpxAgent {
// Track this new connection, deduplicating existing connection if necessary
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
// disconnect command until we've returned from our compute() calculation
final AtomicReference<Runnable> disconnectAction = new AtomicReference<>();
@ -503,6 +509,7 @@ public class RlpxAgent {
private ConnectionInitializer connectionInitializer;
private PeerConnectionEvents connectionEvents;
private MetricsSystem metricsSystem;
private Clock clock;
private Builder() {}
@ -528,7 +535,8 @@ public class RlpxAgent {
peerPrivileges,
config.getMaxPeers(),
config.getMaxRemotelyInitiatedConnections(),
metricsSystem);
metricsSystem,
clock);
}
private void validate() {
@ -538,6 +546,7 @@ public class RlpxAgent {
checkState(peerPrivileges != null, "PeerPrivileges must be configured");
checkState(peerPermissions != null, "PeerPermissions must be configured");
checkState(metricsSystem != null, "MetricsSystem must be configured");
checkState(clock != null, "Clock must be configured");
}
public Builder keyPair(final KeyPair keyPair) {
@ -587,5 +596,11 @@ public class RlpxAgent {
this.metricsSystem = metricsSystem;
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;
protected final CompletableFuture<PeerConnection> future;
private RlpxConnection(final CompletableFuture<PeerConnection> future) {
private RlpxConnection(final CompletableFuture<PeerConnection> future, final long initiatedAt) {
this.future = future;
this.initiatedAt = System.currentTimeMillis();
this.initiatedAt = initiatedAt;
}
public static RlpxConnection inboundConnection(final PeerConnection peerConnection) {
return new RemotelyInitiatedRlpxConnection(peerConnection);
public static RlpxConnection inboundConnection(
final PeerConnection peerConnection, final long initiatedAt) {
return new RemotelyInitiatedRlpxConnection(peerConnection, initiatedAt);
}
public static RlpxConnection outboundConnection(
final Peer peer, final CompletableFuture<PeerConnection> future) {
return new LocallyInitiatedRlpxConnection(peer, future);
final Peer peer, final CompletableFuture<PeerConnection> future, final long initiatedAt) {
return new LocallyInitiatedRlpxConnection(peer, future, initiatedAt);
}
public abstract Peer getPeer();
@ -84,8 +85,9 @@ public abstract class RlpxConnection {
private final PeerConnection peerConnection;
private RemotelyInitiatedRlpxConnection(final PeerConnection peerConnection) {
super(CompletableFuture.completedFuture(peerConnection));
private RemotelyInitiatedRlpxConnection(
final PeerConnection peerConnection, final long initiatedAt) {
super(CompletableFuture.completedFuture(peerConnection), initiatedAt);
this.peerConnection = peerConnection;
}
@ -147,8 +149,8 @@ public abstract class RlpxConnection {
private final Peer peer;
private LocallyInitiatedRlpxConnection(
final Peer peer, final CompletableFuture<PeerConnection> future) {
super(future);
final Peer peer, final CompletableFuture<PeerConnection> future, final long initiatedAt) {
super(future, initiatedAt);
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.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.LocalNode;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
@ -164,10 +163,6 @@ public class NettyConnectionInitializer implements ConnectionInitializer {
public CompletableFuture<PeerConnection> connect(final Peer peer) {
final CompletableFuture<PeerConnection> connectionFuture = new CompletableFuture<>();
if (peer instanceof DiscoveryPeer) {
((DiscoveryPeer) peer).setLastAttemptedConnection(System.currentTimeMillis());
}
final EnodeURL enode = peer.getEnodeURL();
new Bootstrap()
.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.Action;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissionsBlacklist;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.Collections;
import java.util.List;
@ -73,7 +74,7 @@ public class PeerDiscoveryAgentTest {
// Generate an out-of-band NEIGHBORS message.
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());
helper.sendMessageBetweenAgents(otherNode, agent, packet);
@ -112,7 +113,8 @@ public class PeerDiscoveryAgentTest {
packet =
Packet.create(
PacketType.FIND_NEIGHBORS,
FindNeighborsPacketData.create(otherAgents.get(0).getAdvertisedPeer().get().getId()),
FindNeighborsPacketData.create(
otherAgents.get(0).getAdvertisedPeer().get().getId(), TestClock.fixed()),
testAgent.getKeyPair());
helper.sendMessageBetweenAgents(testAgent, agent, packet);
@ -204,7 +206,7 @@ public class PeerDiscoveryAgentTest {
// Start an agent with no bootstrap peers.
final PeerPermissions peerPermissions = mock(PeerPermissions.class);
final MockPeerDiscoveryAgent agent =
helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions);
helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions, TestClock.fixed());
final Peer localNode = agent.getAdvertisedPeer().get();
// Setup peer and permissions
@ -231,7 +233,7 @@ public class PeerDiscoveryAgentTest {
// Start an agent with no bootstrap peers.
final PeerPermissions peerPermissions = mock(PeerPermissions.class);
final MockPeerDiscoveryAgent agent =
helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions);
helper.startDiscoveryAgent(Collections.emptyList(), peerPermissions, TestClock.fixed());
final Peer localNode = agent.getAdvertisedPeer().get();
// Setup peer and permissions
@ -472,7 +474,8 @@ public class PeerDiscoveryAgentTest {
protected void requestNeighbors(
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());
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.PacketType;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PongPacketData;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.Collections;
import java.util.List;
@ -67,7 +68,8 @@ public class PeerDiscoveryBondingTest {
// ignored because
// we haven't bonded.
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());
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.PingPacketData;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List;
@ -53,7 +54,7 @@ public class PeerDiscoveryBootstrappingTest {
final PingPacketData pingData = pingPacket.getPacketData(PingPacketData.class).get();
assertThat(pingData.getExpiration())
.isGreaterThanOrEqualTo(System.currentTimeMillis() / 1000 - 10000);
.isGreaterThanOrEqualTo(TestClock.fixed().millis() / 1000 - 10000);
assertThat(pingData.getFrom()).isEqualTo(agent.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.
final PingPacketData ping = packet.getPacketData(PingPacketData.class).get();
assertThat(ping.getExpiration())
.isGreaterThanOrEqualTo(System.currentTimeMillis() / 1000 - 10000);
.isGreaterThanOrEqualTo(TestClock.fixed().millis() / 1000 - 10000);
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.internal.MockPeerDiscoveryAgent;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
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
// peers.
final MockPeerDiscoveryAgent agent = helper.createDiscoveryAgent(peers2);
final MockPeerDiscoveryAgent agent = helper.createDiscoveryAgent(peers2, TestClock.fixed());
// A queue for storing peer bonded events.
final List<PeerBondedEvent> events = new ArrayList<>(10);
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.rlp.RLP;
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.MutableBytesValue;
@ -43,7 +44,8 @@ public class PeerDiscoveryPacketSedesTest {
final BytesValue target = BytesValue.wrap(r);
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 Buffer encoded = packet.encode();
assertNotNull(encoded);
@ -61,7 +63,8 @@ public class PeerDiscoveryPacketSedesTest {
new Random().nextBytes(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);
assertNotNull(serialized);
@ -72,14 +75,14 @@ public class PeerDiscoveryPacketSedesTest {
// assertion.
assertThat(deserialized.getExpiration())
.isCloseTo(
System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L));
TestClock.fixed().millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L));
}
@Test
public void neighborsPacketData() {
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);
assertNotNull(serialized);
@ -89,7 +92,7 @@ public class PeerDiscoveryPacketSedesTest {
// assertion.
assertThat(deserialized.getExpiration())
.isCloseTo(
System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L));
TestClock.fixed().millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS, offset(1500L));
}
@Test(expected = RLPException.class)
@ -98,7 +101,8 @@ public class PeerDiscoveryPacketSedesTest {
new Random().nextBytes(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);
assertNotNull(serialized);
@ -113,7 +117,7 @@ public class PeerDiscoveryPacketSedesTest {
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 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.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissions.PeerPermissions;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.time.Clock;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@ -80,7 +82,8 @@ public class PeerDiscoveryTestHelper {
PacketType.PING,
PingPacketData.create(
fromAgent.getAdvertisedPeer().get().getEndpoint(),
toAgent.getAdvertisedPeer().get().getEndpoint()),
toAgent.getAdvertisedPeer().get().getEndpoint(),
TestClock.fixed()),
fromAgent.getKeyPair());
}
@ -122,7 +125,19 @@ public class PeerDiscoveryTestHelper {
* @return a list of discovery agents.
*/
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);
}
@ -133,6 +148,12 @@ public class PeerDiscoveryTestHelper {
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.
*
@ -141,9 +162,11 @@ public class PeerDiscoveryTestHelper {
* @return a list of discovery agents.
*/
public MockPeerDiscoveryAgent startDiscoveryAgent(
final List<DiscoveryPeer> bootstrapPeers, final PeerPermissions peerPermissions) {
final List<DiscoveryPeer> bootstrapPeers,
final PeerPermissions peerPermissions,
final Clock clock) {
final AgentBuilder agentBuilder =
agentBuilder().bootstrapPeers(bootstrapPeers).peerPermissions(peerPermissions);
agentBuilder().bootstrapPeers(bootstrapPeers).peerPermissions(peerPermissions).clock(clock);
return startDiscoveryAgent(agentBuilder);
}
@ -154,8 +177,9 @@ public class PeerDiscoveryTestHelper {
return agent;
}
public MockPeerDiscoveryAgent createDiscoveryAgent(final List<DiscoveryPeer> bootstrapPeers) {
final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers);
public MockPeerDiscoveryAgent createDiscoveryAgent(
final List<DiscoveryPeer> bootstrapPeers, final Clock clock) {
final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers).clock(clock);
return createDiscoveryAgent(agentBuilder);
}
@ -179,6 +203,7 @@ public class PeerDiscoveryTestHelper {
private List<EnodeURL> bootnodes = Collections.emptyList();
private boolean active = true;
private PeerPermissions peerPermissions = PeerPermissions.noop();
private Clock clock = TestClock.fixed();
private AgentBuilder(
final Map<BytesValue, MockPeerDiscoveryAgent> agents,
@ -215,6 +240,11 @@ public class PeerDiscoveryTestHelper {
return this;
}
public AgentBuilder clock(final Clock clock) {
this.clock = clock;
return this;
}
public MockPeerDiscoveryAgent build() {
final DiscoveryConfiguration config = new DiscoveryConfiguration();
config.setBootnodes(bootnodes);
@ -222,7 +252,7 @@ public class PeerDiscoveryTestHelper {
config.setActive(active);
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.PingPacketData;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.Subscribers;
import java.util.Collections;
@ -38,6 +39,7 @@ import org.junit.Test;
public class PeerDiscoveryTimestampsTest {
private final PeerDiscoveryTestHelper helper = new PeerDiscoveryTestHelper();
private final TestClock testClock = new TestClock();
@Test
public void lastSeenAndFirstDiscoveredTimestampsUpdatedOnMessage() {
@ -60,11 +62,14 @@ public class PeerDiscoveryTimestampsTest {
.tableRefreshIntervalMs(TimeUnit.HOURS.toMillis(1))
.peerBondedObservers(Subscribers.create())
.metricsSystem(new NoOpMetricsSystem())
.clock(testClock)
.build();
controller.start();
testClock.stepMillis(1_000);
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));
controller.onMessage(packet, peers.get(1));
@ -74,6 +79,7 @@ public class PeerDiscoveryTimestampsTest {
assertThat(controller.streamDiscoveredPeers()).hasSize(1);
testClock.stepMillis(1_000);
DiscoveryPeer p = controller.streamDiscoveredPeers().iterator().next();
assertThat(p.getLastSeen()).isGreaterThan(0);
assertThat(p.getFirstDiscovered()).isGreaterThan(0);
@ -81,6 +87,7 @@ public class PeerDiscoveryTimestampsTest {
lastSeen.set(p.getLastSeen());
firstDiscovered.set(p.getFirstDiscovered());
testClock.stepMillis(1_000);
controller.onMessage(packet, peers.get(1));
assertThat(controller.streamDiscoveredPeers()).hasSize(1);
@ -92,11 +99,12 @@ public class PeerDiscoveryTimestampsTest {
@Test
public void lastContactedTimestampUpdatedOnOutboundMessage() {
final MockPeerDiscoveryAgent agent = helper.startDiscoveryAgent(Collections.emptyList());
final MockPeerDiscoveryAgent agent =
helper.startDiscoveryAgent(Collections.emptyList(), testClock);
assertThat(agent.streamDiscoveredPeers()).hasSize(0);
// 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);
helper.sendMessageBetweenAgents(testAgent, agent, ping);
@ -120,6 +128,7 @@ public class PeerDiscoveryTimestampsTest {
firstDiscovered.set(fd);
// Send another packet and ensure that timestamps are updated accordingly.
testClock.stepMillis(1_000);
helper.sendMessageBetweenAgents(testAgent, agent, ping);
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.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import org.junit.Test;
@ -24,10 +25,11 @@ import org.junit.Test;
public class FindNeighborsPacketDataTest {
@Test
public void serializeDeserialize() {
final long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
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 FindNeighborsPacketData deserialized =
FindNeighborsPacketData.readFrom(RLP.input(serialized));
@ -38,7 +40,7 @@ public class FindNeighborsPacketDataTest {
@Test
public void readFrom() {
final long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final BytesValue target = Peer.randomId();
BytesValueRLPOutput out = new BytesValueRLPOutput();
@ -56,7 +58,7 @@ public class FindNeighborsPacketDataTest {
@Test
public void readFrom_withExtraFields() {
final long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final BytesValue target = Peer.randomId();
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.peers.Peer;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.Bytes32;
import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -30,7 +31,8 @@ public class MockPacketDataFactory {
final DiscoveryPeer from, final DiscoveryPeer... neighbors) {
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));
final BytesValue id = from.getId();
@ -44,7 +46,8 @@ public class MockPacketDataFactory {
public static Packet mockPongPacket(final DiscoveryPeer from, final BytesValue pingHash) {
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));
final BytesValue id = from.getId();
when(packet.getNodeId()).thenReturn(id);
@ -60,7 +63,8 @@ public class MockPacketDataFactory {
BytesValue.fromHexString(
"0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40");
final FindNeighborsPacketData packetData = FindNeighborsPacketData.create(target);
final FindNeighborsPacketData packetData =
FindNeighborsPacketData.create(target, TestClock.fixed());
when(packet.getPacketData(any())).thenReturn(Optional.of(packetData));
final BytesValue id = from.getId();
when(packet.getNodeId()).thenReturn(id);

@ -22,6 +22,7 @@ import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetSocketAddress;
import java.time.Clock;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
@ -39,8 +40,9 @@ public class MockPeerDiscoveryAgent extends PeerDiscoveryAgent {
final KeyPair keyPair,
final DiscoveryConfiguration config,
final PeerPermissions peerPermissions,
final Map<BytesValue, MockPeerDiscoveryAgent> agentNetwork) {
super(keyPair, config, peerPermissions, Optional.empty(), new NoOpMetricsSystem());
final Map<BytesValue, MockPeerDiscoveryAgent> agentNetwork,
final Clock clock) {
super(keyPair, config, peerPermissions, Optional.empty(), new NoOpMetricsSystem(), clock);
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.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Arrays;
@ -29,11 +30,11 @@ public class NeighborsPacketDataTest {
@Test
public void serializeDeserialize() {
final long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final List<DiscoveryPeer> peers =
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 NeighborsPacketData deserialized = NeighborsPacketData.readFrom(RLP.input(serialized));
@ -43,7 +44,7 @@ public class NeighborsPacketDataTest {
@Test
public void readFrom() {
final long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final List<DiscoveryPeer> peers =
Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode()));
@ -61,7 +62,7 @@ public class NeighborsPacketDataTest {
@Test
public void readFrom_extraFields() {
final long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final List<DiscoveryPeer> peers =
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.PeerPermissionsBlacklist;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.Bytes32;
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,
// which gets validated when receiving the PONG.
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));
mockPingPacketCreation(mockPacket);
@ -183,7 +185,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet, so that we can control the hash,
// which gets validated when receiving the PONG.
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));
mockPingPacketCreation(mockPacket);
@ -201,7 +204,7 @@ public class PeerDiscoveryControllerTest {
// Simulate a PONG message from peer 0.
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));
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,
// which gets validated when receiving the PONG.
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));
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
// when receiving the PONG.
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));
mockPingPacketCreation(mockPacket);
@ -287,7 +292,7 @@ public class PeerDiscoveryControllerTest {
// Simulate PONG messages from all peers
for (int i = 0; i < 3; i++) {
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));
controller.onMessage(packet0, peers.get(i));
}
@ -332,7 +337,8 @@ public class PeerDiscoveryControllerTest {
// when
// processing the PONG.
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));
mockPingPacketCreation(mockPacket);
@ -346,7 +352,8 @@ public class PeerDiscoveryControllerTest {
// Send a PONG packet from peer 1, with an incorrect hash.
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));
controller.onMessage(packet, peers.get(1));
@ -381,7 +388,8 @@ public class PeerDiscoveryControllerTest {
// when
// processing the PONG.
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));
mockPingPacketCreation(mockPacket);
controller.setRetryDelayFunction((prev) -> 999999999L);
@ -423,7 +431,8 @@ public class PeerDiscoveryControllerTest {
private void respondWithPong(
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);
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
// when processing the PONG.
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));
mockPingPacketCreation(pingPacket);
@ -471,7 +481,7 @@ public class PeerDiscoveryControllerTest {
.hasSize(1);
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));
controller.onMessage(pongPacket, peers.get(1));
@ -481,7 +491,7 @@ public class PeerDiscoveryControllerTest {
// Simulate a NEIGHBORS message from peer[0] listing peer[2].
final NeighborsPacketData neighbors0 =
NeighborsPacketData.create(Collections.singletonList(peers.get(2)));
NeighborsPacketData.create(Collections.singletonList(peers.get(2)), TestClock.fixed());
final Packet neighborsPacket0 =
Packet.create(PacketType.NEIGHBORS, neighbors0, keyPairs.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
// in the peer list.
final NeighborsPacketData neighbors1 =
NeighborsPacketData.create(Collections.singletonList(peers.get(2)));
NeighborsPacketData.create(Collections.singletonList(peers.get(2)), TestClock.fixed());
final Packet neighborsPacket1 =
Packet.create(PacketType.NEIGHBORS, neighbors1, keyPairs.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.
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));
controller.onMessage(pongPacket2, peers.get(2));
@ -605,7 +615,8 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer
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));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -622,13 +633,15 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to otherPeer after neighbors packet is received
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));
mockPacketCreation(PacketType.PING, otherPeer, pingPacket);
// Setup ping to be sent to otherPeer2 after neighbors packet is received
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));
mockPacketCreation(PacketType.PING, otherPeer2, pingPacket2);
@ -683,7 +696,8 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer
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));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -699,13 +713,15 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to otherPeer after neighbors packet is received
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));
mockPacketCreation(PacketType.PING, otherPeer, pingPacket);
// Setup ping to be sent to otherPeer2 after neighbors packet is received
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));
mockPacketCreation(PacketType.PING, otherPeer2, pingPacket2);
@ -738,7 +754,7 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
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));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -778,7 +794,7 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
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));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -819,7 +835,7 @@ public class PeerDiscoveryControllerTest {
// Setup ping to be sent to discoPeer
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
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));
mockPacketCreation(PacketType.PING, discoPeer, discoPeerPing);
@ -848,7 +864,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet to control hash for PONG.
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
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 OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class);
@ -887,7 +904,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of PING packets to control hash PONG packets.
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
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));
mockPingPacketCreation(pingPacket);
@ -946,7 +964,8 @@ public class PeerDiscoveryControllerTest {
// Mock the creation of the PING packet to control hash for PONG.
final List<SECP256K1.KeyPair> keyPairs = PeerDiscoveryTestHelper.generateKeyPairs(1);
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 OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class);
@ -1177,7 +1196,7 @@ public class PeerDiscoveryControllerTest {
final Packet packet = mock(Packet.class);
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));
final BytesValue id = from.getId();
when(packet.getNodeId()).thenReturn(id);
@ -1309,6 +1328,7 @@ public class PeerDiscoveryControllerTest {
.peerPermissions(peerPermissions)
.peerBondedObservers(peerBondedObservers)
.metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.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.PeerDiscoveryTestHelper;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -62,12 +63,14 @@ public class PeerDiscoveryTableRefreshTest {
.tableRefreshIntervalMs(0)
.peerBondedObservers(Subscribers.create())
.metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.build());
controller.start();
// Send a PING, so as to add a Peer in the controller.
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));
controller.onMessage(pingPacket, peers.get(1));
@ -76,7 +79,7 @@ public class PeerDiscoveryTableRefreshTest {
// Simulate a PONG message from peer 0.
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 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.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.OptionalInt;
@ -27,11 +28,11 @@ public class PingPacketDataTest {
@Test
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 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 PingPacketData deserialized = PingPacketData.readFrom(RLP.input(serialized));
@ -45,7 +46,7 @@ public class PingPacketDataTest {
final int version = 4;
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 long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final BytesValueRLPOutput out = new BytesValueRLPOutput();
out.startList();
@ -68,7 +69,7 @@ public class PingPacketDataTest {
final int version = 4;
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 long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final BytesValueRLPOutput out = new BytesValueRLPOutput();
out.startList();
@ -93,7 +94,7 @@ public class PingPacketDataTest {
final int version = 99;
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 long time = System.currentTimeMillis();
final long time = TestClock.fixed().millis();
final BytesValueRLPOutput out = new BytesValueRLPOutput();
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.rlp.BytesValueRLPOutput;
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.BytesValue;
@ -28,11 +29,11 @@ public class PongPacketDataTest {
@Test
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 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 PongPacketData deserialized = PongPacketData.readFrom(RLP.input(serialized));
@ -43,7 +44,7 @@ public class PongPacketDataTest {
@Test
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 Bytes32 hash = Bytes32.fromHexStringLenient("0x1234");
@ -63,7 +64,7 @@ public class PongPacketDataTest {
@Test
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 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.nat.upnp.UpnpNatManager;
import tech.pegasys.pantheon.nat.upnp.UpnpNatManager.Protocol;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.ArrayList;
import java.util.List;
@ -215,7 +216,7 @@ public final class DefaultP2PNetworkTest {
when(natManager.queryExternalIPAddress())
.thenReturn(CompletableFuture.completedFuture(externalIp));
final P2PNetwork network = builder().natManager(natManager).build();
final P2PNetwork network = builder().natManager(natManager).clock(TestClock.fixed()).build();
network.start();
verify(natManager)
@ -231,7 +232,7 @@ public final class DefaultP2PNetworkTest {
final DefaultP2PNetwork network = network();
network.start();
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);
verify(rlpxAgent, times(1)).connect(peer);
@ -244,7 +245,7 @@ public final class DefaultP2PNetworkTest {
final DiscoveryPeer peer =
DiscoveryPeer.fromIdAndEndpoint(
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);
verify(rlpxAgent, times(1)).connect(peer);
@ -305,7 +306,7 @@ public final class DefaultP2PNetworkTest {
}
private DefaultP2PNetwork network() {
return (DefaultP2PNetwork) builder().build();
return (DefaultP2PNetwork) builder().clock(TestClock.fixed()).build();
}
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.rlpx.wire.Capability;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import java.io.IOException;
import java.util.Arrays;
@ -157,6 +158,7 @@ public class NetworkingServiceLifecycleTest {
.keyPair(keyPair)
.config(config)
.metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.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.messages.DisconnectMessage.DisconnectReason;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetAddress;
@ -326,6 +327,7 @@ public class P2PNetworkTest {
.config(config)
.keyPair(KeyPair.generate())
.metricsSystem(new NoOpMetricsSystem())
.clock(TestClock.fixed())
.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.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.testutil.TestClock;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Arrays;
@ -971,6 +972,7 @@ public class RlpxAgentTest {
.peerPrivileges(peerPrivileges)
.localNode(localNode)
.metricsSystem(metrics)
.clock(TestClock.fixed())
.connectionInitializer(connectionInitializer)
.connectionEvents(peerConnectionEvents)
.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.rlpx.connections.RlpxConnection.ConnectionNotEstablishedException;
import tech.pegasys.pantheon.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason;
import tech.pegasys.pantheon.testutil.TestClock;
import java.util.concurrent.CompletableFuture;
@ -32,7 +33,8 @@ public class RlpxConnectionTest {
public void getPeer_pendingOutboundConnection() {
final Peer peer = createPeer();
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);
}
@ -41,7 +43,8 @@ public class RlpxConnectionTest {
public void getPeer_establishedOutboundConnection() {
final Peer peer = createPeer();
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));
assertThat(conn.getPeer()).isEqualTo(peer);
@ -51,7 +54,8 @@ public class RlpxConnectionTest {
public void getPeer_inboundConnection() {
final Peer peer = createPeer();
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);
}
@ -60,7 +64,8 @@ public class RlpxConnectionTest {
public void disconnect_pendingOutboundConnection() {
final Peer peer = createPeer();
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;
conn.disconnect(reason);
@ -79,7 +84,8 @@ public class RlpxConnectionTest {
public void disconnect_activeOutboundConnection() {
final Peer peer = createPeer();
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);
future.complete(peerConnection);
@ -95,7 +101,8 @@ public class RlpxConnectionTest {
public void disconnect_failedOutboundConnection() {
final Peer peer = createPeer();
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"));
assertThat(conn.isFailedOrDisconnected()).isTrue();
@ -108,7 +115,8 @@ public class RlpxConnectionTest {
public void disconnect_inboundConnection() {
final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection);
final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
assertThat(conn.isFailedOrDisconnected()).isFalse();
final DisconnectReason reason = DisconnectReason.REQUESTED;
@ -123,7 +131,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_pendingOutboundConnection() {
final Peer peer = createPeer();
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)
.isInstanceOf(ConnectionNotEstablishedException.class);
@ -133,7 +142,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_activeOutboundConnection() {
final Peer peer = createPeer();
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);
future.complete(peerConnection);
@ -144,7 +154,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_failedOutboundConnection() {
final Peer peer = createPeer();
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"));
assertThatThrownBy(conn::getPeerConnection)
@ -155,7 +166,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_disconnectedOutboundConnection() {
final Peer peer = createPeer();
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);
future.complete(peerConnection);
conn.disconnect(DisconnectReason.REQUESTED);
@ -167,7 +179,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_activeInboundConnection() {
final Peer peer = createPeer();
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);
}
@ -176,7 +189,8 @@ public class RlpxConnectionTest {
public void getPeerConnection_disconnectedInboundConnection() {
final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection);
final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
conn.disconnect(DisconnectReason.REQUESTED);
assertThat(conn.getPeerConnection()).isEqualTo(peerConnection);
@ -186,7 +200,8 @@ public class RlpxConnectionTest {
public void checkState_pendingOutboundConnection() {
final Peer peer = createPeer();
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.isActive()).isFalse();
@ -198,7 +213,8 @@ public class RlpxConnectionTest {
public void checkState_activeOutboundConnection() {
final Peer peer = createPeer();
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);
future.complete(peerConnection);
@ -212,7 +228,8 @@ public class RlpxConnectionTest {
public void checkState_failedOutboundConnection() {
final Peer peer = createPeer();
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"));
assertThat(conn.initiatedRemotely()).isFalse();
@ -225,7 +242,8 @@ public class RlpxConnectionTest {
public void checkState_disconnectedOutboundConnection() {
final Peer peer = createPeer();
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);
future.complete(peerConnection);
conn.disconnect(DisconnectReason.UNKNOWN);
@ -240,7 +258,8 @@ public class RlpxConnectionTest {
public void checkState_activeInboundConnection() {
final Peer peer = createPeer();
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.isActive()).isTrue();
@ -252,7 +271,8 @@ public class RlpxConnectionTest {
public void checkState_disconnectedInboundConnection() {
final Peer peer = createPeer();
final PeerConnection peerConnection = peerConnection(peer);
final RlpxConnection conn = RlpxConnection.inboundConnection(peerConnection);
final RlpxConnection conn =
RlpxConnection.inboundConnection(peerConnection, TestClock.fixed().millis());
conn.disconnect(DisconnectReason.UNKNOWN);
assertThat(conn.initiatedRemotely()).isTrue();

@ -35,6 +35,7 @@ import tech.pegasys.pantheon.metrics.MetricsSystem;
import tech.pegasys.pantheon.metrics.PantheonMetricCategory;
import java.io.IOException;
import java.time.Clock;
import com.google.common.io.Resources;
import org.junit.Test;
@ -51,7 +52,8 @@ public class NodeSmartContractPermissioningControllerTest {
private NodeSmartContractPermissioningController setupController(
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 =
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.math.BigInteger;
import java.time.Clock;
import com.google.common.io.Resources;
import org.junit.Test;
@ -55,7 +56,8 @@ public class TransactionSmartContractPermissioningControllerTest {
private TransactionSmartContractPermissioningController setupController(
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 =
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.BlockImporter;
import java.time.Clock;
import org.apache.logging.log4j.Logger;
import picocli.CommandLine.RunLast;
@ -40,6 +42,7 @@ public final class Pantheon {
new RunnerBuilder(),
new PantheonController.Builder(),
new PantheonPluginContextImpl(),
Clock.systemUTC(),
System.getenv());
pantheonCommand.parse(

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

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

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

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

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

@ -86,6 +86,6 @@ public class MainnetPantheonControllerBuilder extends PantheonControllerBuilder<
@Override
protected ProtocolSchedule<Void> createProtocolSchedule() {
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