diff --git a/CHANGELOG.md b/CHANGELOG.md index f60fe46e32b..5181bdfef07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * Added new endpoints to get miner data, `eth_getMinerDataByBlockHash` and `eth_getMinerDataByBlockNumber`. [\#1538](https://github.com/hyperledger/besu/pull/1538) * Added direct support for OpenTelemetry metrics [\#1492](https://github.com/hyperledger/besu/pull/1492) * Added support for `qip714block` config parameter in genesis file, paving the way towards permissioning interoperability between Besu and Quorum. [\#1545](https://github.com/hyperledger/besu/pull/1545) +* Added new CLI option `--compatibility-eth64-forkid-enabled`. [\#1542](https://github.com/hyperledger/besu/pull/1542) ### Bug Fixes diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java index 5664af4f755..b838f6646d0 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java @@ -31,6 +31,8 @@ public class EthProtocolOptions implements CLIOptions private static final String MAX_GET_NODE_DATA_FLAG = "--Xewp-max-get-node-data"; private static final String MAX_GET_POOLED_TRANSACTIONS = "--Xewp-max-get-pooled-transactions"; private static final String ETH_65_ENABLED = "--Xeth-65-enabled"; + private static final String LEGACY_ETH_64_FORK_ID_ENABLED = + "--compatibility-eth64-forkid-enabled"; @CommandLine.Option( hidden = true, @@ -80,10 +82,17 @@ public class EthProtocolOptions implements CLIOptions @CommandLine.Option( hidden = true, names = {ETH_65_ENABLED}, - paramLabel = "", + paramLabel = "", description = "Enable the Eth/65 subprotocol. (default: ${DEFAULT-VALUE})") private Boolean eth65Enabled = EthProtocolConfiguration.DEFAULT_ETH_65_ENABLED; + @CommandLine.Option( + names = {LEGACY_ETH_64_FORK_ID_ENABLED}, + paramLabel = "", + description = "Enable the legacy Eth/64 fork id. (default: ${DEFAULT-VALUE})") + private Boolean legacyEth64ForkIdEnabled = + EthProtocolConfiguration.DEFAULT_LEGACY_ETH_64_FORK_ID_ENABLED; + private EthProtocolOptions() {} public static EthProtocolOptions create() { @@ -98,6 +107,7 @@ public static EthProtocolOptions fromConfig(final EthProtocolConfiguration confi options.maxGetNodeData = PositiveNumber.fromInt(config.getMaxGetNodeData()); options.maxGetPooledTransactions = PositiveNumber.fromInt(config.getMaxGetPooledTransactions()); options.eth65Enabled = config.isEth65Enabled(); + options.legacyEth64ForkIdEnabled = config.isLegacyEth64ForkIdEnabled(); return options; } @@ -110,6 +120,7 @@ public EthProtocolConfiguration toDomainObject() { .maxGetNodeData(maxGetNodeData) .maxGetPooledTransactions(maxGetPooledTransactions) .eth65Enabled(eth65Enabled) + .legacyEth64ForkIdEnabled(legacyEth64ForkIdEnabled) .build(); } @@ -126,6 +137,7 @@ public List getCLIOptions() { OptionParser.format(maxGetNodeData.getValue()), MAX_GET_POOLED_TRANSACTIONS, OptionParser.format(maxGetPooledTransactions.getValue()), - ETH_65_ENABLED + "=" + eth65Enabled); + ETH_65_ENABLED + "=" + eth65Enabled, + LEGACY_ETH_64_FORK_ID_ENABLED + "=" + legacyEth64ForkIdEnabled); } } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index b4194882c98..da600628094 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -3789,4 +3789,47 @@ public void assertThatAllPortsSpecifiedSucceeds() { "--miner-stratum-port=15"); assertThat(commandErrorOutput.toString()).isEmpty(); } + + @Test + public void compatibilityEth64ForkIdEnabledMustBeUsed() { + parseCommand("--compatibility-eth64-forkid-enabled"); + verify(mockControllerBuilder) + .ethProtocolConfiguration(ethProtocolConfigurationArgumentCaptor.capture()); + assertThat(ethProtocolConfigurationArgumentCaptor.getValue().isLegacyEth64ForkIdEnabled()) + .isTrue(); + assertThat(commandOutput.toString()).isEmpty(); + assertThat(commandErrorOutput.toString()).isEmpty(); + } + + @Test + public void compatibilityEth64ForkIdNotEnabledMustBeUsed() { + parseCommand("--compatibility-eth64-forkid-enabled=false"); + verify(mockControllerBuilder) + .ethProtocolConfiguration(ethProtocolConfigurationArgumentCaptor.capture()); + assertThat(ethProtocolConfigurationArgumentCaptor.getValue().isLegacyEth64ForkIdEnabled()) + .isFalse(); + assertThat(commandOutput.toString()).isEmpty(); + assertThat(commandErrorOutput.toString()).isEmpty(); + } + + @Test + public void assertThatCompatibilityEth64ForkIdIsNotEnabledByDefault() { + parseCommand(); + verify(mockControllerBuilder) + .ethProtocolConfiguration(ethProtocolConfigurationArgumentCaptor.capture()); + assertThat(ethProtocolConfigurationArgumentCaptor.getValue().isLegacyEth64ForkIdEnabled()) + .isFalse(); + assertThat(commandOutput.toString()).isEmpty(); + assertThat(commandErrorOutput.toString()).isEmpty(); + } + + @Test + public void assertThatCompatibilityEth64ForkIdIsPresentInHelpMessage() { + parseCommand("--help"); + assertThat(commandOutput.toString()) + .contains( + "--compatibility-eth64-forkid-enabled", + "Enable the legacy Eth/64 fork id. (default: false)"); + assertThat(commandErrorOutput.toString()).isEmpty(); + } } diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index d92693e2d36..2e6f5231b88 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -46,6 +46,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; import org.hyperledger.besu.ethereum.eth.sync.BlockBroadcaster; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -155,6 +156,7 @@ public abstract class CommandTestAbstract { @Captor protected ArgumentCaptor wsRpcConfigArgumentCaptor; @Captor protected ArgumentCaptor metricsConfigArgumentCaptor; @Captor protected ArgumentCaptor storageProviderArgumentCaptor; + @Captor protected ArgumentCaptor ethProtocolConfigurationArgumentCaptor; @Captor protected ArgumentCaptor permissioningConfigurationArgumentCaptor; diff --git a/besu/src/test/resources/everything_config.toml b/besu/src/test/resources/everything_config.toml index 3b32888c72b..6ac9c92c644 100644 --- a/besu/src/test/resources/everything_config.toml +++ b/besu/src/test/resources/everything_config.toml @@ -166,3 +166,6 @@ Xethstats-contact="contact@mail.n" # feature flags Xsecp256k1-native-enabled=false Xaltbn128-native-enabled=false + +# compatibility flags +compatibility-eth64-forkid-enabled=false \ No newline at end of file diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolConfiguration.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolConfiguration.java index 48c9b41955c..fc40cb2f66d 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolConfiguration.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolConfiguration.java @@ -28,6 +28,7 @@ public class EthProtocolConfiguration { public static final int DEFAULT_MAX_GET_NODE_DATA = 384; public static final int DEFAULT_MAX_GET_POOLED_TRANSACTIONS = 256; public static final boolean DEFAULT_ETH_65_ENABLED = false; + public static final boolean DEFAULT_LEGACY_ETH_64_FORK_ID_ENABLED = false; private final int maxGetBlockHeaders; private final int maxGetBlockBodies; @@ -35,6 +36,7 @@ public class EthProtocolConfiguration { private final int maxGetNodeData; private final int maxGetPooledTransactions; private final boolean eth65Enabled; + private final boolean legacyEth64ForkIdEnabled; public EthProtocolConfiguration( final int maxGetBlockHeaders, @@ -42,13 +44,15 @@ public EthProtocolConfiguration( final int maxGetReceipts, final int maxGetNodeData, final int maxGetPooledTransactions, - final boolean eth65Enabled) { + final boolean eth65Enabled, + final boolean legacyEth64ForkIdEnabled) { this.maxGetBlockHeaders = maxGetBlockHeaders; this.maxGetBlockBodies = maxGetBlockBodies; this.maxGetReceipts = maxGetReceipts; this.maxGetNodeData = maxGetNodeData; this.maxGetPooledTransactions = maxGetPooledTransactions; this.eth65Enabled = eth65Enabled; + this.legacyEth64ForkIdEnabled = legacyEth64ForkIdEnabled; } public static EthProtocolConfiguration defaultConfig() { @@ -58,7 +62,8 @@ public static EthProtocolConfiguration defaultConfig() { DEFAULT_MAX_GET_RECEIPTS, DEFAULT_MAX_GET_NODE_DATA, DEFAULT_MAX_GET_POOLED_TRANSACTIONS, - DEFAULT_ETH_65_ENABLED); + DEFAULT_ETH_65_ENABLED, + DEFAULT_LEGACY_ETH_64_FORK_ID_ENABLED); } public static Builder builder() { @@ -89,6 +94,10 @@ public boolean isEth65Enabled() { return eth65Enabled; } + public boolean isLegacyEth64ForkIdEnabled() { + return legacyEth64ForkIdEnabled; + } + @Override public boolean equals(final Object o) { if (this == o) { @@ -138,6 +147,8 @@ public static class Builder { PositiveNumber.fromInt(EthProtocolConfiguration.DEFAULT_MAX_GET_POOLED_TRANSACTIONS); private boolean eth65Enabled = EthProtocolConfiguration.DEFAULT_ETH_65_ENABLED; + private boolean legacyEth64ForkIdEnabled = + EthProtocolConfiguration.DEFAULT_LEGACY_ETH_64_FORK_ID_ENABLED; public Builder maxGetBlockHeaders(final PositiveNumber maxGetBlockHeaders) { this.maxGetBlockHeaders = maxGetBlockHeaders; @@ -169,6 +180,11 @@ public Builder eth65Enabled(final boolean eth65Enabled) { return this; } + public Builder legacyEth64ForkIdEnabled(final boolean legacyEth64ForkIdEnabled) { + this.legacyEth64ForkIdEnabled = legacyEth64ForkIdEnabled; + return this; + } + public EthProtocolConfiguration build() { return new EthProtocolConfiguration( maxGetBlockHeaders.getValue(), @@ -176,7 +192,8 @@ public EthProtocolConfiguration build() { maxGetReceipts.getValue(), maxGetNodeData.getValue(), maxGetPooledTransactions.getValue(), - eth65Enabled); + eth65Enabled, + legacyEth64ForkIdEnabled); } } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java index 1a638b2326b..6aa0667ce55 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java @@ -139,7 +139,10 @@ public EthProtocolManager( peerValidators, fastSyncEnabled, scheduler, - new ForkIdManager(blockchain, Collections.emptyList())); + new ForkIdManager( + blockchain, + Collections.emptyList(), + ethereumWireProtocolConfiguration.isLegacyEth64ForkIdEnabled())); } public EthProtocolManager( @@ -167,7 +170,8 @@ public EthProtocolManager( peerValidators, fastSyncEnabled, scheduler, - new ForkIdManager(blockchain, forks)); + new ForkIdManager( + blockchain, forks, ethereumWireProtocolConfiguration.isLegacyEth64ForkIdEnabled())); } public EthContext ethContext() { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkId.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkId.java index ce003730545..4ae0dc6d4aa 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkId.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkId.java @@ -29,7 +29,7 @@ public class ForkId { final Bytes next; Bytes forkIdRLP; - protected ForkId(final Bytes hash, final Bytes next) { + public ForkId(final Bytes hash, final Bytes next) { this.hash = hash; this.next = next; createForkIdRLP(); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java index 79723feec3a..d8846f3a627 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java @@ -42,16 +42,19 @@ public class ForkIdManager { private final boolean onlyZerosForkBlocks; private final long highestKnownFork; private Bytes genesisHashCrc; + private final boolean legacyEth64; - public ForkIdManager(final Blockchain blockchain, final List nonFilteredForks) { + public ForkIdManager( + final Blockchain blockchain, final List nonFilteredForks, final boolean legacyEth64) { checkNotNull(blockchain); checkNotNull(nonFilteredForks); this.chainHeadSupplier = blockchain::getChainHeadBlockNumber; this.genesisHash = blockchain.getGenesisBlock().getHash(); this.forkAndHashList = new ArrayList<>(); + this.legacyEth64 = legacyEth64; this.forks = nonFilteredForks.stream() - .filter(fork -> fork > 0) + .filter(fork -> fork > 0L) .distinct() .sorted() .collect(Collectors.toUnmodifiableList()); @@ -61,6 +64,9 @@ public ForkIdManager(final Blockchain blockchain, final List nonFilteredFo } public ForkId computeForkId() { + if (legacyEth64) { + return forkAndHashList.isEmpty() ? null : forkAndHashList.get(forkAndHashList.size() - 1); + } final long head = chainHeadSupplier.getAsLong(); for (final ForkId forkId : forkAndHashList) { if (head < forkId.getNext()) { diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdBackwardCompatibilityTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdBackwardCompatibilityTest.java new file mode 100644 index 00000000000..b057f607da9 --- /dev/null +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdBackwardCompatibilityTest.java @@ -0,0 +1,127 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.GenesisHash; +import static org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.mockBlockchain; + +import org.hyperledger.besu.ethereum.eth.manager.ForkId; +import org.hyperledger.besu.ethereum.eth.manager.ForkIdManager; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.tuweni.bytes.Bytes; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class ForkIdBackwardCompatibilityTest { + private static final Logger LOG = LogManager.getLogger(); + + private final String name; + private final String genesisHash; + private final long head; + private final List forks; + private final boolean legacyEth64; + private final ForkId wantForkId; + + public ForkIdBackwardCompatibilityTest( + final String name, + final String genesisHash, + final long head, + final List forks, + final boolean legacyEth64, + final ForkId wantForkId) { + this.name = name; + this.genesisHash = genesisHash; + this.head = head; + this.forks = forks; + this.legacyEth64 = legacyEth64; + this.wantForkId = wantForkId; + } + + @Parameterized.Parameters(name = "{index}: {0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + { + "with 0 forks and legacyEth64=false", + GenesisHash.PRIVATE, + 2L, + Arrays.asList(0L, 0L, 4L, 5L, 6L), + false, + new ForkId(Bytes.fromHexString("0x190a55ad"), 4L) + }, + { + "with 0 forks and legacyEth64=true", + GenesisHash.PRIVATE, + 2L, + Arrays.asList(0L, 0L, 4L, 5L, 6L), + true, + null + }, + { + "with no 0 forks and legacyEth64=false", + GenesisHash.PRIVATE, + 2L, + Arrays.asList(4L, 5L, 6L), + false, + new ForkId(Bytes.fromHexString("0x190a55ad"), 4L) + }, + { + "with no 0 forks and legacyEth64=true", + GenesisHash.PRIVATE, + 2L, + Arrays.asList(4L, 5L, 6L), + true, + null + }, + { + "post head with 0 forks and legacyEth64=false", + GenesisHash.PRIVATE, + 8L, + Arrays.asList(0L, 0L, 4L, 5L, 6L), + false, + new ForkId(Bytes.fromHexString("0x033462fc"), 0L) + }, + { + "post head with 0 forks and legacyEth64=true", + GenesisHash.PRIVATE, + 8L, + Arrays.asList(0L, 0L, 4L, 5L, 6L), + true, + null + }, + }); + } + + @Test + public void assertBackwardCompatibilityWorks() { + LOG.info("Running test case {}", name); + final ForkIdManager forkIdManager = + new ForkIdManager(mockBlockchain(genesisHash, head), forks, legacyEth64); + final ForkId legacyForkId = + legacyEth64 + ? new LegacyForkIdManager(mockBlockchain(genesisHash, head), forks).getLatestForkId() + : null; + assertThat(forkIdManager.computeForkId()).isEqualTo(legacyEth64 ? legacyForkId : wantForkId); + } +} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdTestUtil.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdTestUtil.java new file mode 100644 index 00000000000..c0712df0a9c --- /dev/null +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdTestUtil.java @@ -0,0 +1,156 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.Block; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.ethereum.eth.manager.ForkId; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.LongSupplier; + +import org.apache.tuweni.bytes.Bytes; + +public class ForkIdTestUtil { + + public static Blockchain mockBlockchain(final String genesisHash, final long chainHeight) { + return mockBlockchain(genesisHash, () -> chainHeight); + } + + public static Blockchain mockBlockchain( + final String genesisHash, final LongSupplier chainHeightSupplier) { + final Blockchain mockchain = mock(Blockchain.class); + final BlockHeader mockHeader = mock(BlockHeader.class); + final Block block = new Block(mockHeader, null); + when(mockchain.getGenesisBlock()).thenReturn(block); + when(mockchain.getChainHeadBlockNumber()).thenReturn(chainHeightSupplier.getAsLong()); + when(mockHeader.getHash()).thenReturn(Hash.fromHexString(genesisHash)); + return mockchain; + } + + public static class GenesisHash { + public static final String MAINNET = + "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"; + public static final String ROPSTEN = + "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"; + public static final String RINKEBY = + "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; + public static final String GOERLI = + "0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a"; + public static final String PRIVATE = + "0x0000000000000000000000000000000000000000000000000000000000000000"; + } + + public static class Forks { + public static final List MAINNET = + Arrays.asList( + 1920000L, 1150000L, 2463000L, 2675000L, 2675000L, 4370000L, 7280000L, 7280000L, + 9069000L, 9200000L); + public static final List ROPSTEN = + Arrays.asList(0L, 0L, 10L, 1700000L, 4230000L, 4939394L, 6485846L, 7117117L); + public static final List RINKEBY = + Arrays.asList(1L, 2L, 3L, 3L, 1035301L, 3660663L, 4321234L, 5435345L); + public static final List GOERLI = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1561651L); + public static final List PRIVATE = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L); + } + + public static class ForkIds { + public static final List MAINNET = + Arrays.asList( + new ForkId(Bytes.fromHexString("0xfc64ec04"), 1150000L), // Unsynced + new ForkId(Bytes.fromHexString("0x97c2c34c"), 1920000L), // First Homestead block + new ForkId(Bytes.fromHexString("0x91d1f948"), 2463000L), // First DAO block + new ForkId(Bytes.fromHexString("0x7a64da13"), 2675000L), // First Tangerine block + new ForkId(Bytes.fromHexString("0x3edd5b10"), 4370000L), // First Spurious block + new ForkId(Bytes.fromHexString("0xa00bc324"), 7280000L), // First Byzantium block + new ForkId(Bytes.fromHexString("0x668db0af"), 9069000L), + new ForkId(Bytes.fromHexString("0x879d6e30"), 9200000L), + new ForkId(Bytes.fromHexString("0xe029e991"), 0L)); + public static final List ROPSTEN = + Arrays.asList( + new ForkId(Bytes.fromHexString("0x30c7ddbc"), 10L), + new ForkId(Bytes.fromHexString("0x63760190"), 1700000L), + new ForkId(Bytes.fromHexString("0x3ea159c7"), 4230000L), + new ForkId(Bytes.fromHexString("0x97b544f3"), 4939394L), + new ForkId(Bytes.fromHexString("0xd6e2149b"), 6485846L), + new ForkId(Bytes.fromHexString("0x4bc66396"), 7117117L), + new ForkId(Bytes.fromHexString("0x6727ef90"), 0L)); + public static final List RINKEBY = + Arrays.asList( + new ForkId(Bytes.fromHexString("0x3b8e0691"), 1L), + new ForkId(Bytes.fromHexString("0x60949295"), 2L), + new ForkId(Bytes.fromHexString("0x8bde40dd"), 3L), + new ForkId(Bytes.fromHexString("0xcb3a64bb"), 1035301L), + new ForkId(Bytes.fromHexString("0x8d748b57"), 3660663L), + new ForkId(Bytes.fromHexString("0xe49cab14"), 4321234L), + new ForkId(Bytes.fromHexString("0xafec6b27"), 5435345L), + new ForkId(Bytes.fromHexString("0xcbdb8838"), 0L)); + public static final List GOERLI = + Arrays.asList( + new ForkId(Bytes.fromHexString("0xa3f5ab08"), 1561651L), + new ForkId(Bytes.fromHexString("0xc25efa5c"), 0L)); + } + + public static class Network { + public static final Network MAINNET = network(GenesisHash.MAINNET, Forks.MAINNET); + public static final Network ROPSTEN = network(GenesisHash.ROPSTEN, Forks.ROPSTEN); + public static final Network RINKEBY = network(GenesisHash.RINKEBY, Forks.RINKEBY); + public static final Network GOERLI = network(GenesisHash.GOERLI, Forks.GOERLI); + public static final Network PRIVATE = network(GenesisHash.PRIVATE, Forks.PRIVATE); + public final String hash; + public final List forks; + + public Network(final String hash, final List forks) { + this.hash = hash; + this.forks = forks; + } + + public static Network network(final String hash, final List forks) { + return new Network(hash, forks); + } + } + + public static class PeerCheckCase { + public final String forkIdHash; + public final long forkIdNext; + public final boolean want; + + public PeerCheckCase(final String forkIdHash, final long forkIdNext, final boolean want) { + this.forkIdHash = forkIdHash; + this.forkIdNext = forkIdNext; + this.want = want; + } + } + + public static ForkId forkId(final String hash, final long next) { + return new ForkId(Bytes.fromHexString(hash), next); + } + + public static Optional wantForkId(final String hash, final long next) { + return Optional.of(forkId(hash, next)); + } + + public static Optional wantPeerCheck( + final String hash, final long next, final boolean want) { + return Optional.of(new PeerCheckCase(hash, next, want)); + } +} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/LegacyForkIdManager.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/LegacyForkIdManager.java new file mode 100644 index 00000000000..e3404196ceb --- /dev/null +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/LegacyForkIdManager.java @@ -0,0 +1,107 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth; + +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.ethereum.eth.manager.ForkId; +import org.hyperledger.besu.ethereum.rlp.RLPInput; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.zip.CRC32; + +import org.apache.tuweni.bytes.Bytes; + +public class LegacyForkIdManager { + + private final Hash genesisHash; + private final List forks; + private List forkAndHashList; + + public LegacyForkIdManager(final Blockchain blockchain, final List forks) { + this.genesisHash = blockchain.getGenesisBlock().getHash(); + // de-dupe and sanitize forks + this.forks = + forks.stream().filter(fork -> fork > 0).distinct().collect(Collectors.toUnmodifiableList()); + createForkIds(); + }; + + public List getForkAndHashList() { + return this.forkAndHashList; + } + + public ForkId getLatestForkId() { + if (forkAndHashList.size() > 0) { + return forkAndHashList.get(forkAndHashList.size() - 1); + } + return null; + } + + public static ForkId readFrom(final RLPInput in) { + in.enterList(); + final Bytes hash = in.readBytes(); + final Bytes next = in.readBytes(); + in.leaveList(); + return new ForkId(hash, next); + } + + private void createForkIds() { + final CRC32 crc = new CRC32(); + crc.update(genesisHash.toArray()); + final List forkHashes = new ArrayList<>(List.of(getCurrentCrcHash(crc))); + for (final Long fork : forks) { + updateCrc(crc, fork); + forkHashes.add(getCurrentCrcHash(crc)); + } + final List forkIds = new ArrayList<>(); + // This loop is for all the fork hashes that have an associated "next fork" + for (int i = 0; i < forks.size(); i++) { + forkIds.add(new ForkId(forkHashes.get(i), forks.get(i))); + } + if (!forks.isEmpty()) { + forkIds.add(new ForkId(forkHashes.get(forkHashes.size() - 1), 0)); + } + this.forkAndHashList = forkIds; + System.out.println(this.forkAndHashList); + } + + private void updateCrc(final CRC32 crc, final Long block) { + final byte[] byteRepresentationFork = longToBigEndian(block); + crc.update(byteRepresentationFork, 0, byteRepresentationFork.length); + } + + private Bytes getCurrentCrcHash(final CRC32 crc) { + return Bytes.ofUnsignedInt(crc.getValue()); + } + + // next two methods adopted from: + // https://github.com/bcgit/bc-java/blob/master/core/src/main/java/org/bouncycastle/util/Pack.java + private static byte[] longToBigEndian(final long n) { + final byte[] bs = new byte[8]; + intToBigEndian((int) (n >>> 32), bs, 0); + intToBigEndian((int) (n & 0xffffffffL), bs, 4); + return bs; + } + + @SuppressWarnings("MethodInputParametersMustBeFinal") + private static void intToBigEndian(final int n, final byte[] bs, int off) { + bs[off] = (byte) (n >>> 24); + bs[++off] = (byte) (n >>> 16); + bs[++off] = (byte) (n >>> 8); + bs[++off] = (byte) (n); + } +} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EIP2124Test.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EIP2124Test.java index dacc7b53b3b..6922005004e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EIP2124Test.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EIP2124Test.java @@ -17,13 +17,14 @@ import static com.google.common.primitives.Longs.asList; import static java.util.Optional.empty; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.mockBlockchain; +import static org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.wantPeerCheck; -import org.hyperledger.besu.ethereum.chain.Blockchain; -import org.hyperledger.besu.ethereum.core.Block; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.ethereum.eth.ForkIdTestUtil; +import org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.ForkIds; +import org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.GenesisHash; +import org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.Network; +import org.hyperledger.besu.ethereum.eth.ForkIdTestUtil.PeerCheckCase; import java.util.Arrays; import java.util.Collection; @@ -51,7 +52,7 @@ public static Collection data() { "Mainnet // Unsynced", Network.MAINNET, 0L, - wantForkId("0xfc64ec04", 1150000L), + ForkIdTestUtil.wantForkId("0xfc64ec04", 1150000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -59,7 +60,7 @@ public static Collection data() { "Mainnet // First Homestead block", Network.MAINNET, 1150000L, - wantForkId("0x97c2c34c", 1920000L), + ForkIdTestUtil.wantForkId("0x97c2c34c", 1920000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -67,7 +68,7 @@ public static Collection data() { "Mainnet // Last Homestead block", Network.MAINNET, 1919999L, - wantForkId("0x97c2c34c", 1920000L), + ForkIdTestUtil.wantForkId("0x97c2c34c", 1920000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -75,7 +76,7 @@ public static Collection data() { "Mainnet // First DAO block", Network.MAINNET, 1920000L, - wantForkId("0x91d1f948", 2463000L), + ForkIdTestUtil.wantForkId("0x91d1f948", 2463000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -83,7 +84,7 @@ public static Collection data() { "Mainnet // Last DAO block", Network.MAINNET, 2462999L, - wantForkId("0x91d1f948", 2463000L), + ForkIdTestUtil.wantForkId("0x91d1f948", 2463000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -91,7 +92,7 @@ public static Collection data() { "Mainnet // First Tangerine block", Network.MAINNET, 2463000L, - wantForkId("0x7a64da13", 2675000L), + ForkIdTestUtil.wantForkId("0x7a64da13", 2675000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -99,7 +100,7 @@ public static Collection data() { "Mainnet // Last Tangerine block", Network.MAINNET, 2674999L, - wantForkId("0x7a64da13", 2675000L), + ForkIdTestUtil.wantForkId("0x7a64da13", 2675000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -107,7 +108,7 @@ public static Collection data() { "Mainnet // First Spurious block", Network.MAINNET, 2675000L, - wantForkId("0x3edd5b10", 4370000L), + ForkIdTestUtil.wantForkId("0x3edd5b10", 4370000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -115,7 +116,7 @@ public static Collection data() { "Mainnet // Last Spurious block", Network.MAINNET, 4369999L, - wantForkId("0x3edd5b10", 4370000L), + ForkIdTestUtil.wantForkId("0x3edd5b10", 4370000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -123,7 +124,7 @@ public static Collection data() { "Mainnet // First Byzantium block", Network.MAINNET, 4370000L, - wantForkId("0xa00bc324", 7280000L), + ForkIdTestUtil.wantForkId("0xa00bc324", 7280000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -131,7 +132,7 @@ public static Collection data() { "Mainnet // Last Byzantium block", Network.MAINNET, 7279999L, - wantForkId("0xa00bc324", 7280000L), + ForkIdTestUtil.wantForkId("0xa00bc324", 7280000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -139,7 +140,7 @@ public static Collection data() { "Mainnet // First and last Constantinople, first Petersburg block", Network.MAINNET, 7280000L, - wantForkId("0x668db0af", 9069000L), + ForkIdTestUtil.wantForkId("0x668db0af", 9069000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -147,7 +148,7 @@ public static Collection data() { "Mainnet // Last Petersburg block", Network.MAINNET, 9068999L, - wantForkId("0x668db0af", 9069000L), + ForkIdTestUtil.wantForkId("0x668db0af", 9069000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -155,7 +156,7 @@ public static Collection data() { "Mainnet // First Istanbul and first Muir Glacier block", Network.MAINNET, 9069000L, - wantForkId("0x879d6e30", 9200000L), + ForkIdTestUtil.wantForkId("0x879d6e30", 9200000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -163,7 +164,7 @@ public static Collection data() { "Mainnet // Last Istanbul and first Muir Glacier block", Network.MAINNET, 9199999L, - wantForkId("0x879d6e30", 9200000L), + ForkIdTestUtil.wantForkId("0x879d6e30", 9200000L), Optional.of(ForkIds.MAINNET), empty() }, @@ -171,7 +172,7 @@ public static Collection data() { "Mainnet // First Muir Glacier block", Network.MAINNET, 9200000L, - wantForkId("0xe029e991", 0L), + ForkIdTestUtil.wantForkId("0xe029e991", 0L), Optional.of(ForkIds.MAINNET), empty() }, @@ -179,7 +180,7 @@ public static Collection data() { "Mainnet // Future Muir Glacier block", Network.MAINNET, 10000000L, - wantForkId("0xe029e991", 0L), + ForkIdTestUtil.wantForkId("0xe029e991", 0L), Optional.of(ForkIds.MAINNET), empty() }, @@ -188,7 +189,7 @@ public static Collection data() { "Ropsten // Unsynced, last Frontier, Homestead and first Tangerine block", Network.ROPSTEN, 0L, - wantForkId("0x30c7ddbc", 10L), + ForkIdTestUtil.wantForkId("0x30c7ddbc", 10L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -196,7 +197,7 @@ public static Collection data() { "Ropsten // Last Tangerine block", Network.ROPSTEN, 9L, - wantForkId("0x30c7ddbc", 10L), + ForkIdTestUtil.wantForkId("0x30c7ddbc", 10L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -204,7 +205,7 @@ public static Collection data() { "Ropsten // First Spurious block", Network.ROPSTEN, 10L, - wantForkId("0x63760190", 1700000L), + ForkIdTestUtil.wantForkId("0x63760190", 1700000L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -212,7 +213,7 @@ public static Collection data() { "Ropsten // Last Spurious block", Network.ROPSTEN, 1699999L, - wantForkId("0x63760190", 1700000L), + ForkIdTestUtil.wantForkId("0x63760190", 1700000L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -220,7 +221,7 @@ public static Collection data() { "Ropsten // First Byzantium block", Network.ROPSTEN, 1700000L, - wantForkId("0x3ea159c7", 4230000L), + ForkIdTestUtil.wantForkId("0x3ea159c7", 4230000L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -228,7 +229,7 @@ public static Collection data() { "Ropsten // First Byzantium block", Network.ROPSTEN, 4229999L, - wantForkId("0x3ea159c7", 4230000L), + ForkIdTestUtil.wantForkId("0x3ea159c7", 4230000L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -236,7 +237,7 @@ public static Collection data() { "Ropsten // First Constantinople block", Network.ROPSTEN, 4230000L, - wantForkId("0x97b544f3", 4939394L), + ForkIdTestUtil.wantForkId("0x97b544f3", 4939394L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -244,7 +245,7 @@ public static Collection data() { "Ropsten // Last Constantinople block", Network.ROPSTEN, 4939393L, - wantForkId("0x97b544f3", 4939394L), + ForkIdTestUtil.wantForkId("0x97b544f3", 4939394L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -252,7 +253,7 @@ public static Collection data() { "Ropsten // First Petersburg block", Network.ROPSTEN, 4939394L, - wantForkId("0xd6e2149b", 6485846L), + ForkIdTestUtil.wantForkId("0xd6e2149b", 6485846L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -260,7 +261,7 @@ public static Collection data() { "Ropsten // Last Petersburg block", Network.ROPSTEN, 6485845L, - wantForkId("0xd6e2149b", 6485846L), + ForkIdTestUtil.wantForkId("0xd6e2149b", 6485846L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -268,7 +269,7 @@ public static Collection data() { "Ropsten // First Istanbul block", Network.ROPSTEN, 6485846L, - wantForkId("0x4bc66396", 7117117L), + ForkIdTestUtil.wantForkId("0x4bc66396", 7117117L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -276,7 +277,7 @@ public static Collection data() { "Ropsten // Last Istanbul block", Network.ROPSTEN, 7117116L, - wantForkId("0x4bc66396", 7117117L), + ForkIdTestUtil.wantForkId("0x4bc66396", 7117117L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -284,7 +285,7 @@ public static Collection data() { "Ropsten // First Muir Glacier block", Network.ROPSTEN, 7117117L, - wantForkId("0x6727ef90", 0L), + ForkIdTestUtil.wantForkId("0x6727ef90", 0L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -292,7 +293,7 @@ public static Collection data() { "Ropsten // Future", Network.ROPSTEN, 7500000L, - wantForkId("0x6727ef90", 0L), + ForkIdTestUtil.wantForkId("0x6727ef90", 0L), Optional.of(ForkIds.ROPSTEN), empty() }, @@ -301,7 +302,7 @@ public static Collection data() { "Rinkeby // Unsynced, last Frontier block", Network.RINKEBY, 0L, - wantForkId("0x3b8e0691", 1L), + ForkIdTestUtil.wantForkId("0x3b8e0691", 1L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -309,7 +310,7 @@ public static Collection data() { "Rinkeby // First and last Homestead block", Network.RINKEBY, 1L, - wantForkId("0x60949295", 2L), + ForkIdTestUtil.wantForkId("0x60949295", 2L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -317,7 +318,7 @@ public static Collection data() { "Rinkeby // First and last Tangerine block", Network.RINKEBY, 2L, - wantForkId("0x8bde40dd", 3L), + ForkIdTestUtil.wantForkId("0x8bde40dd", 3L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -325,7 +326,7 @@ public static Collection data() { "Rinkeby // First Spurious block", Network.RINKEBY, 3L, - wantForkId("0xcb3a64bb", 1035301L), + ForkIdTestUtil.wantForkId("0xcb3a64bb", 1035301L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -333,7 +334,7 @@ public static Collection data() { "Rinkeby // Last Spurious block", Network.RINKEBY, 1035300L, - wantForkId("0xcb3a64bb", 1035301L), + ForkIdTestUtil.wantForkId("0xcb3a64bb", 1035301L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -341,7 +342,7 @@ public static Collection data() { "Rinkeby // First Byzantium block", Network.RINKEBY, 1035301L, - wantForkId("0x8d748b57", 3660663L), + ForkIdTestUtil.wantForkId("0x8d748b57", 3660663L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -349,7 +350,7 @@ public static Collection data() { "Rinkeby // Last Byzantium block", Network.RINKEBY, 3660662L, - wantForkId("0x8d748b57", 3660663L), + ForkIdTestUtil.wantForkId("0x8d748b57", 3660663L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -357,7 +358,7 @@ public static Collection data() { "Rinkeby // First Constantinople block", Network.RINKEBY, 3660663L, - wantForkId("0xe49cab14", 4321234L), + ForkIdTestUtil.wantForkId("0xe49cab14", 4321234L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -365,7 +366,7 @@ public static Collection data() { "Rinkeby // Last Constantinople block", Network.RINKEBY, 4321233L, - wantForkId("0xe49cab14", 4321234L), + ForkIdTestUtil.wantForkId("0xe49cab14", 4321234L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -373,7 +374,7 @@ public static Collection data() { "Rinkeby // First Petersburg block", Network.RINKEBY, 4321234L, - wantForkId("0xafec6b27", 5435345L), + ForkIdTestUtil.wantForkId("0xafec6b27", 5435345L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -381,7 +382,7 @@ public static Collection data() { "Rinkeby // Last Petersburg block", Network.RINKEBY, 5435344L, - wantForkId("0xafec6b27", 5435345L), + ForkIdTestUtil.wantForkId("0xafec6b27", 5435345L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -389,7 +390,7 @@ public static Collection data() { "Rinkeby // First Istanbul block", Network.RINKEBY, 5435345L, - wantForkId("0xcbdb8838", 0L), + ForkIdTestUtil.wantForkId("0xcbdb8838", 0L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -397,7 +398,7 @@ public static Collection data() { "Rinkeby // Future Istanbul block", Network.RINKEBY, 6000000L, - wantForkId("0xcbdb8838", 0L), + ForkIdTestUtil.wantForkId("0xcbdb8838", 0L), Optional.of(ForkIds.RINKEBY), empty() }, @@ -406,7 +407,7 @@ public static Collection data() { "Goerli // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block", Network.GOERLI, 0L, - wantForkId("0xa3f5ab08", 1561651L), + ForkIdTestUtil.wantForkId("0xa3f5ab08", 1561651L), Optional.of(ForkIds.GOERLI), empty() }, @@ -414,7 +415,7 @@ public static Collection data() { "Goerli // Last Petersburg block", Network.GOERLI, 1561650L, - wantForkId("0xa3f5ab08", 1561651L), + ForkIdTestUtil.wantForkId("0xa3f5ab08", 1561651L), Optional.of(ForkIds.GOERLI), empty() }, @@ -422,7 +423,7 @@ public static Collection data() { "Goerli // First Istanbul block", Network.GOERLI, 1561651L, - wantForkId("0xc25efa5c", 0L), + ForkIdTestUtil.wantForkId("0xc25efa5c", 0L), Optional.of(ForkIds.GOERLI), empty() }, @@ -430,7 +431,7 @@ public static Collection data() { "Goerli // Future Istanbul block", Network.GOERLI, 2000000L, - wantForkId("0xc25efa5c", 0L), + ForkIdTestUtil.wantForkId("0xc25efa5c", 0L), Optional.of(ForkIds.GOERLI), empty() }, @@ -439,7 +440,7 @@ public static Collection data() { "Private // Unsynced", Network.PRIVATE, 0L, - wantForkId("0x190a55ad", 0L), + ForkIdTestUtil.wantForkId("0x190a55ad", 0L), empty(), empty() }, @@ -447,7 +448,7 @@ public static Collection data() { "Private // First block", Network.PRIVATE, 1L, - wantForkId("0x190a55ad", 0L), + ForkIdTestUtil.wantForkId("0x190a55ad", 0L), empty(), empty() }, @@ -455,7 +456,7 @@ public static Collection data() { "Private // Future block", Network.PRIVATE, 1000000L, - wantForkId("0x190a55ad", 0L), + ForkIdTestUtil.wantForkId("0x190a55ad", 0L), empty(), empty() }, @@ -554,7 +555,7 @@ public static Collection data() { }, { "check12ByzantiumWithRemoteAnnouncingPetersburgAndFutureForkLocalNeedsUpdate", - Network.network( + ForkIdTestUtil.Network.network( GenesisHash.MAINNET, asList(1150000L, 1920000L, 2463000L, 2675000L, 4370000L, 7280000L)), 7279999L, @@ -586,7 +587,7 @@ public static Collection data() { public void test() { LOG.info("Running test case {}", name); final ForkIdManager forkIdManager = - new ForkIdManager(mockBlockchain(network.hash, head), network.forks); + new ForkIdManager(mockBlockchain(network.hash, head), network.forks, false); wantForkId.ifPresent(forkId -> assertThat(forkIdManager.computeForkId()).isEqualTo(forkId)); wantForkIds.ifPresent( forkIds -> @@ -603,7 +604,7 @@ public void test() { public EIP2124Test( final String name, - final Network network, + final ForkIdTestUtil.Network network, final long head, final Optional wantForkId, final Optional> wantForkIds, @@ -615,121 +616,4 @@ public EIP2124Test( this.wantForkIds = wantForkIds; this.wantPeerCheckCase = wantPeerCheckCase; } - - private static Blockchain mockBlockchain(final String genesisHash, final long chainHeight) { - final Blockchain mockchain = mock(Blockchain.class); - final BlockHeader mockHeader = mock(BlockHeader.class); - final Block block = new Block(mockHeader, null); - when(mockchain.getGenesisBlock()).thenReturn(block); - when(mockchain.getChainHeadBlockNumber()).thenReturn(chainHeight); - when(mockHeader.getHash()).thenReturn(Hash.fromHexString(genesisHash)); - return mockchain; - } - - private static class GenesisHash { - private static final String MAINNET = - "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"; - private static final String ROPSTEN = - "0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"; - private static final String RINKEBY = - "0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177"; - private static final String GOERLI = - "0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a"; - private static final String PRIVATE = - "0x0000000000000000000000000000000000000000000000000000000000000000"; - } - - private static class Forks { - private static final List MAINNET = - Arrays.asList( - 1920000L, 1150000L, 2463000L, 2675000L, 2675000L, 4370000L, 7280000L, 7280000L, - 9069000L, 9200000L); - private static final List ROPSTEN = - Arrays.asList(0L, 0L, 10L, 1700000L, 4230000L, 4939394L, 6485846L, 7117117L); - private static final List RINKEBY = - Arrays.asList(1L, 2L, 3L, 3L, 1035301L, 3660663L, 4321234L, 5435345L); - private static final List GOERLI = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1561651L); - private static final List PRIVATE = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L); - } - - private static class ForkIds { - private static final List MAINNET = - Arrays.asList( - new ForkId(Bytes.fromHexString("0xfc64ec04"), 1150000L), // Unsynced - new ForkId(Bytes.fromHexString("0x97c2c34c"), 1920000L), // First Homestead block - new ForkId(Bytes.fromHexString("0x91d1f948"), 2463000L), // First DAO block - new ForkId(Bytes.fromHexString("0x7a64da13"), 2675000L), // First Tangerine block - new ForkId(Bytes.fromHexString("0x3edd5b10"), 4370000L), // First Spurious block - new ForkId(Bytes.fromHexString("0xa00bc324"), 7280000L), // First Byzantium block - new ForkId(Bytes.fromHexString("0x668db0af"), 9069000L), - new ForkId(Bytes.fromHexString("0x879d6e30"), 9200000L), - new ForkId(Bytes.fromHexString("0xe029e991"), 0L)); - private static final List ROPSTEN = - Arrays.asList( - new ForkId(Bytes.fromHexString("0x30c7ddbc"), 10L), - new ForkId(Bytes.fromHexString("0x63760190"), 1700000L), - new ForkId(Bytes.fromHexString("0x3ea159c7"), 4230000L), - new ForkId(Bytes.fromHexString("0x97b544f3"), 4939394L), - new ForkId(Bytes.fromHexString("0xd6e2149b"), 6485846L), - new ForkId(Bytes.fromHexString("0x4bc66396"), 7117117L), - new ForkId(Bytes.fromHexString("0x6727ef90"), 0L)); - private static final List RINKEBY = - Arrays.asList( - new ForkId(Bytes.fromHexString("0x3b8e0691"), 1L), - new ForkId(Bytes.fromHexString("0x60949295"), 2L), - new ForkId(Bytes.fromHexString("0x8bde40dd"), 3L), - new ForkId(Bytes.fromHexString("0xcb3a64bb"), 1035301L), - new ForkId(Bytes.fromHexString("0x8d748b57"), 3660663L), - new ForkId(Bytes.fromHexString("0xe49cab14"), 4321234L), - new ForkId(Bytes.fromHexString("0xafec6b27"), 5435345L), - new ForkId(Bytes.fromHexString("0xcbdb8838"), 0L)); - private static final List GOERLI = - Arrays.asList( - new ForkId(Bytes.fromHexString("0xa3f5ab08"), 1561651L), - new ForkId(Bytes.fromHexString("0xc25efa5c"), 0L)); - } - - private static class Network { - private static final Network MAINNET = network(GenesisHash.MAINNET, Forks.MAINNET); - private static final Network ROPSTEN = network(GenesisHash.ROPSTEN, Forks.ROPSTEN); - private static final Network RINKEBY = network(GenesisHash.RINKEBY, Forks.RINKEBY); - private static final Network GOERLI = network(GenesisHash.GOERLI, Forks.GOERLI); - private static final Network PRIVATE = network(GenesisHash.PRIVATE, Forks.PRIVATE); - private final String hash; - private final List forks; - - Network(final String hash, final List forks) { - this.hash = hash; - this.forks = forks; - } - - private static Network network(final String hash, final List forks) { - return new Network(hash, forks); - } - } - - private static class PeerCheckCase { - private final String forkIdHash; - private final long forkIdNext; - private final boolean want; - - private PeerCheckCase(final String forkIdHash, final long forkIdNext, final boolean want) { - this.forkIdHash = forkIdHash; - this.forkIdNext = forkIdNext; - this.want = want; - } - } - - private static ForkId forkId(final String hash, final long next) { - return new ForkId(Bytes.fromHexString(hash), next); - } - - private static Optional wantForkId(final String hash, final long next) { - return Optional.of(forkId(hash, next)); - } - - private static Optional wantPeerCheck( - final String hash, final long next, final boolean want) { - return Optional.of(new PeerCheckCase(hash, next, want)); - } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java index 216671c6d37..fdfd5a571f0 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java @@ -273,7 +273,7 @@ public void respondToGetHeadersWithinLimits() throws ExecutionException, Interru () -> false, protocolContext.getWorldStateArchive(), transactionPool, - new EthProtocolConfiguration(limit, limit, limit, limit, limit, true))) { + new EthProtocolConfiguration(limit, limit, limit, limit, limit, true, false))) { final long startBlock = 5L; final int blockCount = 10; final MessageData messageData = @@ -565,7 +565,7 @@ public void respondToGetBodiesWithinLimits() throws ExecutionException, Interrup () -> false, protocolContext.getWorldStateArchive(), transactionPool, - new EthProtocolConfiguration(limit, limit, limit, limit, limit, true))) { + new EthProtocolConfiguration(limit, limit, limit, limit, limit, true, false))) { // Setup blocks query final int blockCount = 10; final long startBlock = blockchain.getChainHeadBlockNumber() - blockCount; @@ -703,7 +703,7 @@ public void respondToGetReceiptsWithinLimits() throws ExecutionException, Interr () -> false, protocolContext.getWorldStateArchive(), transactionPool, - new EthProtocolConfiguration(limit, limit, limit, limit, limit, true))) { + new EthProtocolConfiguration(limit, limit, limit, limit, limit, true, false))) { // Setup blocks query final int blockCount = 10; final long startBlock = blockchain.getChainHeadBlockNumber() - blockCount; diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java index d50ab2dba84..ba30cc55a73 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java @@ -79,7 +79,7 @@ public static EthProtocolManager create( Collections.emptyList(), false, ethScheduler, - new ForkIdManager(blockchain, Collections.emptyList())); + new ForkIdManager(blockchain, Collections.emptyList(), false)); } public static EthProtocolManager create(final Blockchain blockchain) { diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthServerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthServerTest.java index f2fb5416b33..bd7c2f87eeb 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthServerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthServerTest.java @@ -55,7 +55,7 @@ public void setUp() { worldStateArchive, transactionPool, ethMessages, - new EthProtocolConfiguration(2, 2, 2, 2, 2, true)); + new EthProtocolConfiguration(2, 2, 2, 2, 2, true, false)); } @Test diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java index 0b3914d3d27..a26bf8e06e1 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java @@ -111,7 +111,7 @@ public void testDisconnect() { BigInteger.ONE, mock(WorldStateArchive.class), pool, - new EthProtocolConfiguration(5, 5, 5, 5, 5, true), + new EthProtocolConfiguration(5, 5, 5, 5, 5, true, false), ethPeers, mock(EthMessages.class), ethContext, @@ -196,7 +196,7 @@ public void testNoEth65() { BigInteger.ONE, mock(WorldStateArchive.class), pool, - new EthProtocolConfiguration(5, 5, 5, 5, 5, true), + new EthProtocolConfiguration(5, 5, 5, 5, 5, true, false), ethPeers, mock(EthMessages.class), ethContext,