From ec5dc8540352fa4f7141b3b1cb0b735d22aba44e Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Wed, 24 Jul 2019 19:12:05 -0600 Subject: [PATCH] [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 --- .../dsl/node/ThreadPantheonNodeRunner.java | 14 ++-- .../BlockHeaderValidationRulesetFactory.java | 7 +- .../clique/CliqueProtocolSchedule.java | 27 +++++-- .../clique/CliqueProtocolScheduleTest.java | 5 +- .../blockcreation/CliqueBlockCreatorTest.java | 5 +- .../CliqueMinerExecutorTest.java | 9 ++- .../ibft/support/TestContextBuilder.java | 5 +- ...ftBlockHeaderValidationRulesetFactory.java | 7 +- .../consensus/ibft/IbftProtocolSchedule.java | 24 +++--- ...ockHeaderValidationRulesetFactoryTest.java | 23 +++--- .../blockcreation/IbftBlockCreatorTest.java | 5 +- ...ftBlockHeaderValidationRulesetFactory.java | 16 ++-- .../ibftlegacy/IbftProtocolSchedule.java | 19 +++-- ...ockHeaderValidationRulesetFactoryTest.java | 5 +- .../blockcreation/IbftBlockCreatorTest.java | 12 +-- .../errorpronechecks/BannedMethod.java | 9 ++- .../BannedMethodNegativeCases.java | 6 ++ .../BannedMethodPositiveCases.java | 6 ++ .../BlockTransactionSelectorTest.java | 3 +- .../EthHashBlockCreatorTest.java | 4 +- .../operations/OperationBenchmarkHelper.java | 6 +- .../FixedDifficultyProtocolSchedule.java | 17 +++-- .../mainnet/MainnetBlockHeaderValidator.java | 16 ++-- .../mainnet/MainnetProtocolSchedule.java | 31 +++++--- .../mainnet/MainnetProtocolSpecs.java | 62 ++++++++++----- .../mainnet/ProtocolScheduleBuilder.java | 50 +++++++----- .../TimestampBoundedByFutureParameter.java | 11 +-- .../core/ExecutionContextTestFixture.java | 17 ++++- .../ethereum/core/TestCodeExecutor.java | 7 +- .../ethereum/chain/GenesisStateTest.java | 15 ++-- .../fixed/FixedProtocolScheduleTest.java | 4 +- .../MainnetBlockHeaderValidatorTest.java | 13 +++- .../mainnet/MainnetProtocolScheduleTest.java | 14 ++-- .../ProofOfWorkValidationRuleTest.java | 4 +- .../TimestampValidationRuleTest.java | 23 +++--- .../vm/ReferenceTestProtocolSchedules.java | 8 +- .../pantheon/ethereum/vm/VMReferenceTest.java | 4 +- ...stantinopleSStoreOperationGasCostTest.java | 4 +- .../ethereum/eth/manager/EthPeer.java | 2 +- .../eth/manager/EthProtocolManagerTest.java | 3 +- .../manager/EthProtocolManagerTestUtil.java | 3 +- .../ethtaskutils/BlockchainSetupUtil.java | 4 +- .../eth/messages/BlockBodiesMessageTest.java | 3 +- .../eth/messages/BlockHeadersMessageTest.java | 3 +- .../eth/messages/NewBlockMessageTest.java | 4 +- .../DaoForkPeerValidatorTest.java | 11 +-- .../eth/sync/ChainHeadTrackerTest.java | 3 +- .../fullsync/FullSyncTargetManagerTest.java | 4 +- ...neCommonAncestorTaskParameterizedTest.java | 4 +- .../DetermineCommonAncestorTaskTest.java | 4 +- .../worldstate/WorldStateDownloaderTest.java | 5 +- .../ethereum/eth/transactions/TestNode.java | 3 +- .../AbstractEthGraphQLHttpServiceTest.java | 3 +- .../ethereum/jsonrpc/BlockchainImporter.java | 3 +- .../jsonrpc/JsonRpcTestMethodsFactory.java | 3 +- .../AbstractEthJsonRpcHttpServiceTest.java | 5 +- .../JsonRpcHttpServiceHostWhitelistTest.java | 4 +- .../jsonrpc/JsonRpcHttpServiceLoginTest.java | 3 +- .../JsonRpcHttpServiceRpcApisTest.java | 6 +- .../jsonrpc/JsonRpcHttpServiceTest.java | 4 +- .../p2p/discovery/PeerDiscoveryAgent.java | 18 +++-- .../discovery/VertxPeerDiscoveryAgent.java | 6 +- .../internal/FindNeighborsPacketData.java | 6 +- .../internal/NeighborsPacketData.java | 6 +- .../internal/PeerDiscoveryController.java | 34 ++++++--- .../discovery/internal/PingPacketData.java | 7 +- .../discovery/internal/PongPacketData.java | 7 +- .../p2p/network/DefaultP2PNetwork.java | 16 +++- .../pantheon/ethereum/p2p/rlpx/RlpxAgent.java | 25 ++++-- .../p2p/rlpx/connections/RlpxConnection.java | 22 +++--- .../netty/NettyConnectionInitializer.java | 5 -- .../p2p/discovery/PeerDiscoveryAgentTest.java | 13 ++-- .../discovery/PeerDiscoveryBondingTest.java | 4 +- .../PeerDiscoveryBootstrappingTest.java | 5 +- .../discovery/PeerDiscoveryObserversTest.java | 3 +- .../PeerDiscoveryPacketSedesTest.java | 18 +++-- .../discovery/PeerDiscoveryTestHelper.java | 44 +++++++++-- .../PeerDiscoveryTimestampsTest.java | 15 +++- .../internal/FindNeighborsPacketDataTest.java | 10 ++- .../internal/MockPacketDataFactory.java | 10 ++- .../internal/MockPeerDiscoveryAgent.java | 6 +- .../internal/NeighborsPacketDataTest.java | 9 ++- .../internal/PeerDiscoveryControllerTest.java | 76 ++++++++++++------- .../PeerDiscoveryTableRefreshTest.java | 7 +- .../internal/PingPacketDataTest.java | 11 +-- .../internal/PongPacketDataTest.java | 9 ++- .../p2p/network/DefaultP2PNetworkTest.java | 9 ++- .../NetworkingServiceLifecycleTest.java | 2 + .../ethereum/p2p/network/P2PNetworkTest.java | 2 + .../ethereum/p2p/rlpx/RlpxAgentTest.java | 2 + .../rlpx/connections/RlpxConnectionTest.java | 58 +++++++++----- ...rtContractPermissioningControllerTest.java | 4 +- ...rtContractPermissioningControllerTest.java | 4 +- .../java/tech/pegasys/pantheon/Pantheon.java | 3 + .../tech/pegasys/pantheon/RunnerBuilder.java | 15 +++- .../pegasys/pantheon/cli/PantheonCommand.java | 6 +- .../CliquePantheonControllerBuilder.java | 6 +- .../IbftLegacyPantheonControllerBuilder.java | 2 +- .../IbftPantheonControllerBuilder.java | 2 +- .../MainnetPantheonControllerBuilder.java | 2 +- .../tech/pegasys/pantheon/RunnerTest.java | 1 + .../pantheon/cli/CommandTestAbstract.java | 7 ++ .../cli/operator/OperatorSubCommandTest.java | 4 +- .../pegasys/pantheon/testutil/TestClock.java | 12 ++- 104 files changed, 767 insertions(+), 370 deletions(-) diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java index c74bc1433c..7ae9889437 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/ThreadPantheonNodeRunner.java @@ -63,14 +63,16 @@ public class ThreadPantheonNodeRunner implements PantheonNodeRunner { private final Map 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(); } diff --git a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/BlockHeaderValidationRulesetFactory.java b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/BlockHeaderValidationRulesetFactory.java index cdb7867a5b..bb3005ff1e 100644 --- a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/BlockHeaderValidationRulesetFactory.java +++ b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/BlockHeaderValidationRulesetFactory.java @@ -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 cliqueBlockHeaderValidator( - final long secondsBetweenBlocks, final EpochManager epochManager) { + final long secondsBetweenBlocks, final EpochManager epochManager, final Clock clock) { return new BlockHeaderValidator.Builder() .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( diff --git a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java index dfc98d684e..d96246f108 100644 --- a/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java +++ b/consensus/clique/src/main/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolSchedule.java @@ -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 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 applyCliqueSpecificModifications( final EpochManager epochManager, final long secondsBetweenBlocks, final Address localNodeAddress, - final ProtocolSpecBuilder specBuilder) { + final ProtocolSpecBuilder 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, diff --git a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java index cccaca8427..1412398e67 100644 --- a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java +++ b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/CliqueProtocolScheduleTest.java @@ -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 protocolSchedule = - CliqueProtocolSchedule.create(config, NODE_KEYS, false); + CliqueProtocolSchedule.create(config, NODE_KEYS, false, TestClock.fixed()); final ProtocolSpec homesteadSpec = protocolSchedule.getByBlockNumber(1); final ProtocolSpec tangerineWhistleSpec = protocolSchedule.getByBlockNumber(2); @@ -57,7 +58,7 @@ public class CliqueProtocolScheduleTest { public void parametersAlignWithMainnetWithAdjustments() { final ProtocolSpec homestead = CliqueProtocolSchedule.create( - GenesisConfigFile.DEFAULT.getConfigOptions(), NODE_KEYS, false) + GenesisConfigFile.DEFAULT.getConfigOptions(), NODE_KEYS, false, TestClock.fixed()) .getByBlockNumber(0); assertThat(homestead.getName()).isEqualTo("Frontier"); diff --git a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index fbc7133bb7..473cb90d79 100644 --- a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -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); diff --git a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java index 19012ab83c..116c9fe99b 100644 --- a/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java +++ b/consensus/clique/src/test/java/tech/pegasys/pantheon/consensus/clique/blockcreation/CliqueMinerExecutorTest.java @@ -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, diff --git a/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextBuilder.java b/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextBuilder.java index a5a0d58b4d..bdeef80333 100644 --- a/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextBuilder.java +++ b/consensus/ibft/src/integration-test/java/tech/pegasys/pantheon/consensus/ibft/support/TestContextBuilder.java @@ -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 protocolSchedule = - IbftProtocolSchedule.create(genesisConfigOptions); + IbftProtocolSchedule.create(genesisConfigOptions, Clock.systemUTC()); ///////////////////////////////////////////////////////////////////////////////////// // From here down is BASICALLY taken from IbftPantheonController diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java index c45f8168e0..a866c94ae9 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactory.java @@ -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 ibftBlockHeaderValidator( - final long secondsBetweenBlocks) { + final long secondsBetweenBlocks, final Clock clock) { return new BlockHeaderValidator.Builder() .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<>( diff --git a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java index d9526928d2..5ec3f885e8 100644 --- a/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java +++ b/consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/IbftProtocolSchedule.java @@ -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 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 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 create(final GenesisConfigOptions config) { - return create(config, PrivacyParameters.DEFAULT, false); + public static ProtocolSchedule create( + final GenesisConfigOptions config, final Clock clock) { + return create(config, PrivacyParameters.DEFAULT, false, clock); } private static ProtocolSpecBuilder applyIbftChanges( - final long secondsBetweenBlocks, final ProtocolSpecBuilder builder) { + final long secondsBetweenBlocks, final ProtocolSpecBuilder builder, final Clock clock) { return builder .changeConsensusContextType( - difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), - difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), + difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock), + difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock), MainnetBlockBodyValidator::new, MainnetBlockValidator::new, MainnetBlockImporter::new, diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java index 80649af434..052206a39f 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java +++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/IbftBlockHeaderValidationRulesetFactoryTest.java @@ -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 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 validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( @@ -100,7 +101,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { .buildHeader(); final BlockHeaderValidator 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 validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( @@ -144,7 +145,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { .buildHeader(); final BlockHeaderValidator validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( @@ -167,7 +168,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { .buildHeader(); final BlockHeaderValidator validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( @@ -190,7 +191,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { .buildHeader(); final BlockHeaderValidator validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( @@ -213,7 +214,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { .buildHeader(); final BlockHeaderValidator 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 validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( @@ -258,7 +259,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { .buildHeader(); final BlockHeaderValidator validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( @@ -281,7 +282,7 @@ public class IbftBlockHeaderValidationRulesetFactoryTest { .buildHeader(); final BlockHeaderValidator validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( diff --git a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java index 3f50fb3a98..0aba2c04de 100644 --- a/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java +++ b/consensus/ibft/src/test/java/tech/pegasys/pantheon/consensus/ibft/blockcreation/IbftBlockCreatorTest.java @@ -75,7 +75,8 @@ public class IbftBlockCreatorTest { final ProtocolSchedule protocolSchedule = IbftProtocolSchedule.create( GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}") - .getConfigOptions()); + .getConfigOptions(), + TestClock.fixed()); final ProtocolContext protContext = new ProtocolContext<>( blockchain, @@ -110,7 +111,7 @@ public class IbftBlockCreatorTest { final Block block = blockCreator.createBlock(Instant.now().getEpochSecond()); final BlockHeaderValidator 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 = diff --git a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java index 68dc7ab542..b6e8d84ed4 100644 --- a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactory.java @@ -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 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 ibftProposedBlockValidator( - final long secondsBetweenBlocks) { - return createValidator(secondsBetweenBlocks, false); + final long secondsBetweenBlocks, final Clock clock) { + return createValidator(secondsBetweenBlocks, false, clock); } private static BlockHeaderValidator createValidator( - final long secondsBetweenBlocks, final boolean validateCommitSeals) { + final long secondsBetweenBlocks, final boolean validateCommitSeals, final Clock clock) { return new BlockHeaderValidator.Builder() .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<>( diff --git a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java index 321557b9c0..6b7eab7064 100644 --- a/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java +++ b/consensus/ibftlegacy/src/main/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftProtocolSchedule.java @@ -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 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 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 applyIbftChanges( - final long secondsBetweenBlocks, final ProtocolSpecBuilder builder) { + final long secondsBetweenBlocks, final ProtocolSpecBuilder builder, final Clock clock) { return builder .changeConsensusContextType( - difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), - difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks), + difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock), + difficultyCalculator -> ibftBlockHeaderValidator(secondsBetweenBlocks, clock), MainnetBlockBodyValidator::new, MainnetBlockValidator::new, MainnetBlockImporter::new, diff --git a/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java index fd44e0b010..bf4ef179e5 100644 --- a/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/IbftBlockHeaderValidationRulesetFactoryTest.java @@ -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 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 validator = - IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5); + IbftBlockHeaderValidationRulesetFactory.ibftBlockHeaderValidator(5, TestClock.fixed()); assertThat( validator.validateHeader( diff --git a/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java index 2163e0fe71..7ebdf72125 100644 --- a/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java +++ b/consensus/ibftlegacy/src/test/java/tech/pegasys/pantheon/consensus/ibftlegacy/blockcreation/IbftBlockCreatorTest.java @@ -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 protocolSchedule = IbftProtocolSchedule.create( GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}") .getConfigOptions(), - false); + false, + testClock); final ProtocolContext 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 rules = - IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator(0); + IbftBlockHeaderValidationRulesetFactory.ibftProposedBlockValidator(0, testClock); final boolean validationResult = rules.validateHeader( diff --git a/errorprone-checks/src/main/java/tech/pegasys/errorpronechecks/BannedMethod.java b/errorprone-checks/src/main/java/tech/pegasys/errorpronechecks/BannedMethod.java index 28e065c70a..90cbff84ef 100644 --- a/errorprone-checks/src/main/java/tech/pegasys/errorpronechecks/BannedMethod.java +++ b/errorprone-checks/src/main/java/tech/pegasys/errorpronechecks/BannedMethod.java @@ -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, 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 diff --git a/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodNegativeCases.java b/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodNegativeCases.java index e8e236a2d6..9c2965ea94 100644 --- a/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodNegativeCases.java +++ b/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodNegativeCases.java @@ -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(); + } + } diff --git a/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodPositiveCases.java b/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodPositiveCases.java index 31818f8119..b183e0f02f 100644 --- a/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodPositiveCases.java +++ b/errorprone-checks/src/test/resources/tech/pegasys/errorpronechecks/BannedMethodPositiveCases.java @@ -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(); + } } diff --git a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java index 346101f9cf..c3f02961f4 100644 --- a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/BlockTransactionSelectorTest.java @@ -93,7 +93,8 @@ public class BlockTransactionSelectorTest { @Test public void emptyPendingTransactionsResultsInEmptyVettingResult() { final ProtocolSchedule protocolSchedule = - FixedDifficultyProtocolSchedule.create(GenesisConfigFile.development().getConfigOptions()); + FixedDifficultyProtocolSchedule.create( + GenesisConfigFile.development().getConfigOptions(), TestClock.fixed()); final TransactionProcessor mainnetTransactionProcessor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor(); diff --git a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java index ad80f58bd9..15eaa78da9 100644 --- a/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/tech/pegasys/pantheon/ethereum/blockcreation/EthHashBlockCreatorTest.java @@ -58,8 +58,10 @@ public class EthHashBlockCreatorTest { BigInteger.valueOf(42), Function.identity(), PrivacyParameters.DEFAULT, - false) + false, + TestClock.fixed()) .createProtocolSchedule()) + .clock(TestClock.fixed()) .build(); @Test diff --git a/ethereum/core/src/jmh/java/tech/pegasys/pantheon/ethereum/vm/operations/OperationBenchmarkHelper.java b/ethereum/core/src/jmh/java/tech/pegasys/pantheon/ethereum/vm/operations/OperationBenchmarkHelper.java index 8b7147ee62..8968b5ec6b 100644 --- a/ethereum/core/src/jmh/java/tech/pegasys/pantheon/ethereum/vm/operations/OperationBenchmarkHelper.java +++ b/ethereum/core/src/jmh/java/tech/pegasys/pantheon/ethereum/vm/operations/OperationBenchmarkHelper.java @@ -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++) { diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java index d9df25023d..885964ac3f 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedDifficultyProtocolSchedule.java @@ -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 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 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 create(final GenesisConfigOptions config) { - return create(config, PrivacyParameters.DEFAULT, false); + public static ProtocolSchedule create( + final GenesisConfigOptions config, final Clock clock) { + return create(config, PrivacyParameters.DEFAULT, false, clock); } } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidator.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidator.java index 0b4cbb33ae..f0fd9b5691 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidator.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidator.java @@ -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 create( - final DifficultyCalculator difficultyCalculator) { - return createValidator(difficultyCalculator).build(); + final DifficultyCalculator difficultyCalculator, final Clock clock) { + return createValidator(difficultyCalculator, clock).build(); } - public static BlockHeaderValidator createDaoValidator( - final DifficultyCalculator difficultyCalculator) { - return createValidator(difficultyCalculator) + static BlockHeaderValidator createDaoValidator( + final DifficultyCalculator 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 createValidator( - final DifficultyCalculator difficultyCalculator) { + final DifficultyCalculator difficultyCalculator, final Clock clock) { return new BlockHeaderValidator.Builder() .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()); } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java index 181203303f..f282092ba2 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSchedule.java @@ -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 create() { + public static ProtocolSchedule 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 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( + 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 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 fromConfig(final GenesisConfigOptions config) { - return fromConfig(config, PrivacyParameters.DEFAULT, false); + public static ProtocolSchedule fromConfig( + final GenesisConfigOptions config, final Clock clock) { + return fromConfig(config, PrivacyParameters.DEFAULT, false, clock); } } diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java index e99d9bbe1f..1c6a0c8a15 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java @@ -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 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() @@ -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 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 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 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 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 spuriousDragonDefinition( final Optional 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 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 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 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 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) diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleBuilder.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleBuilder.java index c6d3ddb611..2b71b6d505 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleBuilder.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/ProtocolScheduleBuilder.java @@ -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 { private final Optional defaultChainId; private final PrivacyParameters privacyParameters; private final boolean isRevertReasonEnabled; + private final Clock clock; public ProtocolScheduleBuilder( final GenesisConfigOptions config, final BigInteger defaultChainId, final Function, ProtocolSpecBuilder> 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> 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 { final Optional defaultChainId, final Function, ProtocolSpecBuilder> 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 createProtocolSchedule() { - final Optional chainId = - config.getChainId().map(Optional::of).orElse(defaultChainId); + final Optional chainId = config.getChainId().or(() -> defaultChainId); final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule<>(chainId); validateForkOrdering(); @@ -79,12 +91,12 @@ public class ProtocolScheduleBuilder { 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 { 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 { 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 { chainId, config.getContractSizeLimit(), config.getEvmStackSize(), - isRevertReasonEnabled)); + isRevertReasonEnabled, + clock)); addProtocolSpec( protocolSchedule, config.getConstantinopleBlockNumber(), @@ -132,7 +145,8 @@ public class ProtocolScheduleBuilder { chainId, config.getContractSizeLimit(), config.getEvmStackSize(), - isRevertReasonEnabled)); + isRevertReasonEnabled, + clock)); addProtocolSpec( protocolSchedule, config.getConstantinopleFixBlockNumber(), @@ -140,7 +154,8 @@ public class ProtocolScheduleBuilder { chainId, config.getContractSizeLimit(), config.getEvmStackSize(), - isRevertReasonEnabled)); + isRevertReasonEnabled, + clock)); addProtocolSpec( protocolSchedule, config.getIstanbulBlockNumber(), @@ -148,7 +163,8 @@ public class ProtocolScheduleBuilder { chainId, config.getContractSizeLimit(), config.getEvmStackSize(), - isRevertReasonEnabled)); + isRevertReasonEnabled, + clock)); LOG.info("Protocol schedule created with milestones: {}", protocolSchedule.listMilestones()); return protocolSchedule; diff --git a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampBoundedByFutureParameter.java b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampBoundedByFutureParameter.java index 2d7a77e133..add41a9f66 100644 --- a/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampBoundedByFutureParameter.java +++ b/ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampBoundedByFutureParameter.java @@ -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 {}", diff --git a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java index 8263349f54..a7d889355d 100644 --- a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/ExecutionContextTestFixture.java @@ -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 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) { diff --git a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java index 9e1c3876a6..5dbf2ba306 100644 --- a/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java +++ b/ethereum/core/src/test-support/java/tech/pegasys/pantheon/ethereum/core/TestCodeExecutor.java @@ -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 protocolSchedule) { - fixture = ExecutionContextTestFixture.builder().protocolSchedule(protocolSchedule).build(); + fixture = + ExecutionContextTestFixture.builder() + .protocolSchedule(protocolSchedule) + .clock(TestClock.fixed()) + .build(); } public MessageFrame executeCode( diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java index 1669f047cb..45d95cd10f 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/chain/GenesisStateTest.java @@ -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())) diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java index df66f56073..ca406c3c6a 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java @@ -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 schedule = - FixedDifficultyProtocolSchedule.create(GenesisConfigFile.development().getConfigOptions()); + FixedDifficultyProtocolSchedule.create( + GenesisConfigFile.development().getConfigOptions(), TestClock.fixed()); final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidatorTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidatorTest.java index c31517898c..ec95ff1b16 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidatorTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetBlockHeaderValidatorTest.java @@ -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 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 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 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 headerValidator = - MainnetBlockHeaderValidator.create(MainnetDifficultyCalculators.BYZANTIUM); + MainnetBlockHeaderValidator.create( + MainnetDifficultyCalculators.BYZANTIUM, TestClock.fixed()); assertThat( headerValidator.validateHeader( ValidationTestUtils.readHeader(4400001), diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java index 6834be93fc..1e7547c9e6 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolScheduleTest.java @@ -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 sched = MainnetProtocolSchedule.create(); + final ProtocolSchedule 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 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 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"); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRuleTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRuleTest.java index 88e853dc5e..cc2a6661da 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRuleTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/ProofOfWorkValidationRuleTest.java @@ -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 protocolSchedule = MainnetProtocolSchedule.create(); + final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(TestClock.fixed()); return ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); } } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java index b6aac2e3ab..65faf00a33 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/mainnet/headervalidationrules/TimestampValidationRuleTest.java @@ -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) diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java index 4d2ff6c6b9..0eb18f036d 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/ReferenceTestProtocolSchedules.java @@ -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 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(); } } diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java index b144eed64c..5596917d8c 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/VMReferenceTest.java @@ -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 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)); diff --git a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ConstantinopleSStoreOperationGasCostTest.java b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ConstantinopleSStoreOperationGasCostTest.java index 2aa6fe735f..9c20cb1715 100644 --- a/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ConstantinopleSStoreOperationGasCostTest.java +++ b/ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/vm/operations/ConstantinopleSStoreOperationGasCostTest.java @@ -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 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() { diff --git a/ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/EthPeer.java b/ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/EthPeer.java index 68c9fbe5a5..f65f36512e 100644 --- a/ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/EthPeer.java +++ b/ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/EthPeer.java @@ -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) { diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTest.java index 9dee76e5b9..bbf19486ea 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTest.java @@ -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 protocolSchdeule = MainnetProtocolSchedule.create(); + final ProtocolSchedule protocolSchdeule = + MainnetProtocolSchedule.create(TestClock.fixed()); for (final NewBlockMessage msg : messageSentCaptor.getAllValues()) { assertThat(msg.block(protocolSchdeule)).isEqualTo(minedBlock); assertThat(msg.totalDifficulty(protocolSchdeule)).isEqualTo(expectedTotalDifficulty); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java index f55c4abc35..5f25be8c5c 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/EthProtocolManagerTestUtil.java @@ -65,7 +65,8 @@ public class EthProtocolManagerTestUtil { } public static EthProtocolManager create(final EthScheduler ethScheduler) { - final ProtocolSchedule protocolSchedule = MainnetProtocolSchedule.create(); + final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(TestClock.fixed()); final GenesisConfigFile config = GenesisConfigFile.mainnet(); final GenesisState genesisState = GenesisState.fromConfig(config, protocolSchedule); final Blockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java index e98313e6fa..b267806825 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/BlockchainSetupUtil.java @@ -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 { } public static BlockchainSetupUtil forTesting() { - final ProtocolSchedule protocolSchedule = MainnetProtocolSchedule.create(); + final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(TestClock.fixed()); final TemporaryFolder temp = new TemporaryFolder(); try { temp.create(); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java index 07318cdaf6..953fceb36d 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockBodiesMessageTest.java @@ -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)); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java index c018da2238..e5c104d20f 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/BlockHeadersMessageTest.java @@ -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 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)); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/NewBlockMessageTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/NewBlockMessageTest.java index 8a89bac981..020d86ef85 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/NewBlockMessageTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/messages/NewBlockMessageTest.java @@ -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 protocolSchedule = MainnetProtocolSchedule.create(); + private static final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(TestClock.fixed()); @Test public void roundTripNewBlockMessage() { diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java index 81b8f97309..3eaff2ac0f 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java @@ -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); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java index fc8c011db9..f5e0a0a9d7 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/ChainHeadTrackerTest.java @@ -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 protocolSchedule = FixedDifficultyProtocolSchedule.create( - GenesisConfigFile.development().getConfigOptions(), false); + GenesisConfigFile.development().getConfigOptions(), false, TestClock.fixed()); private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class); private final ChainHeadTracker chainHeadTracker = diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java index 424bad6938..ecf05aba37 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java @@ -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 localBlockchainSetup = BlockchainSetupUtil.forTesting(); localBlockchain = localBlockchainSetup.getBlockchain(); - final ProtocolSchedule protocolSchedule = MainnetProtocolSchedule.create(); + final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(TestClock.fixed()); final ProtocolContext protocolContext = new ProtocolContext<>(localBlockchain, localWorldState, null); ethProtocolManager = diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java index 68ef637161..49ff1faad0 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java @@ -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 protocolSchedule = MainnetProtocolSchedule.create(); + private final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(TestClock.fixed()); private static final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java index 22a5324eff..e1efc4f627 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java @@ -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; diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/worldstate/WorldStateDownloaderTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/worldstate/WorldStateDownloaderTest.java index b80dfdb78f..1ac5b4ae66 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/worldstate/WorldStateDownloaderTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/worldstate/WorldStateDownloaderTest.java @@ -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 diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java index 8fd3d66ea7..919665970a 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNode.java @@ -95,7 +95,7 @@ public class TestNode implements Closeable { final GenesisConfigFile genesisConfigFile = GenesisConfigFile.development(); final ProtocolSchedule 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()) diff --git a/ethereum/graphql/src/test/java/tech/pegasys/pantheon/ethereum/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/graphql/src/test/java/tech/pegasys/pantheon/ethereum/graphql/AbstractEthGraphQLHttpServiceTest.java index 1d07b12f52..3437c96996 100644 --- a/ethereum/graphql/src/test/java/tech/pegasys/pantheon/ethereum/graphql/AbstractEthGraphQLHttpServiceTest.java +++ b/ethereum/graphql/src/test/java/tech/pegasys/pantheon/ethereum/graphql/AbstractEthGraphQLHttpServiceTest.java @@ -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(); diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java index 41c801dc02..52508e7c69 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/BlockchainImporter.java @@ -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 = diff --git a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java index d22bc1d15d..f3a641622c 100644 --- a/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcTestMethodsFactory.java @@ -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, diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java index 302c80e212..cc9bb80952 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/AbstractEthJsonRpcHttpServiceTest.java @@ -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, diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java index cd42b7f540..7c69743e49 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java @@ -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), diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceLoginTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceLoginTest.java index cf43813b47..b9288d18aa 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceLoginTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceLoginTest.java @@ -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), diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java index 825c102703..17520ec251 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceRpcApisTest.java @@ -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), diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java index 1ef60e6b78..92c2c2e137 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/JsonRpcHttpServiceTest.java @@ -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), diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgent.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgent.java index b48a5e7c45..4036ab0e33 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgent.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgent.java @@ -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 peerRequirements = new CopyOnWriteArrayList<>(); private final PeerPermissions peerPermissions; private final Optional natManager; + private final Clock clock; private final MetricsSystem metricsSystem; /* The peer controller, which takes care of the state machine of peers. */ protected Optional controller = Optional.empty(); @@ -87,20 +89,23 @@ public abstract class PeerDiscoveryAgent { final DiscoveryConfiguration config, final PeerPermissions peerPermissions, final Optional 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()); }); } diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/VertxPeerDiscoveryAgent.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/VertxPeerDiscoveryAgent.java index 693fae42c0..b147e0a0c7 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/VertxPeerDiscoveryAgent.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/VertxPeerDiscoveryAgent.java @@ -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 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; diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketData.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketData.java index b89593e1d0..c18a4d6572 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketData.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketData.java @@ -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 diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketData.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketData.java index bc2d1d6e8c..11ee7b366a 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketData.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketData.java @@ -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 peers) { - return new NeighborsPacketData( - peers, System.currentTimeMillis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS); + public static NeighborsPacketData create(final List peers, final Clock clock) { + return new NeighborsPacketData(peers, clock.millis() + PacketData.DEFAULT_EXPIRATION_PERIOD_MS); } public static NeighborsPacketData readFrom(final RLPInput in) { diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryController.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryController.java index 38f869d27c..150e572147 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryController.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryController.java @@ -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 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 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 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 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 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; + } } } diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketData.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketData.java index eee997ab8c..e91c444fdb 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketData.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketData.java @@ -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) { diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketData.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketData.java index b26bd3dba8..a1576682fb 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketData.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketData.java @@ -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) { diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java index bc58d90cc5..495a2687ef 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java @@ -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 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; diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgent.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgent.java index 118a644873..74b793edc0 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgent.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgent.java @@ -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 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 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 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 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; + } } } diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnection.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnection.java index 868659f3a2..c9492a9c7c 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnection.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnection.java @@ -24,18 +24,19 @@ public abstract class RlpxConnection { private final long initiatedAt; protected final CompletableFuture future; - private RlpxConnection(final CompletableFuture future) { + private RlpxConnection(final CompletableFuture 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 future) { - return new LocallyInitiatedRlpxConnection(peer, future); + final Peer peer, final CompletableFuture 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 future) { - super(future); + final Peer peer, final CompletableFuture future, final long initiatedAt) { + super(future, initiatedAt); this.peer = peer; } diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/netty/NettyConnectionInitializer.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/netty/NettyConnectionInitializer.java index a86ff6a525..aa3b914760 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/netty/NettyConnectionInitializer.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/netty/NettyConnectionInitializer.java @@ -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 connect(final Peer peer) { final CompletableFuture connectionFuture = new CompletableFuture<>(); - if (peer instanceof DiscoveryPeer) { - ((DiscoveryPeer) peer).setLastAttemptedConnection(System.currentTimeMillis()); - } - final EnodeURL enode = peer.getEnodeURL(); new Bootstrap() .group(workers) diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgentTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgentTest.java index f3f9a8de68..c7086e4f4d 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgentTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgentTest.java @@ -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 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); } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBondingTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBondingTest.java index 6e458c0261..7e9a0022c2 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBondingTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBondingTest.java @@ -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); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBootstrappingTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBootstrappingTest.java index a549991434..9d9f241dfd 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBootstrappingTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBootstrappingTest.java @@ -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()); } } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryObserversTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryObserversTest.java index cb084aefed..b36c202e34 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryObserversTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryObserversTest.java @@ -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 events = new ArrayList<>(10); agent.observePeerBondedEvents(events::add); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryPacketSedesTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryPacketSedesTest.java index 7e830443d8..b48a3c9549 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryPacketSedesTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryPacketSedesTest.java @@ -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 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()); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTestHelper.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTestHelper.java index 7840ef1942..0e2a18c876 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTestHelper.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTestHelper.java @@ -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 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 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 bootstrapPeers, final PeerPermissions peerPermissions) { + final List 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 bootstrapPeers) { - final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers); + public MockPeerDiscoveryAgent createDiscoveryAgent( + final List bootstrapPeers, final Clock clock) { + final AgentBuilder agentBuilder = agentBuilder().bootstrapPeers(bootstrapPeers).clock(clock); return createDiscoveryAgent(agentBuilder); } @@ -179,6 +203,7 @@ public class PeerDiscoveryTestHelper { private List bootnodes = Collections.emptyList(); private boolean active = true; private PeerPermissions peerPermissions = PeerPermissions.noop(); + private Clock clock = TestClock.fixed(); private AgentBuilder( final Map 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); } } } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTimestampsTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTimestampsTest.java index 4206fb9635..89e70e3612 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTimestampsTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTimestampsTest.java @@ -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(); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketDataTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketDataTest.java index 9d58ca24df..3a7831aedb 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketDataTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/FindNeighborsPacketDataTest.java @@ -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(); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPacketDataFactory.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPacketDataFactory.java index 230b9ff88c..8565513024 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPacketDataFactory.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPacketDataFactory.java @@ -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); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPeerDiscoveryAgent.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPeerDiscoveryAgent.java index 09f9be1312..8452a8bc98 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPeerDiscoveryAgent.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPeerDiscoveryAgent.java @@ -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 agentNetwork) { - super(keyPair, config, peerPermissions, Optional.empty(), new NoOpMetricsSystem()); + final Map agentNetwork, + final Clock clock) { + super(keyPair, config, peerPermissions, Optional.empty(), new NoOpMetricsSystem(), clock); this.agentNetwork = agentNetwork; } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketDataTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketDataTest.java index 996055131b..cd8d4665c7 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketDataTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/NeighborsPacketDataTest.java @@ -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 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 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 peers = Arrays.asList(DiscoveryPeer.fromEnode(enode()), DiscoveryPeer.fromEnode(enode())); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java index 59e0653699..7b3cfc30d9 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java @@ -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 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 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 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 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 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 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 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 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()); } } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryTableRefreshTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryTableRefreshTest.java index 7a9d7f79e4..b78f207c82 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryTableRefreshTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryTableRefreshTest.java @@ -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 captor = ArgumentCaptor.forClass(Packet.class); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketDataTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketDataTest.java index 4672717b07..28f937d12a 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketDataTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PingPacketDataTest.java @@ -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(); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketDataTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketDataTest.java index 172db39c6b..6b5d509563 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketDataTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PongPacketDataTest.java @@ -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"); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java index d4ccace260..51972270dc 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java @@ -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() { diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/NetworkingServiceLifecycleTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/NetworkingServiceLifecycleTest.java index 194aa97ab1..17aad220d0 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/NetworkingServiceLifecycleTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/NetworkingServiceLifecycleTest.java @@ -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))); } } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java index 6af15bc806..205b70a44e 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java @@ -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))); } } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgentTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgentTest.java index 6dd972d23a..778fa6fe41 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgentTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgentTest.java @@ -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(); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnectionTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnectionTest.java index dceff248ea..4f76186a60 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnectionTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/connections/RlpxConnectionTest.java @@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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(); diff --git a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java index cb2a1c81a9..7386df0522 100644 --- a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java @@ -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 protocolSchedule = MainnetProtocolSchedule.create(); + final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(Clock.systemUTC()); final String emptyContractFile = Resources.toString(this.getClass().getResource(resourceName), UTF_8); diff --git a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java index 7d83df8375..4d19af447e 100644 --- a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java @@ -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 protocolSchedule = MainnetProtocolSchedule.create(); + final ProtocolSchedule protocolSchedule = + MainnetProtocolSchedule.create(Clock.systemUTC()); final String emptyContractFile = Resources.toString(this.getClass().getResource(resourceName), UTF_8); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java b/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java index ce8f09bb56..129dcd0aad 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/Pantheon.java @@ -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( diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java index 1349654ed7..2c394b4239 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java @@ -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 = Optional.empty(); private Collection 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(); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java index 76005dbdca..51c1d9be70 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java @@ -622,6 +622,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable { private Optional permissioningConfiguration; private Collection staticNodes; private PantheonController pantheonController; + private Clock clock; private final Supplier 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 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); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java index 269b5e8427..49f7beee54 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/CliquePantheonControllerBuilder.java @@ -121,7 +121,11 @@ public class CliquePantheonControllerBuilder extends PantheonControllerBuilder createProtocolSchedule() { return CliqueProtocolSchedule.create( - genesisConfig.getConfigOptions(), nodeKeys, privacyParameters, isRevertReasonEnabled); + genesisConfig.getConfigOptions(), + nodeKeys, + privacyParameters, + isRevertReasonEnabled, + clock); } @Override diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java index 2112e81106..fa88a252c9 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftLegacyPantheonControllerBuilder.java @@ -64,7 +64,7 @@ public class IbftLegacyPantheonControllerBuilder extends PantheonControllerBuild @Override protected ProtocolSchedule createProtocolSchedule() { return IbftProtocolSchedule.create( - genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled); + genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled, clock); } @Override diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java index e985947e52..9a261260ca 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/IbftPantheonControllerBuilder.java @@ -211,7 +211,7 @@ public class IbftPantheonControllerBuilder extends PantheonControllerBuilder createProtocolSchedule() { return IbftProtocolSchedule.create( - genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled); + genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled, clock); } @Override diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java index a77f17d5d5..e6c09d1ac2 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/controller/MainnetPantheonControllerBuilder.java @@ -86,6 +86,6 @@ public class MainnetPantheonControllerBuilder extends PantheonControllerBuilder< @Override protected ProtocolSchedule createProtocolSchedule() { return MainnetProtocolSchedule.fromConfig( - genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled); + genesisConfig.getConfigOptions(), privacyParameters, isRevertReasonEnabled, clock); } } diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java index 8e45bd6f63..8d59aa3bc9 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java @@ -178,6 +178,7 @@ public final class RunnerTest { .graphQLConfiguration(aheadGraphQLConfiguration) .webSocketConfiguration(aheadWebSocketConfiguration) .metricsConfiguration(aheadMetricsConfiguration) + .clock(TestClock.fixed()) .dataDir(dbAhead) .build(); try { diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java b/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java index a823c88a47..1b051349d7 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/cli/CommandTestAbstract.java @@ -45,6 +45,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration; import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration; import tech.pegasys.pantheon.services.PantheonPluginContextImpl; +import tech.pegasys.pantheon.testutil.TestClock; import tech.pegasys.pantheon.util.BlockExporter; import tech.pegasys.pantheon.util.BlockImporter; import tech.pegasys.pantheon.util.bytes.BytesValue; @@ -55,6 +56,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.nio.file.Path; +import java.time.Clock; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -85,6 +87,7 @@ public abstract class CommandTestAbstract { protected final ByteArrayOutputStream commandErrorOutput = new ByteArrayOutputStream(); private final PrintStream errPrintStream = new PrintStream(commandErrorOutput); + private final Clock testClock = new TestClock(); private final HashMap environment = new HashMap<>(); @Mock protected RunnerBuilder mockRunnerBuilder; @@ -178,6 +181,7 @@ public abstract class CommandTestAbstract { when(mockRunnerBuilder.metricsSystem(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.metricsConfiguration(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.staticNodes(any())).thenReturn(mockRunnerBuilder); + when(mockRunnerBuilder.clock(any())).thenReturn(mockRunnerBuilder); when(mockRunnerBuilder.build()).thenReturn(mockRunner); } @@ -224,6 +228,7 @@ public abstract class CommandTestAbstract { mockControllerBuilderFactory, keyLoader, mockPantheonPluginContext, + testClock, environment); // parse using Ansi.OFF to be able to assert on non formatted output results @@ -253,6 +258,7 @@ public abstract class CommandTestAbstract { final PantheonController.Builder controllerBuilderFactory, final KeyLoader keyLoader, final PantheonPluginContextImpl pantheonPluginContext, + final Clock clock, final Map environment) { super( mockLogger, @@ -261,6 +267,7 @@ public abstract class CommandTestAbstract { mockRunnerBuilder, controllerBuilderFactory, pantheonPluginContext, + clock, environment); this.keyLoader = keyLoader; } diff --git a/pantheon/src/test/java/tech/pegasys/pantheon/cli/operator/OperatorSubCommandTest.java b/pantheon/src/test/java/tech/pegasys/pantheon/cli/operator/OperatorSubCommandTest.java index 39f539e30b..47b60c5541 100644 --- a/pantheon/src/test/java/tech/pegasys/pantheon/cli/operator/OperatorSubCommandTest.java +++ b/pantheon/src/test/java/tech/pegasys/pantheon/cli/operator/OperatorSubCommandTest.java @@ -13,7 +13,6 @@ package tech.pegasys.pantheon.cli.operator; import static java.lang.String.format; -import static java.lang.System.currentTimeMillis; import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.Files.createTempDirectory; import static java.util.Arrays.asList; @@ -28,6 +27,7 @@ import static tech.pegasys.pantheon.cli.subcommands.operator.OperatorSubCommand. import static tech.pegasys.pantheon.cli.subcommands.operator.OperatorSubCommand.GENERATE_BLOCKCHAIN_CONFIG_SUBCOMMAND_NAME; import tech.pegasys.pantheon.cli.CommandTestAbstract; +import tech.pegasys.pantheon.testutil.TestClock; import java.io.File; import java.io.IOException; @@ -70,7 +70,7 @@ public class OperatorSubCommandTest extends CommandTestAbstract { @Before public void init() throws IOException { - tmpOutputDirectoryPath = createTempDirectory(format("output-%d", currentTimeMillis())); + tmpOutputDirectoryPath = createTempDirectory(format("output-%d", TestClock.fixed().millis())); } @Test diff --git a/testutil/src/main/java/tech/pegasys/pantheon/testutil/TestClock.java b/testutil/src/main/java/tech/pegasys/pantheon/testutil/TestClock.java index 1ff18a8c82..291308047d 100644 --- a/testutil/src/main/java/tech/pegasys/pantheon/testutil/TestClock.java +++ b/testutil/src/main/java/tech/pegasys/pantheon/testutil/TestClock.java @@ -17,14 +17,20 @@ import java.time.Instant; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.temporal.TemporalUnit; +import java.util.function.Supplier; + +import com.google.common.base.Suppliers; public class TestClock extends Clock { + + private static final Supplier fixedNow = + Suppliers.memoize(() -> Clock.fixed(Instant.now(), ZoneOffset.UTC)); + private Instant now = fixedNow.get().instant(); + public static Clock fixed() { - return Clock.fixed(Instant.ofEpochSecond(10_000_000), ZoneId.systemDefault()); + return fixedNow.get(); } - private Instant now = Instant.ofEpochSecond(24982948294L); - @Override public ZoneId getZone() { return ZoneOffset.UTC;