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

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

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

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

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

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

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

@ -130,10 +130,15 @@ public class QbftBesuControllerBuilder extends BftBesuControllerBuilder {
@Override
protected JsonRpcMethods createAdditionalJsonRpcMethodFactory(
final ProtocolContext protocolContext) {
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters) {
return new QbftJsonRpcMethods(
protocolContext, createReadOnlyValidatorProvider(protocolContext.getBlockchain()));
protocolContext,
protocolSchedule,
miningParameters,
createReadOnlyValidatorProvider(protocolContext.getBlockchain()));
}
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.chain.MutableBlockchain;
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;
@ -99,10 +101,13 @@ public class QbftBesuControllerBuilderTest extends AbstractBftBesuControllerBuil
@Test
public void missingTransactionValidatorProviderThrowsError() {
final ProtocolContext protocolContext = mock(ProtocolContext.class);
final ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class);
when(protocolContext.getBlockchain()).thenReturn(mock(MutableBlockchain.class));
assertThatThrownBy(
() -> bftBesuControllerBuilder.createAdditionalJsonRpcMethodFactory(protocolContext))
() ->
bftBesuControllerBuilder.createAdditionalJsonRpcMethodFactory(
protocolContext, protocolSchedule, MiningParameters.newDefault()))
.isInstanceOf(NullPointerException.class)
.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.core.Block;
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.evm.log.Log;
import org.hyperledger.besu.evm.worldstate.WorldView;
@ -74,7 +75,12 @@ class TraceServiceImplTest {
blockchainSetupUtil.importAllBlocks();
blockchain = blockchainSetupUtil.getBlockchain();
worldStateArchive = blockchainSetupUtil.getWorldArchive();
blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive);
blockchainQueries =
new BlockchainQueries(
blockchainSetupUtil.getProtocolSchedule(),
blockchain,
worldStateArchive,
MiningParameters.newDefault());
traceService =
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.query.BlockchainQueries;
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 java.util.Map;
@ -38,14 +40,23 @@ import java.util.Map;
/** The Clique json rpc methods. */
public class CliqueJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final ProtocolContext context;
private final ProtocolSchedule protocolSchedule;
private final MiningParameters miningParameters;
/**
* 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.protocolSchedule = protocolSchedule;
this.miningParameters = miningParameters;
}
@Override
@ -58,7 +69,7 @@ public class CliqueJsonRpcMethods extends ApiGroupJsonRpcMethods {
final MutableBlockchain blockchain = context.getBlockchain();
final WorldStateArchive worldStateArchive = context.getWorldStateArchive();
final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, worldStateArchive);
new BlockchainQueries(protocolSchedule, blockchain, worldStateArchive, miningParameters);
final ValidatorProvider validatorProvider =
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.query.BlockchainQueries;
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;
@ -39,14 +41,23 @@ import java.util.Map;
public class IbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final ProtocolContext context;
private final ProtocolSchedule protocolSchedule;
private final MiningParameters miningParameters;
/**
* 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.protocolSchedule = protocolSchedule;
this.miningParameters = miningParameters;
}
@Override
@ -58,7 +69,8 @@ public class IbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
protected Map<String, JsonRpcMethod> create() {
final MutableBlockchain blockchain = context.getBlockchain();
final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, context.getWorldStateArchive());
new BlockchainQueries(
protocolSchedule, blockchain, context.getWorldStateArchive(), miningParameters);
final BftContext bftContext = context.getConsensusContext(BftContext.class);
final BlockInterface blockInterface = bftContext.getBlockInterface();
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.methods.ApiGroupJsonRpcMethods;
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;
@ -36,17 +38,26 @@ public class QbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final ProtocolContext context;
private final ValidatorProvider readOnlyValidatorProvider;
private final ProtocolSchedule protocolSchedule;
private final MiningParameters miningParameters;
/**
* 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
*/
public QbftJsonRpcMethods(
final ProtocolContext context, final ValidatorProvider readOnlyValidatorProvider) {
final ProtocolContext context,
final ProtocolSchedule protocolSchedule,
final MiningParameters miningParameters,
final ValidatorProvider readOnlyValidatorProvider) {
this.context = context;
this.readOnlyValidatorProvider = readOnlyValidatorProvider;
this.protocolSchedule = protocolSchedule;
this.miningParameters = miningParameters;
}
@Override
@ -57,7 +68,11 @@ public class QbftJsonRpcMethods extends ApiGroupJsonRpcMethods {
@Override
protected Map<String, JsonRpcMethod> create() {
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 BlockInterface blockInterface = bftContext.getBlockInterface();
final ValidatorProvider validatorProvider = bftContext.getValidatorProvider();

@ -89,7 +89,9 @@ public class JsonRpcTestMethodsFactory {
final BlockImporter blockImporter = protocolSpec.getBlockImporter();
blockImporter.importBlock(context, block, HeaderValidationMode.FULL);
}
this.blockchainQueries = new BlockchainQueries(blockchain, stateArchive);
this.blockchainQueries =
new BlockchainQueries(
protocolSchedule, blockchain, stateArchive, MiningParameters.newDefault());
}
public JsonRpcTestMethodsFactory(
@ -101,7 +103,12 @@ public class JsonRpcTestMethodsFactory {
this.blockchain = blockchain;
this.stateArchive = stateArchive;
this.context = context;
this.blockchainQueries = new BlockchainQueries(blockchain, stateArchive);
this.blockchainQueries =
new BlockchainQueries(
importer.getProtocolSchedule(),
blockchain,
stateArchive,
MiningParameters.newDefault());
this.synchronizer = mock(Synchronizer.class);
}
@ -116,7 +123,12 @@ public class JsonRpcTestMethodsFactory {
this.stateArchive = stateArchive;
this.context = context;
this.synchronizer = synchronizer;
this.blockchainQueries = new BlockchainQueries(blockchain, stateArchive);
this.blockchainQueries =
new BlockchainQueries(
importer.getProtocolSchedule(),
blockchain,
stateArchive,
MiningParameters.newDefault());
}
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.Difficulty;
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.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
@ -123,7 +124,11 @@ public class EthGetFilterChangesIntegrationTest {
TransactionPoolConfiguration.DEFAULT);
transactionPool.setEnabled();
final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive());
new BlockchainQueries(
executionContext.getProtocolSchedule(),
blockchain,
protocolContext.getWorldStateArchive(),
MiningParameters.newDefault());
filterManager =
new FilterManagerBuilder()
.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.Difficulty;
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.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
@ -123,7 +124,11 @@ public class EthGetFilterChangesIntegrationTest {
TransactionPoolConfiguration.DEFAULT);
transactionPool.setEnabled();
final BlockchainQueries blockchainQueries =
new BlockchainQueries(blockchain, protocolContext.getWorldStateArchive());
new BlockchainQueries(
executionContext.getProtocolSchedule(),
blockchain,
protocolContext.getWorldStateArchive(),
MiningParameters.newDefault());
filterManager =
new FilterManagerBuilder()
.blockchainQueries(blockchainQueries)

@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.ethereum.api;
import java.util.function.LongSupplier;
import org.hyperledger.besu.datatypes.Wei;
import org.immutables.value.Value;
@ -36,14 +36,8 @@ public abstract class ApiConfiguration {
}
@Value.Default
@Value.Auxiliary
public LongSupplier getGasPriceMinSupplier() {
return () -> 1_000_000_000L; // 1 GWei
}
@Value.Default
public long getGasPriceMax() {
return 500_000_000_000L; // 500 GWei
public Wei getGasPriceMax() {
return Wei.of(500_000_000_000L); // 500 GWei
}
@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.LogsQuery;
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.Synchronizer;
import org.hyperledger.besu.ethereum.core.Transaction;
@ -117,17 +116,12 @@ public class GraphQLDataFetchers {
};
}
DataFetcher<Optional<Wei>> getGasPriceDataFetcher() {
DataFetcher<Wei> getGasPriceDataFetcher() {
return dataFetchingEnvironment -> {
final GraphQLContext graphQLContext = dataFetchingEnvironment.getGraphQlContext();
final BlockchainQueries blockchainQueries =
graphQLContext.get(GraphQLContextType.BLOCKCHAIN_QUERIES);
final MiningCoordinator miningCoordinator =
graphQLContext.get(GraphQLContextType.MINING_COORDINATOR);
return blockchainQueries
.gasPrice()
.map(Wei::of)
.or(() -> Optional.of(miningCoordinator.getMinTransactionGasPrice()));
return blockchainQueries.gasPrice();
};
}

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

@ -175,7 +175,7 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods {
new EthMining(miningCoordinator),
new EthCoinbase(miningCoordinator),
new EthProtocolVersion(supportedCapabilities),
new EthGasPrice(blockchainQueries, miningCoordinator, apiConfiguration),
new EthGasPrice(blockchainQueries, apiConfiguration),
new EthGetWork(miningCoordinator),
new EthSubmitWork(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.BlockHeader;
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.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
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.evm.account.Account;
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.units.bigints.UInt256;
import org.apache.tuweni.units.bigints.UInt256s;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BlockchainQueries {
private static final Logger LOG = LoggerFactory.getLogger(BlockchainQueries.class);
private final ProtocolSchedule protocolSchedule;
private final WorldStateArchive worldStateArchive;
private final Blockchain blockchain;
private final Optional<Path> cachePath;
private final Optional<TransactionLogBloomCacher> transactionLogBloomCacher;
private final Optional<EthScheduler> ethScheduler;
private final ApiConfiguration apiConfig;
private final MiningParameters miningParameters;
public BlockchainQueries(final Blockchain blockchain, final WorldStateArchive worldStateArchive) {
this(blockchain, worldStateArchive, Optional.empty(), Optional.empty());
public BlockchainQueries(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain,
final WorldStateArchive worldStateArchive,
final MiningParameters miningParameters) {
this(
protocolSchedule,
blockchain,
worldStateArchive,
Optional.empty(),
Optional.empty(),
miningParameters);
}
public BlockchainQueries(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain,
final WorldStateArchive worldStateArchive,
final EthScheduler scheduler) {
this(blockchain, worldStateArchive, Optional.empty(), Optional.ofNullable(scheduler));
final EthScheduler scheduler,
final MiningParameters miningParameters) {
this(
protocolSchedule,
blockchain,
worldStateArchive,
Optional.empty(),
Optional.ofNullable(scheduler),
miningParameters);
}
public BlockchainQueries(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain,
final WorldStateArchive worldStateArchive,
final Optional<Path> cachePath,
final Optional<EthScheduler> scheduler) {
final Optional<EthScheduler> scheduler,
final MiningParameters miningParameters) {
this(
protocolSchedule,
blockchain,
worldStateArchive,
cachePath,
scheduler,
ImmutableApiConfiguration.builder().build());
ImmutableApiConfiguration.builder().build(),
miningParameters);
}
public BlockchainQueries(
final ProtocolSchedule protocolSchedule,
final Blockchain blockchain,
final WorldStateArchive worldStateArchive,
final Optional<Path> cachePath,
final Optional<EthScheduler> scheduler,
final ApiConfiguration apiConfig) {
final ApiConfiguration apiConfig,
final MiningParameters miningParameters) {
this.protocolSchedule = protocolSchedule;
this.blockchain = blockchain;
this.worldStateArchive = worldStateArchive;
this.cachePath = cachePath;
@ -113,6 +144,7 @@ public class BlockchainQueries {
new TransactionLogBloomCacher(blockchain, cachePath.get(), scheduler.get()))
: Optional.empty();
this.apiConfig = apiConfig;
this.miningParameters = miningParameters;
}
public Blockchain getBlockchain() {
@ -943,10 +975,15 @@ public class BlockchainQueries {
return getAndMapWorldState(blockHash, mapper);
}
public Optional<Long> gasPrice() {
public Wei gasPrice() {
final long blockHeight = headBlockNumber();
final long[] gasCollection =
LongStream.range(Math.max(0, blockHeight - apiConfig.getGasPriceBlocks()), blockHeight)
final var chainHeadHeader = blockchain.getChainHeadHeader();
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(
l ->
blockchain
@ -957,20 +994,46 @@ public class BlockchainQueries {
() -> new IllegalStateException("Could not retrieve block #" + l)))
.flatMap(Collection::stream)
.filter(t -> t.getGasPrice().isPresent())
.mapToLong(t -> t.getGasPrice().get().toLong())
.map(t -> t.getGasPrice().get())
.sorted()
.toArray();
.toArray(Wei[]::new);
return (gasCollection == null || gasCollection.length == 0)
? Optional.empty()
: Optional.of(
Math.max(
apiConfig.getGasPriceMinSupplier().getAsLong(),
Math.min(
? gasPriceLowerBound(chainHeadHeader, nextBlockFeeMarket)
: UInt256s.max(
gasPriceLowerBound(chainHeadHeader, nextBlockFeeMarket),
UInt256s.min(
apiConfig.getGasPriceMax(),
gasCollection[
Math.min(
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() {
@ -1000,6 +1063,31 @@ public class BlockchainQueries {
(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(
final Address address,
final Hash blockHash,

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

@ -216,7 +216,7 @@ public class GraphQLHttpServiceTest {
@Test
public void query_get() throws Exception {
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);
try (final Response resp = client.newCall(buildGetRequest("?query={gasPrice}")).execute()) {

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

@ -15,7 +15,9 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
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.JsonRpcSuccessResponse;
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.core.Block;
import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader;
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.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 java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.Mock;
import org.mockito.internal.verification.VerificationModeFactory;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class EthGasPriceTest {
@Mock private PoWMiningCoordinator miningCoordinator;
private static final String JSON_RPC_VERSION = "2.0";
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;
private EthGasPrice method;
private final String JSON_RPC_VERSION = "2.0";
private final String ETH_METHOD = "eth_gasPrice";
private MiningParameters miningParameters;
@BeforeEach
public void setUp() {
ApiConfiguration apiConfig = createDefaultApiConfiguration();
miningParameters =
MiningParameters.newDefault().setMinTransactionGasPrice(DEFAULT_MIN_GAS_PRICE);
method = createEthGasPriceMethod(apiConfig);
}
@ -73,41 +94,57 @@ public class EthGasPriceTest {
@Test
public void shouldReturnMinValueWhenNoTransactionsExist() {
final JsonRpcRequestContext request = requestWithParams();
final String expectedWei = "0x4d2";
final String expectedWei = "0x4d2"; // minGasPrice > nextBlockBaseFee
miningParameters.setMinTransactionGasPrice(Wei.fromHexString(expectedWei));
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei);
when(miningCoordinator.getMinTransactionGasPrice()).thenReturn(Wei.of(1234));
when(blockchain.getChainHeadBlockNumber()).thenReturn(1000L);
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(invocation -> createEmptyBlock(invocation.getArgument(0, Long.class)));
mockBaseFeeMarket();
mockBlockchain(1000, 0);
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(miningCoordinator).getMinTransactionGasPrice();
verifyNoMoreInteractions(miningCoordinator);
verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(100)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain);
}
@Test
public void shouldReturnMedianWhenTransactionsExist() {
public void shouldReturnBaseFeeAsMinValueOnGenesis() {
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 =
new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei);
when(blockchain.getChainHeadBlockNumber()).thenReturn(1000L);
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(invocation -> createFakeBlock(invocation.getArgument(0, Long.class)));
mockBaseFeeMarket();
mockBlockchain(0, 0);
final JsonRpcResponse actualResponse = method.response(request);
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, VerificationModeFactory.times(100)).getBlockByNumber(anyLong());
@ -117,21 +154,19 @@ public class EthGasPriceTest {
@Test
public void shortChainQueriesAllBlocks() {
final JsonRpcRequestContext request = requestWithParams();
final String expectedWei = "0x2625a00";
final String expectedWei = "0x64190"; // 410 kwei
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(request.getRequest().getId(), expectedWei);
when(blockchain.getChainHeadBlockNumber()).thenReturn(80L);
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(invocation -> createFakeBlock(invocation.getArgument(0, Long.class)));
mockBaseFeeMarket();
mockBlockchain(80L, 1);
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verifyNoMoreInteractions(miningCoordinator);
verify(blockchain).getChainHeadBlockNumber();
verify(blockchain, VerificationModeFactory.times(80)).getBlockByNumber(anyLong());
verify(blockchain, VerificationModeFactory.times(81)).getBlockByNumber(anyLong());
verifyNoMoreInteractions(blockchain);
}
@ -141,9 +176,9 @@ public class EthGasPriceTest {
*/
@Test
public void shouldReturnLimitedPriceWhenLowerBoundIsPresent() {
long gasPrice = 5000000;
long lowerBoundGasPrice = gasPrice + 1;
verifyGasPriceLimit(lowerBoundGasPrice, null, lowerBoundGasPrice);
long expectedGasPrice = 31_841 * 2;
long lowerBoundCoefficient = 200;
verifyGasPriceLimit(lowerBoundCoefficient, null, expectedGasPrice);
}
/**
@ -152,9 +187,9 @@ public class EthGasPriceTest {
*/
@Test
public void shouldReturnLimitedPriceWhenUpperBoundIsPresent() {
long gasPrice = 5000000;
long upperBoundGasPrice = gasPrice - 1;
verifyGasPriceLimit(null, upperBoundGasPrice, upperBoundGasPrice);
long expectedGasPrice = (long) (31_841 * 1.5);
long upperBoundCoefficient = 150;
verifyGasPriceLimit(null, upperBoundCoefficient, expectedGasPrice);
}
/**
@ -163,25 +198,83 @@ public class EthGasPriceTest {
*/
@Test
public void shouldReturnActualGasPriceWhenWithinBoundRange() {
long gasPrice = 5000000;
long lowerBoundGasPrice = gasPrice - 1;
long upperBoundGasPrice = gasPrice + 1;
verifyGasPriceLimit(lowerBoundGasPrice, upperBoundGasPrice, gasPrice);
long gasPrice = 60_000;
long lowerBoundCoefficient = 120;
long upperBoundCoefficient = 200;
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.
*
* @param lowerBound The lower bound of the gas price.
* @param upperBound The upper bound of the gas price.
* @param lowerBoundCoefficient The lower bound of the gas price.
* @param upperBoundCoefficient The upper bound of the gas price.
* @param expectedGasPrice The expected gas price.
*/
private void verifyGasPriceLimit(
final Long lowerBound, final Long upperBound, final long expectedGasPrice) {
when(miningCoordinator.getMinTransactionGasPrice()).thenReturn(Wei.of(100));
final Long lowerBoundCoefficient,
final Long upperBoundCoefficient,
final long expectedGasPrice) {
miningParameters.setMinTransactionGasPrice(Wei.of(100));
mockBaseFeeMarket();
var apiConfig =
createApiConfiguration(Optional.ofNullable(lowerBound), Optional.ofNullable(upperBound));
createApiConfiguration(
Optional.ofNullable(lowerBoundCoefficient), Optional.ofNullable(upperBoundCoefficient));
method = createEthGasPriceMethod(apiConfig);
final JsonRpcRequestContext request = requestWithParams();
@ -189,17 +282,73 @@ public class EthGasPriceTest {
new JsonRpcSuccessResponse(
request.getRequest().getId(), Wei.of(expectedGasPrice).toShortHexString());
when(blockchain.getChainHeadBlockNumber()).thenReturn(10L);
when(blockchain.getBlockByNumber(anyLong()))
.thenAnswer(invocation -> createFakeBlock(invocation.getArgument(0, Long.class)));
final var chainHeadBlockNumber = 10L;
mockBlockchain(chainHeadBlockNumber, 1);
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
}
private Object createFakeBlock(final Long height) {
return Optional.of(
new Block(
private void mockBaseFeeMarket() {
mockFeeMarket(new LondonFeeMarket(0));
}
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(
Hash.EMPTY,
Hash.EMPTY_TRIE_HASH,
@ -210,11 +359,11 @@ public class EthGasPriceTest {
LogsBloomFilter.builder().build(),
Difficulty.ONE,
height,
0,
0,
gasLimit,
gasUsed,
0,
Bytes.EMPTY,
Wei.ZERO,
baseFee,
Hash.EMPTY,
0,
null,
@ -224,43 +373,17 @@ public class EthGasPriceTest {
null,
null),
new BlockBody(
List.of(
IntStream.range(0, txsNum)
.mapToObj(
i ->
new Transaction.Builder()
.nonce(0)
.gasPrice(Wei.of(height * 1000000L))
.gasLimit(0)
.nonce(i)
.gasPrice(Wei.of(height * 10_000L))
.gasLimit(gasUsed)
.value(Wei.ZERO)
.build()),
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())));
.build())
.toList(),
List.of()));
}
private JsonRpcRequestContext requestWithParams(final Object... params) {
@ -272,16 +395,15 @@ public class EthGasPriceTest {
}
private ApiConfiguration createApiConfiguration(
final Optional<Long> lowerBound, final Optional<Long> upperBound) {
ImmutableApiConfiguration.Builder builder =
ImmutableApiConfiguration.builder().gasPriceMinSupplier(() -> 100);
final Optional<Long> lowerBoundCoefficient, final Optional<Long> upperBoundCoefficient) {
ImmutableApiConfiguration.Builder builder = ImmutableApiConfiguration.builder();
lowerBound.ifPresent(
lowerBoundCoefficient.ifPresent(
value ->
builder
.isGasAndPriorityFeeLimitingEnabled(true)
.lowerBoundGasAndPriorityFeeCoefficient(value));
upperBound.ifPresent(
upperBoundCoefficient.ifPresent(
value ->
builder
.isGasAndPriorityFeeLimitingEnabled(true)
@ -292,8 +414,14 @@ public class EthGasPriceTest {
private EthGasPrice createEthGasPriceMethod(final ApiConfiguration apiConfig) {
return new EthGasPrice(
new BlockchainQueries(blockchain, null, Optional.empty(), Optional.empty(), apiConfig),
miningCoordinator,
new BlockchainQueries(
protocolSchedule,
blockchain,
null,
Optional.empty(),
Optional.empty(),
apiConfig,
miningParameters),
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.BlockDataGenerator;
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.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.List;
@ -66,6 +68,7 @@ public class EthGetBlockByNumberTest {
private EthGetBlockByNumber method;
@Mock private Synchronizer synchronizer;
@Mock private WorldStateArchive worldStateArchive;
@Mock private ProtocolSchedule protocolSchedule;
@BeforeEach
public void setUp() {
@ -87,7 +90,10 @@ public class EthGetBlockByNumberTest {
latestHeader.getStateRoot(), latestHeader.getHash()))
.thenReturn(Boolean.TRUE);
blockchainQueries = spy(new BlockchainQueries(blockchain, worldStateArchive));
blockchainQueries =
spy(
new BlockchainQueries(
protocolSchedule, blockchain, worldStateArchive, MiningParameters.newDefault()));
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.core.Block;
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.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
@ -82,7 +83,10 @@ public class EthGetBlockReceiptsTest {
blockchain.appendBlock(block, receipts);
}
blockchainQueries = spy(new BlockchainQueries(blockchain, worldStateArchive));
blockchainQueries =
spy(
new BlockchainQueries(
protocolSchedule, blockchain, worldStateArchive, MiningParameters.newDefault()));
protocolSchedule = mock(ProtocolSchedule.class);
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.ChainHead;
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.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
@ -63,6 +65,7 @@ import org.mockito.quality.Strictness;
@MockitoSettings(strictness = Strictness.LENIENT)
class EthGetProofTest {
@Mock private Blockchain blockchain;
@Mock private ProtocolSchedule protocolSchedule;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private WorldStateArchive archive;
@ -83,7 +86,10 @@ class EthGetProofTest {
@BeforeEach
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.headBlockNumber()).thenReturn(14L);
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.BlockHeader;
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.TransactionReceipt;
import org.hyperledger.besu.ethereum.mainnet.PoWHasher;
@ -189,7 +190,12 @@ public class EthGetTransactionReceiptTest {
private final Blockchain blockchain = mock(Blockchain.class);
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 =
new EthGetTransactionReceipt(blockchainQueries, protocolSchedule);
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.BlockDataGenerator;
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.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.ethereum.storage.keyvalue.VariablesKeyValueStorage;
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.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
@ -73,9 +76,16 @@ public class NewBlockHeadersSubscriptionServiceTest {
private final SubscriptionManager subscriptionManagerSpy =
new SubscriptionManager(new NoOpMetricsSystem());
@Mock ProtocolSchedule protocolSchedule;
@Spy
private final BlockchainQueries blockchainQueriesSpy =
Mockito.spy(new BlockchainQueries(blockchain, createInMemoryWorldStateArchive()));
Mockito.spy(
new BlockchainQueries(
protocolSchedule,
blockchain,
createInMemoryWorldStateArchive(),
MiningParameters.newDefault()));
@BeforeEach
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.BlockHeader;
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.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.log.LogsBloomFilter;
@ -63,6 +65,7 @@ public class BlockchainQueriesLogCacheTest {
private Hash testHash;
private static LogsBloomFilter testLogsBloomFilter;
@Mock ProtocolSchedule protocolSchedule;
@Mock MutableBlockchain blockchain;
@Mock WorldStateArchive worldStateArchive;
@Mock EthScheduler scheduler;
@ -127,7 +130,12 @@ public class BlockchainQueriesLogCacheTest {
when(blockchain.getBlockBody(any())).thenReturn(Optional.of(fakeBody));
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.BlockHeader;
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.TransactionReceipt;
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.evm.account.Account;
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.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
public class BlockchainQueriesTest {
private BlockDataGenerator gen;
@ -504,6 +507,9 @@ public class BlockchainQueriesTest {
assertThat(retrievedOmmerBlockHeader).isEqualTo(ommerBlockHeader);
}
@Test
public void getGasPriceLowerBound() {}
private void assertBlockMatchesResult(
final Block targetBlock, final BlockWithMetadata<TransactionWithMetadata, Hash> result) {
assertThat(result.getHeader()).isEqualTo(targetBlock.getHeader());
@ -587,17 +593,15 @@ public class BlockchainQueriesTest {
this.blockchain = blockchain;
this.blockData = blockData;
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 {
final Block block;
final List<TransactionReceipt> receipts;
private BlockData(final Block block, final List<TransactionReceipt> receipts) {
this.block = block;
this.receipts = receipts;
}
}
private record BlockData(Block block, List<TransactionReceipt> receipts) {}
}

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

@ -181,7 +181,9 @@ public class RetestethContext {
blockchain = createInMemoryBlockchain(genesisState.getBlock());
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", "");
headerValidationMode =

Loading…
Cancel
Save