Make `eth_gasPrice` aware of the base fee market (#7102)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
pull/7134/head
Fabio Di Fabio 6 months ago committed by GitHub
parent bd12986fb0
commit 8df6bcaddd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 19
      besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java
  3. 36
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  4. 9
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/ApiConfigurationOptions.java
  5. 8
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  6. 6
      besu/src/main/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilder.java
  7. 6
      besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java
  8. 6
      besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java
  9. 9
      besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java
  10. 7
      besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java
  11. 8
      besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java
  12. 17
      consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/jsonrpc/CliqueJsonRpcMethods.java
  13. 18
      consensus/ibft/src/main/java/org/hyperledger/besu/consensus/ibft/jsonrpc/IbftJsonRpcMethods.java
  14. 21
      consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/jsonrpc/QbftJsonRpcMethods.java
  15. 18
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java
  16. 7
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthGetFilterChangesIntegrationTest.java
  17. 7
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthGetFilterChangesIntegrationTest.java
  18. 12
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/ApiConfiguration.java
  19. 10
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLDataFetchers.java
  20. 43
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPrice.java
  21. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java
  22. 124
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java
  23. 15
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java
  24. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLHttpServiceTest.java
  25. 5
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java
  26. 312
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java
  27. 8
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockByNumberTest.java
  28. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockReceiptsTest.java
  29. 8
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetProofTest.java
  30. 8
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionReceiptTest.java
  31. 12
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/blockheaders/NewBlockHeadersSubscriptionServiceTest.java
  32. 10
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java
  33. 24
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesTest.java
  34. 2
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_gasPrice.json
  35. 4
      ethereum/retesteth/src/main/java/org/hyperledger/besu/ethereum/retesteth/RetestethContext.java

@ -12,6 +12,7 @@
### Bug fixes ### Bug fixes
- Fix parsing `gasLimit` parameter when its value is > `Long.MAX_VALUE` [#7116](https://github.com/hyperledger/besu/pull/7116) - Fix parsing `gasLimit` parameter when its value is > `Long.MAX_VALUE` [#7116](https://github.com/hyperledger/besu/pull/7116)
- Make `eth_gasPrice` aware of the base fee market [#7102](https://github.com/hyperledger/besu/pull/7102)
- Skip validation of withdrawals when importing BFT blocks since withdrawals don't apply to BFT chains [#7115](https://github.com/hyperledger/besu/pull/7115) - Skip validation of withdrawals when importing BFT blocks since withdrawals don't apply to BFT chains [#7115](https://github.com/hyperledger/besu/pull/7115)
## 24.5.1 ## 24.5.1

@ -106,7 +106,6 @@ import org.hyperledger.besu.ethereum.privacy.PrivateTransactionObserver;
import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.stratum.StratumServer; import org.hyperledger.besu.ethereum.stratum.StratumServer;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.ethstats.EthStatsService; import org.hyperledger.besu.ethstats.EthStatsService;
import org.hyperledger.besu.ethstats.util.EthStatsConnectOptions; import org.hyperledger.besu.ethstats.util.EthStatsConnectOptions;
import org.hyperledger.besu.metrics.MetricsService; import org.hyperledger.besu.metrics.MetricsService;
@ -725,14 +724,17 @@ public class RunnerBuilder {
final TransactionPool transactionPool = besuController.getTransactionPool(); final TransactionPool transactionPool = besuController.getTransactionPool();
final MiningCoordinator miningCoordinator = besuController.getMiningCoordinator(); final MiningCoordinator miningCoordinator = besuController.getMiningCoordinator();
final MiningParameters miningParameters = besuController.getMiningParameters();
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries( new BlockchainQueries(
protocolSchedule,
context.getBlockchain(), context.getBlockchain(),
context.getWorldStateArchive(), context.getWorldStateArchive(),
Optional.of(dataDir.resolve(CACHE_PATH)), Optional.of(dataDir.resolve(CACHE_PATH)),
Optional.of(besuController.getProtocolManager().ethContext().getScheduler()), Optional.of(besuController.getProtocolManager().ethContext().getScheduler()),
apiConfiguration); apiConfiguration,
miningParameters);
final PrivacyParameters privacyParameters = besuController.getPrivacyParameters(); final PrivacyParameters privacyParameters = besuController.getPrivacyParameters();
@ -749,7 +751,6 @@ public class RunnerBuilder {
final P2PNetwork peerNetwork = networkRunner.getNetwork(); final P2PNetwork peerNetwork = networkRunner.getNetwork();
final MiningParameters miningParameters = besuController.getMiningParameters();
Optional<StratumServer> stratumServer = Optional.empty(); Optional<StratumServer> stratumServer = Optional.empty();
if (miningParameters.isStratumMiningEnabled()) { if (miningParameters.isStratumMiningEnabled()) {
@ -957,10 +958,7 @@ public class RunnerBuilder {
rpcEndpointServiceImpl); rpcEndpointServiceImpl);
createLogsSubscriptionService( createLogsSubscriptionService(
context.getBlockchain(), context.getBlockchain(), subscriptionManager, privacyParameters, blockchainQueries);
context.getWorldStateArchive(),
subscriptionManager,
privacyParameters);
createNewBlockHeadersSubscriptionService( createNewBlockHeadersSubscriptionService(
context.getBlockchain(), blockchainQueries, subscriptionManager); context.getBlockchain(), blockchainQueries, subscriptionManager);
@ -1273,15 +1271,12 @@ public class RunnerBuilder {
private void createLogsSubscriptionService( private void createLogsSubscriptionService(
final Blockchain blockchain, final Blockchain blockchain,
final WorldStateArchive worldStateArchive,
final SubscriptionManager subscriptionManager, final SubscriptionManager subscriptionManager,
final PrivacyParameters privacyParameters) { final PrivacyParameters privacyParameters,
final BlockchainQueries blockchainQueries) {
Optional<PrivacyQueries> privacyQueries = Optional.empty(); Optional<PrivacyQueries> privacyQueries = Optional.empty();
if (privacyParameters.isEnabled()) { if (privacyParameters.isEnabled()) {
final BlockchainQueries blockchainQueries =
new BlockchainQueries(
blockchain, worldStateArchive, Optional.empty(), Optional.empty(), apiConfiguration);
privacyQueries = privacyQueries =
Optional.of( Optional.of(
new PrivacyQueries( new PrivacyQueries(

@ -327,6 +327,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
Suppliers.memoize(this::readGenesisConfigFile); Suppliers.memoize(this::readGenesisConfigFile);
private final Supplier<GenesisConfigOptions> genesisConfigOptionsSupplier = private final Supplier<GenesisConfigOptions> genesisConfigOptionsSupplier =
Suppliers.memoize(this::readGenesisConfigOptions); Suppliers.memoize(this::readGenesisConfigOptions);
private final Supplier<MiningParameters> miningParametersSupplier =
Suppliers.memoize(this::getMiningParameters);
private RocksDBPlugin rocksDBPlugin; private RocksDBPlugin rocksDBPlugin;
@ -898,7 +900,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private Collection<EnodeURL> staticNodes; private Collection<EnodeURL> staticNodes;
private BesuController besuController; private BesuController besuController;
private BesuConfigurationImpl pluginCommonConfiguration; private BesuConfigurationImpl pluginCommonConfiguration;
private MiningParameters miningParameters;
private BesuComponent besuComponent; private BesuComponent besuComponent;
private final Supplier<ObservableMetricsSystem> metricsSystem = private final Supplier<ObservableMetricsSystem> metricsSystem =
@ -1351,8 +1352,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
TraceService.class, TraceService.class,
new TraceServiceImpl( new TraceServiceImpl(
new BlockchainQueries( new BlockchainQueries(
besuController.getProtocolSchedule(),
besuController.getProtocolContext().getBlockchain(), besuController.getProtocolContext().getBlockchain(),
besuController.getProtocolContext().getWorldStateArchive()), besuController.getProtocolContext().getWorldStateArchive(),
miningParametersSupplier.get()),
besuController.getProtocolSchedule())); besuController.getProtocolSchedule()));
besuController.getAdditionalPluginServices().appendPluginServices(besuPluginContext); besuController.getAdditionalPluginServices().appendPluginServices(besuPluginContext);
@ -1374,7 +1377,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
"--privacy-marker-transaction-signing-key-file can not be used in conjunction with a plugin that specifies a PrivateMarkerTransactionFactory"); "--privacy-marker-transaction-signing-key-file can not be used in conjunction with a plugin that specifies a PrivateMarkerTransactionFactory");
} }
if (Wei.ZERO.compareTo(getMiningParameters().getMinTransactionGasPrice()) < 0 if (Wei.ZERO.compareTo(miningParametersSupplier.get().getMinTransactionGasPrice()) < 0
&& (privacyOptionGroup.privateMarkerTransactionSigningKeyPath == null && (privacyOptionGroup.privateMarkerTransactionSigningKeyPath == null
&& (privacyPluginService == null && (privacyPluginService == null
|| privacyPluginService.getPrivateMarkerTransactionFactory() == null))) { || privacyPluginService.getPrivateMarkerTransactionFactory() == null))) {
@ -1755,7 +1758,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
unstableIpcOptions.isEnabled(), unstableIpcOptions.isEnabled(),
unstableIpcOptions.getIpcPath(), unstableIpcOptions.getIpcPath(),
unstableIpcOptions.getRpcIpcApis()); unstableIpcOptions.getRpcIpcApis());
apiConfiguration = apiConfigurationOptions.apiConfiguration(getMiningParameters()); apiConfiguration = apiConfigurationOptions.apiConfiguration();
dataStorageConfiguration = getDataStorageConfiguration(); dataStorageConfiguration = getDataStorageConfiguration();
// hostsWhitelist is a hidden option. If it is specified, add the list to hostAllowlist // hostsWhitelist is a hidden option. If it is specified, add the list to hostAllowlist
if (!hostsWhitelist.isEmpty()) { if (!hostsWhitelist.isEmpty()) {
@ -1844,7 +1847,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
dataDir(), dataDir(),
dataDir().resolve(DATABASE_PATH), dataDir().resolve(DATABASE_PATH),
getDataStorageConfiguration(), getDataStorageConfiguration(),
getMiningParameters()); miningParametersSupplier.get());
final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName); final KeyValueStorageProvider storageProvider = keyValueStorageProvider(keyValueStorageName);
return controllerBuilderFactory return controllerBuilderFactory
.fromEthNetworkConfig(updateNetworkConfig(network), getDefaultSyncModeIfNotSet()) .fromEthNetworkConfig(updateNetworkConfig(network), getDefaultSyncModeIfNotSet())
@ -1853,7 +1856,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.networkConfiguration(unstableNetworkingOptions.toDomainObject()) .networkConfiguration(unstableNetworkingOptions.toDomainObject())
.dataDirectory(dataDir()) .dataDirectory(dataDir())
.dataStorageConfiguration(getDataStorageConfiguration()) .dataStorageConfiguration(getDataStorageConfiguration())
.miningParameters(getMiningParameters()) .miningParameters(miningParametersSupplier.get())
.transactionPoolConfiguration(buildTransactionPoolConfiguration()) .transactionPoolConfiguration(buildTransactionPoolConfiguration())
.nodeKey(new NodeKey(securityModule())) .nodeKey(new NodeKey(securityModule()))
.metricsSystem(metricsSystem.get()) .metricsSystem(metricsSystem.get())
@ -1864,7 +1867,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.isRevertReasonEnabled(isRevertReasonEnabled) .isRevertReasonEnabled(isRevertReasonEnabled)
.storageProvider(storageProvider) .storageProvider(storageProvider)
.gasLimitCalculator( .gasLimitCalculator(
getMiningParameters().getTargetGasLimit().isPresent() miningParametersSupplier.get().getTargetGasLimit().isPresent()
? new FrontierTargetingGasLimitCalculator() ? new FrontierTargetingGasLimitCalculator()
: GasLimitCalculator.constant()) : GasLimitCalculator.constant())
.requiredBlocks(requiredBlocks) .requiredBlocks(requiredBlocks)
@ -2157,14 +2160,17 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
txPoolConfBuilder.priceBump(Percentage.ZERO); txPoolConfBuilder.priceBump(Percentage.ZERO);
} }
if (getMiningParameters().getMinTransactionGasPrice().equals(Wei.ZERO) if (miningParametersSupplier.get().getMinTransactionGasPrice().equals(Wei.ZERO)
&& !transactionPoolOptions.isPriceBumpSet(commandLine)) { && !transactionPoolOptions.isPriceBumpSet(commandLine)) {
logger.info( logger.info(
"Forcing price bump for transaction replacement to 0, since min-gas-price is set to 0"); "Forcing price bump for transaction replacement to 0, since min-gas-price is set to 0");
txPoolConfBuilder.priceBump(Percentage.ZERO); txPoolConfBuilder.priceBump(Percentage.ZERO);
} }
if (getMiningParameters().getMinTransactionGasPrice().lessThan(txPoolConf.getMinGasPrice())) { if (miningParametersSupplier
.get()
.getMinTransactionGasPrice()
.lessThan(txPoolConf.getMinGasPrice())) {
if (transactionPoolOptions.isMinGasPriceSet(commandLine)) { if (transactionPoolOptions.isMinGasPriceSet(commandLine)) {
throw new ParameterException( throw new ParameterException(
commandLine, "tx-pool-min-gas-price cannot be greater than the value of min-gas-price"); commandLine, "tx-pool-min-gas-price cannot be greater than the value of min-gas-price");
@ -2175,9 +2181,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
// the user of the change // the user of the change
logger.warn( logger.warn(
"Forcing tx-pool-min-gas-price=" "Forcing tx-pool-min-gas-price="
+ getMiningParameters().getMinTransactionGasPrice().toDecimalString() + miningParametersSupplier.get().getMinTransactionGasPrice().toDecimalString()
+ ", since it cannot be greater than the value of min-gas-price"); + ", since it cannot be greater than the value of min-gas-price");
txPoolConfBuilder.minGasPrice(getMiningParameters().getMinTransactionGasPrice()); txPoolConfBuilder.minGasPrice(miningParametersSupplier.get().getMinTransactionGasPrice());
} }
} }
@ -2185,13 +2191,11 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
} }
private MiningParameters getMiningParameters() { private MiningParameters getMiningParameters() {
if (miningParameters == null) {
miningOptions.setTransactionSelectionService(transactionSelectionServiceImpl); miningOptions.setTransactionSelectionService(transactionSelectionServiceImpl);
miningParameters = miningOptions.toDomainObject(); final var miningParameters = miningOptions.toDomainObject();
getGenesisBlockPeriodSeconds(genesisConfigOptionsSupplier.get()) getGenesisBlockPeriodSeconds(genesisConfigOptionsSupplier.get())
.ifPresent(miningParameters::setBlockPeriodSeconds); .ifPresent(miningParameters::setBlockPeriodSeconds);
initMiningParametersMetrics(miningParameters); initMiningParametersMetrics(miningParameters);
}
return miningParameters; return miningParameters;
} }
@ -2567,8 +2571,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
effectivePorts, metricsOptionGroup.metricsPort, metricsOptionGroup.isMetricsEnabled); effectivePorts, metricsOptionGroup.metricsPort, metricsOptionGroup.isMetricsEnabled);
addPortIfEnabled( addPortIfEnabled(
effectivePorts, effectivePorts,
getMiningParameters().getStratumPort(), miningParametersSupplier.get().getStratumPort(),
getMiningParameters().isStratumMiningEnabled()); miningParametersSupplier.get().isStratumMiningEnabled());
return effectivePorts; return effectivePorts;
} }

@ -17,9 +17,9 @@ package org.hyperledger.besu.cli.options.stable;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import org.hyperledger.besu.cli.util.CommandLineUtils; import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.ApiConfiguration;
import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.slf4j.Logger; import org.slf4j.Logger;
import picocli.CommandLine; import picocli.CommandLine;
@ -119,17 +119,14 @@ public class ApiConfigurationOptions {
/** /**
* Creates an ApiConfiguration based on the provided options. * Creates an ApiConfiguration based on the provided options.
* *
* @param miningParameters The mining parameters
* @return An ApiConfiguration instance * @return An ApiConfiguration instance
*/ */
public ApiConfiguration apiConfiguration(final MiningParameters miningParameters) { public ApiConfiguration apiConfiguration() {
var builder = var builder =
ImmutableApiConfiguration.builder() ImmutableApiConfiguration.builder()
.gasPriceBlocks(apiGasPriceBlocks) .gasPriceBlocks(apiGasPriceBlocks)
.gasPricePercentile(apiGasPricePercentile) .gasPricePercentile(apiGasPricePercentile)
.gasPriceMinSupplier( .gasPriceMax(Wei.of(apiGasPriceMax))
miningParameters.getMinTransactionGasPrice().getAsBigInteger()::longValueExact)
.gasPriceMax(apiGasPriceMax)
.maxLogsRange(rpcMaxLogsRange) .maxLogsRange(rpcMaxLogsRange)
.gasCap(rpcGasCap) .gasCap(rpcGasCap)
.isGasAndPriorityFeeLimitingEnabled(apiGasAndPriorityFeeLimitingEnabled) .isGasAndPriorityFeeLimitingEnabled(apiGasAndPriorityFeeLimitingEnabled)

@ -731,7 +731,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
createSubProtocolConfiguration(ethProtocolManager, maybeSnapProtocolManager); createSubProtocolConfiguration(ethProtocolManager, maybeSnapProtocolManager);
final JsonRpcMethods additionalJsonRpcMethodFactory = final JsonRpcMethods additionalJsonRpcMethodFactory =
createAdditionalJsonRpcMethodFactory(protocolContext); createAdditionalJsonRpcMethodFactory(protocolContext, protocolSchedule, miningParameters);
if (dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled() if (dataStorageConfiguration.getUnstable().getBonsaiLimitTrieLogsEnabled()
&& DataStorageFormat.BONSAI.equals(dataStorageConfiguration.getDataStorageFormat())) { && DataStorageFormat.BONSAI.equals(dataStorageConfiguration.getDataStorageFormat())) {
@ -884,10 +884,14 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
* Create additional json rpc method factory json rpc methods. * Create additional json rpc method factory json rpc methods.
* *
* @param protocolContext the protocol context * @param protocolContext the protocol context
* @param protocolSchedule the protocol schedule
* @param miningParameters the mining parameters
* @return the json rpc methods * @return the json rpc methods
*/ */
protected JsonRpcMethods createAdditionalJsonRpcMethodFactory( protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
final ProtocolContext protocolContext) { final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
return apis -> Collections.emptyMap(); return apis -> Collections.emptyMap();
} }

@ -72,8 +72,10 @@ public class CliqueBesuControllerBuilder extends BesuControllerBuilder {
@Override @Override
protected JsonRpcMethods createAdditionalJsonRpcMethodFactory( protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
final ProtocolContext protocolContext) { final ProtocolContext protocolContext,
return new CliqueJsonRpcMethods(protocolContext); final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
return new CliqueJsonRpcMethods(protocolContext, protocolSchedule, miningParameters);
} }
@Override @Override

@ -204,10 +204,12 @@ public class ConsensusScheduleBesuControllerBuilder extends BesuControllerBuilde
@Override @Override
protected JsonRpcMethods createAdditionalJsonRpcMethodFactory( protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
final ProtocolContext protocolContext) { final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
return besuControllerBuilderSchedule return besuControllerBuilderSchedule
.get(0L) .get(0L)
.createAdditionalJsonRpcMethodFactory(protocolContext); .createAdditionalJsonRpcMethodFactory(protocolContext, protocolSchedule, miningParameters);
} }
@Override @Override

@ -111,8 +111,10 @@ public class IbftBesuControllerBuilder extends BftBesuControllerBuilder {
@Override @Override
protected JsonRpcMethods createAdditionalJsonRpcMethodFactory( protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
final ProtocolContext protocolContext) { final ProtocolContext protocolContext,
return new IbftJsonRpcMethods(protocolContext); final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
return new IbftJsonRpcMethods(protocolContext, protocolSchedule, miningParameters);
} }
@Override @Override

@ -130,10 +130,15 @@ public class QbftBesuControllerBuilder extends BftBesuControllerBuilder {
@Override @Override
protected JsonRpcMethods createAdditionalJsonRpcMethodFactory( protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
final ProtocolContext protocolContext) { final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
return new QbftJsonRpcMethods( return new QbftJsonRpcMethods(
protocolContext, createReadOnlyValidatorProvider(protocolContext.getBlockchain())); protocolContext,
protocolSchedule,
miningParameters,
createReadOnlyValidatorProvider(protocolContext.getBlockchain()));
} }
private ValidatorProvider createReadOnlyValidatorProvider(final Blockchain blockchain) { private ValidatorProvider createReadOnlyValidatorProvider(final Blockchain blockchain) {

@ -32,6 +32,8 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.util.List; import java.util.List;
@ -99,10 +101,13 @@ public class QbftBesuControllerBuilderTest extends AbstractBftBesuControllerBuil
@Test @Test
public void missingTransactionValidatorProviderThrowsError() { public void missingTransactionValidatorProviderThrowsError() {
final ProtocolContext protocolContext = mock(ProtocolContext.class); final ProtocolContext protocolContext = mock(ProtocolContext.class);
final ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class);
when(protocolContext.getBlockchain()).thenReturn(mock(MutableBlockchain.class)); when(protocolContext.getBlockchain()).thenReturn(mock(MutableBlockchain.class));
assertThatThrownBy( assertThatThrownBy(
() -> bftBesuControllerBuilder.createAdditionalJsonRpcMethodFactory(protocolContext)) () ->
bftBesuControllerBuilder.createAdditionalJsonRpcMethodFactory(
protocolContext, protocolSchedule, MiningParameters.newDefault()))
.isInstanceOf(NullPointerException.class) .isInstanceOf(NullPointerException.class)
.hasMessage("transactionValidatorProvider should have been initialised"); .hasMessage("transactionValidatorProvider should have been initialised");
} }

@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.log.Log; import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.worldstate.WorldView; import org.hyperledger.besu.evm.worldstate.WorldView;
@ -74,7 +75,12 @@ class TraceServiceImplTest {
blockchainSetupUtil.importAllBlocks(); blockchainSetupUtil.importAllBlocks();
blockchain = blockchainSetupUtil.getBlockchain(); blockchain = blockchainSetupUtil.getBlockchain();
worldStateArchive = blockchainSetupUtil.getWorldArchive(); worldStateArchive = blockchainSetupUtil.getWorldArchive();
blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive); blockchainQueries =
new BlockchainQueries(
blockchainSetupUtil.getProtocolSchedule(),
blockchain,
worldStateArchive,
MiningParameters.newDefault());
traceService = traceService =
new TraceServiceImpl(blockchainQueries, blockchainSetupUtil.getProtocolSchedule()); new TraceServiceImpl(blockchainQueries, blockchainSetupUtil.getProtocolSchedule());
} }

@ -31,6 +31,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.Map; import java.util.Map;
@ -38,14 +40,23 @@ import java.util.Map;
/** The Clique json rpc methods. */ /** The Clique json rpc methods. */
public class CliqueJsonRpcMethods extends ApiGroupJsonRpcMethods { public class CliqueJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final ProtocolContext context; private final ProtocolContext context;
private final ProtocolSchedule protocolSchedule;
private final MiningParameters miningParameters;
/** /**
* Instantiates a new Clique json rpc methods. * Instantiates a new Clique json rpc methods.
* *
* @param context the context * @param context the protocol context
* @param protocolSchedule the protocol schedule
* @param miningParameters the mining parameters
*/ */
public CliqueJsonRpcMethods(final ProtocolContext context) { public CliqueJsonRpcMethods(
final ProtocolContext context,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
this.context = context; this.context = context;
this.protocolSchedule = protocolSchedule;
this.miningParameters = miningParameters;
} }
@Override @Override
@ -58,7 +69,7 @@ public class CliqueJsonRpcMethods extends ApiGroupJsonRpcMethods {
final MutableBlockchain blockchain = context.getBlockchain(); final MutableBlockchain blockchain = context.getBlockchain();
final WorldStateArchive worldStateArchive = context.getWorldStateArchive(); final WorldStateArchive worldStateArchive = context.getWorldStateArchive();
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, worldStateArchive); new BlockchainQueries(protocolSchedule, blockchain, worldStateArchive, miningParameters);
final ValidatorProvider validatorProvider = final ValidatorProvider validatorProvider =
context.getConsensusContext(CliqueContext.class).getValidatorProvider(); context.getConsensusContext(CliqueContext.class).getValidatorProvider();

@ -32,6 +32,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.util.Map; import java.util.Map;
@ -39,14 +41,23 @@ import java.util.Map;
public class IbftJsonRpcMethods extends ApiGroupJsonRpcMethods { public class IbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final ProtocolContext context; private final ProtocolContext context;
private final ProtocolSchedule protocolSchedule;
private final MiningParameters miningParameters;
/** /**
* Instantiates a new Ibft json rpc methods. * Instantiates a new Ibft json rpc methods.
* *
* @param context the context * @param context the protocol context
* @param protocolSchedule the protocol schedule
* @param miningParameters the mining parameters
*/ */
public IbftJsonRpcMethods(final ProtocolContext context) { public IbftJsonRpcMethods(
final ProtocolContext context,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
this.context = context; this.context = context;
this.protocolSchedule = protocolSchedule;
this.miningParameters = miningParameters;
} }
@Override @Override
@ -58,7 +69,8 @@ public class IbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
protected Map<String, JsonRpcMethod> create() { protected Map<String, JsonRpcMethod> create() {
final MutableBlockchain blockchain = context.getBlockchain(); final MutableBlockchain blockchain = context.getBlockchain();
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, context.getWorldStateArchive()); new BlockchainQueries(
protocolSchedule, blockchain, context.getWorldStateArchive(), miningParameters);
final BftContext bftContext = context.getConsensusContext(BftContext.class); final BftContext bftContext = context.getConsensusContext(BftContext.class);
final BlockInterface blockInterface = bftContext.getBlockInterface(); final BlockInterface blockInterface = bftContext.getBlockInterface();
final ValidatorProvider validatorProvider = final ValidatorProvider validatorProvider =

@ -28,6 +28,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.ApiGroupJsonRpcMethods;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.util.Map; import java.util.Map;
@ -36,17 +38,26 @@ public class QbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final ProtocolContext context; private final ProtocolContext context;
private final ValidatorProvider readOnlyValidatorProvider; private final ValidatorProvider readOnlyValidatorProvider;
private final ProtocolSchedule protocolSchedule;
private final MiningParameters miningParameters;
/** /**
* Instantiates a new Qbft json rpc methods. * Instantiates a new Qbft json rpc methods.
* *
* @param context the context * @param context the protocol context
* @param protocolSchedule the protocol schedule
* @param miningParameters the mining parameters
* @param readOnlyValidatorProvider the read only validator provider * @param readOnlyValidatorProvider the read only validator provider
*/ */
public QbftJsonRpcMethods( public QbftJsonRpcMethods(
final ProtocolContext context, final ValidatorProvider readOnlyValidatorProvider) { final ProtocolContext context,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters,
final ValidatorProvider readOnlyValidatorProvider) {
this.context = context; this.context = context;
this.readOnlyValidatorProvider = readOnlyValidatorProvider; this.readOnlyValidatorProvider = readOnlyValidatorProvider;
this.protocolSchedule = protocolSchedule;
this.miningParameters = miningParameters;
} }
@Override @Override
@ -57,7 +68,11 @@ public class QbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
@Override @Override
protected Map<String, JsonRpcMethod> create() { protected Map<String, JsonRpcMethod> create() {
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries(context.getBlockchain(), context.getWorldStateArchive()); new BlockchainQueries(
protocolSchedule,
context.getBlockchain(),
context.getWorldStateArchive(),
miningParameters);
final BftContext bftContext = context.getConsensusContext(BftContext.class); final BftContext bftContext = context.getConsensusContext(BftContext.class);
final BlockInterface blockInterface = bftContext.getBlockInterface(); final BlockInterface blockInterface = bftContext.getBlockInterface();
final ValidatorProvider validatorProvider = bftContext.getValidatorProvider(); final ValidatorProvider validatorProvider = bftContext.getValidatorProvider();

@ -89,7 +89,9 @@ public class JsonRpcTestMethodsFactory {
final BlockImporter blockImporter = protocolSpec.getBlockImporter(); final BlockImporter blockImporter = protocolSpec.getBlockImporter();
blockImporter.importBlock(context, block, HeaderValidationMode.FULL); blockImporter.importBlock(context, block, HeaderValidationMode.FULL);
} }
this.blockchainQueries = new BlockchainQueries(blockchain, stateArchive); this.blockchainQueries =
new BlockchainQueries(
protocolSchedule, blockchain, stateArchive, MiningParameters.newDefault());
} }
public JsonRpcTestMethodsFactory( public JsonRpcTestMethodsFactory(
@ -101,7 +103,12 @@ public class JsonRpcTestMethodsFactory {
this.blockchain = blockchain; this.blockchain = blockchain;
this.stateArchive = stateArchive; this.stateArchive = stateArchive;
this.context = context; this.context = context;
this.blockchainQueries = new BlockchainQueries(blockchain, stateArchive); this.blockchainQueries =
new BlockchainQueries(
importer.getProtocolSchedule(),
blockchain,
stateArchive,
MiningParameters.newDefault());
this.synchronizer = mock(Synchronizer.class); this.synchronizer = mock(Synchronizer.class);
} }
@ -116,7 +123,12 @@ public class JsonRpcTestMethodsFactory {
this.stateArchive = stateArchive; this.stateArchive = stateArchive;
this.context = context; this.context = context;
this.synchronizer = synchronizer; this.synchronizer = synchronizer;
this.blockchainQueries = new BlockchainQueries(blockchain, stateArchive); this.blockchainQueries =
new BlockchainQueries(
importer.getProtocolSchedule(),
blockchain,
stateArchive,
MiningParameters.newDefault());
} }
public BlockchainQueries getBlockchainQueries() { public BlockchainQueries getBlockchainQueries() {

@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthContext;
@ -123,7 +124,11 @@ public class EthGetFilterChangesIntegrationTest {
TransactionPoolConfiguration.DEFAULT); TransactionPoolConfiguration.DEFAULT);
transactionPool.setEnabled(); transactionPool.setEnabled();
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive()); new BlockchainQueries(
executionContext.getProtocolSchedule(),
blockchain,
protocolContext.getWorldStateArchive(),
MiningParameters.newDefault());
filterManager = filterManager =
new FilterManagerBuilder() new FilterManagerBuilder()
.blockchainQueries(blockchainQueries) .blockchainQueries(blockchainQueries)

@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthContext;
@ -123,7 +124,11 @@ public class EthGetFilterChangesIntegrationTest {
TransactionPoolConfiguration.DEFAULT); TransactionPoolConfiguration.DEFAULT);
transactionPool.setEnabled(); transactionPool.setEnabled();
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive()); new BlockchainQueries(
executionContext.getProtocolSchedule(),
blockchain,
protocolContext.getWorldStateArchive(),
MiningParameters.newDefault());
filterManager = filterManager =
new FilterManagerBuilder() new FilterManagerBuilder()
.blockchainQueries(blockchainQueries) .blockchainQueries(blockchainQueries)

@ -14,7 +14,7 @@
*/ */
package org.hyperledger.besu.ethereum.api; package org.hyperledger.besu.ethereum.api;
import java.util.function.LongSupplier; import org.hyperledger.besu.datatypes.Wei;
import org.immutables.value.Value; import org.immutables.value.Value;
@ -36,14 +36,8 @@ public abstract class ApiConfiguration {
} }
@Value.Default @Value.Default
@Value.Auxiliary public Wei getGasPriceMax() {
public LongSupplier getGasPriceMinSupplier() { return Wei.of(500_000_000_000L); // 500 GWei
return () -> 1_000_000_000L; // 1 GWei
}
@Value.Default
public long getGasPriceMax() {
return 500_000_000_000L; // 500 GWei
} }
@Value.Derived @Value.Derived

@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.LogsQuery; import org.hyperledger.besu.ethereum.api.query.LogsQuery;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import org.hyperledger.besu.ethereum.core.LogWithMetadata; import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
@ -117,17 +116,12 @@ public class GraphQLDataFetchers {
}; };
} }
DataFetcher<Optional<Wei>> getGasPriceDataFetcher() { DataFetcher<Wei> getGasPriceDataFetcher() {
return dataFetchingEnvironment -> { return dataFetchingEnvironment -> {
final GraphQLContext graphQLContext = dataFetchingEnvironment.getGraphQlContext(); final GraphQLContext graphQLContext = dataFetchingEnvironment.getGraphQlContext();
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
graphQLContext.get(GraphQLContextType.BLOCKCHAIN_QUERIES); graphQLContext.get(GraphQLContextType.BLOCKCHAIN_QUERIES);
final MiningCoordinator miningCoordinator = return blockchainQueries.gasPrice();
graphQLContext.get(GraphQLContextType.MINING_COORDINATOR);
return blockchainQueries
.gasPrice()
.map(Wei::of)
.or(() -> Optional.of(miningCoordinator.getMinTransactionGasPrice()));
}; };
} }

