Skip to content

Commit

Permalink
Improve linea_estimateGas error response (#650)
Browse files Browse the repository at this point in the history
* Improve linea_estimateGas error response

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>

* Update arithmetization/src/main/java/net/consensys/linea/rpc/linea/LineaEstimateGas.java

Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>

---------

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 Mar 25, 2024
1 parent 6b13c9c commit b624a4b
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@

import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.List;

import linea.plugin.acc.test.LineaPluginTestBase;
import linea.plugin.acc.test.TestCommandLineOptionsBuilder;
import linea.plugin.acc.test.tests.web3j.generated.SimpleStorage;
import net.consensys.linea.bl.TransactionProfitabilityCalculator;
import net.consensys.linea.config.LineaProfitabilityCliOptions;
import net.consensys.linea.config.LineaProfitabilityConfiguration;
Expand All @@ -32,12 +37,16 @@
import org.bouncycastle.crypto.digests.KeccakDigest;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.account.Accounts;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.Response;
import org.web3j.protocol.http.HttpService;

public class EstimateGasTest extends LineaPluginTestBase {
protected static final int VERIFICATION_GAS_COST = 1_200_000;
Expand Down Expand Up @@ -87,7 +96,8 @@ public void lineaEstimateGasMatchesEthEstimateGas() {
final Account sender = accounts.getSecondaryBenefactor();

final CallParams callParams =
new CallParams(sender.getAddress(), sender.getAddress(), null, Bytes.EMPTY.toHexString());
new CallParams(
sender.getAddress(), sender.getAddress(), null, Bytes.EMPTY.toHexString(), "0");

final var reqEth = new RawEstimateGasRequest(callParams);
final var reqLinea = new LineaEstimateGasRequest(callParams);
Expand All @@ -113,7 +123,7 @@ public void lineaEstimateGasIsProfitable() {
final var payload = Bytes.wrap(txData.toString().getBytes(StandardCharsets.UTF_8));

final CallParams callParams =
new CallParams(sender.getAddress(), sender.getAddress(), null, payload.toHexString());
new CallParams(sender.getAddress(), sender.getAddress(), null, payload.toHexString(), "0");

final var reqLinea = new LineaEstimateGasRequest(callParams);
final var respLinea = reqLinea.execute(minerNode.nodeRequests());
Expand Down Expand Up @@ -168,10 +178,9 @@ protected void assertIsProfitable(

@Test
public void lineaEstimateGasPriorityFeeMinGasPriceLowerBound() {

final Account sender = accounts.getSecondaryBenefactor();

final CallParams callParams = new CallParams(sender.getAddress(), null, "", "");
final CallParams callParams = new CallParams(sender.getAddress(), null, "", "", "0");

final var reqLinea = new LineaEstimateGasRequest(callParams);
final var respLinea = reqLinea.execute(minerNode.nodeRequests());
Expand All @@ -183,6 +192,63 @@ public void lineaEstimateGasPriorityFeeMinGasPriceLowerBound() {
assertMinGasPriceLowerBound(baseFee, estimatedMaxGasPrice);
}

@Test
public void invalidParametersLineaEstimateGasRequestReturnErrorResponse() {
final Account sender = accounts.getSecondaryBenefactor();
final CallParams callParams =
new CallParams(sender.getAddress(), null, "", "", String.valueOf(Integer.MAX_VALUE));
final var reqLinea = new BadLineaEstimateGasRequest(callParams);
final var respLinea = reqLinea.execute(minerNode.nodeRequests());
assertThat(respLinea.getCode()).isEqualTo(RpcErrorType.INVALID_PARAMS.getCode());
assertThat(respLinea.getMessage()).isEqualTo(RpcErrorType.INVALID_PARAMS.getMessage());
}

@Test
public void revertedTransactionReturnErrorResponse() throws Exception {
final SimpleStorage simpleStorage = deploySimpleStorage();
final Account sender = accounts.getSecondaryBenefactor();
final var reqLinea =
new BadLineaEstimateGasRequest(
new CallParams(sender.getAddress(), simpleStorage.getContractAddress(), "", "", "0"));
final var respLinea = reqLinea.execute(minerNode.nodeRequests());
assertThat(respLinea.getCode()).isEqualTo(-32000);
assertThat(respLinea.getMessage()).isEqualTo("Execution reverted");
assertThat(respLinea.getData()).isEqualTo("\"0x\"");
}

@Test
public void failedTransactionReturnErrorResponse() {
final Account sender = accounts.getSecondaryBenefactor();
final var reqLinea =
new BadLineaEstimateGasRequest(
new CallParams(
sender.getAddress(), null, "", Accounts.GENESIS_ACCOUNT_TWO_PRIVATE_KEY, "0"));
final var respLinea = reqLinea.execute(minerNode.nodeRequests());
assertThat(respLinea.getCode()).isEqualTo(-32000);
assertThat(respLinea.getMessage()).isEqualTo("Failed transaction, reason: INVALID_OPERATION");
}

@Test
public void parseErrorLineaEstimateGasRequestReturnErrorResponse()
throws IOException, InterruptedException {
final var httpService = (HttpService) minerNode.nodeRequests().getWeb3jService();
final var httpClient = HttpClient.newHttpClient();
final var badJsonRequest =
HttpRequest.newBuilder(URI.create(httpService.getUrl()))
.headers("Content-Type", "application/json")
.POST(
HttpRequest.BodyPublishers.ofString(
"""
{"jsonrpc":"2.0","method":"linea_estimateGas","params":[malformed json],"id":53}
"""))
.build();
final var errorResponse = httpClient.send(badJsonRequest, HttpResponse.BodyHandlers.ofString());
assertThat(errorResponse.body())
.isEqualTo(
"""
{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}""");
}

protected void assertMinGasPriceLowerBound(final Wei baseFee, final Wei estimatedMaxGasPrice) {
final var minGasPrice = minerNode.getMiningParameters().getMinTransactionGasPrice();
assertThat(estimatedMaxGasPrice).isEqualTo(minGasPrice);
Expand Down Expand Up @@ -215,6 +281,34 @@ static class LineaEstimateGasResponse extends org.web3j.protocol.core.Response<R
record Response(String gasLimit, String baseFeePerGas, String priorityFeePerGas) {}
}

static class BadLineaEstimateGasRequest
implements Transaction<org.web3j.protocol.core.Response.Error> {
private final CallParams badCallParams;

public BadLineaEstimateGasRequest(final CallParams badCallParams) {
this.badCallParams = badCallParams;
}

@Override
public org.web3j.protocol.core.Response.Error execute(final NodeRequests nodeRequests) {
try {
return new Request<>(
"linea_estimateGas",
List.of(badCallParams),
nodeRequests.getWeb3jService(),
BadLineaEstimateGasResponse.class)
.send()
.getError();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

static class BadLineaEstimateGasResponse extends org.web3j.protocol.core.Response<Response> {}

record Response(String gasLimit, String baseFeePerGas, String priorityFeePerGas) {}
}

static class RawEstimateGasRequest implements Transaction<String> {
private final CallParams callParams;

Expand All @@ -240,5 +334,5 @@ public String execute(final NodeRequests nodeRequests) {
static class RawEstimateGasResponse extends org.web3j.protocol.core.Response<String> {}
}

record CallParams(String from, String to, String value, String data) {}
record CallParams(String from, String to, String value, String data, String gasLimit) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ PUB_HASH_INFO = 8192
PUB_LOG = 16384
PUB_LOG_INFO = 16384
RLP = 128
ROM = 2400
ROM = 2402
ROM_LEX = 20
SHF = 20
SHF_RT = 2305
Expand Down
1 change: 1 addition & 0 deletions acceptance-tests/src/test/solidity/SimpleStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ contract SimpleStorage {
uint sum;

function set(string memory value) public {
require(bytes(value).length != 0);
data = value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.common.cache.CacheBuilder;
import lombok.extern.slf4j.Slf4j;
import net.consensys.linea.zktracer.ZkTracer;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.plugin.BesuContext;
import org.hyperledger.besu.plugin.services.TraceService;
import org.hyperledger.besu.plugin.services.exception.PluginRpcEndpointException;
Expand Down Expand Up @@ -97,7 +98,7 @@ public Counters execute(final PluginRpcRequest request) {
log.info("counters for {} returned in {}", requestedBlockNumber, sw);
return r;
} catch (Exception ex) {
throw new PluginRpcEndpointException(ex.getMessage());
throw new PluginRpcEndpointException(RpcErrorType.PLUGIN_INTERNAL_ERROR, ex.getMessage());
}
}

Expand Down
Loading

0 comments on commit b624a4b

Please sign in to comment.