use of org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket in project besu by hyperledger.
the class EthFeeHistory method response.
@Override
public JsonRpcResponse response(final JsonRpcRequestContext request) {
final Object requestId = request.getRequest().getId();
final long blockCount = Optional.of(request.getRequiredParameter(0, UnsignedLongParameter.class)).map(UnsignedLongParameter::getValue).orElse(0L);
if (blockCount < 1 || blockCount > 1024) {
return new JsonRpcErrorResponse(requestId, JsonRpcError.INVALID_PARAMS);
}
final BlockParameter highestBlock = request.getRequiredParameter(1, BlockParameter.class);
final Optional<List<Double>> maybeRewardPercentiles = request.getOptionalParameter(2, Double[].class).map(Arrays::asList);
final long chainHeadBlockNumber = blockchain.getChainHeadBlockNumber();
final long resolvedHighestBlockNumber = highestBlock.getNumber().orElse(chainHeadBlockNumber);
if (resolvedHighestBlockNumber > chainHeadBlockNumber) {
return new JsonRpcErrorResponse(requestId, JsonRpcError.INVALID_PARAMS);
}
final long oldestBlock = Math.max(0, resolvedHighestBlockNumber - (blockCount - 1));
final List<BlockHeader> blockHeaders = LongStream.range(oldestBlock, oldestBlock + blockCount).mapToObj(blockchain::getBlockHeader).flatMap(Optional::stream).collect(toUnmodifiableList());
// we return the base fees for the blocks requested and 1 more because we can always compute it
final List<Wei> explicitlyRequestedBaseFees = blockHeaders.stream().map(blockHeader -> blockHeader.getBaseFee().orElse(Wei.ZERO)).collect(toUnmodifiableList());
final long nextBlockNumber = resolvedHighestBlockNumber + 1;
final Wei nextBaseFee = blockchain.getBlockHeader(nextBlockNumber).map(blockHeader -> blockHeader.getBaseFee().orElse(Wei.ZERO)).orElseGet(() -> Optional.of(protocolSchedule.getByBlockNumber(nextBlockNumber).getFeeMarket()).filter(FeeMarket::implementsBaseFee).map(BaseFeeMarket.class::cast).map(feeMarket -> {
final BlockHeader lastBlockHeader = blockHeaders.get(blockHeaders.size() - 1);
return feeMarket.computeBaseFee(nextBlockNumber, explicitlyRequestedBaseFees.get(explicitlyRequestedBaseFees.size() - 1), lastBlockHeader.getGasUsed(), feeMarket.targetGasUsed(lastBlockHeader));
}).orElse(Wei.ZERO));
final List<Double> gasUsedRatios = blockHeaders.stream().map(blockHeader -> blockHeader.getGasUsed() / (double) blockHeader.getGasLimit()).collect(toUnmodifiableList());
final Optional<List<List<Wei>>> maybeRewards = maybeRewardPercentiles.map(rewardPercentiles -> LongStream.range(oldestBlock, oldestBlock + blockCount).mapToObj(blockchain::getBlockByNumber).flatMap(Optional::stream).map(block -> computeRewards(rewardPercentiles.stream().sorted().collect(toUnmodifiableList()), block)).collect(toUnmodifiableList()));
return new JsonRpcSuccessResponse(requestId, FeeHistory.FeeHistoryResult.from(ImmutableFeeHistory.builder().oldestBlock(oldestBlock).baseFeePerGas(Stream.concat(explicitlyRequestedBaseFees.stream(), Stream.of(nextBaseFee)).collect(toUnmodifiableList())).gasUsedRatio(gasUsedRatios).reward(maybeRewards).build()));
}
use of org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket in project besu by hyperledger.
the class AbstractBlockCreator method createPendingBlockHeader.
private ProcessableBlockHeader createPendingBlockHeader(final long timestamp, final Optional<Bytes32> maybePrevRandao) {
final long newBlockNumber = parentHeader.getNumber() + 1;
long gasLimit = protocolSpec.getGasLimitCalculator().nextGasLimit(parentHeader.getGasLimit(), targetGasLimitSupplier.get().orElse(parentHeader.getGasLimit()), newBlockNumber);
final DifficultyCalculator difficultyCalculator = protocolSpec.getDifficultyCalculator();
final BigInteger difficulty = difficultyCalculator.nextDifficulty(timestamp, parentHeader, protocolContext);
final Wei baseFee = Optional.of(protocolSpec.getFeeMarket()).filter(FeeMarket::implementsBaseFee).map(BaseFeeMarket.class::cast).map(feeMarket -> feeMarket.computeBaseFee(newBlockNumber, parentHeader.getBaseFee().orElse(Wei.ZERO), parentHeader.getGasUsed(), feeMarket.targetGasUsed(parentHeader))).orElse(null);
final Bytes32 prevRandao = maybePrevRandao.orElse(null);
return BlockHeaderBuilder.create().parentHash(parentHeader.getHash()).coinbase(coinbase).difficulty(Difficulty.of(difficulty)).number(newBlockNumber).gasLimit(gasLimit).timestamp(timestamp).baseFee(baseFee).prevRandao(prevRandao).buildProcessableBlockHeader();
}
use of org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket in project besu by hyperledger.
the class BftBlockCreatorTest method createdBlockPassesValidationRulesAndHasAppropriateHashAndMixHash.
@Test
public void createdBlockPassesValidationRulesAndHasAppropriateHashAndMixHash() {
// Construct a parent block.
final BlockHeaderTestFixture blockHeaderBuilder = new BlockHeaderTestFixture();
// required to pass validation rule checks.
blockHeaderBuilder.gasLimit(5000);
final BlockHeader parentHeader = blockHeaderBuilder.buildHeader();
final Optional<BlockHeader> optionalHeader = Optional.of(parentHeader);
// Construct a block chain and world state
final MutableBlockchain blockchain = mock(MutableBlockchain.class);
when(blockchain.getChainHeadHash()).thenReturn(parentHeader.getHash());
when(blockchain.getBlockHeader(any())).thenReturn(optionalHeader);
final BlockHeader blockHeader = mock(BlockHeader.class);
when(blockHeader.getBaseFee()).thenReturn(Optional.empty());
when(blockchain.getChainHeadHeader()).thenReturn(blockHeader);
final List<Address> initialValidatorList = Lists.newArrayList();
for (int i = 0; i < 4; i++) {
initialValidatorList.add(AddressHelpers.ofValue(i));
}
final IbftExtraDataCodec bftExtraDataEncoder = new IbftExtraDataCodec();
final BaseBftProtocolSchedule bftProtocolSchedule = new BaseBftProtocolSchedule() {
@Override
public BlockHeaderValidator.Builder createBlockHeaderRuleset(final BftConfigOptions config, final FeeMarket feeMarket) {
return IbftBlockHeaderValidationRulesetFactory.blockHeaderValidator(5, Optional.empty());
}
};
final GenesisConfigOptions configOptions = GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}").getConfigOptions();
final ForksSchedule<BftConfigOptions> forksSchedule = new ForksSchedule<>(List.of(new ForkSpec<>(0, configOptions.getBftConfigOptions())));
final ProtocolSchedule protocolSchedule = bftProtocolSchedule.createProtocolSchedule(configOptions, forksSchedule, PrivacyParameters.DEFAULT, false, bftExtraDataEncoder, EvmConfiguration.DEFAULT);
final ProtocolContext protContext = new ProtocolContext(blockchain, createInMemoryWorldStateArchive(), setupContextWithBftExtraDataEncoder(initialValidatorList, bftExtraDataEncoder));
final GasPricePendingTransactionsSorter pendingTransactions = new GasPricePendingTransactionsSorter(TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS, 1, TestClock.fixed(), metricsSystem, blockchain::getChainHeadHeader, TransactionPoolConfiguration.DEFAULT_PRICE_BUMP);
final BftBlockCreator blockCreator = new BftBlockCreator(forksSchedule, initialValidatorList.get(0), () -> Optional.of(10_000_000L), parent -> bftExtraDataEncoder.encode(new BftExtraData(Bytes.wrap(new byte[32]), Collections.emptyList(), Optional.empty(), 0, initialValidatorList)), pendingTransactions, protContext, protocolSchedule, Wei.ZERO, 0.8, parentHeader, bftExtraDataEncoder);
final int secondsBetweenBlocks = 1;
final Block block = blockCreator.createBlock(parentHeader.getTimestamp() + 1);
final BlockHeaderValidator rules = IbftBlockHeaderValidationRulesetFactory.blockHeaderValidator(secondsBetweenBlocks, Optional.empty()).build();
// NOTE: The header will not contain commit seals, so can only do light validation on header.
final boolean validationResult = rules.validateHeader(block.getHeader(), parentHeader, protContext, HeaderValidationMode.LIGHT);
assertThat(validationResult).isTrue();
final BlockHeader header = block.getHeader();
final BftExtraData extraData = bftExtraDataEncoder.decode(header);
assertThat(block.getHash()).isEqualTo(new BftBlockHashing(bftExtraDataEncoder).calculateDataHashForCommittedSeal(header, extraData));
}
use of org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket in project besu by hyperledger.
the class MainnetProtocolSpecs method londonDefinition.
static ProtocolSpecBuilder londonDefinition(final Optional<BigInteger> chainId, final OptionalInt configContractSizeLimit, final OptionalInt configStackSizeLimit, final boolean enableRevertReason, final GenesisConfigOptions genesisConfigOptions, final boolean quorumCompatibilityMode, final EvmConfiguration evmConfiguration) {
final int contractSizeLimit = configContractSizeLimit.orElse(SPURIOUS_DRAGON_CONTRACT_SIZE_LIMIT);
final int stackSizeLimit = configStackSizeLimit.orElse(MessageFrame.DEFAULT_MAX_STACK_SIZE);
final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(Long.MAX_VALUE);
final BaseFeeMarket londonFeeMarket = FeeMarket.london(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas());
return berlinDefinition(chainId, configContractSizeLimit, configStackSizeLimit, enableRevertReason, quorumCompatibilityMode, evmConfiguration).gasCalculator(LondonGasCalculator::new).gasLimitCalculator(new LondonTargetingGasLimitCalculator(londonForkBlockNumber, londonFeeMarket)).transactionValidatorBuilder(gasCalculator -> new MainnetTransactionValidator(gasCalculator, londonFeeMarket, true, chainId, Set.of(TransactionType.FRONTIER, TransactionType.ACCESS_LIST, TransactionType.EIP1559), quorumCompatibilityMode)).transactionProcessorBuilder((gasCalculator, transactionValidator, contractCreationProcessor, messageCallProcessor) -> new MainnetTransactionProcessor(gasCalculator, transactionValidator, contractCreationProcessor, messageCallProcessor, true, stackSizeLimit, londonFeeMarket, CoinbaseFeePriceCalculator.eip1559())).contractCreationProcessorBuilder((gasCalculator, evm) -> new ContractCreationProcessor(gasCalculator, evm, true, List.of(MaxCodeSizeRule.of(contractSizeLimit), PrefixCodeRule.of()), 1, SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES)).evmBuilder((gasCalculator, jdCacheConfig) -> MainnetEVMs.london(gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)).feeMarket(londonFeeMarket).difficultyCalculator(MainnetDifficultyCalculators.LONDON).blockHeaderValidatorBuilder(feeMarket -> MainnetBlockHeaderValidator.createBaseFeeMarketValidator(londonFeeMarket)).ommerHeaderValidatorBuilder(feeMarket -> MainnetBlockHeaderValidator.createBaseFeeMarketOmmerValidator(londonFeeMarket)).blockBodyValidatorBuilder(BaseFeeBlockBodyValidator::new).name(LONDON_FORK_NAME);
}
use of org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket in project besu by hyperledger.
the class TransactionPool method validateTransaction.
private ValidationResult<TransactionInvalidReason> validateTransaction(final Transaction transaction, final boolean isLocal) {
final BlockHeader chainHeadBlockHeader = getChainHeadBlockHeader();
final FeeMarket feeMarket = protocolSchedule.getByBlockNumber(chainHeadBlockHeader.getNumber()).getFeeMarket();
// Check whether it's a GoQuorum transaction
boolean goQuorumCompatibilityMode = getTransactionValidator().getGoQuorumCompatibilityMode();
if (transaction.isGoQuorumPrivateTransaction(goQuorumCompatibilityMode)) {
final Optional<Wei> weiValue = ofNullable(transaction.getValue());
if (weiValue.isPresent() && !weiValue.get().isZero()) {
return ValidationResult.invalid(TransactionInvalidReason.ETHER_VALUE_NOT_SUPPORTED);
}
}
// executable:
if ((!effectiveGasPriceIsAboveConfiguredMinGasPrice(transaction) && !miningParameters.isMiningEnabled()) || (!feeMarket.satisfiesFloorTxCost(transaction))) {
return ValidationResult.invalid(TransactionInvalidReason.GAS_PRICE_TOO_LOW);
}
final ValidationResult<TransactionInvalidReason> basicValidationResult = getTransactionValidator().validate(transaction, chainHeadBlockHeader.getBaseFee(), TransactionValidationParams.transactionPool());
if (!basicValidationResult.isValid()) {
return basicValidationResult;
}
if (isLocal && strictReplayProtectionShouldBeEnforceLocally(chainHeadBlockHeader) && transaction.getChainId().isEmpty()) {
// Strict replay protection is enabled but the tx is not replay-protected
return ValidationResult.invalid(TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURE_REQUIRED);
}
if (transaction.getGasLimit() > chainHeadBlockHeader.getGasLimit()) {
return ValidationResult.invalid(TransactionInvalidReason.EXCEEDS_BLOCK_GAS_LIMIT, String.format("Transaction gas limit of %s exceeds block gas limit of %s", transaction.getGasLimit(), chainHeadBlockHeader.getGasLimit()));
}
if (transaction.getType().equals(TransactionType.EIP1559) && !feeMarket.implementsBaseFee()) {
return ValidationResult.invalid(TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, "EIP-1559 transaction are not allowed yet");
}
return protocolContext.getWorldStateArchive().getMutable(chainHeadBlockHeader.getStateRoot(), chainHeadBlockHeader.getHash(), false).map(worldState -> {
final Account senderAccount = worldState.get(transaction.getSender());
return getTransactionValidator().validateForSender(transaction, senderAccount, TransactionValidationParams.transactionPool());
}).orElseGet(() -> ValidationResult.invalid(CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE));
}
Aggregations