From 478b6d0184ef8154d68a45bcd3419295e35893e4 Mon Sep 17 00:00:00 2001 From: krsh24 Date: Tue, 11 Jun 2024 16:01:59 +0800 Subject: [PATCH] Support for eth_maxPriorityFeePerGasPrice (#7194) * Error out on permissions config accounts-allowlist validation errors. Signed-off-by: krishnannarayanan * Fixing compilation errors Signed-off-by: krishnannarayanan * Incorrect file check in Signed-off-by: krishnannarayanan * Support for eth_maxPriorityFeePerGas Signed-off-by: krishnannarayanan * Change log update for my PRs Signed-off-by: krishnannarayanan --------- Signed-off-by: krishnannarayanan --- CHANGELOG.md | 4 +- .../besu/ethereum/api/jsonrpc/RpcMethod.java | 1 + .../methods/EthMaxPriorityFeePerGas.java | 54 +++++++ .../jsonrpc/methods/EthJsonRpcMethods.java | 4 +- .../methods/EthMaxPriorityFeePerGasTest.java | 133 ++++++++++++++++++ 5 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java create mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c53b586a129..9b64946ae01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,10 +22,10 @@ - Promote experimental --Xbonsai-trie-logs-pruning-window-size to production-ready, --bonsai-trie-logs-pruning-window-size [#7192](https://github.com/hyperledger/besu/pull/7192) - `admin_nodeInfo` JSON/RPC call returns the currently active EVM version [#7127](https://github.com/hyperledger/besu/pull/7127) - Improve the selection of the most profitable built block [#7174](https://github.com/hyperledger/besu/pull/7174) - +- Support for eth_maxPriorityFeePerGas [#5658](https://github.com/hyperledger/besu/issues/5658) ### Bug fixes - Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102) - +- Validation errors ignored in accounts-allowlist and empty list [#7138](https://github.com/hyperledger/besu/issues/7138) ## 24.5.2 ### Upcoming Breaking Changes diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java index 36e4ff8b8a5..4174fdf8313 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java @@ -109,6 +109,7 @@ public enum RpcMethod { ETH_GET_FILTER_CHANGES("eth_getFilterChanges"), ETH_GET_FILTER_LOGS("eth_getFilterLogs"), ETH_GET_LOGS("eth_getLogs"), + ETH_GET_MAX_PRIORITY_FEE_PER_GAS("eth_maxPriorityFeePerGas"), ETH_GET_MINER_DATA_BY_BLOCK_HASH("eth_getMinerDataByBlockHash"), ETH_GET_MINER_DATA_BY_BLOCK_NUMBER("eth_getMinerDataByBlockNumber"), ETH_GET_PROOF("eth_getProof"), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java new file mode 100644 index 00000000000..2828fee7aca --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGas.java @@ -0,0 +1,54 @@ +/* + * 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.api.jsonrpc.internal.methods; + +import org.hyperledger.besu.datatypes.Wei; +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.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; + +import java.util.Optional; + +public class EthMaxPriorityFeePerGas implements JsonRpcMethod { + + private final BlockchainQueries blockchainQueries; + private final MiningCoordinator miningCoordinator; + + public EthMaxPriorityFeePerGas( + final BlockchainQueries blockchainQueries, final MiningCoordinator miningCoordinator) { + this.blockchainQueries = blockchainQueries; + this.miningCoordinator = miningCoordinator; + } + + @Override + public String getName() { + return RpcMethod.ETH_GET_MAX_PRIORITY_FEE_PER_GAS.getMethodName(); + } + + @Override + public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { + return new JsonRpcSuccessResponse( + requestContext.getRequest().getId(), Quantity.create(fetchAndLimitPriorityFeePerGas())); + } + + private Wei fetchAndLimitPriorityFeePerGas() { + final Optional gasPrice = blockchainQueries.gasPriorityFee(); + return gasPrice.orElseGet(miningCoordinator::getMinPriorityFeePerGas); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java index 678df31824e..c7575a5435a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java @@ -52,6 +52,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetUncleCountByBlockNumber; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthGetWork; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthHashrate; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthMaxPriorityFeePerGas; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthMining; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthNewBlockFilter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.EthNewFilter; @@ -183,6 +184,7 @@ protected Map create() { new EthChainId(protocolSchedule.getChainId()), new EthGetMinerDataByBlockHash(blockchainQueries, protocolSchedule), new EthGetMinerDataByBlockNumber(blockchainQueries, protocolSchedule), - new EthBlobBaseFee(blockchainQueries.getBlockchain(), protocolSchedule)); + new EthBlobBaseFee(blockchainQueries.getBlockchain(), protocolSchedule), + new EthMaxPriorityFeePerGas(blockchainQueries, miningCoordinator)); } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java new file mode 100644 index 00000000000..02d526107a1 --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthMaxPriorityFeePerGasTest.java @@ -0,0 +1,133 @@ +/* + * 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.api.jsonrpc.internal.methods; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +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.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.internal.verification.VerificationModeFactory; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class EthMaxPriorityFeePerGasTest { + private static final String JSON_RPC_VERSION = "2.0"; + private static final String ETH_METHOD = + RpcMethod.ETH_GET_MAX_PRIORITY_FEE_PER_GAS.getMethodName(); + private EthMaxPriorityFeePerGas method; + + @Mock private BlockchainQueries blockchainQueries; + @Mock private MiningCoordinator miningCoordinator; + + @BeforeEach + public void setUp() { + method = createEthMaxPriorityFeePerGasMethod(); + } + + @Test + public void shouldReturnCorrectMethodName() { + assertThat(method.getName()).isEqualTo(ETH_METHOD); + } + + @Test + public void whenNoTransactionsExistReturnMinPriorityFeePerGasPrice() { + final JsonRpcRequestContext request = requestWithParams(); + final String expectedWei = Wei.ONE.toShortHexString(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); + when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(Wei.ONE); + + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.empty()); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(1)).getMinPriorityFeePerGas(); + } + + @ParameterizedTest + @MethodSource("minPriorityFeePerGasValues") + public void whenNoTransactionsExistReturnMinPriorityFeePerGasPriceExist( + final Wei minPriorityFeePerGasValue) { + final JsonRpcRequestContext request = requestWithParams(); + final String expectedWei = minPriorityFeePerGasValue.toShortHexString(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); + when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(minPriorityFeePerGasValue); + + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.empty()); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(1)).getMinPriorityFeePerGas(); + } + + @Test + public void whenNoTransactionsExistReturnNullMinPriorityFeePerGasPriceExist() { + final JsonRpcRequestContext request = requestWithParams(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), null); + when(miningCoordinator.getMinPriorityFeePerGas()).thenReturn(null); + + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.empty()); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(1)).getMinPriorityFeePerGas(); + } + + @Test + public void whenTransactionsExistReturnMaxPriorityFeePerGasPrice() { + final JsonRpcRequestContext request = requestWithParams(); + final String expectedWei = Wei.of(2000000000).toShortHexString(); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); + mockBlockchainQueriesMaxPriorityFeePerGasPrice(Optional.of(Wei.of(2000000000))); + final JsonRpcResponse actualResponse = method.response(request); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(miningCoordinator, VerificationModeFactory.times(0)).getMinPriorityFeePerGas(); + } + + private static Stream minPriorityFeePerGasValues() { + return Stream.of(Arguments.of(Wei.ONE), Arguments.of(Wei.ZERO)); + } + + private void mockBlockchainQueriesMaxPriorityFeePerGasPrice(final Optional result) { + when(blockchainQueries.gasPriorityFee()).thenReturn(result); + } + + private JsonRpcRequestContext requestWithParams(final Object... params) { + return new JsonRpcRequestContext(new JsonRpcRequest(JSON_RPC_VERSION, ETH_METHOD, params)); + } + + private EthMaxPriorityFeePerGas createEthMaxPriorityFeePerGasMethod() { + return new EthMaxPriorityFeePerGas(blockchainQueries, miningCoordinator); + } +}