Handle legacy fork id Eth/64 (#1542)

* Handle legacy fork id Eth/64

Signed-off-by: Abdelhamid Bakhta <abdelhamid.bakhta@consensys.net>
pull/1566/head
Abdelhamid Bakhta 4 years ago committed by GitHub
parent 6a1e73395f
commit 0bedfffe02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 16
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/EthProtocolOptions.java
  3. 43
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  4. 2
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  5. 3
      besu/src/test/resources/everything_config.toml
  6. 23
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/EthProtocolConfiguration.java
  7. 8
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManager.java
  8. 2
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkId.java
  9. 10
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/ForkIdManager.java
  10. 127
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdBackwardCompatibilityTest.java
  11. 156
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdTestUtil.java
  12. 107
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/LegacyForkIdManager.java
  13. 238
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EIP2124Test.java
  14. 6
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java
  15. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java
  16. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthServerTest.java
  17. 4
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java

@ -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

@ -31,6 +31,8 @@ public class EthProtocolOptions implements CLIOptions<EthProtocolConfiguration>
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<EthProtocolConfiguration>
@CommandLine.Option(
hidden = true,
names = {ETH_65_ENABLED},
paramLabel = "<INTEGER>",
paramLabel = "<Boolean>",
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 = "<Boolean>",
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 class EthProtocolOptions implements CLIOptions<EthProtocolConfiguration>
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 class EthProtocolOptions implements CLIOptions<EthProtocolConfiguration>
.maxGetNodeData(maxGetNodeData)
.maxGetPooledTransactions(maxGetPooledTransactions)
.eth65Enabled(eth65Enabled)
.legacyEth64ForkIdEnabled(legacyEth64ForkIdEnabled)
.build();
}
@ -126,6 +137,7 @@ public class EthProtocolOptions implements CLIOptions<EthProtocolConfiguration>
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);
}
}

@ -3789,4 +3789,47 @@ public class BesuCommandTest extends CommandTestAbstract {
"--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();
}
}

@ -46,6 +46,7 @@ import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
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<WebSocketConfiguration> wsRpcConfigArgumentCaptor;
@Captor protected ArgumentCaptor<MetricsConfiguration> metricsConfigArgumentCaptor;
@Captor protected ArgumentCaptor<StorageProvider> storageProviderArgumentCaptor;
@Captor protected ArgumentCaptor<EthProtocolConfiguration> ethProtocolConfigurationArgumentCaptor;
@Captor
protected ArgumentCaptor<PermissioningConfiguration> permissioningConfigurationArgumentCaptor;

@ -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

@ -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 class 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 class EthProtocolConfiguration {
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 class EthProtocolConfiguration {
return eth65Enabled;
}
public boolean isLegacyEth64ForkIdEnabled() {
return legacyEth64ForkIdEnabled;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
@ -138,6 +147,8 @@ public class EthProtocolConfiguration {
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 class EthProtocolConfiguration {
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 class EthProtocolConfiguration {
maxGetReceipts.getValue(),
maxGetNodeData.getValue(),
maxGetPooledTransactions.getValue(),
eth65Enabled);
eth65Enabled,
legacyEth64ForkIdEnabled);
}
}
}

@ -139,7 +139,10 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
peerValidators,
fastSyncEnabled,
scheduler,
new ForkIdManager(blockchain, Collections.emptyList()));
new ForkIdManager(
blockchain,
Collections.emptyList(),
ethereumWireProtocolConfiguration.isLegacyEth64ForkIdEnabled()));
}
public EthProtocolManager(
@ -167,7 +170,8 @@ public class EthProtocolManager implements ProtocolManager, MinedBlockObserver {
peerValidators,
fastSyncEnabled,
scheduler,
new ForkIdManager(blockchain, forks));
new ForkIdManager(
blockchain, forks, ethereumWireProtocolConfiguration.isLegacyEth64ForkIdEnabled()));
}
public EthContext ethContext() {

@ -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();

@ -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<Long> nonFilteredForks) {
public ForkIdManager(
final Blockchain blockchain, final List<Long> 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 class ForkIdManager {
}
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()) {

@ -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<Long> forks;
private final boolean legacyEth64;
private final ForkId wantForkId;
public ForkIdBackwardCompatibilityTest(
final String name,
final String genesisHash,
final long head,
final List<Long> 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<Object[]> 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);
}
}