@ -22,30 +22,15 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcRespon
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; 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.jsonrpc.internal.results.Quantity;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
import java.util.Optional;
import java.util.function.Supplier;
public class EthGasPrice implements JsonRpcMethod { public class EthGasPrice implements JsonRpcMethod {
private final Supplier<BlockchainQueries> blockchain; private final BlockchainQueries blockchainQueries;
private final MiningCoordinator miningCoordinator;
private final ApiConfiguration apiConfiguration; private final ApiConfiguration apiConfiguration;
public EthGasPrice( public EthGasPrice(
final BlockchainQueries blockchain, final BlockchainQueries blockchainQueries, final ApiConfiguration apiConfiguration) {
final MiningCoordinator miningCoordinator, this.blockchainQueries = blockchainQueries;
final ApiConfiguration apiConfiguration) {
this(() -> blockchain, miningCoordinator, apiConfiguration);
}
public EthGasPrice(
final Supplier<BlockchainQueries> blockchain,
final MiningCoordinator miningCoordinator,
final ApiConfiguration apiConfiguration) {
this.blockchain = blockchain;
this.miningCoordinator = miningCoordinator;
this.apiConfiguration = apiConfiguration; this.apiConfiguration = apiConfiguration;
} }
@ -61,30 +46,26 @@ public class EthGasPrice implements JsonRpcMethod {
} }
private Wei calculateGasPrice() { private Wei calculateGasPrice() {
Wei gasPrice = getGasPrice().orElseGet(miningCoordinator::getMinTransactionGasPrice); final Wei gasPrice = blockchainQueries.gasPrice();
return isGasPriceLimitingEnabled() ? limitGasPrice(gasPrice) : gasPrice; return isGasPriceLimitingEnabled() ? limitGasPrice(gasPrice) : gasPrice;
} }
private Optional<Wei> getGasPrice() {
return blockchain.get().gasPrice().map(Wei::of);
}
private boolean isGasPriceLimitingEnabled() { private boolean isGasPriceLimitingEnabled() {
return apiConfiguration.isGasAndPriorityFeeLimitingEnabled(); return apiConfiguration.isGasAndPriorityFeeLimitingEnabled();
} }
private Wei limitGasPrice(final Wei gasPrice) { private Wei limitGasPrice(final Wei gasPrice) {
Wei minTransactionGasPrice = miningCoordinator.getMinTransactionGasPrice(); final Wei lowerBoundGasPrice = blockchainQueries.gasPriceLowerBound();
Wei lowerBound = final Wei forcedLowerBound =
calculateBound( calculateBound(
minTransactionGasPrice, apiConfiguration.getLowerBoundGasAndPriorityFeeCoefficient()); lowerBoundGasPrice, apiConfiguration.getLowerBoundGasAndPriorityFeeCoefficient());
Wei upperBound = final Wei forcedUpperBound =
calculateBound( calculateBound(
minTransactionGasPrice, apiConfiguration.getUpperBoundGasAndPriorityFeeCoefficient()); lowerBoundGasPrice, apiConfiguration.getUpperBoundGasAndPriorityFeeCoefficient());
return gasPrice.compareTo(lowerBound) <= 0 return gasPrice.compareTo(forcedLowerBound) <= 0
? lowerBound ? forcedLowerBound
: gasPrice.compareTo(upperBound) >= 0 ? upperBound : gasPrice; : gasPrice.compareTo(forcedUpperBound) >= 0 ? forcedUpperBound : gasPrice;
} }
private Wei calculateBound(final Wei price, final long coefficient) { private Wei calculateBound(final Wei price, final long coefficient) {

@ -175,7 +175,7 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
new EthMining(miningCoordinator), new EthMining(miningCoordinator),
new EthCoinbase(miningCoordinator), new EthCoinbase(miningCoordinator),
new EthProtocolVersion(supportedCapabilities), new EthProtocolVersion(supportedCapabilities),
new EthGasPrice(blockchainQueries, miningCoordinator, apiConfiguration), new EthGasPrice(blockchainQueries, apiConfiguration),
new EthGetWork(miningCoordinator), new EthGetWork(miningCoordinator),
new EthSubmitWork(miningCoordinator), new EthSubmitWork(miningCoordinator),
new EthHashrate(miningCoordinator), new EthHashrate(miningCoordinator),

@ -30,12 +30,15 @@ import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.LogWithMetadata; import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.log.LogsBloomFilter; import org.hyperledger.besu.evm.log.LogsBloomFilter;
@ -60,49 +63,77 @@ import java.util.stream.LongStream;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.apache.tuweni.units.bigints.UInt256s;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class BlockchainQueries { public class BlockchainQueries {
private static final Logger LOG = LoggerFactory.getLogger(BlockchainQueries.class); private static final Logger LOG = LoggerFactory.getLogger(BlockchainQueries.class);
private final ProtocolSchedule protocolSchedule;
private final WorldStateArchive worldStateArchive; private final WorldStateArchive worldStateArchive;
private final Blockchain blockchain; private final Blockchain blockchain;
private final Optional<Path> cachePath; private final Optional<Path> cachePath;
private final Optional<TransactionLogBloomCacher> transactionLogBloomCacher; private final Optional<TransactionLogBloomCacher> transactionLogBloomCacher;
private final Optional<EthScheduler> ethScheduler; private final Optional<EthScheduler> ethScheduler;
private final ApiConfiguration apiConfig; private final ApiConfiguration apiConfig;
private final MiningParameters miningParameters;
public BlockchainQueries(final Blockchain blockchain, final WorldStateArchive worldStateArchive) { public BlockchainQueries(
this(blockchain, worldStateArchive, Optional.empty(), Optional.empty()); final ProtocolSchedule protocolSchedule,
final Blockchain blockchain,
final WorldStateArchive worldStateArchive,
final MiningParameters miningParameters) {
this(
protocolSchedule,
blockchain,
worldStateArchive,
Optional.empty(),
Optional.empty(),
miningParameters);
} }
public BlockchainQueries( public BlockchainQueries(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain, final Blockchain blockchain,
final WorldStateArchive worldStateArchive, final WorldStateArchive worldStateArchive,
final EthScheduler scheduler) { final EthScheduler scheduler,
this(blockchain, worldStateArchive, Optional.empty(), Optional.ofNullable(scheduler)); final MiningParameters miningParameters) {
this(
protocolSchedule,
blockchain,
worldStateArchive,
Optional.empty(),
Optional.ofNullable(scheduler),
miningParameters);
} }
public BlockchainQueries( public BlockchainQueries(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain, final Blockchain blockchain,
final WorldStateArchive worldStateArchive, final WorldStateArchive worldStateArchive,
final Optional<Path> cachePath, final Optional<Path> cachePath,
final Optional<EthScheduler> scheduler) { final Optional<EthScheduler> scheduler,
final MiningParameters miningParameters) {
this( this(
protocolSchedule,
blockchain, blockchain,
worldStateArchive, worldStateArchive,
cachePath, cachePath,
scheduler, scheduler,
ImmutableApiConfiguration.builder().build()); ImmutableApiConfiguration.builder().build(),
miningParameters);
} }
public BlockchainQueries( public BlockchainQueries(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain, final Blockchain blockchain,
final WorldStateArchive worldStateArchive, final WorldStateArchive worldStateArchive,
final Optional<Path> cachePath, final Optional<Path> cachePath,
final Optional<EthScheduler> scheduler, final Optional<EthScheduler> scheduler,
final ApiConfiguration apiConfig) { final ApiConfiguration apiConfig,
final MiningParameters miningParameters) {
this.protocolSchedule = protocolSchedule;
this.blockchain = blockchain; this.blockchain = blockchain;
this.worldStateArchive = worldStateArchive; this.worldStateArchive = worldStateArchive;
this.cachePath = cachePath; this.cachePath = cachePath;
@ -113,6 +144,7 @@ public class BlockchainQueries {
new TransactionLogBloomCacher(blockchain, cachePath.get(), scheduler.get())) new TransactionLogBloomCacher(blockchain, cachePath.get(), scheduler.get()))
: Optional.empty(); : Optional.empty();
this.apiConfig = apiConfig; this.apiConfig = apiConfig;
this.miningParameters = miningParameters;
} }
public Blockchain getBlockchain() { public Blockchain getBlockchain() {
@ -943,10 +975,15 @@ public class BlockchainQueries {
return getAndMapWorldState(blockHash, mapper); return getAndMapWorldState(blockHash, mapper);
} }
public Optional<Long> gasPrice() { public Wei gasPrice() {
final long blockHeight = headBlockNumber(); final long blockHeight = headBlockNumber();
final long[] gasCollection = final var chainHeadHeader = blockchain.getChainHeadHeader();
LongStream.range(Math.max(0, blockHeight - apiConfig.getGasPriceBlocks()), blockHeight) final var nextBlockProtocolSpec =
protocolSchedule.getForNextBlockHeader(chainHeadHeader, System.currentTimeMillis());
final var nextBlockFeeMarket = nextBlockProtocolSpec.getFeeMarket();
final Wei[] gasCollection =
LongStream.rangeClosed(
Math.max(0, blockHeight - apiConfig.getGasPriceBlocks() + 1), blockHeight)
.mapToObj( .mapToObj(
l -> l ->
blockchain blockchain
@ -957,20 +994,46 @@ public class BlockchainQueries {
() -> new IllegalStateException("Could not retrieve block #" + l))) () -> new IllegalStateException("Could not retrieve block #" + l)))
.flatMap(Collection::stream) .flatMap(Collection::stream)
.filter(t -> t.getGasPrice().isPresent()) .filter(t -> t.getGasPrice().isPresent())
.mapToLong(t -> t.getGasPrice().get().toLong()) .map(t -> t.getGasPrice().get())
.sorted() .sorted()
.toArray(); .toArray(Wei[]::new);
return (gasCollection == null || gasCollection.length == 0) return (gasCollection == null || gasCollection.length == 0)
? Optional.empty() ? gasPriceLowerBound(chainHeadHeader, nextBlockFeeMarket)
: Optional.of( : UInt256s.max(
Math.max( gasPriceLowerBound(chainHeadHeader, nextBlockFeeMarket),
apiConfig.getGasPriceMinSupplier().getAsLong(), UInt256s.min(
Math.min(
apiConfig.getGasPriceMax(), apiConfig.getGasPriceMax(),
gasCollection[ gasCollection[
Math.min( Math.min(
gasCollection.length - 1, gasCollection.length - 1,
(int) ((gasCollection.length) * apiConfig.getGasPriceFraction()))]))); (int) ((gasCollection.length) * apiConfig.getGasPriceFraction()))]));
}
/**
* Return the min gas required for a tx to be mineable. On networks with gas price fee market it
* is just the minGasPrice, while on networks with base fee market it is the max between the
* minGasPrice and the baseFee for the next block.
*
* @return the min gas required for a tx to be mineable.
*/
public Wei gasPriceLowerBound() {
final var chainHeadHeader = blockchain.getChainHeadHeader();
final var nextBlockProtocolSpec =
protocolSchedule.getForNextBlockHeader(chainHeadHeader, System.currentTimeMillis());
final var nextBlockFeeMarket = nextBlockProtocolSpec.getFeeMarket();
return gasPriceLowerBound(chainHeadHeader, nextBlockFeeMarket);
}
private Wei gasPriceLowerBound(
final BlockHeader chainHeadHeader, final FeeMarket nextBlockFeeMarket) {
final var minGasPrice = miningParameters.getMinTransactionGasPrice();
if (nextBlockFeeMarket.implementsBaseFee()) {
return UInt256s.max(
getNextBlockBaseFee(chainHeadHeader, (BaseFeeMarket) nextBlockFeeMarket), minGasPrice);
}
return minGasPrice;
} }
public Optional<Wei> gasPriorityFee() { public Optional<Wei> gasPriorityFee() {
@ -1000,6 +1063,31 @@ public class BlockchainQueries {
(int) ((gasCollection.length) * apiConfig.getGasPriceFraction()))])); (int) ((gasCollection.length) * apiConfig.getGasPriceFraction()))]));
} }
/**
* Calculate and return the value of the base fee for the next block, if the network has a base
* fee market, otherwise return empty.
*
* @return the optional base fee
*/
public Optional<Wei> getNextBlockBaseFee() {
final var chainHeadHeader = blockchain.getChainHeadHeader();
final var nextBlockProtocolSpec =
protocolSchedule.getForNextBlockHeader(chainHeadHeader, System.currentTimeMillis());
final var nextBlockFeeMarket = nextBlockProtocolSpec.getFeeMarket();
return nextBlockFeeMarket.implementsBaseFee()
? Optional.of(getNextBlockBaseFee(chainHeadHeader, (BaseFeeMarket) nextBlockFeeMarket))
: Optional.empty();
}
private Wei getNextBlockBaseFee(
final BlockHeader chainHeadHeader, final BaseFeeMarket nextBlockFeeMarket) {
return nextBlockFeeMarket.computeBaseFee(
chainHeadHeader.getNumber() + 1,
chainHeadHeader.getBaseFee().orElse(Wei.ZERO),
chainHeadHeader.getGasUsed(),
nextBlockFeeMarket.targetGasUsed(chainHeadHeader));
}
private <T> Optional<T> fromAccount( private <T> Optional<T> fromAccount(
final Address address, final Address address,
final Hash blockHash, final Hash blockHash,

@ -14,6 +14,7 @@
*/ */
package org.hyperledger.besu.ethereum.api.graphql; package org.hyperledger.besu.ethereum.api.graphql;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.TransactionType;
@ -26,6 +27,7 @@ import org.hyperledger.besu.ethereum.chain.BadBlockManager;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.ethereum.core.DefaultSyncStatus; import org.hyperledger.besu.ethereum.core.DefaultSyncStatus;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocol;
@ -80,14 +82,13 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
@BeforeEach @BeforeEach
public void setupTest() throws Exception { public void setupTest() throws Exception {
final Synchronizer synchronizerMock = Mockito.mock(Synchronizer.class); final Synchronizer synchronizerMock = mock(Synchronizer.class);
final SyncStatus status = new DefaultSyncStatus(1, 2, 3, Optional.of(4L), Optional.of(5L)); final SyncStatus status = new DefaultSyncStatus(1, 2, 3, Optional.of(4L), Optional.of(5L));
when(synchronizerMock.getSyncStatus()).thenReturn(Optional.of(status)); when(synchronizerMock.getSyncStatus()).thenReturn(Optional.of(status));
final PoWMiningCoordinator miningCoordinatorMock = Mockito.mock(PoWMiningCoordinator.class); final PoWMiningCoordinator miningCoordinatorMock = mock(PoWMiningCoordinator.class);
when(miningCoordinatorMock.getMinTransactionGasPrice()).thenReturn(Wei.of(16));
final TransactionPool transactionPoolMock = Mockito.mock(TransactionPool.class); final TransactionPool transactionPoolMock = mock(TransactionPool.class);
when(transactionPoolMock.addTransactionViaApi(ArgumentMatchers.any(Transaction.class))) when(transactionPoolMock.addTransactionViaApi(ArgumentMatchers.any(Transaction.class)))
.thenReturn(ValidationResult.valid()); .thenReturn(ValidationResult.valid());
@ -112,11 +113,13 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
blockchain, blockchainSetupUtil.getWorldArchive(), null, new BadBlockManager()); blockchain, blockchainSetupUtil.getWorldArchive(), null, new BadBlockManager());
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries( new BlockchainQueries(
blockchainSetupUtil.getProtocolSchedule(),
context.getBlockchain(), context.getBlockchain(),
context.getWorldStateArchive(), context.getWorldStateArchive(),
Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(),
ImmutableApiConfiguration.builder().gasPriceMinSupplier(() -> 0).build()); ImmutableApiConfiguration.builder().build(),
MiningParameters.newDefault().setMinTransactionGasPrice(Wei.ZERO));
final Set<Capability> supportedCapabilities = new HashSet<>(); final Set<Capability> supportedCapabilities = new HashSet<>();
supportedCapabilities.add(EthProtocol.ETH62); supportedCapabilities.add(EthProtocol.ETH62);
@ -147,7 +150,7 @@ public abstract class AbstractEthGraphQLHttpServiceTest {
synchronizerMock, synchronizerMock,
GraphQLContextType.GAS_CAP, GraphQLContextType.GAS_CAP,
0L), 0L),
Mockito.mock(EthScheduler.class)); mock(EthScheduler.class));
service.start().join(); service.start().join();
client = new OkHttpClient(); client = new OkHttpClient();

