diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a68d120a9f..f5b115f9440 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Additions and Improvements ### Bug Fixes +- Make 'to' field optional in eth_call method according to the spec [#3177] (https://github.com/hyperledger/besu/pull/3177) ## 22.1.0-RC1 diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java index 9491726f9c2..9659b44462b 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods.fork.frontier; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; @@ -23,7 +22,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcTestMethodsFactory; 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.exception.InvalidJsonRpcParameters; 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; @@ -111,7 +109,7 @@ public void shouldReturnExpectedResultForCallAtSpecificBlock() { } @Test - public void shouldReturnInvalidRequestWhenMissingToField() { + public void shouldReturnSuccessWhenCreatingContract() { final JsonCallParameter callParameter = new JsonCallParameter( Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), @@ -121,16 +119,18 @@ public void shouldReturnInvalidRequestWhenMissingToField() { null, null, null, - Bytes.fromHexString("0x12a7b914"), + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), null); final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse( + null, + "0x60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"); - final Throwable thrown = catchThrowable(() -> method.response(request)); + final JsonRpcResponse response = method.response(request); - assertThat(thrown) - .isInstanceOf(InvalidJsonRpcParameters.class) - .hasNoCause() - .hasMessage("Missing \"to\" field in call arguments"); + assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); } @Test diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java index 49cac9f9c3a..eb979b52708 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java @@ -126,9 +126,6 @@ private JsonRpcErrorResponse errorResponse( private JsonCallParameter validateAndGetCallParams(final JsonRpcRequestContext request) { final JsonCallParameter callParams = request.getRequiredParameter(0, JsonCallParameter.class); - if (callParams.getTo() == null) { - throw new InvalidJsonRpcParameters("Missing \"to\" field in call arguments"); - } if (callParams.getGasPrice() != null && (callParams.getMaxFeePerGas().isPresent() || callParams.getMaxPriorityFeePerGas().isPresent())) { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java index 5e6599fef17..26a4c6e36f4 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.BLOCK_NOT_FOUND; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.INTERNAL_ERROR; import static org.mockito.ArgumentMatchers.any; @@ -30,7 +29,6 @@ import org.hyperledger.besu.datatypes.Wei; 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.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; @@ -77,32 +75,6 @@ public void shouldReturnCorrectMethodName() { assertThat(method.getName()).isEqualTo("eth_call"); } - @Test - public void shouldThrowInvalidJsonRpcParametersExceptionWhenMissingToField() { - final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0x0"), - null, - Gas.ZERO, - Wei.ZERO, - null, - null, - Wei.ZERO, - Bytes.EMPTY, - null); - final JsonRpcRequestContext request = ethCallRequest(callParameter, "latest"); - when(blockchainQueries.getBlockchain()).thenReturn(blockchain); - when(blockchainQueries.getBlockchain().getChainHead()).thenReturn(chainHead); - when(blockchainQueries.getBlockchain().getChainHead().getHash()).thenReturn(Hash.ZERO); - - final Throwable thrown = catchThrowable(() -> method.response(request)); - - assertThat(thrown) - .isInstanceOf(InvalidJsonRpcParameters.class) - .hasNoCause() - .hasMessage("Missing \"to\" field in call arguments"); - } - @Test public void shouldReturnInternalErrorWhenProcessorReturnsEmpty() { final JsonRpcRequestContext request = ethCallRequest(callParameter(), "latest"); @@ -124,8 +96,7 @@ public void shouldReturnInternalErrorWhenProcessorReturnsEmpty() { @Test public void shouldAcceptRequestWhenMissingOptionalFields() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, Address.fromHexString("0x0"), null, null, null, null, null, null, null); + new JsonCallParameter(null, null, null, null, null, null, null, null, null); final JsonRpcRequestContext request = ethCallRequest(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Bytes.of().toString()); diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_contractCreation.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_contractCreation.json new file mode 100644 index 00000000000..8b4f59d80e9 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_contractCreation.json @@ -0,0 +1,20 @@ +{ + "request": { + "id": 4, + "jsonrpc": "2.0", + "method": "eth_call", + "params": [ + { + "from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "data": "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029" + }, + "latest" + ] + }, + "response": { + "jsonrpc": "2.0", + "id": 4, + "result": "0x60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029" + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_toMissing_block_8.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_toMissing_block_8.json deleted file mode 100644 index 87db58189c9..00000000000 --- a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_toMissing_block_8.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "request": { - "id": 4, - "jsonrpc": "2.0", - "method": "eth_call", - "params": [ - { - "from": "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "data": "0x12a7b914" - }, - "0x8" - ] - }, - "response": { - "jsonrpc": "2.0", - "id": 4, - "error":{ - "code":-32602, - "message":"Invalid params" - } - }, - "statusCode": 400 -} \ No newline at end of file