@ -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<Long> MAINNET =
Arrays.asList(
1920000L, 1150000L, 2463000L, 2675000L, 2675000L, 4370000L, 7280000L, 7280000L,
9069000L, 9200000L);
public static final List<Long> ROPSTEN =
Arrays.asList(0L, 0L, 10L, 1700000L, 4230000L, 4939394L, 6485846L, 7117117L);
public static final List<Long> RINKEBY =
Arrays.asList(1L, 2L, 3L, 3L, 1035301L, 3660663L, 4321234L, 5435345L);
public static final List<Long> GOERLI = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1561651L);
public static final List<Long> PRIVATE = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
}
public static class ForkIds {
public static final List<ForkId> 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<ForkId> 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<ForkId> 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<ForkId> 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<Long> forks;
public Network(final String hash, final List<Long> forks) {
this.hash = hash;
this.forks = forks;
}
public static Network network(final String hash, final List<Long> 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<ForkId> wantForkId(final String hash, final long next) {
return Optional.of(forkId(hash, next));
}
public static Optional<PeerCheckCase> wantPeerCheck(
final String hash, final long next, final boolean want) {
return Optional.of(new PeerCheckCase(hash, next, want));
}
}

@ -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<Long> forks;
private List<ForkId> forkAndHashList;
public LegacyForkIdManager(final Blockchain blockchain, final List<Long> 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<ForkId> 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<Bytes> forkHashes = new ArrayList<>(List.of(getCurrentCrcHash(crc)));
for (final Long fork : forks) {
updateCrc(crc, fork);
forkHashes.add(getCurrentCrcHash(crc));
}
final List<ForkId> 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);
}
}

