Skip to content

Commit

Permalink
Check existence of hardfork milestone to decide if engine APIs should…
Browse files Browse the repository at this point in the history
… be added or not (#8136)

* check existence of hardfork milestone to decide if engine APIs should be added or not

Signed-off-by: Daniel Lehrner <[email protected]>

* add test

Signed-off-by: Daniel Lehrner <[email protected]>

* move pragueAllMilestonesZeroProtocolSchedule to JsonRpcMethodsFactoryTest to not break other tests using ProtocolScheduleFixture

Signed-off-by: Daniel Lehrner <[email protected]>

* trim down genesis file

Signed-off-by: Daniel Lehrner <[email protected]>

* increase timeout to make tests pass in CI

Signed-off-by: Daniel Lehrner <[email protected]>

---------

Signed-off-by: Daniel Lehrner <[email protected]>
  • Loading branch information
daniellehrner authored Jan 22, 2025
1 parent e9a94f3 commit a54c46a
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.methods;

import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.CANCUN;
import static org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId.PRAGUE;

import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
Expand Down Expand Up @@ -172,7 +175,7 @@ protected Map<String, JsonRpcMethod> create() {
new EngineGetBlobsV1(
consensusEngineServer, protocolContext, engineQosTimer, transactionPool)));

if (protocolSchedule.anyMatch(p -> p.spec().getName().equalsIgnoreCase("cancun"))) {
if (protocolSchedule.milestoneFor(CANCUN).isPresent()) {
executionEngineApisSupported.add(
new EngineGetPayloadV3(
consensusEngineServer,
Expand All @@ -183,7 +186,7 @@ protected Map<String, JsonRpcMethod> create() {
protocolSchedule));
}

if (protocolSchedule.anyMatch(p -> p.spec().getName().equalsIgnoreCase("prague"))) {
if (protocolSchedule.milestoneFor(PRAGUE).isPresent()) {
executionEngineApisSupported.add(
new EngineGetPayloadV4(
consensusEngineServer,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright contributors to Besu.
*
* 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.api.jsonrpc.methods;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture.getGenesisConfigOptions;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.StubGenesisConfigOptions;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.filter.FilterManager;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.BadBlockManager;
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability;
import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController;
import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.testutil.DeterministicEthScheduler;

import java.math.BigInteger;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import io.vertx.core.Vertx;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class JsonRpcMethodsFactoryTest {
private static final String CLIENT_NODE_NAME = "TestClientVersion/0.1.0";
private static final String CLIENT_VERSION = "0.1.0";
private static final String CLIENT_COMMIT = "12345678";
private static final BigInteger NETWORK_ID = BigInteger.valueOf(123);

@Mock private BlockchainQueries blockchainQueries;
@Mock private MergeMiningCoordinator mergeCoordinator;

@TempDir private Path folder;

final Set<Capability> supportedCapabilities = new HashSet<>();
private final NatService natService = new NatService(Optional.empty());
private final Vertx vertx = Vertx.vertx();

private ProtocolSchedule pragueAllMilestonesZeroProtocolSchedule;
private JsonRpcConfiguration configuration;

@BeforeEach
public void setup() {
configuration = JsonRpcConfiguration.createEngineDefault();
configuration.setPort(0);

pragueAllMilestonesZeroProtocolSchedule =
MainnetProtocolSchedule.fromConfig(
getPragueAllZeroMilestonesConfigOptions(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
MiningConfiguration.newDefault(),
new BadBlockManager(),
false,
new NoOpMetricsSystem());

when(mergeCoordinator.isCompatibleWithEngineApi()).thenReturn(true);
}

@Test
public void shouldActivateEngineApisIfMilestonesAreAllZero() {
final Map<String, JsonRpcMethod> rpcMethods =
new JsonRpcMethodsFactory()
.methods(
CLIENT_NODE_NAME,
CLIENT_VERSION,
CLIENT_COMMIT,
NETWORK_ID,
new StubGenesisConfigOptions(),
mock(P2PNetwork.class),
blockchainQueries,
mock(Synchronizer.class),
pragueAllMilestonesZeroProtocolSchedule,
mock(ProtocolContext.class),
mock(FilterManager.class),
mock(TransactionPool.class),
mock(MiningConfiguration.class),
mergeCoordinator,
new NoOpMetricsSystem(),
supportedCapabilities,
Optional.of(mock(AccountLocalConfigPermissioningController.class)),
Optional.of(mock(NodeLocalConfigPermissioningController.class)),
configuration.getRpcApis(),
mock(PrivacyParameters.class),
mock(JsonRpcConfiguration.class),
mock(WebSocketConfiguration.class),
mock(MetricsConfiguration.class),
mock(GraphQLConfiguration.class),
natService,
new HashMap<>(),
folder,
mock(EthPeers.class),
vertx,
mock(ApiConfiguration.class),
Optional.empty(),
mock(TransactionSimulator.class),
new DeterministicEthScheduler());

assertThat(rpcMethods).containsKey("engine_getPayloadV3");
assertThat(rpcMethods).containsKey("engine_getPayloadV4");
assertThat(rpcMethods).containsKey("engine_newPayloadV4");
}

private GenesisConfigOptions getPragueAllZeroMilestonesConfigOptions() {
return getGenesisConfigOptions("/prague_all_milestones_zero.json");
}
}
56 changes: 56 additions & 0 deletions ethereum/api/src/test/resources/prague_all_milestones_zero.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"config": {
"chainId":20211,
"homesteadBlock":0,
"eip150Block":0,
"eip155Block":0,
"eip158Block":0,
"byzantiumBlock":0,
"constantinopleBlock":0,
"petersburgBlock":0,
"istanbulBlock":0,
"muirGlacierBlock":0,
"berlinBlock":0,
"londonBlock":0,
"terminalTotalDifficulty":0,
"cancunTime":0,
"pragueTime":0,
"blobSchedule": {
"cancun": {
"target": 3,
"max": 6,
"baseFeeUpdateFraction": 3338477
},
"prague": {
"target": 6,
"max": 9,
"baseFeeUpdateFraction": 5007716
},
"osaka": {
"target": 9,
"max": 12,
"baseFeeUpdateFraction": 5007716
}
},
"ethash": {
},
"depositContractAddress": "0x4242424242424242424242424242424242424242",
"withdrawalRequestContractAddress": "0x00A3ca265EBcb825B45F985A16CEFB49958cE017",
"consolidationRequestContractAddress": "0x00b42dbF2194e931E80326D950320f7d9Dbeac02"
},
"nonce":"0x42",
"timestamp":"0x0",
"gasLimit":"0x1C9C380",
"difficulty":"0x400000000",
"coinbase":"0x0000000000000000000000000000000000000000",
"alloc":{
"a05b21E5186Ce93d2a226722b85D6e550Ac7D6E3": {
"privateKey": "3a4ff6d22d7502ef2452368165422861c01a0f72f851793b372b87888dc3c453",
"balance": "90000000000000000000000"
}
},
"number":"0x0",
"gasUsed":"0x0",
"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas":"0x7"
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,13 @@ public class ProtocolScheduleFixture {
new NoOpMetricsSystem());

private static GenesisConfigOptions getMainnetConfigOptions() {
return getGenesisConfigOptions("/mainnet.json");
}

public static GenesisConfigOptions getGenesisConfigOptions(final String genesisConfig) {
// this method avoids reading all the alloc accounts when all we want is the "config" section
try (final JsonParser jsonParser =
new JsonFactory().createParser(GenesisConfig.class.getResource("/mainnet.json"))) {
new JsonFactory().createParser(GenesisConfig.class.getResource(genesisConfig))) {

while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
if ("config".equals(jsonParser.getCurrentName())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public void shouldAwokeWhenConditionReachedAndReady() throws Exception {

completionCaptor.getValue().onInitialSyncCompleted();

voidCompletableFuture.get(800, TimeUnit.MILLISECONDS);
voidCompletableFuture.get(5, TimeUnit.SECONDS);
assertThat(voidCompletableFuture).isCompleted();

verify(context.getSyncState()).unsubscribeTTDReached(88L);
Expand Down

0 comments on commit a54c46a

Please sign in to comment.