Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import java.math.BigInteger;
import java.util.List;
import java.util.NavigableSet;
import java.util.Optional;
import java.util.function.Predicate;

Expand Down Expand Up @@ -252,4 +253,9 @@ public Optional<ScheduledProtocolSpec> getNextProtocolSpec(final long currentTim
public Optional<ScheduledProtocolSpec> getLatestProtocolSpec() {
return getPostMergeSchedule().getLatestProtocolSpec();
}

@Override
public NavigableSet<ScheduledProtocolSpec> getProtocolSpecs() {
return getPostMergeSchedule().getProtocolSpecs();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;

import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.datatypes.HardforkId;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.forkid.ForkIdManager;
Expand All @@ -31,11 +35,13 @@

import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableSet;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Supplier;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Suppliers;

Expand All @@ -46,6 +52,8 @@ public class EthConfig implements JsonRpcMethod {
private final BlockchainQueries blockchain;
private final ProtocolSchedule protocolSchedule;
private final ForkIdManager forkIdManager;
private final Long firstTimestampMilestone;
private final Long firstBlobsMilestone;

public EthConfig(
final BlockchainQueries blockchain,
Expand All @@ -59,6 +67,10 @@ public EthConfig(
blockchain.getBlockchain(),
genesisConfigOptions.getForkBlockNumbers(),
genesisConfigOptions.getForkBlockTimestamps());
firstTimestampMilestone =
protocolSchedule.milestoneFor(HardforkId.MainnetHardforkId.SHANGHAI).orElse(0L);
firstBlobsMilestone =
protocolSchedule.milestoneFor(HardforkId.MainnetHardforkId.CANCUN).orElse(0L);
}

@Override
Expand All @@ -68,13 +80,24 @@ public String getName() {

@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
ObjectNode result = mapperSupplier.get().createObjectNode();
if (showAllForks(requestContext)) {
final ArrayNode allForks = result.putArray("all");
final NavigableSet<ScheduledProtocolSpec> protocolSpecs = protocolSchedule.getProtocolSpecs();
final var it = protocolSpecs.descendingIterator();
while (it.hasNext()) {
final ScheduledProtocolSpec spec = it.next();
generateConfig(allForks.addObject(), spec.fork(), spec.spec());
}
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result);
}

BlockHeader header = blockchain.getBlockchain().getChainHeadHeader();
long currentTime = System.currentTimeMillis() / 1000;
ProtocolSpec current = protocolSchedule.getForNextBlockHeader(header, currentTime);
Optional<ScheduledProtocolSpec> next = protocolSchedule.getNextProtocolSpec(currentTime);
Optional<ScheduledProtocolSpec> last = protocolSchedule.getLatestProtocolSpec();

ObjectNode result = mapperSupplier.get().createObjectNode();
ObjectNode currentNode = result.putObject("current");
generateConfig(currentNode, current);
if (next.isPresent()) {
Expand All @@ -93,8 +116,23 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), result);
}

private String getForkIdAsHexString(final long currentTime) {
return forkIdManager.getForkIdByTimestamp(currentTime).getHash().toHexString();
private boolean showAllForks(final JsonRpcRequestContext requestContext) {
try {
final Optional<Boolean> optionalParameter =
requestContext.getOptionalParameter(0, Boolean.class);
return optionalParameter.orElse(false);
} catch (JsonRpcParameter.JsonRpcParameterException e) {
throw new InvalidJsonRpcParameters(
"Invalid showAllForks boolean parameter (index 0)", RpcErrorType.INVALID_PARAMS, e);
}
}

private String getForkIdAsHexString(final long milestone) {
if (milestone >= firstTimestampMilestone) {
return forkIdManager.getForkIdByTimestamp(milestone).getHash().toHexString();
} else {
return forkIdManager.getForkIdByBlockNumber(milestone).getHash().toHexString();
}
}

void generateConfig(final ObjectNode result, final ScheduledProtocolSpec scheduledSpec) {
Expand All @@ -106,13 +144,19 @@ void generateConfig(final ObjectNode result, final ProtocolSpec spec) {
}

void generateConfig(final ObjectNode result, final Hardfork forkId, final ProtocolSpec spec) {
result.put("activationTime", forkId.milestone());
if (forkId.milestone() < firstTimestampMilestone) {
result.put("activationBlock", forkId.milestone());
} else {
result.put("activationTime", forkId.milestone());
}

ObjectNode blobs = result.putObject("blobSchedule");
blobs.put(
"baseFeeUpdateFraction", spec.getFeeMarket().getBaseFeeUpdateFraction().longValueExact());
blobs.put("max", spec.getGasLimitCalculator().currentBlobGasLimit() / (128 * 1024));
blobs.put("target", spec.getGasLimitCalculator().getTargetBlobGasPerBlock() / (128 * 1024));
if (forkId.milestone() >= firstBlobsMilestone) {
ObjectNode blobs = result.putObject("blobSchedule");
blobs.put(
"baseFeeUpdateFraction", spec.getFeeMarket().getBaseFeeUpdateFraction().longValueExact());
blobs.put("max", spec.getGasLimitCalculator().currentBlobGasLimit() / (128 * 1024));
blobs.put("target", spec.getGasLimitCalculator().getTargetBlobGasPerBlock() / (128 * 1024));
}

result.put(
"chainId", protocolSchedule.getChainId().map(c -> "0x" + c.toString(16)).orElse(null));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* 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.internal.methods;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;

import java.math.BigInteger;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class EthConfigTest {

private EthConfig method;

@Mock private BlockchainQueries blockchainQueries;
@Mock private GenesisConfigOptions genesisConfigOptions;
protected BlockchainSetupUtil blockchainSetupUtil;

@BeforeEach
void setup() {
blockchainSetupUtil = BlockchainSetupUtil.forMainnet();
when(blockchainQueries.getBlockchain()).thenReturn(blockchainSetupUtil.getBlockchain());
method =
new EthConfig(
blockchainQueries, blockchainSetupUtil.getProtocolSchedule(), genesisConfigOptions);
}

@Test
void ethConfigForMainnet() {
final JsonRpcSuccessResponse res =
((JsonRpcSuccessResponse)
method.response(
new JsonRpcRequestContext(
new JsonRpcRequest("2.0", "eth_config", new Object[] {true}))));
final ObjectNode result = (ObjectNode) res.getResult();
assertThat(result.has("all")).isTrue();
assertThat(result.get("all").size()).isGreaterThan(3);
for (JsonNode forkObj : result.get("all")) {
assertThat(forkObj.get("chainId").asText()).isEqualTo("0x" + BigInteger.ONE.toString(16));
}
System.out.println(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,13 @@ public ForkId getForkIdByTimestamp(final long timestamp) {
}
return allForkIds.isEmpty() ? new ForkId(genesisHashCrc, 0) : allForkIds.getLast();
}

public ForkId getForkIdByBlockNumber(final long blockNumber) {
for (final ForkId forkId : blockNumbersForkIds) {
if (blockNumber < forkId.getNext()) {
return forkId;
}
}
return allForkIds.isEmpty() ? new ForkId(genesisHashCrc, 0) : allForkIds.getLast();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ public Optional<ScheduledProtocolSpec> getLatestProtocolSpec() {
return protocolSpecs.stream().max(Comparator.comparing(ScheduledProtocolSpec::fork));
}

@Override
public NavigableSet<ScheduledProtocolSpec> getProtocolSpecs() {
return protocolSpecs;
}

@Override
public Optional<BigInteger> getChainId() {
return chainId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Optional;
import java.util.function.Predicate;

Expand All @@ -50,6 +51,8 @@ default ProtocolSpec getForNextBlockHeader(

Optional<ScheduledProtocolSpec> getLatestProtocolSpec();

NavigableSet<ScheduledProtocolSpec> getProtocolSpecs();

Optional<BigInteger> getChainId();

String listMilestones();
Expand Down