@ -216,7 +216,7 @@ public class GraphQLHttpServiceTest {
@Test @Test
public void query_get() throws Exception { public void query_get() throws Exception {
final Wei price = Wei.of(16); final Wei price = Wei.of(16);
Mockito.when(blockchainQueries.gasPrice()).thenReturn(Optional.of(price.toLong())); Mockito.when(blockchainQueries.gasPrice()).thenReturn(price);
Mockito.when(miningCoordinatorMock.getMinTransactionGasPrice()).thenReturn(price); Mockito.when(miningCoordinatorMock.getMinTransactionGasPrice()).thenReturn(price);
try (final Response resp = client.newCall(buildGetRequest("?query={gasPrice}")).execute()) { try (final Response resp = client.newCall(buildGetRequest("?query={gasPrice}")).execute()) {

@ -145,7 +145,10 @@ public abstract class AbstractJsonRpcHttpServiceTest {
final BlockchainQueries blockchainQueries = final BlockchainQueries blockchainQueries =
new BlockchainQueries( new BlockchainQueries(
blockchainSetupUtil.getBlockchain(), blockchainSetupUtil.getWorldArchive()); blockchainSetupUtil.getProtocolSchedule(),
blockchainSetupUtil.getBlockchain(),
blockchainSetupUtil.getWorldArchive(),
miningParameters);
final FilterIdGenerator filterIdGenerator = mock(FilterIdGenerator.class); final FilterIdGenerator filterIdGenerator = mock(FilterIdGenerator.class);
final FilterRepository filterRepository = new FilterRepository(); final FilterRepository filterRepository = new FilterRepository();
when(filterIdGenerator.nextId()).thenReturn("0x1"); when(filterIdGenerator.nextId()).thenReturn("0x1");

@ -15,7 +15,9 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -30,38 +32,57 @@ 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.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.blockcreation.PoWMiningCoordinator;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.feemarket.CancunFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.LegacyFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.LondonFeeMarket;
import org.hyperledger.besu.evm.log.LogsBloomFilter; import org.hyperledger.besu.evm.log.LogsBloomFilter;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; 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.Mock;
import org.mockito.internal.verification.VerificationModeFactory; import org.mockito.internal.verification.VerificationModeFactory;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class EthGasPriceTest { public class EthGasPriceTest {
private static final String JSON_RPC_VERSION = "2.0";
@Mock private PoWMiningCoordinator miningCoordinator; private static final String ETH_METHOD = "eth_gasPrice";
private static final long DEFAULT_BLOCK_GAS_LIMIT = 100_000;
private static final long DEFAULT_BLOCK_GAS_USED = 21_000;
private static final Wei DEFAULT_MIN_GAS_PRICE = Wei.of(1_000);
private static final Wei DEFAULT_BASE_FEE = Wei.of(100_000);
@Mock private ProtocolSchedule protocolSchedule;
@Mock private Blockchain blockchain; @Mock private Blockchain blockchain;
private EthGasPrice method; private EthGasPrice method;
private final String JSON_RPC_VERSION = "2.0"; private MiningParameters miningParameters;
private final String ETH_METHOD = "eth_gasPrice";
@BeforeEach @BeforeEach
public void setUp() { public void setUp() {
ApiConfiguration apiConfig = createDefaultApiConfiguration(); ApiConfiguration apiConfig = createDefaultApiConfiguration();
miningParameters =
MiningParameters.newDefault().setMinTransactionGasPrice(DEFAULT_MIN_GAS_PRICE);
method = createEthGasPriceMethod(apiConfig); method = createEthGasPriceMethod(apiConfig);
} }
@ -73,41 +94,57 @@ public class EthGasPriceTest {
@Test @Test
public void shouldReturnMinValueWhenNoTransactionsExist() { public void shouldReturnMinValueWhenNoTransactionsExist() {
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
final String expectedWei = "0x4d2"; final String expectedWei = "0x4d2"; // minGasPrice > nextBlockBaseFee
miningParameters.setMinTransactionGasPrice(Wei.fromHexString(expectedWei));
final JsonRpcResponse expectedResponse = final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei);
when(miningCoordinator.getMinTransactionGasPrice()).thenReturn(Wei.of(1234));
when(blockchain.getChainHeadBlockNumber()).thenReturn(1000L); mockBaseFeeMarket();
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(invocation -> createEmptyBlock(invocation.getArgument(0, Long.class))); mockBlockchain(1000, 0);
final JsonRpcResponse actualResponse = method.response(request); final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(miningCoordinator).getMinTransactionGasPrice();
verifyNoMoreInteractions(miningCoordinator);
verify(blockchain).getChainHeadBlockNumber(); verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(100)).getBlockByNumber(anyLong()); verify(blockchain, VerificationModeFactory.times(100)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain); verifyNoMoreInteractions(blockchain);
} }
@Test @Test
public void shouldReturnMedianWhenTransactionsExist() { public void shouldReturnBaseFeeAsMinValueOnGenesis() {
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
final String expectedWei = "0x389fd980"; // 950Wei, gas prices are 900-999 wei. final String expectedWei =
DEFAULT_BASE_FEE.toShortHexString(); // nextBlockBaseFee > minGasPrice
miningParameters.setMinTransactionGasPrice(Wei.fromHexString(expectedWei));
final JsonRpcResponse expectedResponse = final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei);
when(blockchain.getChainHeadBlockNumber()).thenReturn(1000L); mockBaseFeeMarket();
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(invocation -> createFakeBlock(invocation.getArgument(0, Long.class))); mockBlockchain(0, 0);
final JsonRpcResponse actualResponse = method.response(request); final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verifyNoMoreInteractions(miningCoordinator); verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(1)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain);
}
@Test
public void shouldReturnMedianWhenTransactionsExist() {
final JsonRpcRequestContext request = requestWithParams();
final String expectedWei = "0x911c70"; // 9.51 mwei, gas prices are 9.01-10 mwei.
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei);
mockBaseFeeMarket();
mockBlockchain(1000L, 1);
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(blockchain).getChainHeadBlockNumber(); verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(100)).getBlockByNumber(anyLong()); verify(blockchain, VerificationModeFactory.times(100)).getBlockByNumber(anyLong());
@ -117,21 +154,19 @@ public class EthGasPriceTest {
@Test @Test
public void shortChainQueriesAllBlocks() { public void shortChainQueriesAllBlocks() {
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
final String expectedWei = "0x2625a00"; final String expectedWei = "0x64190"; // 410 kwei
final JsonRpcResponse expectedResponse = final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei); new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei);
when(blockchain.getChainHeadBlockNumber()).thenReturn(80L); mockBaseFeeMarket();
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(invocation -> createFakeBlock(invocation.getArgument(0, Long.class))); mockBlockchain(80L, 1);
final JsonRpcResponse actualResponse = method.response(request); final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verifyNoMoreInteractions(miningCoordinator);
verify(blockchain).getChainHeadBlockNumber(); verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(80)).getBlockByNumber(anyLong()); verify(blockchain, VerificationModeFactory.times(81)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain); verifyNoMoreInteractions(blockchain);
} }
@ -141,9 +176,9 @@ public class EthGasPriceTest {
*/ */
@Test @Test
public void shouldReturnLimitedPriceWhenLowerBoundIsPresent() { public void shouldReturnLimitedPriceWhenLowerBoundIsPresent() {
long gasPrice = 5000000; long expectedGasPrice = 31_841 * 2;
long lowerBoundGasPrice = gasPrice + 1; long lowerBoundCoefficient = 200;
verifyGasPriceLimit(lowerBoundGasPrice, null, lowerBoundGasPrice); verifyGasPriceLimit(lowerBoundCoefficient, null, expectedGasPrice);
} }
/** /**
@ -152,9 +187,9 @@ public class EthGasPriceTest {
*/ */
@Test @Test
public void shouldReturnLimitedPriceWhenUpperBoundIsPresent() { public void shouldReturnLimitedPriceWhenUpperBoundIsPresent() {
long gasPrice = 5000000; long expectedGasPrice = (long) (31_841 * 1.5);
long upperBoundGasPrice = gasPrice - 1; long upperBoundCoefficient = 150;
verifyGasPriceLimit(null, upperBoundGasPrice, upperBoundGasPrice); verifyGasPriceLimit(null, upperBoundCoefficient, expectedGasPrice);
} }
/** /**
@ -163,25 +198,83 @@ public class EthGasPriceTest {
*/ */
@Test @Test
public void shouldReturnActualGasPriceWhenWithinBoundRange() { public void shouldReturnActualGasPriceWhenWithinBoundRange() {
long gasPrice = 5000000; long gasPrice = 60_000;
long lowerBoundGasPrice = gasPrice - 1; long lowerBoundCoefficient = 120;
long upperBoundGasPrice = gasPrice + 1; long upperBoundCoefficient = 200;
verifyGasPriceLimit(lowerBoundGasPrice, upperBoundGasPrice, gasPrice); verifyGasPriceLimit(lowerBoundCoefficient, upperBoundCoefficient, gasPrice);
}
private static Stream<Arguments> ethGasPriceAtGenesis() {
return Stream.of(
// base fee > min gas price
Arguments.of(
DEFAULT_MIN_GAS_PRICE.divide(2),
Optional.of(DEFAULT_MIN_GAS_PRICE),
DEFAULT_MIN_GAS_PRICE.subtract(
DEFAULT_MIN_GAS_PRICE
.multiply(125)
.divide(1000)) // expect base fee for the 1st block
),
// base fee < min gas price
Arguments.of(
DEFAULT_BASE_FEE.multiply(2),
Optional.of(DEFAULT_BASE_FEE),
DEFAULT_BASE_FEE.multiply(2)) // expect min gas price value
,
// no base fee market
Arguments.of(
DEFAULT_MIN_GAS_PRICE,
Optional.empty(),
DEFAULT_MIN_GAS_PRICE // expect min gas price value
));
}
@ParameterizedTest
@MethodSource("ethGasPriceAtGenesis")
public void ethGasPriceAtGenesis(
final Wei minGasPrice, final Optional<Wei> maybeGenesisBaseFee, final Wei expectedGasPrice) {
miningParameters.setMinTransactionGasPrice(minGasPrice);
if (maybeGenesisBaseFee.isPresent()) {
mockBaseFeeMarket();
mockBlockchain(maybeGenesisBaseFee.get(), 0, 0);
} else {
mockGasPriceMarket();
mockBlockchain(null, 0, 0);
}
final JsonRpcRequestContext request = requestWithParams();
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
request.getRequest().getId(), expectedGasPrice.toShortHexString());
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(1)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain);
} }
/** /**
* Helper method to verify the gas price limit. * Helper method to verify the gas price limit.
* *
* @param lowerBound The lower bound of the gas price. * @param lowerBoundCoefficient The lower bound of the gas price.
* @param upperBound The upper bound of the gas price. * @param upperBoundCoefficient The upper bound of the gas price.
* @param expectedGasPrice The expected gas price. * @param expectedGasPrice The expected gas price.
*/ */
private void verifyGasPriceLimit( private void verifyGasPriceLimit(
final Long lowerBound, final Long upperBound, final long expectedGasPrice) { final Long lowerBoundCoefficient,
when(miningCoordinator.getMinTransactionGasPrice()).thenReturn(Wei.of(100)); final Long upperBoundCoefficient,
final long expectedGasPrice) {
miningParameters.setMinTransactionGasPrice(Wei.of(100));
mockBaseFeeMarket();
var apiConfig = var apiConfig =
createApiConfiguration(Optional.ofNullable(lowerBound), Optional.ofNullable(upperBound)); createApiConfiguration(
Optional.ofNullable(lowerBoundCoefficient), Optional.ofNullable(upperBoundCoefficient));
method = createEthGasPriceMethod(apiConfig); method = createEthGasPriceMethod(apiConfig);
final JsonRpcRequestContext request = requestWithParams(); final JsonRpcRequestContext request = requestWithParams();
@ -189,17 +282,73 @@ public class EthGasPriceTest {
new JsonRpcSuccessResponse( new JsonRpcSuccessResponse(
request.getRequest().getId(), Wei.of(expectedGasPrice).toShortHexString()); request.getRequest().getId(), Wei.of(expectedGasPrice).toShortHexString());
when(blockchain.getChainHeadBlockNumber()).thenReturn(10L); final var chainHeadBlockNumber = 10L;
when(blockchain.getBlockByNumber(anyLong())) mockBlockchain(chainHeadBlockNumber, 1);
.thenAnswer(invocation -> createFakeBlock(invocation.getArgument(0, Long.class)));
final JsonRpcResponse actualResponse = method.response(request); final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
} }
private Object createFakeBlock(final Long height) { private void mockBaseFeeMarket() {
return Optional.of( mockFeeMarket(new LondonFeeMarket(0));
new Block( }
private void mockGasPriceMarket() {
mockFeeMarket(new LegacyFeeMarket());
}
private void mockFeeMarket(final FeeMarket feeMarket) {
final var protocolSpec = mock(ProtocolSpec.class);
when(protocolSpec.getFeeMarket()).thenReturn(feeMarket);
when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(protocolSpec);
}
private void mockBlockchain(final long chainHeadBlockNumber, final int txsNum) {
mockBlockchain(DEFAULT_BASE_FEE, chainHeadBlockNumber, txsNum);
}
private void mockBlockchain(
final Wei genesisBaseFee, final long chainHeadBlockNumber, final int txsNum) {
final var blocksByNumber = new HashMap<Long, Block>();
final var genesisBlock = createFakeBlock(0, 0, genesisBaseFee);
blocksByNumber.put(0L, genesisBlock);
final var baseFeeMarket = new CancunFeeMarket(0, Optional.empty());
var baseFee = genesisBaseFee;
for (long i = 1; i <= chainHeadBlockNumber; i++) {
final var parentHeader = blocksByNumber.get(i - 1).getHeader();
baseFee =
baseFeeMarket.computeBaseFee(
i,
parentHeader.getBaseFee().get(),
parentHeader.getGasUsed(),
parentHeader.getGasLimit());
blocksByNumber.put(i, createFakeBlock(i, txsNum, baseFee));
}
when(blockchain.getChainHeadBlockNumber()).thenReturn(chainHeadBlockNumber);
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(
invocation -> Optional.of(blocksByNumber.get(invocation.getArgument(0, Long.class))));
when(blockchain.getChainHeadHeader())
.thenReturn(blocksByNumber.get(chainHeadBlockNumber).getHeader());
}
private Block createFakeBlock(final long height, final int txsNum, final Wei baseFee) {
return createFakeBlock(
height, txsNum, baseFee, DEFAULT_BLOCK_GAS_LIMIT, DEFAULT_BLOCK_GAS_USED * txsNum);
}
private Block createFakeBlock(
final long height,
final int txsNum,
final Wei baseFee,
final long gasLimit,
final long gasUsed) {
return new Block(
new BlockHeader( new BlockHeader(
Hash.EMPTY, Hash.EMPTY,
Hash.EMPTY_TRIE_HASH, Hash.EMPTY_TRIE_HASH,
@ -210,11 +359,11 @@ public class EthGasPriceTest {
LogsBloomFilter.builder().build(), LogsBloomFilter.builder().build(),
Difficulty.ONE, Difficulty.ONE,
height, height,
0, gasLimit,
0, gasUsed,
0, 0,
Bytes.EMPTY, Bytes.EMPTY,
Wei.ZERO, baseFee,
Hash.EMPTY, Hash.EMPTY,
0, 0,
null, null,
@ -224,43 +373,17 @@ public class EthGasPriceTest {
null, null,
null), null),
new BlockBody( new BlockBody(
List.of( IntStream.range(0, txsNum)
.mapToObj(
i ->
new Transaction.Builder() new Transaction.Builder()
.nonce(0) .nonce(i)
.gasPrice(Wei.of(height * 1000000L)) .gasPrice(Wei.of(height * 10_000L))
.gasLimit(0) .gasLimit(gasUsed)
.value(Wei.ZERO) .value(Wei.ZERO)
.build()), .build())
List.of()))); .toList(),
} List.of()));
private Object createEmptyBlock(final Long height) {
return Optional.of(
new Block(
new BlockHeader(
Hash.EMPTY,
Hash.EMPTY_TRIE_HASH,
Address.ZERO,
Hash.EMPTY_TRIE_HASH,
Hash.EMPTY_TRIE_HASH,
Hash.EMPTY_TRIE_HASH,
LogsBloomFilter.builder().build(),
Difficulty.ONE,
height,
0,
0,
0,
Bytes.EMPTY,
Wei.ZERO,
Hash.EMPTY,
0,
null,
null,
null,
null,
null,
null),
new BlockBody(List.of(), List.of())));
} }
private JsonRpcRequestContext requestWithParams(final Object... params) { private JsonRpcRequestContext requestWithParams(final Object... params) {
@ -272,16 +395,15 @@ public class EthGasPriceTest {
} }
private ApiConfiguration createApiConfiguration( private ApiConfiguration createApiConfiguration(
final Optional<Long> lowerBound, final Optional<Long> upperBound) { final Optional<Long> lowerBoundCoefficient, final Optional<Long> upperBoundCoefficient) {
ImmutableApiConfiguration.Builder builder = ImmutableApiConfiguration.Builder builder = ImmutableApiConfiguration.builder();
ImmutableApiConfiguration.builder().gasPriceMinSupplier(() -> 100);
lowerBound.ifPresent( lowerBoundCoefficient.ifPresent(
value -> value ->
builder builder
.isGasAndPriorityFeeLimitingEnabled(true) .isGasAndPriorityFeeLimitingEnabled(true)
.lowerBoundGasAndPriorityFeeCoefficient(value)); .lowerBoundGasAndPriorityFeeCoefficient(value));
upperBound.ifPresent( upperBoundCoefficient.ifPresent(
value -> value ->
builder builder
.isGasAndPriorityFeeLimitingEnabled(true) .isGasAndPriorityFeeLimitingEnabled(true)
@ -292,8 +414,14 @@ public class EthGasPriceTest {
private EthGasPrice createEthGasPriceMethod(final ApiConfiguration apiConfig) { private EthGasPrice createEthGasPriceMethod(final ApiConfiguration apiConfig) {
return new EthGasPrice( return new EthGasPrice(
new BlockchainQueries(blockchain, null, Optional.empty(), Optional.empty(), apiConfig), new BlockchainQueries(
miningCoordinator, protocolSchedule,
blockchain,
null,
Optional.empty(),
Optional.empty(),
apiConfig,
miningParameters),
apiConfig); apiConfig);
} }
} }

@ -36,8 +36,10 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Synchronizer;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.List; import java.util.List;
@ -66,6 +68,7 @@ public class EthGetBlockByNumberTest {
private EthGetBlockByNumber method; private EthGetBlockByNumber method;
@Mock private Synchronizer synchronizer; @Mock private Synchronizer synchronizer;
@Mock private WorldStateArchive worldStateArchive; @Mock private WorldStateArchive worldStateArchive;
@Mock private ProtocolSchedule protocolSchedule;
@BeforeEach @BeforeEach
public void setUp() { public void setUp() {
@ -87,7 +90,10 @@ public class EthGetBlockByNumberTest {
latestHeader.getStateRoot(), latestHeader.getHash())) latestHeader.getStateRoot(), latestHeader.getHash()))
.thenReturn(Boolean.TRUE); .thenReturn(Boolean.TRUE);
blockchainQueries = spy(new BlockchainQueries(blockchain, worldStateArchive)); blockchainQueries =
spy(
new BlockchainQueries(
protocolSchedule, blockchain, worldStateArchive, MiningParameters.newDefault()));
method = new EthGetBlockByNumber(blockchainQueries, blockResult, synchronizer); method = new EthGetBlockByNumber(blockchainQueries, blockResult, synchronizer);
} }

@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
@ -82,7 +83,10 @@ public class EthGetBlockReceiptsTest {
blockchain.appendBlock(block, receipts); blockchain.appendBlock(block, receipts);
} }
blockchainQueries = spy(new BlockchainQueries(blockchain, worldStateArchive)); blockchainQueries =
spy(
new BlockchainQueries(
protocolSchedule, blockchain, worldStateArchive, MiningParameters.newDefault()));
protocolSchedule = mock(ProtocolSchedule.class); protocolSchedule = mock(ProtocolSchedule.class);
method = new EthGetBlockReceipts(blockchainQueries, protocolSchedule); method = new EthGetBlockReceipts(blockchainQueries, protocolSchedule);
} }

@ -39,6 +39,8 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.ChainHead; import org.hyperledger.besu.ethereum.chain.ChainHead;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.proof.WorldStateProof; import org.hyperledger.besu.ethereum.proof.WorldStateProof;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue; import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
@ -63,6 +65,7 @@ import org.mockito.quality.Strictness;
@MockitoSettings(strictness = Strictness.LENIENT) @MockitoSettings(strictness = Strictness.LENIENT)
class EthGetProofTest { class EthGetProofTest {
@Mock private Blockchain blockchain; @Mock private Blockchain blockchain;
@Mock private ProtocolSchedule protocolSchedule;
@Mock(answer = Answers.RETURNS_DEEP_STUBS) @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private WorldStateArchive archive; private WorldStateArchive archive;
@ -83,7 +86,10 @@ class EthGetProofTest {
@BeforeEach @BeforeEach
public void setUp() { public void setUp() {
blockchainQueries = spy(new BlockchainQueries(blockchain, archive)); blockchainQueries =
spy(
new BlockchainQueries(
protocolSchedule, blockchain, archive, MiningParameters.newDefault()));
when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
when(blockchainQueries.headBlockNumber()).thenReturn(14L); when(blockchainQueries.headBlockNumber()).thenReturn(14L);
when(blockchain.getChainHead()).thenReturn(chainHead); when(blockchain.getChainHead()).thenReturn(chainHead);

@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.PoWHasher; import org.hyperledger.besu.ethereum.mainnet.PoWHasher;
@ -189,7 +190,12 @@ public class EthGetTransactionReceiptTest {
private final Blockchain blockchain = mock(Blockchain.class); private final Blockchain blockchain = mock(Blockchain.class);
private final BlockchainQueries blockchainQueries = private final BlockchainQueries blockchainQueries =
spy(new BlockchainQueries(blockchain, mock(WorldStateArchive.class))); spy(
new BlockchainQueries(
protocolSchedule,
blockchain,
mock(WorldStateArchive.class),
MiningParameters.newDefault()));
private final EthGetTransactionReceipt ethGetTransactionReceipt = private final EthGetTransactionReceipt ethGetTransactionReceipt =
new EthGetTransactionReceipt(blockchainQueries, protocolSchedule); new EthGetTransactionReceipt(blockchainQueries, protocolSchedule);
private final String receiptString = private final String receiptString =

@ -32,8 +32,10 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions; import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage; import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
@ -47,6 +49,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Captor; import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.Spy; import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
@ -73,9 +76,16 @@ public class NewBlockHeadersSubscriptionServiceTest {
private final SubscriptionManager subscriptionManagerSpy = private final SubscriptionManager subscriptionManagerSpy =
new SubscriptionManager(new NoOpMetricsSystem()); new SubscriptionManager(new NoOpMetricsSystem());
@Mock ProtocolSchedule protocolSchedule;
@Spy @Spy
private final BlockchainQueries blockchainQueriesSpy = private final BlockchainQueries blockchainQueriesSpy =
Mockito.spy(new BlockchainQueries(blockchain, createInMemoryWorldStateArchive())); Mockito.spy(
new BlockchainQueries(
protocolSchedule,
blockchain,
createInMemoryWorldStateArchive(),
MiningParameters.newDefault()));
@BeforeEach @BeforeEach
public void before() { public void before() {

@ -28,8 +28,10 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.log.Log; import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.log.LogsBloomFilter; import org.hyperledger.besu.evm.log.LogsBloomFilter;
@ -63,6 +65,7 @@ public class BlockchainQueriesLogCacheTest {
private Hash testHash; private Hash testHash;
private static LogsBloomFilter testLogsBloomFilter; private static LogsBloomFilter testLogsBloomFilter;
@Mock ProtocolSchedule protocolSchedule;
@Mock MutableBlockchain blockchain; @Mock MutableBlockchain blockchain;
@Mock WorldStateArchive worldStateArchive; @Mock WorldStateArchive worldStateArchive;
@Mock EthScheduler scheduler; @Mock EthScheduler scheduler;
@ -127,7 +130,12 @@ public class BlockchainQueriesLogCacheTest {
when(blockchain.getBlockBody(any())).thenReturn(Optional.of(fakeBody)); when(blockchain.getBlockBody(any())).thenReturn(Optional.of(fakeBody));
blockchainQueries = blockchainQueries =
new BlockchainQueries( new BlockchainQueries(
blockchain, worldStateArchive, Optional.of(cacheDir), Optional.of(scheduler)); protocolSchedule,
blockchain,
worldStateArchive,
Optional.of(cacheDir),
Optional.of(scheduler),
MiningParameters.newDefault());
} }
/** /**

@ -28,9 +28,11 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions; import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.LogWithMetadata; import org.hyperledger.besu.ethereum.core.LogWithMetadata;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.worldstate.WorldState; import org.hyperledger.besu.evm.worldstate.WorldState;
@ -46,6 +48,7 @@ import java.util.stream.Collectors;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
public class BlockchainQueriesTest { public class BlockchainQueriesTest {
private BlockDataGenerator gen; private BlockDataGenerator gen;
@ -504,6 +507,9 @@ public class BlockchainQueriesTest {
assertThat(retrievedOmmerBlockHeader).isEqualTo(ommerBlockHeader); assertThat(retrievedOmmerBlockHeader).isEqualTo(ommerBlockHeader);
} }
@Test
public void getGasPriceLowerBound() {}
private void assertBlockMatchesResult( private void assertBlockMatchesResult(
final Block targetBlock, final BlockWithMetadata<TransactionWithMetadata, Hash> result) { final Block targetBlock, final BlockWithMetadata<TransactionWithMetadata, Hash> result) {
assertThat(result.getHeader()).isEqualTo(targetBlock.getHeader()); assertThat(result.getHeader()).isEqualTo(targetBlock.getHeader());
@ -587,17 +593,15 @@ public class BlockchainQueriesTest {
this.blockchain = blockchain; this.blockchain = blockchain;
this.blockData = blockData; this.blockData = blockData;
this.worldStateArchive = worldStateArchive; this.worldStateArchive = worldStateArchive;
this.blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive, scheduler); this.blockchainQueries =
new BlockchainQueries(
Mockito.mock(ProtocolSchedule.class),
blockchain,
worldStateArchive,
scheduler,
MiningParameters.newDefault());
} }
} }
private static class BlockData { private record BlockData(Block block, List<TransactionReceipt> receipts) {}
final Block block;
final List<TransactionReceipt> receipts;
private BlockData(final Block block, final List<TransactionReceipt> receipts) {
this.block = block;
this.receipts = receipts;
}
}
} }

@ -2,7 +2,7 @@
"request": "{ gasPrice maxPriorityFeePerGas }", "request": "{ gasPrice maxPriorityFeePerGas }",
"response": { "response": {
"data": { "data": {
"gasPrice": "0x1", "gasPrice": "0x2dbc88c1",
"maxPriorityFeePerGas": "0x3b9aca00" "maxPriorityFeePerGas": "0x3b9aca00"
} }
}, },

@ -181,7 +181,9 @@ public class RetestethContext {
blockchain = createInMemoryBlockchain(genesisState.getBlock()); blockchain = createInMemoryBlockchain(genesisState.getBlock());
protocolContext = new ProtocolContext(blockchain, worldStateArchive, null, badBlockManager); protocolContext = new ProtocolContext(blockchain, worldStateArchive, null, badBlockManager);
blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive, ethScheduler); blockchainQueries =
new BlockchainQueries(
protocolSchedule, blockchain, worldStateArchive, ethScheduler, miningParameters);
final String sealengine = JsonUtil.getString(genesisConfig, "sealengine", ""); final String sealengine = JsonUtil.getString(genesisConfig, "sealengine", "");
headerValidationMode = headerValidationMode =

Loading…
Cancel
Save