Add Shandong network and fork (#4599)

* Add Shandong network and fork

Add the transient Shandong fork and network definitions.  For Shanghai
fork testing. Besu doesn't sync, but it does connect.

Signed-off-by: Danno Ferrin <danno.ferrin@swirldslabs.com>
pull/4620/head
Danno Ferrin 2 years ago committed by GitHub
parent 5f9c68a946
commit 1c143f167e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 1
      besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java
  3. 6
      besu/src/test/java/org/hyperledger/besu/ForkIdsTest.java
  4. 40
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  5. 1
      besu/src/test/java/org/hyperledger/besu/cli/NetworkDeprecationMessageTest.java
  6. 9
      besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java
  7. 13
      besu/src/test/java/org/hyperledger/besu/ethereum/p2p/config/DefaultDiscoveryConfiguration.java
  8. 21
      config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java
  9. 2
      config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java
  10. 38
      config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java
  11. 30
      config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java
  12. 869
      config/src/main/resources/shandong.json
  13. 71
      config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java
  14. 13
      config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java
  15. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java
  16. 18
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetDifficultyCalculators.java
  17. 11
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java
  18. 29
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java
  19. 93
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java
  20. 13
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java
  21. 7
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/RequestManager.java
  22. 5
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/ForkIdTestUtil.java
  23. 25
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EIP2124Test.java
  24. 24
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/RequestManagerTest.java
  25. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStatePeerTrieNodeFinderTest.java
  26. 1
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java
  27. 1
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/methods/TestSetChainParams.java
  28. 32
      evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java

@ -5,6 +5,7 @@
- Fields `publicKey` and `raw` removed from RPC API `Transaction` result object [#4575](https://github.com/hyperledger/besu/pull/4575)
### Additions and Improvements
- Support for ephemeral testnet Shandong. EIPs are still in flux, besu does not fully sync yet, and the network is subject to restarts. [#//FIXME](https://github.com/hyperledger/besu/pull///FIXME)
### Bug Fixes

@ -25,6 +25,7 @@ public enum NetworkName {
ROPSTEN("/ropsten.json", BigInteger.valueOf(3)),
SEPOLIA("/sepolia.json", BigInteger.valueOf(11155111)),
GOERLI("/goerli.json", BigInteger.valueOf(5)),
SHANDONG("/shandong.json", BigInteger.valueOf(1337903)),
KILN("/kiln.json", BigInteger.valueOf(1337802), false),
DEV("/dev.json", BigInteger.valueOf(2018), false),
CLASSIC("/classic.json", BigInteger.valueOf(1)),

@ -101,6 +101,12 @@ public class ForkIdsTest {
new ForkId(Bytes.ofUnsignedInt(0xb8c6299dL), 0L),
new ForkId(Bytes.ofUnsignedInt(0xb8c6299dL), 0L))
},
new Object[] {
NetworkName.SHANDONG,
List.of(
new ForkId(Bytes.ofUnsignedInt(0xc42480d3L), 0L),
new ForkId(Bytes.ofUnsignedInt(0xc42480d3L), 0L))
},
new Object[] {
NetworkName.MAINNET,
List.of(

@ -29,6 +29,7 @@ import static org.hyperledger.besu.cli.config.NetworkName.MORDOR;
import static org.hyperledger.besu.cli.config.NetworkName.RINKEBY;
import static org.hyperledger.besu.cli.config.NetworkName.ROPSTEN;
import static org.hyperledger.besu.cli.config.NetworkName.SEPOLIA;
import static org.hyperledger.besu.cli.config.NetworkName.SHANDONG;
import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG;
import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPRECATION_WARNING_MSG;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.ENGINE;
@ -43,6 +44,7 @@ import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfigura
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.MAINNET_DISCOVERY_URL;
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_BOOTSTRAP_NODES;
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_DISCOVERY_URL;
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.SHANDONG_BOOTSTRAP_NODES;
import static org.hyperledger.besu.ethereum.worldstate.DataStorageFormat.BONSAI;
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
import static org.junit.Assume.assumeThat;
@ -1041,6 +1043,22 @@ public class BesuCommandTest extends CommandTestAbstract {
assertThat(config.getNetworkId()).isEqualTo(BigInteger.valueOf(4));
}
@Test
public void testGenesisPathShandongEthConfig() {
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
parseCommand("--network", "shandong");
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
final EthNetworkConfig config = networkArg.getValue();
assertThat(config.getBootNodes()).isEqualTo(SHANDONG_BOOTSTRAP_NODES);
assertThat(config.getDnsDiscoveryUrl()).isNull();
assertThat(config.getNetworkId()).isEqualTo(BigInteger.valueOf(1337903));
}
@Test
public void genesisAndNetworkMustNotBeUsedTogether() throws Exception {
final Path genesisFile = createFakeGenesisFile(GENESIS_VALID_JSON);
@ -3976,6 +3994,24 @@ public class BesuCommandTest extends CommandTestAbstract {
verify(mockLogger, never()).warn(contains("Sepolia is deprecated and will be shutdown"));
}
@Test
public void shandongValuesAreUsed() {
parseCommand("--network", "shandong");
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(SHANDONG));
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
verify(mockLogger, never()).warn(contains("Shandong is deprecated and will be shutdown"));
}
@Test
public void classicValuesAreUsed() throws Exception {
parseCommand("--network", "classic");
@ -4039,6 +4075,10 @@ public class BesuCommandTest extends CommandTestAbstract {
networkValuesCanBeOverridden("ropsten");
}
public void shandongValuesCanBeOverridden() throws Exception {
networkValuesCanBeOverridden("shandong");
}
@Test
public void devValuesCanBeOverridden() throws Exception {
networkValuesCanBeOverridden("dev");

@ -40,6 +40,7 @@ class NetworkDeprecationMessageTest {
"MAINNET",
"SEPOLIA",
"GOERLI",
"SHANDONG",
"DEV",
"CLASSIC",
"KOTTI",

@ -22,6 +22,7 @@ import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfigura
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.MAINNET_DISCOVERY_URL;
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_BOOTSTRAP_NODES;
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.RINKEBY_DISCOVERY_URL;
import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.SHANDONG_BOOTSTRAP_NODES;
import java.math.BigInteger;
@ -56,6 +57,14 @@ public class EthNetworkConfigTest {
assertThat(config.getNetworkId()).isEqualTo(BigInteger.valueOf(5));
}
@Test
public void testDefaultShandongConfig() {
EthNetworkConfig config = EthNetworkConfig.getNetworkConfig(NetworkName.SHANDONG);
assertThat(config.getDnsDiscoveryUrl()).isNull();
assertThat(config.getBootNodes()).isEqualTo(SHANDONG_BOOTSTRAP_NODES);
assertThat(config.getNetworkId()).isEqualTo(BigInteger.valueOf(1337903));
}
@Test
public void testDefaultDevConfig() {
EthNetworkConfig config = EthNetworkConfig.getNetworkConfig(NetworkName.DEV);

@ -96,6 +96,19 @@ public class DefaultDiscoveryConfiguration {
"enode://9246d00bc8fd1742e5ad2428b80fc4dc45d786283e05ef6edbd9002cbc335d40998444732fbe921cb88e1d2c73d1b1de53bae6a2237996e9bfe14f871baf7066@18.168.182.86:30303")
.map(EnodeURLImpl::fromString)
.collect(toList()));
public static final List<EnodeURL> SHANDONG_BOOTSTRAP_NODES =
Collections.unmodifiableList(
Stream.of(
"enode://11e43515d6258ab2bd814b25a50c911c155a46a27e9be8ce6ea68e293ec13aa4cd6740418baf9abf1e79ba9252c497d66aa4a293c94ef8168d0e7c211ef73690@46.101.126.45:30303",
"enode://95b683a66aba396551bafff688644fc6dc1bada2de78491f89b268ebdcf3d88dfc9942a9f2833ecc3887d49dfb4e96851c2f5eb0adde41847cc356f15ac4ac67@178.128.206.76:30303",
"enode://bcd3eeabca8ff3a1c3b19384e064cc79fda547939324e0699d030041a8960a1d68f1e19141d19305e79675be50434521d024352a5eae00da8ace7933abf20fdf@142.93.160.7:30303",
"enode://6a65c7e62360e1fcc98c88cf8dd8e9492d2e95372f5d7b742b73ab8f82e849bae196bd18b79bc9502b204cef7bf64b589147700368d877c32a76f9c4fd7dd941@104.248.21.4:30303",
"enode://2ae5ef4b4c338e4ee15a347aba8e60bcb451ca19d26f8d67e731bb5f2972ad6ce867ec85f9942a5efe349470106b21c49a9aeb5b00b91063e35f1c1643c0930c@104.248.251.20:30303",
"enode://85ecd8fcab723a33ee68e5f8530c9d264bd601899dc74af7f020bc2f8e0d0ad8ec5c5324364f127c77ddab607bc16e1c5fbae2c675b6d94a79a24222e7e4766e@164.92.174.56:30303",
"enode://24951d3b76f20aed18e32096941d572b98518c9e4dace6b7d0b1f34292dfc5ee7d295453b955be4d2967c6ce1948c11513cd70d76dbee8d3034ddb40d63f5517@142.93.173.170:30303",
"enode://73e2396ac78c462287edd22957096890ca1995a4995c51a1fe24accbe931209fb0fc5359fc1043a0edad3fc53ba64fba5262255c70a03e5fca86f924c261ad4f@178.128.203.243:30303")
.map(EnodeURLImpl::fromString)
.collect(toList()));
public static final List<EnodeURL> CLASSIC_BOOTSTRAP_NODES =
Collections.unmodifiableList(
Stream.of(

@ -37,7 +37,7 @@ public class GenesisConfigFile {
public static final GenesisConfigFile DEFAULT =
new GenesisConfigFile(JsonUtil.createEmptyObjectNode());
public static final Wei BASEFEE_AT_GENESIS_DEFAULT_VALUE = Wei.of(1000000000L);
public static final Wei BASEFEE_AT_GENESIS_DEFAULT_VALUE = Wei.of(1_000_000_000L);
private final ObjectNode configRoot;
private GenesisConfigFile(final ObjectNode config) {
@ -139,12 +139,17 @@ public class GenesisConfigFile {
}
public Optional<Wei> getGenesisBaseFeePerGas() {
// if we have a base fee market at genesis, get either the configured baseFeePerGas, or the
// default
return getBaseFeePerGas()
.map(Optional::of)
.orElseGet(() -> Optional.of(BASEFEE_AT_GENESIS_DEFAULT_VALUE))
.filter(z -> 0L == getConfigOptions().getLondonBlockNumber().orElse(-1L));
if (getBaseFeePerGas().isPresent()) {
// always use specified basefee if present
return getBaseFeePerGas();
} else if (getConfigOptions().getLondonBlockNumber().orElse(-1L) == 0) {
// if not specified, and we specify london at block zero use a default fee
// this is needed for testing.
return Optional.of(BASEFEE_AT_GENESIS_DEFAULT_VALUE);
} else {
// no explicit base fee and no london block zero means no basefee at genesis
return Optional.empty();
}
}
public String getMixHash() {
@ -170,7 +175,7 @@ public class GenesisConfigFile {
private String getFirstRequiredString(final String... keys) {
List<String> keysList = Arrays.asList(keys);
return keysList.stream()
.filter(key -> configRoot.has(key))
.filter(configRoot::has)
.findFirst()
.map(key -> configRoot.get(key).asText())
.orElseThrow(

@ -90,6 +90,8 @@ public interface GenesisConfigOptions {
OptionalLong getMergeNetSplitBlockNumber();
OptionalLong getShandongBlockNumber();
Optional<Wei> getBaseFeePerGas();
Optional<UInt256> getTerminalTotalDifficulty();

@ -30,7 +30,6 @@ import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableMap;
import org.apache.tuweni.units.bigints.UInt256;
@ -60,17 +59,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
static JsonGenesisConfigOptions fromJsonObjectWithOverrides(
final ObjectNode configRoot, final Map<String, String> configOverrides) {
final TransitionsConfigOptions transitionsConfigOptions;
try {
transitionsConfigOptions = loadTransitionsFrom(configRoot);
} catch (final JsonProcessingException e) {
throw new RuntimeException("Transitions section of genesis file failed to decode.", e);
}
transitionsConfigOptions = loadTransitionsFrom(configRoot);
return new JsonGenesisConfigOptions(configRoot, configOverrides, transitionsConfigOptions);
}
private static TransitionsConfigOptions loadTransitionsFrom(final ObjectNode parentNode)
throws JsonProcessingException {
private static TransitionsConfigOptions loadTransitionsFrom(final ObjectNode parentNode) {
final Optional<ObjectNode> transitionsNode =
JsonUtil.getObjectNode(parentNode, TRANSITIONS_CONFIG_KEY);
if (transitionsNode.isEmpty()) {
@ -285,6 +278,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
return getOptionalLong("mergenetsplitblock");
}
@Override
public OptionalLong getShandongBlockNumber() {
return getOptionalLong("shandongblock");
}
@Override
public Optional<Wei> getBaseFeePerGas() {
return Optional.ofNullable(configOverrides.get("baseFeePerGas"))
@ -422,21 +420,9 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
// mainnet fork blocks
getHomesteadBlockNumber().ifPresent(l -> builder.put("homesteadBlock", l));
getDaoForkBlock()
.ifPresent(
l -> {
builder.put("daoForkBlock", l);
});
getTangerineWhistleBlockNumber()
.ifPresent(
l -> {
builder.put("eip150Block", l);
});
getSpuriousDragonBlockNumber()
.ifPresent(
l -> {
builder.put("eip158Block", l);
});
getDaoForkBlock().ifPresent(l -> builder.put("daoForkBlock", l));
getTangerineWhistleBlockNumber().ifPresent(l -> builder.put("eip150Block", l));
getSpuriousDragonBlockNumber().ifPresent(l -> builder.put("eip158Block", l));
getByzantiumBlockNumber().ifPresent(l -> builder.put("byzantiumBlock", l));
getConstantinopleBlockNumber().ifPresent(l -> builder.put("constantinopleBlock", l));
getPetersburgBlockNumber().ifPresent(l -> builder.put("petersburgBlock", l));
@ -447,6 +433,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
getArrowGlacierBlockNumber().ifPresent(l -> builder.put("arrowGlacierBlock", l));
getGrayGlacierBlockNumber().ifPresent(l -> builder.put("grayGlacierBlock", l));
getMergeNetSplitBlockNumber().ifPresent(l -> builder.put("mergeNetSplitBlock", l));
getShandongBlockNumber().ifPresent(l -> builder.put("shandongBlock", l));
getTerminalBlockNumber().ifPresent(l -> builder.put("terminalBlockNumber", l));
getTerminalBlockHash().ifPresent(h -> builder.put("terminalBlockHash", h.toHexString()));
@ -548,7 +535,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
final String overrideHash = configOverrides.get(key);
return Optional.of(Hash.fromHexString(overrideHash));
} else {
return JsonUtil.getValueAsString(configRoot, key).map(s -> Hash.fromHexString(s));
return JsonUtil.getValueAsString(configRoot, key).map(Hash::fromHexString);
}
}
@ -570,6 +557,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
getArrowGlacierBlockNumber(),
getGrayGlacierBlockNumber(),
getMergeNetSplitBlockNumber(),
getShandongBlockNumber(),
getEcip1015BlockNumber(),
getDieHardBlockNumber(),
getGothamBlockNumber(),

@ -44,6 +44,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
private OptionalLong arrowGlacierBlockNumber = OptionalLong.empty();
private OptionalLong grayGlacierBlockNumber = OptionalLong.empty();
private OptionalLong mergeNetSplitBlockNumber = OptionalLong.empty();
private OptionalLong shandongBlockNumber = OptionalLong.empty();
private OptionalLong terminalBlockNumber = OptionalLong.empty();
private Optional<Hash> terminalBlockHash = Optional.empty();
private Optional<UInt256> terminalTotalDifficulty = Optional.empty();
@ -69,7 +70,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
private QbftConfigOptions qbftConfigOptions = JsonQbftConfigOptions.DEFAULT;
private BftConfigOptions bftConfigOptions = JsonBftConfigOptions.DEFAULT;
private TransitionsConfigOptions transitions = TransitionsConfigOptions.DEFAULT;
private final DiscoveryOptions discoveryOptions = DiscoveryOptions.DEFAULT;
private static final DiscoveryOptions DISCOVERY_OPTIONS = DiscoveryOptions.DEFAULT;
@Override
public String getConsensusEngine() {
@ -133,7 +134,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
@Override
public DiscoveryOptions getDiscoveryOptions() {
return discoveryOptions;
return DISCOVERY_OPTIONS;
}
@Override
@ -216,6 +217,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return mergeNetSplitBlockNumber;
}
@Override
public OptionalLong getShandongBlockNumber() {
return shandongBlockNumber;
}
@Override
public Optional<Wei> getBaseFeePerGas() {
return baseFeePerGas;
@ -319,21 +325,13 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
@Override
public Map<String, Object> asMap() {
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
getChainId().ifPresent(chainId -> builder.put("chainId", chainId));
getChainId().ifPresent(id -> builder.put("chainId", id));
// mainnet fork blocks
getHomesteadBlockNumber().ifPresent(l -> builder.put("homesteadBlock", l));
getDaoForkBlock()
.ifPresent(
l -> {
builder.put("daoForkBlock", l);
});
getDaoForkBlock().ifPresent(l -> builder.put("daoForkBlock", l));
getTangerineWhistleBlockNumber().ifPresent(l -> builder.put("eip150Block", l));
getSpuriousDragonBlockNumber()
.ifPresent(
l -> {
builder.put("eip158Block", l);
});
getSpuriousDragonBlockNumber().ifPresent(l -> builder.put("eip158Block", l));
getByzantiumBlockNumber().ifPresent(l -> builder.put("byzantiumBlock", l));
getConstantinopleBlockNumber().ifPresent(l -> builder.put("constantinopleBlock", l));
getPetersburgBlockNumber().ifPresent(l -> builder.put("petersburgBlock", l));
@ -344,6 +342,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
getArrowGlacierBlockNumber().ifPresent(l -> builder.put("arrowGlacierBlock", l));
getGrayGlacierBlockNumber().ifPresent(l -> builder.put("grayGlacierBlock", l));
getMergeNetSplitBlockNumber().ifPresent(l -> builder.put("mergeNetSplitBlock", l));
getShandongBlockNumber().ifPresent(l -> builder.put("shandongBlock", l));
getTerminalBlockNumber().ifPresent(l -> builder.put("terminalBlockNumber", l));
getTerminalBlockHash().ifPresent(h -> builder.put("terminalBlockHash", h));
// classic fork blocks
@ -487,6 +486,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return this;
}
public StubGenesisConfigOptions shandongBlock(final long blockNumber) {
shandongBlockNumber = OptionalLong.of(blockNumber);
return this;
}
public StubGenesisConfigOptions terminalTotalDifficulty(
final UInt256 updatedTerminalTotalDifficulty) {
terminalTotalDifficulty = Optional.of(updatedTerminalTotalDifficulty);

File diff suppressed because one or more lines are too long

@ -160,37 +160,34 @@ public class GenesisConfigFileTest {
// no specified baseFeePerGas:
assertThat(withBaseFeeAtGenesis.getBaseFeePerGas()).isNotPresent();
// supply a default genesis baseFeePerGas when london-at-genesis:
assertThat(withBaseFeeAtGenesis.getGenesisBaseFeePerGas().get())
.isEqualTo(GenesisConfigFile.BASEFEE_AT_GENESIS_DEFAULT_VALUE);
assertThat(withBaseFeeAtGenesis.getGenesisBaseFeePerGas())
.contains(GenesisConfigFile.BASEFEE_AT_GENESIS_DEFAULT_VALUE);
}
@Test
public void shouldNotGetBaseFeeAtGenesis() {
public void shouldGetBaseFeeExplicitlyAtGenesis() {
GenesisConfigFile withBaseFeeNotAtGenesis =
GenesisConfigFile.fromConfig("{\"config\":{\"londonBlock\":10},\"baseFeePerGas\":\"0xa\"}");
// specified baseFeePerGas:
assertThat(withBaseFeeNotAtGenesis.getBaseFeePerGas().get().toLong()).isEqualTo(10L);
Wei expectedBaseFee = Wei.of(0xa);
assertThat(withBaseFeeNotAtGenesis.getBaseFeePerGas()).contains(expectedBaseFee);
// but no baseFeePerGas since london block is not at genesis:
assertThat(withBaseFeeNotAtGenesis.getGenesisBaseFeePerGas()).isNotPresent();
assertThat(withBaseFeeNotAtGenesis.getGenesisBaseFeePerGas()).contains(expectedBaseFee);
}
@Test
public void shouldOverrideConfigOptionsBaseFeeWhenSpecified() {
GenesisConfigOptions withOverrides =
EMPTY_CONFIG.getConfigOptions(Map.of("baseFeePerGas", Wei.of(8).toString()));
assertThat(withOverrides.getBaseFeePerGas().get().toLong()).isEqualTo(8L);
assertThat(withOverrides.getBaseFeePerGas()).contains(Wei.of(8L));
}
@Test
public void shouldGetTerminalTotalDifficultyAtGenesis() {
GenesisConfigFile withTerminalTotalDifficultyAtGenesis =
fromConfig("{\"config\":{\"terminalTotalDifficulty\":1000}}");
assertThat(
withTerminalTotalDifficultyAtGenesis
.getConfigOptions()
.getTerminalTotalDifficulty()
.get())
.isEqualTo(UInt256.valueOf(1000L));
assertThat(withTerminalTotalDifficultyAtGenesis.getConfigOptions().getTerminalTotalDifficulty())
.contains(UInt256.valueOf(1000L));
}
@Test
@ -204,8 +201,8 @@ public class GenesisConfigFileTest {
GenesisConfigFile.genesisFileFromResources("/ropsten.json").getConfigOptions();
assertThat(ropstenOptions.getTerminalTotalDifficulty()).isPresent();
assertThat(ropstenOptions.getTerminalTotalDifficulty().get())
.isEqualTo(UInt256.valueOf(new BigInteger("50000000000000000")));
assertThat(ropstenOptions.getTerminalTotalDifficulty())
.contains(UInt256.valueOf(new BigInteger("50000000000000000")));
}
@Test
@ -214,8 +211,8 @@ public class GenesisConfigFileTest {
GenesisConfigFile.genesisFileFromResources("/sepolia.json").getConfigOptions();
assertThat(sepoliaOptions.getTerminalTotalDifficulty()).isPresent();
assertThat(sepoliaOptions.getTerminalTotalDifficulty().get())
.isEqualTo(UInt256.valueOf(new BigInteger("17000000000000000")));
assertThat(sepoliaOptions.getTerminalTotalDifficulty())
.contains(UInt256.valueOf(new BigInteger("17000000000000000")));
}
@Test
@ -224,8 +221,8 @@ public class GenesisConfigFileTest {
GenesisConfigFile.genesisFileFromResources("/goerli.json").getConfigOptions();
assertThat(goerliOptions.getTerminalTotalDifficulty()).isPresent();
assertThat(goerliOptions.getTerminalTotalDifficulty().get())
.isEqualTo(UInt256.valueOf(new BigInteger("10790000")));
assertThat(goerliOptions.getTerminalTotalDifficulty())
.contains(UInt256.valueOf(new BigInteger("10790000")));
}
@Test
@ -235,8 +232,8 @@ public class GenesisConfigFileTest {
assertThat(mainnetOptions.getTerminalTotalDifficulty()).isPresent();
// tentative as of 2022-08-11:
assertThat(mainnetOptions.getTerminalTotalDifficulty().get())
.isEqualTo(UInt256.valueOf(new BigInteger("58750000000000000000000")));
assertThat(mainnetOptions.getTerminalTotalDifficulty())
.contains(UInt256.valueOf(new BigInteger("58750000000000000000000")));
}
@Test
@ -246,8 +243,8 @@ public class GenesisConfigFileTest {
.getConfigOptions(Map.of("terminalTotalDifficulty", String.valueOf(Long.MAX_VALUE)));
assertThat(ropstenOverrideOptions.getTerminalTotalDifficulty()).isPresent();
assertThat(ropstenOverrideOptions.getTerminalTotalDifficulty().get())
.isEqualTo(UInt256.valueOf(Long.MAX_VALUE));
assertThat(ropstenOverrideOptions.getTerminalTotalDifficulty())
.contains(UInt256.valueOf(Long.MAX_VALUE));
}
@Test
@ -298,8 +295,8 @@ public class GenesisConfigFileTest {
config
.streamAllocations()
.collect(Collectors.toMap(GenesisAllocation::getAddress, Function.identity()));
assertThat(allocations.keySet())
.containsOnly(
assertThat(allocations)
.containsOnlyKeys(
"fe3b557e8fb62b89f4916b721be55ceb828dbd73",
"627306090abab3a6e1400e9345bc60c78a8bef57",
"f17f52151ebef6c7334fad080c5704d77216b732");
@ -310,17 +307,15 @@ public class GenesisConfigFileTest {
assertThat(alloc1.getBalance()).isEqualTo("0xad78ebc5ac6200000");
assertThat(alloc2.getBalance()).isEqualTo("1000");
assertThat(alloc3.getBalance()).isEqualTo("90000000000000000000000");
assertThat(alloc3.getStorage().size()).isEqualTo(2);
assertThat(
alloc3
.getStorage()
.get("0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a4"))
.isEqualTo("0x937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0");
assertThat(
alloc3
.getStorage()
.get("0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a3"))
.isEqualTo("0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012");
assertThat(alloc3.getStorage()).hasSize(2);
assertThat(alloc3.getStorage())
.containsEntry(
"0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a4",
"0x937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0");
assertThat(alloc3.getStorage())
.containsEntry(
"0xc4c3a3f99b26e5e534b71d6f33ca6ea5c174decfb16dd7237c60eff9774ef4a3",
"0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012");
}
@Test
@ -387,7 +382,7 @@ public class GenesisConfigFileTest {
final int bigBlock = 999_999_999;
final String bigBlockString = Integer.toString(bigBlock);
final Map<String, String> override = new HashMap<>();
// as speicified
// as specified
override.put("istanbulBlock", bigBlockString);
// ALL CAPS
override.put("CHAINID", bigBlockString);
@ -541,8 +536,8 @@ public class GenesisConfigFileTest {
* all_forks.json will also be updated.
*
* <p>This catches a common error in JsonGenesisConfigOptions where internally the names are all
* lower ase but 'canonicaly' they are mixed case, as well as being mixed case almost everywhere
* else in the code. Case differences are common in custom genesis files so historically we have
* lower ase but 'canonically' they are mixed case, as well as being mixed case almost everywhere
* else in the code. Case differences are common in custom genesis files, so historically we have
* been case agnostic.
*/
@Test

@ -59,7 +59,7 @@ public class GenesisConfigOptionsTest {
public void shouldUseIbftLegacyWhenIbftInConfig() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("ibft", emptyMap()));
assertThat(config.isIbftLegacy()).isTrue();
assertThat(config.getIbftLegacyConfigOptions()).isNotSameAs(JsonBftConfigOptions.DEFAULT);
assertThat(config.getIbftLegacyConfigOptions()).isNotSameAs(IbftLegacyConfigOptions.DEFAULT);
assertThat(config.getConsensusEngine()).isEqualTo("ibft");
}
@ -197,6 +197,12 @@ public class GenesisConfigOptionsTest {
assertThat(config.getGrayGlacierBlockNumber()).hasValue(4242);
}
@Test
public void shouldGetShandongBlockNumber() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("shandongBlock", 1337));
assertThat(config.getShandongBlockNumber()).hasValue(1337);
}
@Test
// TODO ECIP-1049 change for the actual fork name when known
public void shouldGetECIP1049BlockNumber() {
@ -220,6 +226,7 @@ public class GenesisConfigOptionsTest {
assertThat(config.getLondonBlockNumber()).isEmpty();
assertThat(config.getArrowGlacierBlockNumber()).isEmpty();
assertThat(config.getGrayGlacierBlockNumber()).isEmpty();
assertThat(config.getShandongBlockNumber()).isEmpty();
assertThat(config.getEcip1049BlockNumber()).isEmpty();
}
@ -244,13 +251,13 @@ public class GenesisConfigOptionsTest {
final GenesisConfigOptions config =
fromConfigOptions(singletonMap("terminalTotalDifficulty", BigInteger.valueOf(1000)));
assertThat(config.getTerminalTotalDifficulty()).isPresent();
assertThat(config.getTerminalTotalDifficulty().get()).isEqualTo(UInt256.valueOf(1000));
assertThat(config.getTerminalTotalDifficulty()).contains(UInt256.valueOf(1000));
// stubJsonGenesis
final GenesisConfigOptions stub =
new StubGenesisConfigOptions().terminalTotalDifficulty(UInt256.valueOf(500));
assertThat(stub.getTerminalTotalDifficulty()).isPresent();
assertThat(stub.getTerminalTotalDifficulty().get()).isEqualTo(UInt256.valueOf(500));
assertThat(stub.getTerminalTotalDifficulty()).contains(UInt256.valueOf(500));
}
@Test

@ -266,7 +266,7 @@ public final class GenesisState {
storage
.entrySet()
.forEach(
(entry) -> {
entry -> {
final UInt256 key =
withNiceErrorMessage("storage key", entry.getKey(), UInt256::fromHexString);
final UInt256 value =

@ -20,7 +20,6 @@ import org.hyperledger.besu.plugin.data.Quantity;
import java.math.BigInteger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.primitives.Ints;
/** Provides the various difficultly calculates used on mainnet hard forks. */
@ -45,7 +44,7 @@ public abstract class MainnetDifficultyCalculators {
private MainnetDifficultyCalculators() {}
public static DifficultyCalculator FRONTIER =
static final DifficultyCalculator FRONTIER =
(time, parent, protocolContext) -> {
final BigInteger parentDifficulty = difficulty(parent.getDifficulty());
final BigInteger adjust = parentDifficulty.divide(DIFFICULTY_BOUND_DIVISOR);
@ -60,7 +59,7 @@ public abstract class MainnetDifficultyCalculators {
return periodCount > 1 ? adjustForPeriod(periodCount, difficulty) : difficulty;
};
public static DifficultyCalculator HOMESTEAD =
static final DifficultyCalculator HOMESTEAD =
(time, parent, protocolContext) -> {
final BigInteger parentDifficulty = difficulty(parent.getDifficulty());
final BigInteger difficulty =
@ -72,31 +71,30 @@ public abstract class MainnetDifficultyCalculators {
return periodCount > 1 ? adjustForPeriod(periodCount, difficulty) : difficulty;
};
@VisibleForTesting
public static DifficultyCalculator BYZANTIUM =
static final DifficultyCalculator BYZANTIUM =
(time, parent, protocolContext) ->
calculateThawedDifficulty(time, parent, BYZANTIUM_FAKE_BLOCK_OFFSET);
static DifficultyCalculator CONSTANTINOPLE =
static final DifficultyCalculator CONSTANTINOPLE =
(time, parent, protocolContext) ->
calculateThawedDifficulty(time, parent, CONSTANTINOPLE_FAKE_BLOCK_OFFSET);
static DifficultyCalculator MUIR_GLACIER =
static final DifficultyCalculator MUIR_GLACIER =
(time, parent, protocolContext) ->
calculateThawedDifficulty(time, parent, MUIR_GLACIER_FAKE_BLOCK_OFFSET);
// As per https://eips.ethereum.org/EIPS/eip-3554
static DifficultyCalculator LONDON =
static final DifficultyCalculator LONDON =
(time, parent, protocolContext) ->
calculateThawedDifficulty(time, parent, LONDON_FAKE_BLOCK_OFFSET);
// As per https://eips.ethereum.org/EIPS/eip-4345
static DifficultyCalculator ARROW_GLACIER =
static final DifficultyCalculator ARROW_GLACIER =
(time, parent, protocolContext) ->
calculateThawedDifficulty(time, parent, ARROW_GLACIER_FAKE_BLOCK_OFFSET);
// As per https://eips.ethereum.org/EIPS/eip-5133
static DifficultyCalculator GRAY_GLACIER =
static final DifficultyCalculator GRAY_GLACIER =
(time, parent, protocolContext) ->
calculateThawedDifficulty(time, parent, GRAY_GLACIER_FAKE_BLOCK_OFFSET);

@ -185,6 +185,17 @@ public class MainnetProtocolSpecFactory {
evmConfiguration);
}
public ProtocolSpecBuilder shandongDefinition(final GenesisConfigOptions genesisConfigOptions) {
return MainnetProtocolSpecs.shandongDefinition(
chainId,
contractSizeLimit,
evmStackSize,
isRevertReasonEnabled,
genesisConfigOptions,
quorumCompatibilityMode,
evmConfiguration);
}
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
// Classic Protocol Specs

@ -69,7 +69,6 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Resources;
import io.vertx.core.json.JsonArray;
@ -88,8 +87,8 @@ public abstract class MainnetProtocolSpecs {
// A consensus bug at Ethereum mainnet transaction 0xcf416c53
// deleted an empty account even when the message execution scope
// failed, but the transaction itself succeeded.
private static final ImmutableSet<Address> SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES =
ImmutableSet.of(RIPEMD160_PRECOMPILE);
private static final Set<Address> SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES =
Set.of(RIPEMD160_PRECOMPILE);
private static final Wei FRONTIER_BLOCK_REWARD = Wei.fromEth(5);
@ -631,6 +630,30 @@ public abstract class MainnetProtocolSpecs {
.name("ParisFork");
}
static ProtocolSpecBuilder shandongDefinition(
final Optional<BigInteger> chainId,
final OptionalInt configContractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason,
final GenesisConfigOptions genesisConfigOptions,
final boolean quorumCompatibilityMode,
final EvmConfiguration evmConfiguration) {
return parisDefinition(
chainId,
configContractSizeLimit,
configStackSizeLimit,
enableRevertReason,
genesisConfigOptions,
quorumCompatibilityMode,
evmConfiguration)
.evmBuilder(
(gasCalculator, jdCacheConfig) ->
MainnetEVMs.shandong(
gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration))
.name("Shandong");
}
private static TransactionReceipt frontierTransactionReceiptFactory(
// ignored because it's always FRONTIER
final TransactionType __,

@ -26,8 +26,8 @@ import java.util.OptionalLong;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -130,8 +130,7 @@ public class ProtocolScheduleBuilder {
}
public ProtocolSchedule createProtocolSchedule() {
final Optional<BigInteger> chainId =
config.getChainId().map(Optional::of).orElse(defaultChainId);
final Optional<BigInteger> chainId = config.getChainId().or(() -> defaultChainId);
final MutableProtocolSchedule protocolSchedule = new MutableProtocolSchedule(chainId);
final MainnetProtocolSpecFactory specFactory =
@ -211,54 +210,45 @@ public class ProtocolScheduleBuilder {
private TreeMap<Long, BuilderMapEntry> buildMilestoneMap(
final MainnetProtocolSpecFactory specFactory) {
final TreeMap<Long, BuilderMapEntry> builders =
Lists.newArrayList(
create(OptionalLong.of(0), specFactory.frontierDefinition()),
create(config.getHomesteadBlockNumber(), specFactory.homesteadDefinition()),
create(
config.getTangerineWhistleBlockNumber(),
specFactory.tangerineWhistleDefinition()),
create(
config.getSpuriousDragonBlockNumber(), specFactory.spuriousDragonDefinition()),
create(config.getByzantiumBlockNumber(), specFactory.byzantiumDefinition()),
create(
config.getConstantinopleBlockNumber(), specFactory.constantinopleDefinition()),
create(config.getPetersburgBlockNumber(), specFactory.petersburgDefinition()),
create(config.getIstanbulBlockNumber(), specFactory.istanbulDefinition()),
create(config.getMuirGlacierBlockNumber(), specFactory.muirGlacierDefinition()),
create(config.getBerlinBlockNumber(), specFactory.berlinDefinition()),
create(config.getLondonBlockNumber(), specFactory.londonDefinition(config)),
create(
config.getArrowGlacierBlockNumber(),
specFactory.arrowGlacierDefinition(config)),
create(
config.getGrayGlacierBlockNumber(), specFactory.grayGlacierDefinition(config)),
create(config.getMergeNetSplitBlockNumber(), specFactory.parisDefinition(config)),
// Classic Milestones
create(config.getEcip1015BlockNumber(), specFactory.tangerineWhistleDefinition()),
create(config.getDieHardBlockNumber(), specFactory.dieHardDefinition()),
create(config.getGothamBlockNumber(), specFactory.gothamDefinition()),
create(
config.getDefuseDifficultyBombBlockNumber(),
specFactory.defuseDifficultyBombDefinition()),
create(config.getAtlantisBlockNumber(), specFactory.atlantisDefinition()),
create(config.getAghartaBlockNumber(), specFactory.aghartaDefinition()),
create(config.getPhoenixBlockNumber(), specFactory.phoenixDefinition()),
create(config.getThanosBlockNumber(), specFactory.thanosDefinition()),
create(config.getMagnetoBlockNumber(), specFactory.magnetoDefinition()),
create(config.getMystiqueBlockNumber(), specFactory.mystiqueDefinition()),
create(config.getEcip1049BlockNumber(), specFactory.ecip1049Definition()))
.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(
Collectors.toMap(
BuilderMapEntry::getBlock,
b -> b,
(existing, replacement) -> replacement,
TreeMap::new));
return builders;
return Stream.of(
create(OptionalLong.of(0), specFactory.frontierDefinition()),
create(config.getHomesteadBlockNumber(), specFactory.homesteadDefinition()),
create(
config.getTangerineWhistleBlockNumber(), specFactory.tangerineWhistleDefinition()),
create(config.getSpuriousDragonBlockNumber(), specFactory.spuriousDragonDefinition()),
create(config.getByzantiumBlockNumber(), specFactory.byzantiumDefinition()),
create(config.getConstantinopleBlockNumber(), specFactory.constantinopleDefinition()),
create(config.getPetersburgBlockNumber(), specFactory.petersburgDefinition()),
create(config.getIstanbulBlockNumber(), specFactory.istanbulDefinition()),
create(config.getMuirGlacierBlockNumber(), specFactory.muirGlacierDefinition()),
create(config.getBerlinBlockNumber(), specFactory.berlinDefinition()),
create(config.getLondonBlockNumber(), specFactory.londonDefinition(config)),
create(config.getArrowGlacierBlockNumber(), specFactory.arrowGlacierDefinition(config)),
create(config.getGrayGlacierBlockNumber(), specFactory.grayGlacierDefinition(config)),
create(config.getMergeNetSplitBlockNumber(), specFactory.parisDefinition(config)),
create(config.getShandongBlockNumber(), specFactory.shandongDefinition(config)),
// Classic Milestones
create(config.getEcip1015BlockNumber(), specFactory.tangerineWhistleDefinition()),
create(config.getDieHardBlockNumber(), specFactory.dieHardDefinition()),
create(config.getGothamBlockNumber(), specFactory.gothamDefinition()),
create(
config.getDefuseDifficultyBombBlockNumber(),
specFactory.defuseDifficultyBombDefinition()),
create(config.getAtlantisBlockNumber(), specFactory.atlantisDefinition()),
create(config.getAghartaBlockNumber(), specFactory.aghartaDefinition()),
create(config.getPhoenixBlockNumber(), specFactory.phoenixDefinition()),
create(config.getThanosBlockNumber(), specFactory.thanosDefinition()),
create(config.getMagnetoBlockNumber(), specFactory.magnetoDefinition()),
create(config.getMystiqueBlockNumber(), specFactory.mystiqueDefinition()),
create(config.getEcip1049BlockNumber(), specFactory.ecip1049Definition()))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(
Collectors.toMap(
BuilderMapEntry::getBlock,
b -> b,
(existing, replacement) -> replacement,
TreeMap::new));
}
private void addProtocolSpec(
@ -326,6 +316,7 @@ public class ProtocolScheduleBuilder {
validateForkOrder("ArrowGlacier", config.getArrowGlacierBlockNumber(), lastForkBlock);
lastForkBlock =
validateForkOrder("GrayGlacier", config.getGrayGlacierBlockNumber(), lastForkBlock);
lastForkBlock = validateForkOrder("Shandong", config.getShandongBlockNumber(), lastForkBlock);
assert (lastForkBlock >= 0);
}

@ -133,6 +133,19 @@ public class MainnetProtocolScheduleTest {
Assertions.assertThat(sched.getByBlockNumber(Long.MAX_VALUE).getName()).isEqualTo("London");
}
@Test
public void shouldCreateShandongConfig() throws Exception {
final ProtocolSchedule sched =
MainnetProtocolSchedule.fromConfig(
GenesisConfigFile.fromConfig(
Resources.toString(
this.getClass().getResource("/shandong.json"), StandardCharsets.UTF_8))
.getConfigOptions(),
EvmConfiguration.DEFAULT);
Assertions.assertThat(sched.getByBlockNumber(0L).getName()).isEqualTo("Shandong");
Assertions.assertThat(sched.getByBlockNumber(Long.MAX_VALUE).getName()).isEqualTo("Shandong");
}
@Test
public void shouldCreateRinkebyConfig() throws Exception {
final ProtocolSchedule sched =

@ -36,7 +36,8 @@ import org.slf4j.LoggerFactory;
public class RequestManager {
private static final Logger LOG = LoggerFactory.getLogger(RequestManager.class);
private final AtomicLong requestIdCounter = new AtomicLong(0);
private final AtomicLong requestIdCounter =
new AtomicLong(1); // some clients have issues encoding zero
private final Map<BigInteger, ResponseStream> responseStreams = new ConcurrentHashMap<>();
private final EthPeer peer;
private final boolean supportsRequestId;
@ -81,9 +82,7 @@ public class RequestManager {
responseStream -> responseStream.processMessage(requestIdAndEthMessage.getValue()),
// Consider incorrect requestIds to be a useless response; too
// many of these and we will disconnect.
() -> {
peer.recordUselessResponse("Request ID incorrect");
});
() -> peer.recordUselessResponse("Request ID incorrect"));
} else {
// otherwise iterate through all of them

@ -58,6 +58,8 @@ public class ForkIdTestUtil {
"0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177";
public static final String GOERLI =
"0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a";
public static final String SHANDONG =
"0xbea94d3492ed9c41556a1c45c27da4947938880fb4c15f31fb742e5a1c10a2fb";
public static final String PRIVATE =
"0x0000000000000000000000000000000000000000000000000000000000000000";
}
@ -74,6 +76,8 @@ public class ForkIdTestUtil {
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> SHANDONG =
Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
public static final List<Long> PRIVATE = Arrays.asList(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
}
@ -129,6 +133,7 @@ public class ForkIdTestUtil {
public static final Network SEPOLIA = network(GenesisHash.SEPOLIA, Forks.SEPOLIA);
public static final Network RINKEBY = network(GenesisHash.RINKEBY, Forks.RINKEBY);
public static final Network GOERLI = network(GenesisHash.GOERLI, Forks.GOERLI);
public static final Network SHANDONG = network(GenesisHash.SHANDONG, Forks.SHANDONG);
public static final Network PRIVATE = network(GenesisHash.PRIVATE, Forks.PRIVATE);
public final String hash;
public final List<Long> forks;

@ -508,6 +508,31 @@ public class EIP2124Test {
Optional.of(ForkIds.GOERLI),
empty()
},
// Shandong network test cases
{
"Shandong // Unsynced",
Network.SHANDONG,
0L,
ForkIdTestUtil.wantForkId("0xc42480d3", 0L),
empty(),
empty()
},
{
"Shandong // First block",
Network.SHANDONG,
1L,
ForkIdTestUtil.wantForkId("0xc42480d3", 0L),
empty(),
empty()
},
{
"Shandong // Future block",
Network.SHANDONG,
1000000L,
ForkIdTestUtil.wantForkId("0xc42480d3", 0L),
empty(),
empty()
},
// Private network test cases
{
"Private // Unsynced",

@ -40,7 +40,7 @@ import org.junit.Test;
public class RequestManagerTest {
private final AtomicLong requestIdCounter = new AtomicLong(0);
private final AtomicLong requestIdCounter = new AtomicLong(1);
@Test
public void dispatchesMessagesReceivedAfterRegisteringCallback() throws Exception {
@ -73,7 +73,7 @@ public class RequestManagerTest {
requestManager.dispatchResponse(mockMessage);
// Response handler should get message
assertThat(receivedMessages.size()).isEqualTo(1);
assertThat(receivedMessages).hasSize(1);
assertResponseCorrect(receivedMessages.get(0), mockMessage, supportsRequestId);
assertThat(closedCount.get()).isEqualTo(1);
}
@ -110,7 +110,7 @@ public class RequestManagerTest {
// Response handler should get message
stream.then(responseHandler);
assertThat(receivedMessages.size()).isEqualTo(1);
assertThat(receivedMessages).hasSize(1);
assertResponseCorrect(receivedMessages.get(0), mockMessage, supportsRequestId);
assertThat(closedCount.get()).isEqualTo(1);
}
@ -147,16 +147,16 @@ public class RequestManagerTest {
// Response handler should get messages sent before it is registered
stream.then(responseHandler);
assertThat(receivedMessages.size()).isEqualTo(1);
assertThat(receivedMessages).hasSize(1);
assertResponseCorrect(receivedMessages.get(0), mockMessage, false);
assertThat(closedCount.get()).isEqualTo(0);
assertThat(closedCount.get()).isZero();
// Dispatch second message
mockMessage = mockMessage(peer, false);
requestManager.dispatchResponse(mockMessage);
// Response handler should get messages sent after it is registered
assertThat(receivedMessages.size()).isEqualTo(2);
assertThat(receivedMessages).hasSize(2);
assertResponseCorrect(receivedMessages.get(1), mockMessage, false);
assertThat(closedCount.get()).isEqualTo(1);
}
@ -203,27 +203,27 @@ public class RequestManagerTest {
requestManager.dispatchResponse(mockMessage);
// Response handler A should get message
assertThat(receivedMessagesA.size()).isEqualTo(1);
assertThat(receivedMessagesA).hasSize(1);
assertResponseCorrect(receivedMessagesA.get(0), mockMessage, false);
assertThat(closedCountA.get()).isEqualTo(0);
assertThat(closedCountA.get()).isZero();
streamB.then(responseHandlerB);
// Response handler B should get message
assertThat(receivedMessagesB.size()).isEqualTo(1);
assertThat(receivedMessagesB).hasSize(1);
assertResponseCorrect(receivedMessagesB.get(0), mockMessage, false);
assertThat(closedCountB.get()).isEqualTo(0);
assertThat(closedCountB.get()).isZero();
// Dispatch second message
mockMessage = mockMessage(peer, false);
requestManager.dispatchResponse(mockMessage);
// Response handler A should get message
assertThat(receivedMessagesA.size()).isEqualTo(2);
assertThat(receivedMessagesA).hasSize(2);
assertResponseCorrect(receivedMessagesA.get(1), mockMessage, false);
assertThat(closedCountA.get()).isEqualTo(1);
// Response handler B should get message
assertThat(receivedMessagesB.size()).isEqualTo(2);
assertThat(receivedMessagesB).hasSize(2);
assertResponseCorrect(receivedMessagesB.get(1), mockMessage, false);
assertThat(closedCountB.get()).isEqualTo(1);
}

@ -95,7 +95,7 @@ public class WorldStatePeerTrieNodeFinderTest {
}
return true;
},
(cap, msg) -> TrieNodesMessage.create(Optional.of(BigInteger.ZERO), List.of(nodeValue)));
(cap, msg) -> TrieNodesMessage.create(Optional.of(BigInteger.ONE), List.of(nodeValue)));
}
@Test

@ -70,6 +70,7 @@ public class ReferenceTestProtocolSchedules {
builder.put("GrayGlacier", createSchedule(new StubGenesisConfigOptions().grayGlacierBlock(0)));
builder.put(
"MergeNetSplit", createSchedule(new StubGenesisConfigOptions().mergeNetSplitBlock(0)));
builder.put("Shandong", createSchedule(new StubGenesisConfigOptions().shandongBlock(0)));
return new ReferenceTestProtocolSchedules(builder.build());
}

@ -126,6 +126,7 @@ public class TestSetChainParams implements JsonRpcMethod {
maybeMoveToNumber(params, "arrowGlacierForkBlock", config, "arrowGlacierBlock");
maybeMoveToNumber(params, "grayGlacierForkBlock", config, "grayGlacierBlock");
maybeMoveToNumber(params, "mergeNetSplitForkBlock", config, "mergeNetSplitBlock");
maybeMoveToNumber(params, "shandongForkBlock", config, "shandongBlock");
maybeMoveToNumber(params, "chainID", config, "chainId", 1);
maybeMove(genesis, "author", chainParamsJson, "coinbase");

@ -112,7 +112,11 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
/** Provides EVMs supporting the appropriate operations for mainnet hard forks. */
public abstract class MainnetEVMs {
public class MainnetEVMs {
private MainnetEVMs() {
// utility class
}
public static final BigInteger DEV_NET_CHAIN_ID = BigInteger.valueOf(1337);
@ -397,4 +401,30 @@ public abstract class MainnetEVMs {
registerLondonOperations(registry, gasCalculator, chainID);
registry.put(new PrevRanDaoOperation(gasCalculator));
}
public static EVM shandong(final BigInteger chainId, final EvmConfiguration evmConfiguration) {
return shandong(new LondonGasCalculator(), chainId, evmConfiguration);
}
public static EVM shandong(
final GasCalculator gasCalculator,
final BigInteger chainId,
final EvmConfiguration evmConfiguration) {
return new EVM(shandongOperations(gasCalculator, chainId), gasCalculator, evmConfiguration);
}
public static OperationRegistry shandongOperations(
final GasCalculator gasCalculator, final BigInteger chainId) {
OperationRegistry operationRegistry = new OperationRegistry();
registerShandongOperations(operationRegistry, gasCalculator, chainId);
return operationRegistry;
}
public static void registerShandongOperations(
final OperationRegistry registry,
final GasCalculator gasCalculator,
final BigInteger chainID) {
registerParisOperations(registry, gasCalculator, chainID);
// PUSH0
}
}

Loading…
Cancel
Save