Skip to content

Commit

Permalink
Support chainId in CallParameters (#7720)
Browse files Browse the repository at this point in the history
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
  • Loading branch information
fab-10 and macfarla authored Oct 4, 2024
1 parent 67d738c commit 5fd87d6
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 10 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
- Add configuration of Consolidation Request Contract Address via genesis configuration [#7647](https://github.com/hyperledger/besu/pull/7647)
- Interrupt pending transaction processing on block creation timeout [#7673](https://github.com/hyperledger/besu/pull/7673)
- Align gas cap calculation for transaction simulation to Geth approach [#7703](https://github.com/hyperledger/besu/pull/7703)
- Expose chainId in the `BlockchainService` [7702](https://github.com/hyperledger/besu/pull/7702)
- Expose chainId in the `BlockchainService` [#7702](https://github.com/hyperledger/besu/pull/7702)
- Add support for `chainId` in `CallParameters` [#7720](https://github.com/hyperledger/besu/pull/7720)

### Bug fixes
- Fix mounted data path directory permissions for besu user [#7575](https://github.com/hyperledger/besu/pull/7575)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ public class JsonRpcTestMethodsFactory {
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);

private final BlockchainImporter importer;
private final MutableBlockchain blockchain;
private final WorldStateArchive stateArchive;
private final ProtocolContext context;
private final BlockchainQueries blockchainQueries;
private final Synchronizer synchronizer;
private final ProtocolSchedule protocolSchedule;

public JsonRpcTestMethodsFactory(final BlockchainImporter importer) {
this.importer = importer;
Expand All @@ -84,7 +84,7 @@ public JsonRpcTestMethodsFactory(final BlockchainImporter importer) {
this.importer.getGenesisState().writeStateTo(stateArchive.getMutable());
this.context = new ProtocolContext(blockchain, stateArchive, null, new BadBlockManager());

final ProtocolSchedule protocolSchedule = importer.getProtocolSchedule();
this.protocolSchedule = importer.getProtocolSchedule();
this.synchronizer = mock(Synchronizer.class);

for (final Block block : importer.getBlocks()) {
Expand All @@ -106,6 +106,7 @@ public JsonRpcTestMethodsFactory(
this.blockchain = blockchain;
this.stateArchive = stateArchive;
this.context = context;
this.protocolSchedule = importer.getProtocolSchedule();
this.blockchainQueries =
new BlockchainQueries(
importer.getProtocolSchedule(),
Expand All @@ -126,6 +127,7 @@ public JsonRpcTestMethodsFactory(
this.stateArchive = stateArchive;
this.context = context;
this.synchronizer = synchronizer;
this.protocolSchedule = importer.getProtocolSchedule();
this.blockchainQueries =
new BlockchainQueries(
importer.getProtocolSchedule(),
Expand All @@ -142,6 +144,10 @@ public WorldStateArchive getStateArchive() {
return stateArchive;
}

public BigInteger getChainId() {
return protocolSchedule.getChainId().get();
}

public Map<String, JsonRpcMethod> methods() {
final P2PNetwork peerDiscovery = mock(P2PNetwork.class);
final EthPeers ethPeers = mock(EthPeers.class);
Expand Down Expand Up @@ -183,7 +189,7 @@ public Map<String, JsonRpcMethod> methods() {
CLIENT_NODE_NAME,
CLIENT_VERSION,
CLIENT_COMMIT,
NETWORK_ID,
getChainId(),
new StubGenesisConfigOptions(),
peerDiscovery,
blockchainQueries,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.testutil.BlockTestUtil;

import java.math.BigInteger;
import java.util.Map;

import com.google.common.base.Charsets;
Expand Down Expand Up @@ -142,6 +143,7 @@ public void shouldReturnErrorWithGasPriceLessThanCurrentBaseFee() {
public void shouldReturnSuccessWithValidMaxFeePerGas() {
final JsonCallParameter callParameter =
new JsonCallParameter.JsonCallParameterBuilder()
.withChainId(BLOCKCHAIN.getChainId())
.withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))
.withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"))
.withMaxFeePerGas(Wei.fromHexString("0x3B9ACA01"))
Expand All @@ -158,6 +160,26 @@ public void shouldReturnSuccessWithValidMaxFeePerGas() {
assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse);
}

@Test
public void shouldReturnErrorWithInvalidChainId() {
final JsonCallParameter callParameter =
new JsonCallParameter.JsonCallParameterBuilder()
.withChainId(BLOCKCHAIN.getChainId().add(BigInteger.ONE))
.withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))
.withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"))
.withMaxFeePerGas(Wei.fromHexString("0x3B9ACA01"))
.withInput(Bytes.fromHexString("0x2e64cec1"))
.build();

final JsonRpcRequestContext request = requestWithParams(callParameter, "latest");
final JsonRpcResponse expectedResponse =
new JsonRpcErrorResponse(null, RpcErrorType.WRONG_CHAIN_ID);

final JsonRpcResponse response = method.response(request);

assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse);
}

@Test
public void shouldReturnSuccessWithValidMaxFeePerGasAndMaxPriorityFeePerGas() {
final JsonCallParameter callParameter =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
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.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.testutil.BlockTestUtil;

import java.math.BigInteger;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -112,6 +117,7 @@ public void shouldReturnExpectedValueForContractDeploy() {
public void shouldReturnExpectedValueForContractDeploy_WithAccessList() {
final JsonCallParameter callParameter =
new JsonCallParameter.JsonCallParameterBuilder()
.withChainId(BLOCKCHAIN.getChainId())
.withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))
.withInput(
Bytes.fromHexString(
Expand All @@ -124,6 +130,30 @@ public void shouldReturnExpectedValueForContractDeploy_WithAccessList() {
assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse);
}

@Test
public void shouldReturnErrorWithInvalidChainId() {
final JsonCallParameter callParameter =
new JsonCallParameter.JsonCallParameterBuilder()
.withChainId(BLOCKCHAIN.getChainId().add(BigInteger.ONE))
.withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))
.withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1"))
.withValue(Wei.ONE)
.build();

final JsonRpcRequestContext request = requestWithParams(callParameter, "latest");
final JsonRpcResponse expectedResponse =
new JsonRpcErrorResponse(
null,
JsonRpcError.from(
ValidationResult.invalid(
TransactionInvalidReason.WRONG_CHAIN_ID,
"transaction was meant for chain id 1983 and not this chain id 1982")));

final JsonRpcResponse response = method.response(request);

assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse);
}

private List<AccessListEntry> createAccessList() {
return List.of(
new AccessListEntry(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ protected abstract Object resultByBlockHeader(
protected CallParameter overrideGasLimitAndPrice(
final JsonCallParameter callParams, final long gasLimit) {
return new CallParameter(
callParams.getChainId(),
callParams.getFrom(),
callParams.getTo(),
gasLimit,
Expand All @@ -111,7 +112,9 @@ protected CallParameter overrideGasLimitAndPrice(
callParams.getMaxFeePerGas(),
callParams.getValue(),
callParams.getPayload(),
callParams.getAccessList());
callParams.getAccessList(),
callParams.getMaxFeePerBlobGas(),
callParams.getBlobVersionedHashes());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.json.ChainIdDeserializer;
import org.hyperledger.besu.ethereum.core.json.GasDeserializer;
import org.hyperledger.besu.ethereum.core.json.HexStringDeserializer;
import org.hyperledger.besu.ethereum.transaction.CallParameter;

import java.math.BigInteger;
import java.util.List;
import java.util.Optional;

Expand All @@ -41,6 +43,7 @@
*
* <pre>{@code
* JsonCallParameter param = new JsonCallParameter.JsonCallParameterBuilder()
* .withChainId(Optional.of(BigInteger.ONE))
* .withFrom(Address.fromHexString("0x..."))
* .withTo(Address.fromHexString("0x..."))
* .withGas(21000L)
Expand Down Expand Up @@ -71,6 +74,7 @@ public class JsonCallParameter extends CallParameter {
private final Optional<Boolean> strict;

private JsonCallParameter(
final Optional<BigInteger> chainId,
final Address from,
final Address to,
final Long gasLimit,
Expand All @@ -85,6 +89,7 @@ private JsonCallParameter(
final Optional<List<VersionedHash>> blobVersionedHashes) {

super(
chainId,
from,
to,
gasLimit,
Expand Down Expand Up @@ -115,6 +120,7 @@ public Optional<Boolean> isMaybeStrict() {
*/
public static final class JsonCallParameterBuilder {
private Optional<Boolean> strict = Optional.empty();
private Optional<BigInteger> chainId = Optional.empty();
private Address from;
private Address to;
private long gas = -1;
Expand Down Expand Up @@ -145,6 +151,18 @@ public JsonCallParameterBuilder withStrict(final Boolean strict) {
return this;
}

/**
* Sets the optional "chainId" for the {@link JsonCallParameter}.
*
* @param chainId the chainId
* @return the {@link JsonCallParameterBuilder} instance for chaining
*/
@JsonDeserialize(using = ChainIdDeserializer.class)
public JsonCallParameterBuilder withChainId(final BigInteger chainId) {
this.chainId = Optional.of(chainId);
return this;
}

/**
* Sets the "from" address for the {@link JsonCallParameter}. This address represents the sender
* of the call.
Expand Down Expand Up @@ -346,6 +364,7 @@ public JsonCallParameter build() {
final Bytes payload = input != null ? input : data;

return new JsonCallParameter(
chainId,
from,
to,
gas,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright contributors to Hyperledger 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.core.json;

import java.io.IOException;
import java.math.BigInteger;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.apache.tuweni.units.bigints.UInt256;

public class ChainIdDeserializer extends StdDeserializer<BigInteger> {

public ChainIdDeserializer() {
this(null);
}

public ChainIdDeserializer(final Class<?> vc) {
super(vc);
}

@Override
public BigInteger deserialize(final JsonParser jsonparser, final DeserializationContext context)
throws IOException {
final var chainId =
UInt256.fromHexString(jsonparser.getCodec().readValue(jsonparser, String.class))
.toBigInteger();
if (chainId.signum() <= 0) {
throw new IllegalArgumentException("Non positive chain id: " + chainId);
}
return chainId;
}
}
Loading

0 comments on commit 5fd87d6

Please sign in to comment.