@ -17,13 +17,14 @@ package org.hyperledger.besu.ethereum.eth.manager;
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 class EIP2124Test {
"Mainnet // Unsynced",
Network.MAINNET,
0L,
wantForkId("0xfc64ec04", 1150000L),
ForkIdTestUtil.wantForkId("0xfc64ec04", 1150000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -59,7 +60,7 @@ public class EIP2124Test {
"Mainnet // First Homestead block",
Network.MAINNET,
1150000L,
wantForkId("0x97c2c34c", 1920000L),
ForkIdTestUtil.wantForkId("0x97c2c34c", 1920000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -67,7 +68,7 @@ public class EIP2124Test {
"Mainnet // Last Homestead block",
Network.MAINNET,
1919999L,
wantForkId("0x97c2c34c", 1920000L),
ForkIdTestUtil.wantForkId("0x97c2c34c", 1920000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -75,7 +76,7 @@ public class EIP2124Test {
"Mainnet // First DAO block",
Network.MAINNET,
1920000L,
wantForkId("0x91d1f948", 2463000L),
ForkIdTestUtil.wantForkId("0x91d1f948", 2463000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -83,7 +84,7 @@ public class EIP2124Test {
"Mainnet // Last DAO block",
Network.MAINNET,
2462999L,
wantForkId("0x91d1f948", 2463000L),
ForkIdTestUtil.wantForkId("0x91d1f948", 2463000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -91,7 +92,7 @@ public class EIP2124Test {
"Mainnet // First Tangerine block",
Network.MAINNET,
2463000L,
wantForkId("0x7a64da13", 2675000L),
ForkIdTestUtil.wantForkId("0x7a64da13", 2675000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -99,7 +100,7 @@ public class EIP2124Test {
"Mainnet // Last Tangerine block",
Network.MAINNET,
2674999L,
wantForkId("0x7a64da13", 2675000L),
ForkIdTestUtil.wantForkId("0x7a64da13", 2675000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -107,7 +108,7 @@ public class EIP2124Test {
"Mainnet // First Spurious block",
Network.MAINNET,
2675000L,
wantForkId("0x3edd5b10", 4370000L),
ForkIdTestUtil.wantForkId("0x3edd5b10", 4370000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -115,7 +116,7 @@ public class EIP2124Test {
"Mainnet // Last Spurious block",
Network.MAINNET,
4369999L,
wantForkId("0x3edd5b10", 4370000L),
ForkIdTestUtil.wantForkId("0x3edd5b10", 4370000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -123,7 +124,7 @@ public class EIP2124Test {
"Mainnet // First Byzantium block",
Network.MAINNET,
4370000L,
wantForkId("0xa00bc324", 7280000L),
ForkIdTestUtil.wantForkId("0xa00bc324", 7280000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -131,7 +132,7 @@ public class EIP2124Test {
"Mainnet // Last Byzantium block",
Network.MAINNET,
7279999L,
wantForkId("0xa00bc324", 7280000L),
ForkIdTestUtil.wantForkId("0xa00bc324", 7280000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -139,7 +140,7 @@ public class EIP2124Test {
"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 class EIP2124Test {
"Mainnet // Last Petersburg block",
Network.MAINNET,
9068999L,
wantForkId("0x668db0af", 9069000L),
ForkIdTestUtil.wantForkId("0x668db0af", 9069000L),
Optional.of(ForkIds.MAINNET),
empty()
},
@ -155,7 +156,7 @@ public class EIP2124Test {
"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 class EIP2124Test {
"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 class EIP2124Test {
"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 class EIP2124Test {
"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 class EIP2124Test {
"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 class EIP2124Test {
"Ropsten // Last Tangerine block",
Network.ROPSTEN,
9L,
wantForkId("0x30c7ddbc", 10L),
ForkIdTestUtil.wantForkId("0x30c7ddbc", 10L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -204,7 +205,7 @@ public class EIP2124Test {
"Ropsten // First Spurious block",
Network.ROPSTEN,
10L,
wantForkId("0x63760190", 1700000L),
ForkIdTestUtil.wantForkId("0x63760190", 1700000L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -212,7 +213,7 @@ public class EIP2124Test {
"Ropsten // Last Spurious block",
Network.ROPSTEN,
1699999L,
wantForkId("0x63760190", 1700000L),
ForkIdTestUtil.wantForkId("0x63760190", 1700000L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -220,7 +221,7 @@ public class EIP2124Test {
"Ropsten // First Byzantium block",
Network.ROPSTEN,
1700000L,
wantForkId("0x3ea159c7", 4230000L),
ForkIdTestUtil.wantForkId("0x3ea159c7", 4230000L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -228,7 +229,7 @@ public class EIP2124Test {
"Ropsten // First Byzantium block",
Network.ROPSTEN,
4229999L,
wantForkId("0x3ea159c7", 4230000L),
ForkIdTestUtil.wantForkId("0x3ea159c7", 4230000L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -236,7 +237,7 @@ public class EIP2124Test {
"Ropsten // First Constantinople block",
Network.ROPSTEN,
4230000L,
wantForkId("0x97b544f3", 4939394L),
ForkIdTestUtil.wantForkId("0x97b544f3", 4939394L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -244,7 +245,7 @@ public class EIP2124Test {
"Ropsten // Last Constantinople block",
Network.ROPSTEN,
4939393L,
wantForkId("0x97b544f3", 4939394L),
ForkIdTestUtil.wantForkId("0x97b544f3", 4939394L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -252,7 +253,7 @@ public class EIP2124Test {
"Ropsten // First Petersburg block",
Network.ROPSTEN,
4939394L,
wantForkId("0xd6e2149b", 6485846L),
ForkIdTestUtil.wantForkId("0xd6e2149b", 6485846L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -260,7 +261,7 @@ public class EIP2124Test {
"Ropsten // Last Petersburg block",
Network.ROPSTEN,
6485845L,
wantForkId("0xd6e2149b", 6485846L),
ForkIdTestUtil.wantForkId("0xd6e2149b", 6485846L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -268,7 +269,7 @@ public class EIP2124Test {
"Ropsten // First Istanbul block",
Network.ROPSTEN,
6485846L,
wantForkId("0x4bc66396", 7117117L),
ForkIdTestUtil.wantForkId("0x4bc66396", 7117117L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -276,7 +277,7 @@ public class EIP2124Test {
"Ropsten // Last Istanbul block",
Network.ROPSTEN,
7117116L,
wantForkId("0x4bc66396", 7117117L),
ForkIdTestUtil.wantForkId("0x4bc66396", 7117117L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -284,7 +285,7 @@ public class EIP2124Test {
"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 class EIP2124Test {
"Ropsten // Future",
Network.ROPSTEN,
7500000L,
wantForkId("0x6727ef90", 0L),
ForkIdTestUtil.wantForkId("0x6727ef90", 0L),
Optional.of(ForkIds.ROPSTEN),
empty()
},
@ -301,7 +302,7 @@ public class EIP2124Test {
"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 class EIP2124Test {
"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 class EIP2124Test {
"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 class EIP2124Test {
"Rinkeby // First Spurious block",
Network.RINKEBY,
3L,
wantForkId("0xcb3a64bb", 1035301L),
ForkIdTestUtil.wantForkId("0xcb3a64bb", 1035301L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -333,7 +334,7 @@ public class EIP2124Test {
"Rinkeby // Last Spurious block",
Network.RINKEBY,
1035300L,
wantForkId("0xcb3a64bb", 1035301L),
ForkIdTestUtil.wantForkId("0xcb3a64bb", 1035301L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -341,7 +342,7 @@ public class EIP2124Test {
"Rinkeby // First Byzantium block",
Network.RINKEBY,
1035301L,
wantForkId("0x8d748b57", 3660663L),
ForkIdTestUtil.wantForkId("0x8d748b57", 3660663L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -349,7 +350,7 @@ public class EIP2124Test {
"Rinkeby // Last Byzantium block",
Network.RINKEBY,
3660662L,
wantForkId("0x8d748b57", 3660663L),
ForkIdTestUtil.wantForkId("0x8d748b57", 3660663L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -357,7 +358,7 @@ public class EIP2124Test {
"Rinkeby // First Constantinople block",
Network.RINKEBY,
3660663L,
wantForkId("0xe49cab14", 4321234L),
ForkIdTestUtil.wantForkId("0xe49cab14", 4321234L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -365,7 +366,7 @@ public class EIP2124Test {
"Rinkeby // Last Constantinople block",
Network.RINKEBY,
4321233L,
wantForkId("0xe49cab14", 4321234L),
ForkIdTestUtil.wantForkId("0xe49cab14", 4321234L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -373,7 +374,7 @@ public class EIP2124Test {
"Rinkeby // First Petersburg block",
Network.RINKEBY,
4321234L,
wantForkId("0xafec6b27", 5435345L),
ForkIdTestUtil.wantForkId("0xafec6b27", 5435345L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -381,7 +382,7 @@ public class EIP2124Test {
"Rinkeby // Last Petersburg block",
Network.RINKEBY,
5435344L,
wantForkId("0xafec6b27", 5435345L),
ForkIdTestUtil.wantForkId("0xafec6b27", 5435345L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -389,7 +390,7 @@ public class EIP2124Test {
"Rinkeby // First Istanbul block",
Network.RINKEBY,
5435345L,
wantForkId("0xcbdb8838", 0L),
ForkIdTestUtil.wantForkId("0xcbdb8838", 0L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -397,7 +398,7 @@ public class EIP2124Test {
"Rinkeby // Future Istanbul block",
Network.RINKEBY,
6000000L,
wantForkId("0xcbdb8838", 0L),
ForkIdTestUtil.wantForkId("0xcbdb8838", 0L),
Optional.of(ForkIds.RINKEBY),
empty()
},
@ -406,7 +407,7 @@ public class EIP2124Test {
"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 class EIP2124Test {
"Goerli // Last Petersburg block",
Network.GOERLI,
1561650L,
wantForkId("0xa3f5ab08", 1561651L),
ForkIdTestUtil.wantForkId("0xa3f5ab08", 1561651L),
Optional.of(ForkIds.GOERLI),
empty()
},
@ -422,7 +423,7 @@ public class EIP2124Test {
"Goerli // First Istanbul block",
Network.GOERLI,
1561651L,
wantForkId("0xc25efa5c", 0L),
ForkIdTestUtil.wantForkId("0xc25efa5c", 0L),
Optional.of(ForkIds.GOERLI),
empty()
},
@ -430,7 +431,7 @@ public class EIP2124Test {
"Goerli // Future Istanbul block",
Network.GOERLI,
2000000L,
wantForkId("0xc25efa5c", 0L),
ForkIdTestUtil.wantForkId("0xc25efa5c", 0L),
Optional.of(ForkIds.GOERLI),
empty()
},
@ -439,7 +440,7 @@ public class EIP2124Test {
"Private // Unsynced",
Network.PRIVATE,
0L,
wantForkId("0x190a55ad", 0L),
ForkIdTestUtil.wantForkId("0x190a55ad", 0L),
empty(),
empty()
},
@ -447,7 +448,7 @@ public class EIP2124Test {
"Private // First block",
Network.PRIVATE,
1L,
wantForkId("0x190a55ad", 0L),
ForkIdTestUtil.wantForkId("0x190a55ad", 0L),
empty(),
empty()
},
@ -455,7 +456,7 @@ public class EIP2124Test {
"Private // Future block",
Network.PRIVATE,
1000000L,
wantForkId("0x190a55ad", 0L),
ForkIdTestUtil.wantForkId("0x190a55ad", 0L),
empty(),
empty()
},
@ -554,7 +555,7 @@ public class EIP2124Test {
},
{
"check12ByzantiumWithRemoteAnnouncingPetersburgAndFutureForkLocalNeedsUpdate",
Network.network(
ForkIdTestUtil.Network.network(
GenesisHash.MAINNET,
asList(1150000L, 1920000L, 2463000L, 2675000L, 4370000L, 7280000L)),
7279999L,
@ -586,7 +587,7 @@ public class EIP2124Test {
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 class EIP2124Test {
public EIP2124Test(
final String name,
final Network network,
final ForkIdTestUtil.Network network,
final long head,
final Optional<ForkId> wantForkId,
final Optional<List<ForkId>> wantForkIds,
@ -615,121 +616,4 @@ public class 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<Long> MAINNET =
Arrays.asList(
1920000L, 1150000L, 2463000L, 2675000L, 2675000L, 4370000L, 7280000L, 7280000L,
9069000L, 9200000L);
private static final List<Long> ROPSTEN =
Arrays.asList(0L, 0L, 10L, 1700000L, 4230000L, 4939394L, 6485846L, 7117117L);
private static final List<Long> RINKEBY =
Arrays.asList(1L, 2L, 3L, 3L, 1035301L, 3660663L, 4321234L, 5435345L);
private static final List<Long> GOERLI = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1561651L);
private static final List<Long> PRIVATE = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
}
private static class ForkIds {
private static final List<ForkId> 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<ForkId> 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<ForkId> 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<ForkId> 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<Long> forks;
Network(final String hash, final List<Long> forks) {
this.hash = hash;
this.forks = forks;
}
private static Network network(final String hash, final List<Long> 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<ForkId> wantForkId(final String hash, final long next) {
return Optional.of(forkId(hash, next));
}
private static Optional<PeerCheckCase> wantPeerCheck(
final String hash, final long next, final boolean want) {
return Optional.of(new PeerCheckCase(hash, next, want));
}
}

@ -273,7 +273,7 @@ public final class EthProtocolManagerTest {
() -> 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 final class EthProtocolManagerTest {
() -> 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 final class EthProtocolManagerTest {
() -> 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;

@ -79,7 +79,7 @@ public class EthProtocolManagerTestUtil {
Collections.emptyList(),
false,
ethScheduler,
new ForkIdManager(blockchain, Collections.emptyList()));
new ForkIdManager(blockchain, Collections.emptyList(), false));
}
public static EthProtocolManager create(final Blockchain blockchain) {

@ -55,7 +55,7 @@ public class EthServerTest {
worldStateArchive,
transactionPool,
ethMessages,
new EthProtocolConfiguration(2, 2, 2, 2, 2, true));
new EthProtocolConfiguration(2, 2, 2, 2, 2, true, false));
}
@Test

@ -111,7 +111,7 @@ public class TransactionPoolFactoryTest {
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 class TransactionPoolFactoryTest {
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,

Loading…
Cancel
Save