Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Fabio Di Fabio
2023-08-23 12:34:45 +02:00
144 changed files with 1684 additions and 986 deletions

View File

@@ -1,37 +1,39 @@
# Changelog
## 23.7.1
## 23.7.2
### Breaking Changes
- Add ABI-decoded revert reason to `eth_call` and `eth_estimateGas` responses [#5705](https://github.com/hyperledger/besu/issues/5705)
### Additions and Improvements
- Add missing methods to the `Transaction` interface [#5732](https://github.com/hyperledger/besu/pull/5732)
- Added `benchmark` subcommand to `evmtool` [#5754](https://github.com/hyperledger/besu/issues/5754)
- JSON output is now compact by default. This can be overridden by the new `--json-pretty-print-enabled` CLI option. [#5766](https://github.com/hyperledger/besu/pull/5766)
### Bug Fixes
- Make smart contract permissioning features work with london fork [#5727](https://github.com/hyperledger/besu/pull/5727)
- Add type to PendingTransactionDetail, fix eth_subscribe [#5729](https://github.com/hyperledger/besu/pull/5729)
- EvmTool "run" mode did not reflect contracts created within the transaction. [#5755](https://github.com/hyperledger/besu/pull/5755)
- Update native libraries that have JPMS friendly module names [#5749](https://github.com/hyperledger/besu/pull/5749)
- Fixing snapsync issue with forest during the heal step [#5776](https://github.com/hyperledger/besu/pull/5776)
### Download Links
## 23.7.0
## 23.7.1
### Breaking Changes
- Removed deprecated GoQuorum permissioning interop [#5607](https://github.com/hyperledger/besu/pull/5607)
- Removed support for version 0 of the database as it is no longer used by any active node. [#5698](https://github.com/hyperledger/besu/pull/5698)
### Additions and Improvements
- `evmtool` launcher binaries now ship as part of the standard distribution. [#5701](https://github.com/hyperledger/besu/pull/5701)
- `evmtool` launcher binaries now ship as part of the standard distribution. [#5701](https://github.com/hyperledger/besu/pull/5701)
- EvmTool now executes the `execution-spec-tests` via the `t8n` and `b11r`. See the [README](ethereum/evmtool/README.md) in EvmTool for more instructions.
- Improve lifecycle management of the transaction pool [#5634](https://github.com/hyperledger/besu/pull/5634)
- Add extension points in AbstractCreateOperation for EVM libraries to react to contract creations [#5656](https://github.com/hyperledger/besu/pull/5656)
- Update to Tuweni 2.4.2. [#5684](https://github.com/hyperledger/besu/pull/5684)
- Decouple data field from Enum JsonRpcError by creating new enum holder RpcErrorType[#5629](https://github.com/hyperledger/besu/pull/5629)
- Update to bouncycastle 1.75 [#5675](https://github.com/hyperledger/besu/pull/5675)
- Update to bouncycastle 1.75 [#5675](https://github.com/hyperledger/besu/pull/5675)
- Extend OperationTracer with new methods [#5662](https://github.com/hyperledger/besu/pull/5662)
- Eip 6780 selfdestruct [#5430](https://github.com/hyperledger/besu/pull/5430)
- Add new debug_getRawTransaction to the DEBUG engine [#5635](https://github.com/hyperledger/besu/pull/5635)
@@ -41,11 +43,18 @@
- Align the implementation of Eth/68 `NewPooledTransactionHashes` to other clients, using unsigned int for encoding size. [#5640](https://github.com/hyperledger/besu/pull/5640)
- Failure at startup when enabling layered txpool before initial sync done [#5636](https://github.com/hyperledger/besu/issues/5636)
- Remove miner-related option warnings if the change isn't using Ethash consensus algorithm [#5669](https://github.com/hyperledger/besu/pull/5669)
- Fix for pending transactions reference leak [#5693](https://github.com/hyperledger/besu/pull/5693)
- Fix for pending transactions reference leak [#5693](https://github.com/hyperledger/besu/pull/5693)
- Address a performance regression observed in import testing [#5734](https://github.com/hyperledger/besu/pull/5734)
- Update native libraries that have JPMS friendly module names [#5749](https://github.com/hyperledger/besu/pull/5749)
### Download Links
https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.7.0/besu-23.7.0.tar.gz / sha256: 083efc26e22fa20bd04c9a6311e50dd93092f001e5d639d023fd7a61173616dd
https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.7.0/besu-23.7.0.zip / sha256: 019a5ce3b7b94e76a6bac08bc23e3fec9880e235928b3c5378541927690046d7
https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.7.1/besu-23.7.1.tar.gz / sha256: 85dce66c2dbd21b4e5d3310770434dd373018a046b78d5037f6d4955256793cd
https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.7.1/besu-23.7.1.zip / sha256: dfac11b2d6d9e8076ab2f86324d48d563badf76fd2a4aadc4469a97aef374ef5
## 23.7.0
- Was not released (failed burn-in test)
## 23.4.4

View File

@@ -57,6 +57,7 @@ public class BlockUtils {
null,
null,
null,
null,
blockHeaderFunctions);
}
}

View File

@@ -4073,6 +4073,6 @@
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas": null,
"dataGasUsed": null,
"excessDataGas": null
"blobGasUsed": null,
"excessBlobGas": null
}

View File

@@ -20,8 +20,8 @@
"blockHash": "0x50c02dc77082fe2060b600cba0e6ce5a491af6d5323b2a90a7bc6359dd18e97b",
"transactions": [],
"withdrawals": [],
"dataGasUsed": null,
"excessDataGas": null
"blobGasUsed": null,
"excessBlobGas": null
}
]
},

View File

@@ -20,8 +20,8 @@
"blockHash": "0x50c02dc77082fe2060b600cba0e6ce5a491af6d5323b2a90a7bc6359dd18e97b",
"transactions": [],
"withdrawals": [],
"dataGasUsed": null,
"excessDataGas": null
"blobGasUsed": null,
"excessBlobGas": null
},
null
]

View File

@@ -22,11 +22,11 @@
"timestamp": "0x1236",
"extraData": "0x",
"baseFeePerGas": "0x2da282a8",
"excessDataGas": "0x0",
"excessBlobGas": "0x0",
"transactions": [],
"withdrawals": [],
"blockNumber": "0x2",
"dataGasUsed": "0x0",
"blobGasUsed": "0x0",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"blockHash": "0xc33d43425366d661ef70df12faf8ccd66ed7d0c6718d16d14868ba49e6786927"
},

View File

@@ -20,8 +20,8 @@
"blockHash": "0xc33d43425366d661ef70df12faf8ccd66ed7d0c6718d16d14868ba49e6786927",
"transactions": [],
"withdrawals": [],
"dataGasUsed": "0x0",
"excessDataGas": "0x0"
"blobGasUsed": "0x0",
"excessBlobGas": "0x0"
},
[]
]

View File

@@ -27,6 +27,7 @@ import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
import static org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration.DEFAULT_GRAPHQL_HTTP_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_JSON_RPC_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_PRETTY_JSON_ENABLED;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.DEFAULT_RPC_APIS;
import static org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis.VALID_APIS;
import static org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService.EPHEMERAL_JWT_FILE;
@@ -781,6 +782,11 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
paramLabel = MANDATORY_LONG_FORMAT_HELP,
description = "Specifies the maximum request content length. (default: ${DEFAULT-VALUE})")
private final Long rpcHttpMaxRequestContentLength = DEFAULT_MAX_REQUEST_CONTENT_LENGTH;
@Option(
names = {"--json-pretty-print-enabled"},
description = "Enable JSON pretty print format (default: ${DEFAULT-VALUE})")
private final Boolean prettyJsonEnabled = DEFAULT_PRETTY_JSON_ENABLED;
}
// JSON-RPC Websocket Options
@@ -2447,6 +2453,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
jsonRpcConfiguration.setMaxBatchSize(jsonRPCHttpOptionGroup.rpcHttpMaxBatchSize);
jsonRpcConfiguration.setMaxRequestContentLength(
jsonRPCHttpOptionGroup.rpcHttpMaxRequestContentLength);
jsonRpcConfiguration.setPrettyJsonEnabled(jsonRPCHttpOptionGroup.prettyJsonEnabled);
return jsonRpcConfiguration;
}

View File

@@ -15,9 +15,9 @@
package org.hyperledger.besu.services;
import static com.google.common.base.Preconditions.checkArgument;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator.calculateExcessDataGasForParent;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.TraceBlock.ChainUpdater;
@@ -111,15 +111,15 @@ public class TraceServiceImpl implements TraceService {
transaction -> {
final Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(header.getParentHash());
final Wei dataGasPrice =
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.dataPricePerGas(
.blobGasPricePerGas(
maybeParentHeader
.map(
parent ->
calculateExcessDataGasForParent(protocolSpec, parent))
.orElse(DataGas.ZERO));
calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
tracer.traceStartTransaction(transaction);
@@ -133,7 +133,7 @@ public class TraceServiceImpl implements TraceService {
tracer,
new CachingBlockHashLookup(header, blockchain),
false,
dataGasPrice);
blobGasPrice);
long transactionGasUsed = transaction.getGasLimit() - result.getGasRemaining();
tracer.traceEndTransaction(result.getOutput(), transactionGasUsed, 0);

View File

@@ -200,7 +200,7 @@ public class BesuEventsImplTest {
mock(EthPeer.class),
new org.hyperledger.besu.ethereum.core.BlockHeader(
null, null, null, null, null, null, null, null, 1, 1, 1, 1, null, null, null, 1, null,
null, null, null, null));
null, null, null, null, null));
}
private void clearSyncTarget() {

View File

@@ -87,6 +87,7 @@ rpc-http-tls-cipher-suites=["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_R
rpc-http-max-batch-size=1
rpc-http-max-request-content-length = 5242880
rpc-max-logs-range=100
json-pretty-print-enabled=false
# PRIVACY TLS
privacy-tls-enabled=false

View File

@@ -248,21 +248,33 @@ public class GenesisConfigFile {
}
/**
* Gets excess data gas.
* Gets excess blob gas.
*
* @return the excess data gas
* @return the excess blob gas
*/
public String getExcessDataGas() {
return JsonUtil.getValueAsString(configRoot, "excessdatagas", "0x0");
public String getExcessBlobGas() {
return JsonUtil.getValueAsString(configRoot, "excessblobgas", "0x0");
}
/**
* Gets data gas used.
* Gets blob gas used.
*
* @return the data gas used
* @return the blob gas used
*/
public String getDataGasUsed() {
return JsonUtil.getValueAsString(configRoot, "datagasused", "0x0");
public String getBlobGasUsed() {
return JsonUtil.getValueAsString(configRoot, "blobgasused", "0x0");
}
/**
* Gets parent beacon block root.
*
* @return the parent beacon block root
*/
public String getParentBeaconBlockRoot() {
return JsonUtil.getValueAsString(
configRoot,
"parentbeaconblockroot",
"0x0000000000000000000000000000000000000000000000000000000000000000");
}
/**

View File

@@ -90,19 +90,22 @@ class MergeBlockCreator extends AbstractBlockCreator {
* @param random the random
* @param timestamp the timestamp
* @param withdrawals optional list of withdrawals
* @param parentBeaconBlockRoot optional root hash of the parent beacon block
* @return the block creation result
*/
public BlockCreationResult createBlock(
final Optional<List<Transaction>> maybeTransactions,
final Bytes32 random,
final long timestamp,
final Optional<List<Withdrawal>> withdrawals) {
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot) {
return createBlock(
maybeTransactions,
Optional.of(Collections.emptyList()),
withdrawals,
Optional.of(random),
parentBeaconBlockRoot,
timestamp,
false);
}

View File

@@ -246,7 +246,8 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
final Long timestamp,
final Bytes32 prevRandao,
final Address feeRecipient,
final Optional<List<Withdrawal>> withdrawals) {
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot) {
// we assume that preparePayload is always called sequentially, since the RPC Engine calls
// are sequential, if this assumption changes then more synchronization should be added to
@@ -273,7 +274,12 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
// put the empty block in first
final Block emptyBlock =
mergeBlockCreator
.createBlock(Optional.of(Collections.emptyList()), prevRandao, timestamp, withdrawals)
.createBlock(
Optional.of(Collections.emptyList()),
prevRandao,
timestamp,
withdrawals,
parentBeaconBlockRoot)
.getBlock();
BlockProcessingResult result = validateProposedBlock(emptyBlock);
@@ -294,7 +300,13 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
}
}
tryToBuildBetterBlock(timestamp, prevRandao, payloadIdentifier, mergeBlockCreator, withdrawals);
tryToBuildBetterBlock(
timestamp,
prevRandao,
payloadIdentifier,
mergeBlockCreator,
withdrawals,
parentBeaconBlockRoot);
return payloadIdentifier;
}
@@ -334,10 +346,13 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
final Bytes32 random,
final PayloadIdentifier payloadIdentifier,
final MergeBlockCreator mergeBlockCreator,
final Optional<List<Withdrawal>> withdrawals) {
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot) {
final Supplier<BlockCreationResult> blockCreator =
() -> mergeBlockCreator.createBlock(Optional.empty(), random, timestamp, withdrawals);
() ->
mergeBlockCreator.createBlock(
Optional.empty(), random, timestamp, withdrawals, parentBeaconBlockRoot);
LOG.debug(
"Block creation started for payload id {}, remaining time is {}ms",
@@ -607,33 +622,30 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
return true;
}
if (newHead.getParentHash().equals(blockchain.getChainHeadHash())) {
LOG.atDebug()
.setMessage(
"Forwarding chain head to the block {} saved from a previous newPayload invocation")
.addArgument(newHead::toLogString)
.log();
if (forwardWorldStateTo(newHead)) {
// move chain head forward:
if (moveWorldStateTo(newHead)) {
if (newHead.getParentHash().equals(blockchain.getChainHeadHash())) {
LOG.atDebug()
.setMessage(
"Forwarding chain head to the block {} saved from a previous newPayload invocation")
.addArgument(newHead::toLogString)
.log();
return blockchain.forwardToBlock(newHead);
} else {
LOG.atDebug()
.setMessage("Failed to move the worldstate forward to hash {}, not moving chain head")
.setMessage("New head {} is a chain reorg, rewind chain head to it")
.addArgument(newHead::toLogString)
.log();
return false;
return blockchain.rewindToBlock(newHead.getHash());
}
}
LOG.atDebug()
.setMessage("New head {} is a chain reorg, rewind chain head to it")
.setMessage("Failed to move the worldstate forward to hash {}, not moving chain head")
.addArgument(newHead::toLogString)
.log();
return blockchain.rewindToBlock(newHead.getHash());
return false;
}
private boolean forwardWorldStateTo(final BlockHeader newHead) {
private boolean moveWorldStateTo(final BlockHeader newHead) {
Optional<MutableWorldState> newWorldState =
protocolContext
.getWorldStateArchive()

View File

@@ -41,6 +41,7 @@ public interface MergeMiningCoordinator extends MiningCoordinator {
* @param prevRandao the prev randao
* @param feeRecipient the fee recipient
* @param withdrawals the optional list of withdrawals
* @param parentBeaconBlockRoot optional root hash of the parent beacon block
* @return the payload identifier
*/
PayloadIdentifier preparePayload(
@@ -48,7 +49,8 @@ public interface MergeMiningCoordinator extends MiningCoordinator {
final Long timestamp,
final Bytes32 prevRandao,
final Address feeRecipient,
final Optional<List<Withdrawal>> withdrawals);
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot);
@Override
default boolean isCompatibleWithEngineApi() {

View File

@@ -147,9 +147,10 @@ public class TransitionCoordinator extends TransitionUtils<MiningCoordinator>
final Long timestamp,
final Bytes32 prevRandao,
final Address feeRecipient,
final Optional<List<Withdrawal>> withdrawals) {
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot) {
return mergeCoordinator.preparePayload(
parentHeader, timestamp, prevRandao, feeRecipient, withdrawals);
parentHeader, timestamp, prevRandao, feeRecipient, withdrawals, parentBeaconBlockRoot);
}
@Override

View File

@@ -60,7 +60,6 @@ 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.TransactionTestFixture;
import org.hyperledger.besu.ethereum.core.Withdrawal;
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BackwardSyncContext;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
@@ -122,7 +121,6 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
"ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f"));
private static final KeyPair KEYS1 =
new KeyPair(PRIVATE_KEY1, SIGNATURE_ALGORITHM.get().createPublicKey(PRIVATE_KEY1));
private static final Optional<List<Withdrawal>> EMPTY_WITHDRAWALS = Optional.empty();
private static final long REPETITION_MIN_DURATION = 100;
@Mock MergeContext mergeContext;
@@ -256,7 +254,8 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.ZERO,
suggestedFeeRecipient,
EMPTY_WITHDRAWALS);
Optional.empty(),
Optional.empty());
ArgumentCaptor<BlockWithReceipts> blockWithReceipts =
ArgumentCaptor.forClass(BlockWithReceipts.class);
@@ -294,7 +293,8 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
.doThrow(new MerkleTrieException("missing leaf"))
.doCallRealMethod()
.when(beingSpiedOn)
.createBlock(any(), any(Bytes32.class), anyLong(), eq(Optional.empty()));
.createBlock(
any(), any(Bytes32.class), anyLong(), eq(Optional.empty()), eq(Optional.empty()));
return beingSpiedOn;
};
@@ -330,6 +330,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.random(),
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
verify(willThrow, never()).addBadBlock(any(), any());
@@ -362,6 +363,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
verify(badBlockManager, never()).addBadBlock(any(), any());
@@ -394,6 +396,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
blockCreationTask.get();
@@ -445,6 +448,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
blockCreationTask.get();
@@ -491,6 +495,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
blockCreationTask.get();
@@ -525,6 +530,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
try {
@@ -567,6 +573,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
System.currentTimeMillis() / 1000,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
waitForBlockCreationInProgress.await();
@@ -613,6 +620,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
timestamp,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
final CompletableFuture<Void> task1 = blockCreationTask;
@@ -623,6 +631,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
timestamp,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
assertThat(payloadId1).isEqualTo(payloadId2);
@@ -658,6 +667,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
timestamp,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
assertThat(coordinator.isBlockCreationCancelled(payloadId1)).isFalse();
@@ -668,6 +678,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
timestamp + 1,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
assertThat(payloadId1).isNotEqualTo(payloadId2);
@@ -697,6 +708,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
1L,
Bytes32.ZERO,
suggestedFeeRecipient,
Optional.empty(),
Optional.empty());
ArgumentCaptor<BlockWithReceipts> blockWithReceipts =

View File

@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
@@ -12,35 +12,18 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.evm;
import org.hyperledger.besu.datatypes.Address;
package org.hyperledger.besu.datatypes;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
/** The Access list entry. */
public class AccessListEntry {
private final Address address;
private final List<Bytes32> storageKeys;
/**
* Instantiates a new Access list entry.
*
* @param address the address
* @param storageKeys the storage keys
*/
public AccessListEntry(final Address address, final List<Bytes32> storageKeys) {
this.address = address;
this.storageKeys = storageKeys;
}
/** An access list entry as defined in EIP-2930 */
public record AccessListEntry(Address address, List<Bytes32> storageKeys) {
/**
* Create access list entry.
*
@@ -56,26 +39,6 @@ public class AccessListEntry {
address, storageKeys.stream().map(Bytes32::fromHexString).collect(Collectors.toList()));
}
/**
* Gets address.
*
* @return the address
*/
@JsonIgnore
public Address getAddress() {
return address;
}
/**
* Gets storage keys.
*
* @return the storage keys
*/
@JsonIgnore
public List<Bytes32> getStorageKeys() {
return storageKeys;
}
/**
* Gets address string.
*

View File

@@ -57,26 +57,30 @@ public class Address extends DelegatingBytes {
public static final Address ALTBN128_PAIRING = Address.precompiled(0x08);
/** The constant BLAKE2B_F_COMPRESSION. */
public static final Address BLAKE2B_F_COMPRESSION = Address.precompiled(0x09);
/** The constant KZG_POINT_EVAL aka POINT_EVALUATION_PRECOMPILE_ADDRESS. */
public static final Address KZG_POINT_EVAL = Address.precompiled(0xA);
/** The constant PARENT_BEACON_BLOCK_ROOT_REGISTRY aka HISTORY_STORAGE_ADDRESS. */
public static final Address PARENT_BEACON_BLOCK_ROOT_REGISTRY = Address.precompiled(0xB);
// TODO: this is not a precompile anymore. The address is correct for testnet 8. Fix after testnet
// 8 when we know what the real address is
/** The constant BLS12_G1ADD. */
public static final Address BLS12_G1ADD = Address.precompiled(0xA);
public static final Address BLS12_G1ADD = Address.precompiled(0xC);
/** The constant BLS12_G1MUL. */
public static final Address BLS12_G1MUL = Address.precompiled(0xB);
public static final Address BLS12_G1MUL = Address.precompiled(0xD);
/** The constant BLS12_G1MULTIEXP. */
public static final Address BLS12_G1MULTIEXP = Address.precompiled(0xC);
public static final Address BLS12_G1MULTIEXP = Address.precompiled(0xE);
/** The constant BLS12_G2ADD. */
public static final Address BLS12_G2ADD = Address.precompiled(0xD);
public static final Address BLS12_G2ADD = Address.precompiled(0xF);
/** The constant BLS12_G2MUL. */
public static final Address BLS12_G2MUL = Address.precompiled(0xE);
public static final Address BLS12_G2MUL = Address.precompiled(0x10);
/** The constant BLS12_G2MULTIEXP. */
public static final Address BLS12_G2MULTIEXP = Address.precompiled(0xF);
public static final Address BLS12_G2MULTIEXP = Address.precompiled(0x11);
/** The constant BLS12_PAIRING. */
public static final Address BLS12_PAIRING = Address.precompiled(0x10);
public static final Address BLS12_PAIRING = Address.precompiled(0x12);
/** The constant BLS12_MAP_FP_TO_G1. */
public static final Address BLS12_MAP_FP_TO_G1 = Address.precompiled(0x11);
public static final Address BLS12_MAP_FP_TO_G1 = Address.precompiled(0x13);
/** The constant BLS12_MAP_FP2_TO_G2. */
public static final Address BLS12_MAP_FP2_TO_G2 = Address.precompiled(0x12);
/** The constant KZG_POINT_EVAL. */
public static final Address KZG_POINT_EVAL = Address.precompiled(0x14);
public static final Address BLS12_MAP_FP2_TO_G2 = Address.precompiled(0x14);
/** The constant ZERO. */
public static final Address ZERO = Address.fromHexString("0x0");

View File

@@ -20,97 +20,97 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.BaseUInt64Value;
import org.apache.tuweni.units.bigints.UInt64;
/** A particular quantity of DataGas */
public final class DataGas extends BaseUInt64Value<DataGas> implements Quantity {
/** A particular quantity of BlobGas */
public final class BlobGas extends BaseUInt64Value<BlobGas> implements Quantity {
/** The constant ZERO. */
public static final DataGas ZERO = of(0);
public static final BlobGas ZERO = of(0);
/** The constant ONE. */
public static final DataGas ONE = of(1);
public static final BlobGas ONE = of(1);
/** The constant MAX_DATA_GAS. */
public static final DataGas MAX_DATA_GAS = of(UInt64.MAX_VALUE);
/** The constant MAX_BLOB_GAS. */
public static final BlobGas MAX_BLOB_GAS = of(UInt64.MAX_VALUE);
/**
* Instantiates a new DataGas.
* Instantiates a new BlobGas.
*
* @param value the value
*/
DataGas(final UInt64 value) {
super(value, DataGas::new);
BlobGas(final UInt64 value) {
super(value, BlobGas::new);
}
private DataGas(final long v) {
private BlobGas(final long v) {
this(UInt64.valueOf(v));
}
private DataGas(final BigInteger v) {
private BlobGas(final BigInteger v) {
this(UInt64.valueOf(v));
}
private DataGas(final String hexString) {
private BlobGas(final String hexString) {
this(UInt64.fromHexString(hexString));
}
/**
* data gas of value.
* blob gas of value.
*
* @param value the value
* @return the data gas
* @return the blob gas
*/
public static DataGas of(final long value) {
return new DataGas(value);
public static BlobGas of(final long value) {
return new BlobGas(value);
}
/**
* data gas of value.
* blob gas of value.
*
* @param value the value
* @return the data gas
* @return the blob gas
*/
public static DataGas of(final BigInteger value) {
return new DataGas(value);
public static BlobGas of(final BigInteger value) {
return new BlobGas(value);
}
/**
* data gas of value.
* blob gas of value.
*
* @param value the value
* @return the data gas
* @return the blob gas
*/
public static DataGas of(final UInt64 value) {
return new DataGas(value);
public static BlobGas of(final UInt64 value) {
return new BlobGas(value);
}
/**
* data gas of value.
* blob gas of value.
*
* @param value the value
* @return the data gas
* @return the blob gas
*/
public static DataGas ofNumber(final Number value) {
return new DataGas((BigInteger) value);
public static BlobGas ofNumber(final Number value) {
return new BlobGas((BigInteger) value);
}
/**
* Wrap data gas.
* Wrap blob gas.
*
* @param value the value
* @return the data gas
* @return the blob gas
*/
public static DataGas wrap(final Bytes value) {
return new DataGas(UInt64.fromBytes(value));
public static BlobGas wrap(final Bytes value) {
return new BlobGas(UInt64.fromBytes(value));
}
/**
* From hex string to data gas.
* From hex string to blob gas.
*
* @param str the str
* @return the data gas
* @return the blob gas
*/
public static DataGas fromHexString(final String str) {
return new DataGas(str);
public static BlobGas fromHexString(final String str) {
return new BlobGas(str);
}
@Override
@@ -134,12 +134,12 @@ public final class DataGas extends BaseUInt64Value<DataGas> implements Quantity
}
/**
* From quantity to data gas.
* From quantity to blob gas.
*
* @param quantity the quantity
* @return the data gas
* @return the blob gas
*/
public static DataGas fromQuantity(final Quantity quantity) {
return DataGas.wrap((Bytes) quantity);
public static BlobGas fromQuantity(final Quantity quantity) {
return BlobGas.wrap((Bytes) quantity);
}
}

View File

@@ -15,6 +15,7 @@
package org.hyperledger.besu.datatypes;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
@@ -73,12 +74,12 @@ public interface Transaction {
}
/**
* A scalar value equal to the max number of Wei to be paid for data gas, as specified in
* A scalar value equal to the max number of Wei to be paid for blob gas, as specified in
* EIP-4844.
*
* @return the quantity of Wei for fee per data gas.
* @return the quantity of Wei for fee per blob gas.
*/
default Optional<? extends Quantity> getMaxFeePerDataGas() {
default Optional<? extends Quantity> getMaxFeePerBlobGas() {
return Optional.empty();
}
@@ -183,4 +184,39 @@ public interface Transaction {
* @return the type of the transaction
*/
TransactionType getType();
/**
* Return the versioned hashes for this transaction.
*
* @return optional list of versioned hashes
*/
Optional<List<VersionedHash>> getVersionedHashes();
/**
* Return the blobs with commitments for this transaction.
*
* @return optional blobs with commitments
*/
Optional<BlobsWithCommitments> getBlobsWithCommitments();
/**
* Return the address of the contract, if the transaction creates one
*
* @return address of new contract or empty otherwise
*/
Optional<Address> contractAddress();
/**
* Return the access list in case of EIP-2930 transaction
*
* @return optional access list
*/
Optional<List<AccessListEntry>> getAccessList();
/**
* Returns the transaction with the proper encoding
*
* @return the encoded transaction as Bytes
*/
Bytes encoded();
}

View File

@@ -127,8 +127,9 @@ public class JsonRpcResponseUtils {
mixHash,
nonce,
withdrawalsRoot,
null, // ToDo 4844: set with the value of data_gas_used field
null, // ToDo 4844: set with the value of excess_data_gas field
null, // ToDo 4844: set with the value of blob_gas_used field
null, // ToDo 4844: set with the value of excess_blob_gas field
null, // TODO 4788: set with the value of the parent beacon block root field
depositsRoot,
blockHeaderFunctions);

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods.fork.frontier;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.BlockchainImporter;
@@ -27,7 +28,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallPar
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.CreateAccessListResult;
import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.testutil.BlockTestUtil;
import java.util.ArrayList;

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods.fork.london;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.BlockchainImporter;
@@ -26,7 +27,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.testutil.BlockTestUtil;
import java.util.List;

View File

@@ -14,8 +14,8 @@
*/
package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.evm.AccessListEntry;
import java.util.ArrayList;
import java.util.List;
@@ -32,11 +32,11 @@ public class AccessListEntryAdapter extends AdapterBase {
}
public List<Bytes32> getStorageKeys() {
final var storage = accessListEntry.getStorageKeys();
final var storage = accessListEntry.storageKeys();
return new ArrayList<>(storage);
}
public Optional<Address> getAddress() {
return Optional.of(accessListEntry.getAddress());
return Optional.of(accessListEntry.address());
}
}

View File

@@ -36,7 +36,7 @@ import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
public class JsonRpcObjectExecutor extends AbstractJsonRpcExecutor {
private static final ObjectWriter jsonObjectWriter = createObjectWriter();
private final ObjectWriter jsonObjectWriter = createObjectWriter();
public JsonRpcObjectExecutor(
final JsonRpcExecutor jsonRpcExecutor,
@@ -64,7 +64,7 @@ public class JsonRpcObjectExecutor extends AbstractJsonRpcExecutor {
return jsonObject.getString("method");
}
private static void handleJsonObjectResponse(
private void handleJsonObjectResponse(
final HttpServerResponse response,
final JsonRpcResponse jsonRpcResponse,
final RoutingContext ctx)
@@ -90,9 +90,12 @@ public class JsonRpcObjectExecutor extends AbstractJsonRpcExecutor {
};
}
private static ObjectWriter createObjectWriter() {
return getJsonObjectMapper()
.writerWithDefaultPrettyPrinter()
private ObjectWriter createObjectWriter() {
ObjectWriter writer =
jsonRpcConfiguration.isPrettyJsonEnabled()
? getJsonObjectMapper().writerWithDefaultPrettyPrinter()
: getJsonObjectMapper().writer();
return writer
.without(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)
.with(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
}

View File

@@ -38,6 +38,7 @@ public class JsonRpcConfiguration {
public static final int DEFAULT_MAX_ACTIVE_CONNECTIONS = 80;
public static final int DEFAULT_MAX_BATCH_SIZE = 1024;
public static final long DEFAULT_MAX_REQUEST_CONTENT_LENGTH = 5 * 1024 * 1024; // 5MB
public static final boolean DEFAULT_PRETTY_JSON_ENABLED = false;
private boolean enabled;
private int port;
@@ -55,6 +56,7 @@ public class JsonRpcConfiguration {
private int maxActiveConnections;
private int maxBatchSize;
private long maxRequestContentLength;
private boolean prettyJsonEnabled;
public static JsonRpcConfiguration createDefault() {
final JsonRpcConfiguration config = new JsonRpcConfiguration();
@@ -66,6 +68,7 @@ public class JsonRpcConfiguration {
config.setMaxActiveConnections(DEFAULT_MAX_ACTIVE_CONNECTIONS);
config.setMaxBatchSize(DEFAULT_MAX_BATCH_SIZE);
config.setMaxRequestContentLength(DEFAULT_MAX_REQUEST_CONTENT_LENGTH);
config.setPrettyJsonEnabled(DEFAULT_PRETTY_JSON_ENABLED);
return config;
}
@@ -196,6 +199,14 @@ public class JsonRpcConfiguration {
this.httpTimeoutSec = httpTimeoutSec;
}
public boolean isPrettyJsonEnabled() {
return prettyJsonEnabled;
}
public void setPrettyJsonEnabled(final boolean prettyJsonEnabled) {
this.prettyJsonEnabled = prettyJsonEnabled;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)

View File

@@ -73,8 +73,8 @@ public class JsonRpcErrorConverter {
return RpcErrorType.NONCE_TOO_FAR_IN_FUTURE_FOR_SENDER;
case LOWER_NONCE_INVALID_TRANSACTION_EXISTS:
return RpcErrorType.LOWER_NONCE_INVALID_TRANSACTION_EXISTS;
case TOTAL_DATA_GAS_TOO_HIGH:
return RpcErrorType.TOTAL_DATA_GAS_TOO_HIGH;
case TOTAL_BLOB_GAS_TOO_HIGH:
return RpcErrorType.TOTAL_BLOB_GAS_TOO_HIGH;
case TX_POOL_DISABLED:
return RpcErrorType.TX_POOL_DISABLED;
default:

View File

@@ -58,6 +58,7 @@ public enum RpcMethod {
ENGINE_NEW_PAYLOAD_V3("engine_newPayloadV3"),
ENGINE_FORKCHOICE_UPDATED_V1("engine_forkchoiceUpdatedV1"),
ENGINE_FORKCHOICE_UPDATED_V2("engine_forkchoiceUpdatedV2"),
ENGINE_FORKCHOICE_UPDATED_V3("engine_forkchoiceUpdatedV3"),
ENGINE_EXCHANGE_TRANSITION_CONFIGURATION("engine_exchangeTransitionConfigurationV1"),
ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1("engine_getPayloadBodiesByHashV1"),
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1("engine_getPayloadBodiesByRangeV1"),

View File

@@ -14,6 +14,7 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
@@ -29,7 +30,6 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.evm.tracing.AccessListOperationTracer;
import java.util.List;

View File

@@ -14,9 +14,9 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator.calculateExcessDataGasForParent;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.chain.Blockchain;
@@ -88,13 +88,13 @@ public class ExecuteTransactionStep implements Function<TransactionTrace, Transa
BlockHeader header = block.getHeader();
final Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(header.getParentHash());
final Wei dataGasPrice =
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.dataPricePerGas(
.blobGasPricePerGas(
maybeParentHeader
.map(parent -> calculateExcessDataGasForParent(protocolSpec, parent))
.orElse(DataGas.ZERO));
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(header, blockchain);
result =
transactionProcessor.processTransaction(
@@ -106,7 +106,7 @@ public class ExecuteTransactionStep implements Function<TransactionTrace, Transa
tracer,
blockHashLookup,
false,
dataGasPrice);
blobGasPrice);
traceFrames = tracer.copyTraceFrames();
tracer.reset();

View File

@@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EngineUpdateFo
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Withdrawal;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec;
import java.util.List;
import java.util.Optional;
@@ -51,6 +52,7 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
private static final Logger LOG = LoggerFactory.getLogger(AbstractEngineForkchoiceUpdated.class);
private final ProtocolSchedule protocolSchedule;
private final MergeMiningCoordinator mergeCoordinator;
private final Long cancunTimestamp;
public AbstractEngineForkchoiceUpdated(
final Vertx vertx,
@@ -61,6 +63,9 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
super(vertx, protocolContext, engineCallListener);
this.protocolSchedule = protocolSchedule;
this.mergeCoordinator = mergeCoordinator;
Optional<ScheduledProtocolSpec.Hardfork> cancun =
protocolSchedule.hardforkFor(s -> s.fork().name().equalsIgnoreCase("Cancun"));
cancunTimestamp = cancun.map(ScheduledProtocolSpec.Hardfork::milestone).orElse(Long.MAX_VALUE);
}
@Override
@@ -178,7 +183,8 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
payloadAttributes.getTimestamp(),
payloadAttributes.getPrevRandao(),
payloadAttributes.getSuggestedFeeRecipient(),
withdrawals));
withdrawals,
Optional.ofNullable(payloadAttributes.getParentBeaconBlockRoot())));
payloadId.ifPresent(
pid ->
@@ -204,12 +210,24 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
final Optional<List<Withdrawal>> maybeWithdrawals,
final BlockHeader headBlockHeader) {
final boolean newTimestampGreaterThanHead =
payloadAttributes.getTimestamp() > headBlockHeader.getTimestamp();
return newTimestampGreaterThanHead
&& getWithdrawalsValidator(
protocolSchedule, headBlockHeader, payloadAttributes.getTimestamp())
.validateWithdrawals(maybeWithdrawals);
if (payloadAttributes.getTimestamp() <= headBlockHeader.getTimestamp()) {
LOG.warn(
"Payload attributes timestamp is smaller than timestamp of header in fork choice update");
return false;
}
if (payloadAttributes.getTimestamp() < cancunTimestamp) {
LOG.warn("Payload attributes are present before cancun hardfork");
} else if (payloadAttributes.getParentBeaconBlockRoot() == null) {
LOG.warn("Parent beacon block root not present in payload attributes after cancun hardfork");
return false;
}
if (!getWithdrawalsValidator(
protocolSchedule, headBlockHeader, payloadAttributes.getTimestamp())
.validateWithdrawals(maybeWithdrawals)) {
return false;
}
return true;
}
private JsonRpcResponse handleNonValidForkchoiceUpdate(

View File

@@ -25,7 +25,7 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INVALID_PARAMS;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
@@ -57,7 +57,7 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator;
import org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.plugin.services.exception.StorageException;
@@ -105,11 +105,24 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
final EnginePayloadParameter blockParam =
requestContext.getRequiredParameter(0, EnginePayloadParameter.class);
Optional<List<String>> maybeVersionedHashParam =
final Optional<List<String>> maybeVersionedHashParam =
requestContext.getOptionalList(1, String.class);
Object reqId = requestContext.getRequest().getId();
Optional<List<VersionedHash>> maybeVersionedHashes;
final Object reqId = requestContext.getRequest().getId();
Optional<String> maybeParentBeaconBlockRootParam =
requestContext.getOptionalParameter(2, String.class);
final Optional<Bytes32> maybeParentBeaconBlockRoot =
maybeParentBeaconBlockRootParam.map(Bytes32::fromHexString);
ValidationResult<RpcErrorType> forkValidationResult =
validateParamsAndForkSupported(
reqId, blockParam, maybeVersionedHashParam, maybeParentBeaconBlockRoot);
if (!forkValidationResult.isValid()) {
return new JsonRpcErrorResponse(reqId, forkValidationResult);
}
final Optional<List<VersionedHash>> maybeVersionedHashes;
try {
maybeVersionedHashes = extractVersionedHashes(maybeVersionedHashParam);
} catch (RuntimeException ex) {
@@ -124,11 +137,6 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
.addArgument(() -> Json.encodePrettily(blockParam))
.log();
ValidationResult<RpcErrorType> forkValidationResult = validateForkSupported(reqId, blockParam);
if (!forkValidationResult.isValid()) {
return new JsonRpcErrorResponse(reqId, forkValidationResult);
}
final Optional<List<Withdrawal>> maybeWithdrawals =
Optional.ofNullable(blockParam.getWithdrawals())
.map(ws -> ws.stream().map(WithdrawalParameter::toWithdrawal).collect(toList()));
@@ -198,10 +206,11 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
blockParam.getPrevRandao(),
0,
maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null),
blockParam.getDataGasUsed() == null ? null : blockParam.getDataGasUsed(),
blockParam.getExcessDataGas() == null
blockParam.getBlobGasUsed() == null ? null : blockParam.getBlobGasUsed(),
blockParam.getExcessBlobGas() == null
? null
: DataGas.fromHexString(blockParam.getExcessDataGas()),
: BlobGas.fromHexString(blockParam.getExcessBlobGas()),
maybeParentBeaconBlockRoot.orElse(null),
maybeDeposits.map(BodyValidation::depositsRoot).orElse(null),
headerFunctions);
@@ -389,8 +398,11 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
return INVALID;
}
protected ValidationResult<RpcErrorType> validateForkSupported(
final Object id, final EnginePayloadParameter payloadParameter) {
protected ValidationResult<RpcErrorType> validateParamsAndForkSupported(
final Object id,
final EnginePayloadParameter payloadParameter,
final Optional<List<String>> maybeVersionedHashParam,
final Optional<Bytes32> parentBeaconBlockRoot) {
return ValidationResult.valid();
}
@@ -428,40 +440,40 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
"Versioned hashes from blob transactions do not match expected values");
}
// Validate excessDataGas
// Validate excessBlobGas
if (maybeParentHeader.isPresent()) {
if (!validateExcessDataGas(header, maybeParentHeader.get(), protocolSpec)) {
if (!validateExcessBlobGas(header, maybeParentHeader.get(), protocolSpec)) {
return ValidationResult.invalid(
RpcErrorType.INVALID_PARAMS,
"Payload excessDataGas does not match calculated excessDataGas");
"Payload excessBlobGas does not match calculated excessBlobGas");
}
}
// Validate dataGasUsed
if (header.getDataGasUsed().isPresent() && maybeVersionedHashes.isPresent()) {
if (!validateDataGasUsed(header, maybeVersionedHashes.get(), protocolSpec)) {
// Validate blobGasUsed
if (header.getBlobGasUsed().isPresent() && maybeVersionedHashes.isPresent()) {
if (!validateBlobGasUsed(header, maybeVersionedHashes.get(), protocolSpec)) {
return ValidationResult.invalid(
RpcErrorType.INVALID_PARAMS,
"Payload DataGasUsed does not match calculated DataGasUsed");
"Payload BlobGasUsed does not match calculated BlobGasUsed");
}
}
return ValidationResult.valid();
}
private boolean validateExcessDataGas(
private boolean validateExcessBlobGas(
final BlockHeader header, final BlockHeader parentHeader, final ProtocolSpec protocolSpec) {
DataGas calculatedDataGas =
ExcessDataGasCalculator.calculateExcessDataGasForParent(protocolSpec, parentHeader);
return header.getExcessDataGas().orElse(DataGas.ZERO).equals(calculatedDataGas);
BlobGas calculatedBlobGas =
ExcessBlobGasCalculator.calculateExcessBlobGasForParent(protocolSpec, parentHeader);
return header.getExcessBlobGas().orElse(BlobGas.ZERO).equals(calculatedBlobGas);
}
private boolean validateDataGasUsed(
private boolean validateBlobGasUsed(
final BlockHeader header,
final List<VersionedHash> maybeVersionedHashes,
final ProtocolSpec protocolSpec) {
var calculatedDataGas =
protocolSpec.getGasCalculator().dataGasCost(maybeVersionedHashes.size());
return header.getDataGasUsed().orElse(0L).equals(calculatedDataGas);
var calculatedBlobGas =
protocolSpec.getGasCalculator().blobGasCost(maybeVersionedHashes.size());
return header.getBlobGasUsed().orElse(0L).equals(calculatedBlobGas);
}
private Optional<List<VersionedHash>> extractVersionedHashes(

View File

@@ -0,0 +1,39 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import io.vertx.core.Vertx;
public class EngineForkchoiceUpdatedV3 extends AbstractEngineForkchoiceUpdated {
public EngineForkchoiceUpdatedV3(
final Vertx vertx,
final ProtocolSchedule protocolSchedule,
final ProtocolContext protocolContext,
final MergeMiningCoordinator mergeCoordinator,
final EngineCallListener engineCallListener) {
super(vertx, protocolSchedule, protocolContext, mergeCoordinator, engineCallListener);
}
@Override
public String getName() {
return RpcMethod.ENGINE_FORKCHOICE_UPDATED_V3.getMethodName();
}
}

View File

@@ -21,13 +21,18 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePaylo
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduledProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import java.util.List;
import java.util.Optional;
import io.vertx.core.Vertx;
import org.apache.tuweni.bytes.Bytes32;
public class EngineNewPayloadV3 extends AbstractEngineNewPayload {
private final ProtocolSchedule timestampSchedule;
private final Long cancunTimestamp;
public EngineNewPayloadV3(
final Vertx vertx,
@@ -38,7 +43,9 @@ public class EngineNewPayloadV3 extends AbstractEngineNewPayload {
final EngineCallListener engineCallListener) {
super(
vertx, timestampSchedule, protocolContext, mergeCoordinator, ethPeers, engineCallListener);
this.timestampSchedule = timestampSchedule;
Optional<ScheduledProtocolSpec.Hardfork> cancun =
timestampSchedule.hardforkFor(s -> s.fork().name().equalsIgnoreCase("Cancun"));
cancunTimestamp = cancun.map(ScheduledProtocolSpec.Hardfork::milestone).orElse(Long.MAX_VALUE);
}
@Override
@@ -47,19 +54,24 @@ public class EngineNewPayloadV3 extends AbstractEngineNewPayload {
}
@Override
protected ValidationResult<RpcErrorType> validateForkSupported(
final Object reqId, final EnginePayloadParameter payloadParameter) {
var cancun = timestampSchedule.hardforkFor(s -> s.fork().name().equalsIgnoreCase("Cancun"));
protected ValidationResult<RpcErrorType> validateParamsAndForkSupported(
final Object reqId,
final EnginePayloadParameter payloadParameter,
final Optional<List<String>> maybeVersionedHashParam,
final Optional<Bytes32> maybeParentBeaconBlockRoot) {
if (cancun.isPresent() && payloadParameter.getTimestamp() >= cancun.get().milestone()) {
if (payloadParameter.getDataGasUsed() == null
|| payloadParameter.getExcessDataGas() == null) {
return ValidationResult.invalid(RpcErrorType.INVALID_PARAMS, "Missing data gas fields");
} else {
return ValidationResult.valid();
}
} else {
return ValidationResult.invalid(RpcErrorType.INVALID_PARAMS, "Fork not supported");
if (payloadParameter.getBlobGasUsed() == null || payloadParameter.getExcessBlobGas() == null) {
return ValidationResult.invalid(RpcErrorType.INVALID_PARAMS, "Missing blob gas fields");
} else if (maybeVersionedHashParam == null) {
return ValidationResult.invalid(
RpcErrorType.INVALID_PARAMS, "Missing versioned hashes field");
} else if (maybeParentBeaconBlockRoot.isEmpty()) {
return ValidationResult.invalid(
RpcErrorType.INVALID_PARAMS, "Missing parent beacon block root field");
}
if (payloadParameter.getTimestamp() < cancunTimestamp) {
return ValidationResult.invalid(RpcErrorType.UNSUPPORTED_FORK, "Fork not supported");
}
return ValidationResult.valid();
}
}

View File

@@ -67,6 +67,7 @@ public class EnginePreparePayloadDebug extends ExecutionEngineJsonRpcMethod {
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty()));
final var requestId = requestContext.getRequest().getId();
@@ -99,6 +100,7 @@ public class EnginePreparePayloadDebug extends ExecutionEngineJsonRpcMethod {
param.getTimestamp().orElse(parentHeader.getTimestamp() + 1L),
param.getPrevRandao(),
param.getFeeRecipient(),
Optional.of(withdrawals)));
Optional.of(withdrawals),
param.getParentBeaconBlockRoot()));
}
}

View File

@@ -30,17 +30,21 @@ public class EnginePayloadAttributesParameter {
final Bytes32 prevRandao;
final Address suggestedFeeRecipient;
final List<WithdrawalParameter> withdrawals;
private final Bytes32 parentBeaconBlockRoot;
@JsonCreator
public EnginePayloadAttributesParameter(
@JsonProperty("timestamp") final String timestamp,
@JsonProperty("prevRandao") final String prevRandao,
@JsonProperty("suggestedFeeRecipient") final String suggestedFeeRecipient,
@JsonProperty("withdrawals") final List<WithdrawalParameter> withdrawals) {
@JsonProperty("withdrawals") final List<WithdrawalParameter> withdrawals,
@JsonProperty("parentBeaconBlockRoot") final String parentBeaconBlockRoot) {
this.timestamp = Long.decode(timestamp);
this.prevRandao = Bytes32.fromHexString(prevRandao);
this.suggestedFeeRecipient = Address.fromHexString(suggestedFeeRecipient);
this.withdrawals = withdrawals;
this.parentBeaconBlockRoot =
parentBeaconBlockRoot == null ? null : Bytes32.fromHexString(parentBeaconBlockRoot);
}
public Long getTimestamp() {
@@ -55,6 +59,10 @@ public class EnginePayloadAttributesParameter {
return suggestedFeeRecipient;
}
public Bytes32 getParentBeaconBlockRoot() {
return parentBeaconBlockRoot;
}
public List<WithdrawalParameter> getWithdrawals() {
return withdrawals;
}
@@ -70,6 +78,9 @@ public class EnginePayloadAttributesParameter {
"withdrawals",
withdrawals.stream().map(WithdrawalParameter::asJsonObject).collect(Collectors.toList()));
}
if (parentBeaconBlockRoot != null) {
json.put("parentBeaconBlockRoot", parentBeaconBlockRoot.toHexString());
}
return json.encode();
}
}

View File

@@ -47,8 +47,8 @@ public class EnginePayloadParameter {
private final LogsBloomFilter logsBloom;
private final List<String> transactions;
private final List<WithdrawalParameter> withdrawals;
private final Long dataGasUsed;
private final String excessDataGas;
private final Long blobGasUsed;
private final String excessBlobGas;
private final List<Bytes32> versionedHashes;
private final List<DepositParameter> deposits;
@@ -64,13 +64,13 @@ public class EnginePayloadParameter {
@JsonProperty("gasUsed") final UnsignedLongParameter gasUsed,
@JsonProperty("timestamp") final UnsignedLongParameter timestamp,
@JsonProperty("extraData") final String extraData,
@JsonProperty("receiptRoot") final Hash receiptsRoot,
@JsonProperty("receiptsRoot") final Hash receiptsRoot,
@JsonProperty("logsBloom") final LogsBloomFilter logsBloom,
@JsonProperty("prevRandao") final String prevRandao,
@JsonProperty("transactions") final List<String> transactions,
@JsonProperty("withdrawals") final List<WithdrawalParameter> withdrawals,
@JsonProperty("dataGasUsed") final UnsignedLongParameter dataGasUsed,
@JsonProperty("excessDataGas") final String excessDataGas,
@JsonProperty("blobGasUsed") final UnsignedLongParameter blobGasUsed,
@JsonProperty("excessBlobGas") final String excessBlobGas,
@JsonProperty("versionedHashes") final List<Bytes32> versionedHashes,
@JsonProperty("deposits") final List<DepositParameter> deposits) {
this.blockHash = blockHash;
@@ -88,8 +88,8 @@ public class EnginePayloadParameter {
this.prevRandao = Bytes32.fromHexString(prevRandao);
this.transactions = transactions;
this.withdrawals = withdrawals;
this.dataGasUsed = dataGasUsed == null ? null : dataGasUsed.getValue();
this.excessDataGas = excessDataGas;
this.blobGasUsed = blobGasUsed == null ? null : blobGasUsed.getValue();
this.excessBlobGas = excessBlobGas;
this.versionedHashes = versionedHashes;
this.deposits = deposits;
}
@@ -154,12 +154,12 @@ public class EnginePayloadParameter {
return withdrawals;
}
public Long getDataGasUsed() {
return dataGasUsed;
public Long getBlobGasUsed() {
return blobGasUsed;
}
public String getExcessDataGas() {
return excessDataGas;
public String getExcessBlobGas() {
return excessBlobGas;
}
public List<DepositParameter> getDeposits() {

View File

@@ -31,6 +31,7 @@ public class EnginePreparePayloadParameter {
private final Bytes32 prevRandao;
private final Optional<Long> timestamp;
final List<WithdrawalParameter> withdrawals;
private final Optional<Bytes32> parentBeaconBlockRoot;
@JsonCreator
public EnginePreparePayloadParameter(
@@ -38,12 +39,14 @@ public class EnginePreparePayloadParameter {
@JsonProperty("feeRecipient") final Optional<Address> feeRecipient,
@JsonProperty("timestamp") final Optional<UnsignedLongParameter> timestamp,
@JsonProperty("prevRandao") final Optional<String> prevRandao,
@JsonProperty("withdrawals") final Optional<List<WithdrawalParameter>> withdrawals) {
@JsonProperty("withdrawals") final Optional<List<WithdrawalParameter>> withdrawals,
@JsonProperty("parentBeaconBlockRoot") final Optional<Bytes32> parentBeaconBlockRoot) {
this.parentHash = parentHash;
this.feeRecipient = feeRecipient.orElse(Address.ZERO);
this.timestamp = timestamp.map(UnsignedLongParameter::getValue);
this.prevRandao = Bytes32.fromHexStringLenient(prevRandao.orElse("deadbeef"));
this.withdrawals = withdrawals.orElse(Collections.emptyList());
this.parentBeaconBlockRoot = parentBeaconBlockRoot;
}
public Optional<Hash> getParentHash() {
@@ -65,4 +68,8 @@ public class EnginePreparePayloadParameter {
public List<WithdrawalParameter> getWithdrawals() {
return withdrawals;
}
public Optional<Bytes32> getParentBeaconBlockRoot() {
return parentBeaconBlockRoot;
}
}

View File

@@ -14,12 +14,12 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.json.HexLongDeserializer;
import org.hyperledger.besu.ethereum.core.json.HexStringDeserializer;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.evm.AccessListEntry;
import java.util.List;
import java.util.Optional;

View File

@@ -14,9 +14,9 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator.calculateExcessDataGasForParent;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.Tracer.TraceableState;
@@ -51,21 +51,21 @@ public class BlockReplay {
block.getHeader(),
block.getBody(),
(body, header, blockchain, transactionProcessor, protocolSpec) -> {
final Wei dataGasPrice =
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.dataPricePerGas(
.blobGasPricePerGas(
blockchain
.getBlockHeader(header.getParentHash())
.map(parent -> calculateExcessDataGasForParent(protocolSpec, parent))
.orElse(DataGas.ZERO));
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
final List<TransactionTrace> transactionTraces =
body.getTransactions().stream()
.map(
transaction ->
action.performAction(
transaction, header, blockchain, transactionProcessor, dataGasPrice))
transaction, header, blockchain, transactionProcessor, blobGasPrice))
.toList();
return Optional.of(new BlockTrace(transactionTraces));
});
@@ -85,20 +85,20 @@ public class BlockReplay {
blockHash,
(body, header, blockchain, transactionProcessor, protocolSpec) -> {
final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(header, blockchain);
final Wei dataGasPrice =
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.dataPricePerGas(
.blobGasPricePerGas(
blockchain
.getBlockHeader(header.getParentHash())
.map(parent -> calculateExcessDataGasForParent(protocolSpec, parent))
.orElse(DataGas.ZERO));
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
for (final Transaction transaction : body.getTransactions()) {
if (transaction.getHash().equals(transactionHash)) {
return Optional.of(
action.performAction(
transaction, header, blockchain, transactionProcessor, dataGasPrice));
transaction, header, blockchain, transactionProcessor, blobGasPrice));
} else {
transactionProcessor.processTransaction(
blockchain,
@@ -109,7 +109,7 @@ public class BlockReplay {
blockHashLookup,
false,
TransactionValidationParams.blockReplay(),
dataGasPrice);
blobGasPrice);
}
}
return Optional.empty();
@@ -125,7 +125,7 @@ public class BlockReplay {
mutableWorldState,
blockHash,
transactionHash,
(transaction, blockHeader, blockchain, transactionProcessor, dataGasPrice) -> {
(transaction, blockHeader, blockchain, transactionProcessor, blobGasPrice) -> {
final ProtocolSpec spec = protocolSchedule.getByBlockHeader(blockHeader);
transactionProcessor.processTransaction(
blockchain,
@@ -136,9 +136,9 @@ public class BlockReplay {
new CachingBlockHashLookup(blockHeader, blockchain),
false,
TransactionValidationParams.blockReplay(),
dataGasPrice);
blobGasPrice);
return action.performAction(
transaction, blockHeader, blockchain, transactionProcessor, dataGasPrice);
transaction, blockHeader, blockchain, transactionProcessor, blobGasPrice);
});
}
@@ -199,6 +199,6 @@ public class BlockReplay {
BlockHeader blockHeader,
Blockchain blockchain,
MainnetTransactionProcessor transactionProcessor,
Wei dataGasPrice);
Wei blobGasPrice);
}
}

View File

@@ -54,7 +54,7 @@ public class BlockTracer {
private BlockReplay.TransactionAction<TransactionTrace> prepareReplayAction(
final MutableWorldState mutableWorldState, final DebugOperationTracer tracer) {
return (transaction, header, blockchain, transactionProcessor, dataGasPrice) -> {
return (transaction, header, blockchain, transactionProcessor, blobGasPrice) -> {
// if we have no prior updater, it must be the first TX, so use the block's initial state
if (chainedUpdater == null) {
chainedUpdater = mutableWorldState.updater();
@@ -73,7 +73,7 @@ public class BlockTracer {
tracer,
new CachingBlockHashLookup(header, blockchain),
false,
dataGasPrice);
blobGasPrice);
final List<TraceFrame> traceFrames = tracer.copyTraceFrames();
tracer.reset();
return new TransactionTrace(transaction, result, traceFrames);

View File

@@ -15,9 +15,9 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor;
import static java.util.function.Predicate.isEqual;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator.calculateExcessDataGasForParent;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams;
@@ -74,7 +74,7 @@ public class TransactionTracer {
mutableWorldState,
blockHash,
transactionHash,
(transaction, header, blockchain, transactionProcessor, dataGasPrice) -> {
(transaction, header, blockchain, transactionProcessor, blobGasPrice) -> {
final TransactionProcessingResult result =
processTransaction(
header,
@@ -83,7 +83,7 @@ public class TransactionTracer {
transaction,
transactionProcessor,
tracer,
dataGasPrice);
blobGasPrice);
return new TransactionTrace(transaction, result, tracer.getTraceFrames());
});
return transactionTrace;
@@ -116,14 +116,14 @@ public class TransactionTracer {
(body, header, blockchain, transactionProcessor, protocolSpec) -> {
WorldUpdater stackedUpdater = mutableWorldState.updater().updater();
final List<String> traces = new ArrayList<>();
final Wei dataGasPrice =
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.dataPricePerGas(
.blobGasPricePerGas(
blockchain
.getBlockHeader(header.getParentHash())
.map(parent -> calculateExcessDataGasForParent(protocolSpec, parent))
.orElse(DataGas.ZERO));
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
for (int i = 0; i < body.getTransactions().size(); i++) {
((StackedUpdater<?, ?>) stackedUpdater).markTransactionBoundary();
final Transaction transaction = body.getTransactions().get(i);
@@ -140,7 +140,7 @@ public class TransactionTracer {
transaction,
transactionProcessor,
new StandardJsonTracer(out, showMemory, true, true),
dataGasPrice);
blobGasPrice);
out.println(
summaryTrace(
transaction, timer.stop().elapsed(TimeUnit.NANOSECONDS), result));
@@ -157,7 +157,7 @@ public class TransactionTracer {
transaction,
transactionProcessor,
OperationTracer.NO_TRACING,
dataGasPrice);
blobGasPrice);
}
}
return Optional.of(traces);
@@ -188,7 +188,7 @@ public class TransactionTracer {
final Transaction transaction,
final MainnetTransactionProcessor transactionProcessor,
final OperationTracer tracer,
final Wei dataGasPrice) {
final Wei blobGasPrice) {
return transactionProcessor.processTransaction(
blockchain,
worldUpdater,
@@ -199,7 +199,7 @@ public class TransactionTracer {
new CachingBlockHashLookup(header, blockchain),
false,
ImmutableTransactionValidationParams.builder().isAllowFutureNonce(true).build(),
dataGasPrice);
blobGasPrice);
}
public static String summaryTrace(

View File

@@ -73,7 +73,7 @@ public enum RpcErrorType {
-32000, "Transaction nonce is too distant from current sender nonce"),
LOWER_NONCE_INVALID_TRANSACTION_EXISTS(
-32000, "An invalid transaction with a lower nonce exists"),
TOTAL_DATA_GAS_TOO_HIGH(-32000, "Total data gas too high"),
TOTAL_BLOB_GAS_TOO_HIGH(-32000, "Total blob gas too high"),
// Execution engine failures
UNKNOWN_PAYLOAD(-32001, "Payload does not exist / is not available"),
@@ -81,6 +81,7 @@ public enum RpcErrorType {
INVALID_FORKCHOICE_STATE(-38002, "Invalid forkchoice state"),
INVALID_PAYLOAD_ATTRIBUTES(-38003, "Invalid payload attributes"),
INVALID_RANGE_REQUEST_TOO_LARGE(-38004, "Too large request"),
UNSUPPORTED_FORK(-38005, "Unsupported fork"),
// Miner failures
COINBASE_NOT_SET(-32010, "Coinbase not set. Unable to start mining without a coinbase"),
NO_HASHES_PER_SECOND(-32011, "No hashes being generated by the current node"),

View File

@@ -30,6 +30,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.tuweni.bytes.Bytes32;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
@@ -84,8 +85,9 @@ public class BlockResult implements JsonRpcResult {
private final String withdrawalsRoot;
private final List<WithdrawalParameter> withdrawals;
private final String dataGasUsed;
private final String excessDataGas;
private final String blobGasUsed;
private final String excessBlobGas;
private final String parentBeaconBlockRoot;
public BlockResult(
final BlockHeader header,
@@ -132,8 +134,10 @@ public class BlockResult implements JsonRpcResult {
.map(w -> w.stream().map(WithdrawalParameter::fromWithdrawal).collect(toList()))
.orElse(null);
this.dataGasUsed = header.getDataGasUsed().map(Quantity::create).orElse(null);
this.excessDataGas = header.getExcessDataGas().map(Quantity::create).orElse(null);
this.blobGasUsed = header.getBlobGasUsed().map(Quantity::create).orElse(null);
this.excessBlobGas = header.getExcessBlobGas().map(Quantity::create).orElse(null);
this.parentBeaconBlockRoot =
header.getParentBeaconBlockRoot().map(Bytes32::toHexString).orElse(null);
}
@JsonGetter(value = "number")
@@ -257,13 +261,18 @@ public class BlockResult implements JsonRpcResult {
return withdrawals;
}
@JsonGetter(value = "dataGasUsed")
public String getDataGasUsed() {
return dataGasUsed;
@JsonGetter(value = "blobGasUsed")
public String getBlobGasUsed() {
return blobGasUsed;
}
@JsonGetter(value = "excessDataGas")
public String getExcessDataGas() {
return excessDataGas;
@JsonGetter(value = "excessBlobGas")
public String getExcessBlobGas() {
return excessBlobGas;
}
@JsonGetter(value = "parentBeaconBlockRoot")
public String getParentBeaconBlockRoot() {
return parentBeaconBlockRoot;
}
}

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.datatypes.AccessListEntry;
import java.util.Collection;
import java.util.List;

View File

@@ -27,11 +27,12 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.tuweni.bytes.Bytes32;
@JsonPropertyOrder({"executionPayload", "blockValue", "blobsBundle"})
@JsonPropertyOrder({"executionPayload", "blockValue", "blobsBundle", "shouldOverrideBuilder"})
public class EngineGetPayloadResultV3 {
protected final PayloadResult executionPayload;
private final String blockValue;
private final BlobsBundleV1 blobsBundle;
private final boolean shouldOverrideBuilder;
public EngineGetPayloadResultV3(
final BlockHeader header,
@@ -42,6 +43,7 @@ public class EngineGetPayloadResultV3 {
this.executionPayload = new PayloadResult(header, transactions, withdrawals);
this.blockValue = blockValue;
this.blobsBundle = blobsBundle;
this.shouldOverrideBuilder = false;
}
@JsonGetter(value = "executionPayload")
@@ -59,6 +61,11 @@ public class EngineGetPayloadResultV3 {
return blobsBundle;
}
@JsonGetter(value = "shouldOverrideBuilder")
public boolean shouldOverrideBuilder() {
return shouldOverrideBuilder;
}
public static class PayloadResult {
protected final String blockHash;
@@ -74,10 +81,9 @@ public class EngineGetPayloadResultV3 {
private final String timestamp;
private final String extraData;
private final String baseFeePerGas;
private final String excessDataGas;
private final String dataGasUsed;
private final String excessBlobGas;
private final String blobGasUsed;
private final String parentBeaconBlockRoot;
protected final List<String> transactions;
private final List<WithdrawalParameter> withdrawals;
@@ -108,9 +114,11 @@ public class EngineGetPayloadResultV3 {
.map(WithdrawalParameter::fromWithdrawal)
.collect(Collectors.toList()))
.orElse(null);
this.dataGasUsed = header.getDataGasUsed().map(Quantity::create).orElse(Quantity.HEX_ZERO);
this.excessDataGas =
header.getExcessDataGas().map(Quantity::create).orElse(Quantity.HEX_ZERO);
this.blobGasUsed = header.getBlobGasUsed().map(Quantity::create).orElse(Quantity.HEX_ZERO);
this.excessBlobGas =
header.getExcessBlobGas().map(Quantity::create).orElse(Quantity.HEX_ZERO);
this.parentBeaconBlockRoot =
header.getParentBeaconBlockRoot().map(Bytes32::toHexString).orElse(null);
}
@JsonGetter(value = "blockNumber")
@@ -189,14 +197,19 @@ public class EngineGetPayloadResultV3 {
return feeRecipient;
}
@JsonGetter(value = "excessDataGas")
public String getExcessDataGas() {
return excessDataGas;
@JsonGetter(value = "excessBlobGas")
public String getExcessBlobGas() {
return excessBlobGas;
}
@JsonGetter(value = "dataGasUsed")
public String getDataGasUseds() {
return dataGasUsed;
@JsonGetter(value = "blobGasUsed")
public String getBlobGasUseds() {
return blobGasUsed;
}
@JsonGetter(value = "parentBeaconBlockRoot")
public String getParentBeaconBlockRoot() {
return parentBeaconBlockRoot;
}
}
}

View File

@@ -14,12 +14,12 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.evm.AccessListEntry;
import java.util.List;
@@ -38,7 +38,7 @@ import org.apache.tuweni.bytes.Bytes;
"gasPrice",
"maxPriorityFeePerGas",
"maxFeePerGas",
"maxFeePerDataGas",
"maxFeePerBlobGas",
"hash",
"input",
"nonce",
@@ -73,7 +73,7 @@ public class TransactionCompleteResult implements TransactionResult {
private final String maxFeePerGas;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String maxFeePerDataGas;
private final String maxFeePerBlobGas;
private final String hash;
private final String input;
@@ -102,8 +102,8 @@ public class TransactionCompleteResult implements TransactionResult {
tx.getTransaction().getMaxPriorityFeePerGas().map(Wei::toShortHexString).orElse(null);
this.maxFeePerGas =
tx.getTransaction().getMaxFeePerGas().map(Wei::toShortHexString).orElse(null);
this.maxFeePerDataGas =
transaction.getMaxFeePerDataGas().map(Wei::toShortHexString).orElse(null);
this.maxFeePerBlobGas =
transaction.getMaxFeePerBlobGas().map(Wei::toShortHexString).orElse(null);
this.gasPrice =
Quantity.create(
transaction
@@ -165,9 +165,9 @@ public class TransactionCompleteResult implements TransactionResult {
return maxFeePerGas;
}
@JsonGetter(value = "maxFeePerDataGas")
public String getMaxFeePerDataGas() {
return maxFeePerDataGas;
@JsonGetter(value = "maxFeePerBlobGas")
public String getMaxFeePerBlobGas() {
return maxFeePerBlobGas;
}
@JsonGetter(value = "gasPrice")

View File

@@ -14,13 +14,13 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.evm.AccessListEntry;
import java.util.List;
@@ -36,7 +36,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
"gasPrice",
"maxPriorityFeePerGas",
"maxFeePerGas",
"maxFeePerDataGas",
"maxFeePerBlobGas",
"hash",
"input",
"nonce",
@@ -66,7 +66,7 @@ public class TransactionPendingResult implements TransactionResult {
private final String maxFeePerGas;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String maxFeePerDataGas;
private final String maxFeePerBlobGas;
private final String hash;
private final String input;
@@ -92,8 +92,8 @@ public class TransactionPendingResult implements TransactionResult {
this.maxPriorityFeePerGas =
transaction.getMaxPriorityFeePerGas().map(Wei::toShortHexString).orElse(null);
this.maxFeePerGas = transaction.getMaxFeePerGas().map(Wei::toShortHexString).orElse(null);
this.maxFeePerDataGas =
transaction.getMaxFeePerDataGas().map(Wei::toShortHexString).orElse(null);
this.maxFeePerBlobGas =
transaction.getMaxFeePerBlobGas().map(Wei::toShortHexString).orElse(null);
this.gasPrice = transaction.getGasPrice().map(Quantity::create).orElse(maxFeePerGas);
this.hash = transaction.getHash().toString();
this.input = transaction.getPayload().toString();
@@ -147,9 +147,9 @@ public class TransactionPendingResult implements TransactionResult {
return maxFeePerGas;
}
@JsonGetter(value = "maxFeePerDataGas")
public String getMaxFeePerDataGas() {
return maxFeePerDataGas;
@JsonGetter(value = "maxFeePerBlobGas")
public String getMaxFeePerBlobGas() {
return maxFeePerBlobGas;
}
@JsonGetter(value = "hash")

View File

@@ -47,8 +47,8 @@ import org.apache.tuweni.bytes.Bytes;
"transactionIndex",
"revertReason",
"type",
"dataGasUsed",
"dataGasPrice"
"blobGasUsed",
"blobGasPrice"
})
public abstract class TransactionReceiptResult {
@@ -69,8 +69,8 @@ public abstract class TransactionReceiptResult {
protected final TransactionReceipt receipt;
protected final String type;
private final String dataGasUsed;
private final String dataGasPrice;
private final String blobGasUsed;
private final String blobGasPrice;
protected TransactionReceiptResult(final TransactionReceiptWithMetadata receiptWithMetadata) {
final Transaction txn = receiptWithMetadata.getTransaction();
@@ -81,8 +81,8 @@ public abstract class TransactionReceiptResult {
this.cumulativeGasUsed = Quantity.create(receipt.getCumulativeGasUsed());
this.from = txn.getSender().toString();
this.gasUsed = Quantity.create(receiptWithMetadata.getGasUsed());
this.dataGasUsed = receiptWithMetadata.getDataGasUsed().map(Quantity::create).orElse(null);
this.dataGasPrice = receiptWithMetadata.getDataGasPrice().map(Quantity::create).orElse(null);
this.blobGasUsed = receiptWithMetadata.getBlobGasUsed().map(Quantity::create).orElse(null);
this.blobGasPrice = receiptWithMetadata.getBlobGasPrice().map(Quantity::create).orElse(null);
this.effectiveGasPrice =
Quantity.create(txn.getEffectiveGasPrice(receiptWithMetadata.getBaseFee()));
@@ -134,16 +134,16 @@ public abstract class TransactionReceiptResult {
return gasUsed;
}
@JsonGetter(value = "dataGasUsed")
@JsonGetter(value = "blobGasUsed")
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getDataGasUsed() {
return dataGasUsed;
public String getBlobGasUsed() {
return blobGasUsed;
}
@JsonGetter(value = "dataGasPrice")
@JsonGetter(value = "blobGasPrice")
@JsonInclude(JsonInclude.Include.NON_NULL)
public String getDataGasPrice() {
return dataGasPrice;
public String getBlobGasPrice() {
return blobGasPrice;
}
@JsonGetter(value = "effectiveGasPrice")

View File

@@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineE
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineExchangeTransitionConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV1;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV2;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineForkchoiceUpdatedV3;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetPayloadBodiesByHashV1;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetPayloadBodiesByRangeV1;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.EngineGetPayloadV1;
@@ -128,6 +129,12 @@ public class ExecutionEngineJsonRpcMethods extends ApiGroupJsonRpcMethods {
protocolContext,
mergeCoordinator.get(),
engineQosTimer),
new EngineForkchoiceUpdatedV3(
consensusEngineServer,
protocolSchedule,
protocolContext,
mergeCoordinator.get(),
engineQosTimer),
new EngineExchangeTransitionConfiguration(
consensusEngineServer, protocolContext, engineQosTimer),
new EngineGetPayloadBodiesByHashV1(

View File

@@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.api.query;
import static com.google.common.base.Preconditions.checkArgument;
import static org.hyperledger.besu.ethereum.api.query.cache.TransactionLogBloomCacher.BLOCKS_PER_BLOOM_CACHE;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator.calculateExcessDataGasForParent;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
@@ -642,11 +642,11 @@ public class BlockchainQueries {
- transactionReceipts.get(location.getTransactionIndex() - 1).getCumulativeGasUsed();
}
Optional<Long> maybeDataGasUsed =
getDataGasUsed(transaction, protocolSchedule.getByBlockHeader(header));
Optional<Long> maybeBlobGasUsed =
getBlobGasUsed(transaction, protocolSchedule.getByBlockHeader(header));
Optional<Wei> maybeDataGasPrice =
getDataGasPrice(transaction, header, protocolSchedule.getByBlockHeader(header));
Optional<Wei> maybeBlobGasPrice =
getBlobGasPrice(transaction, header, protocolSchedule.getByBlockHeader(header));
return Optional.of(
TransactionReceiptWithMetadata.create(
@@ -658,35 +658,35 @@ public class BlockchainQueries {
header.getBaseFee(),
blockhash,
header.getNumber(),
maybeDataGasUsed,
maybeDataGasPrice));
maybeBlobGasUsed,
maybeBlobGasPrice));
}
/**
* Calculates the data gas used for data in a transaction.
* Calculates the blob gas used for data in a transaction.
*
* @param transaction the transaction to calculate the gas for
* @param protocolSpec the protocol specification to use for gas calculation
* @return an Optional containing the data gas used for data if the transaction type supports
* @return an Optional containing the blob gas used for data if the transaction type supports
* blobs, otherwise returns an empty Optional
*/
private Optional<Long> getDataGasUsed(
private Optional<Long> getBlobGasUsed(
final Transaction transaction, final ProtocolSpec protocolSpec) {
return transaction.getType().supportsBlob()
? Optional.of(protocolSpec.getGasCalculator().dataGasCost(transaction.getBlobCount()))
? Optional.of(protocolSpec.getGasCalculator().blobGasCost(transaction.getBlobCount()))
: Optional.empty();
}
/**
* Calculates the data gas price for data in a transaction.
* Calculates the blob gas price for data in a transaction.
*
* @param transaction the transaction to calculate the gas price for
* @param header the block header of the current block
* @param protocolSpec the protocol specification to use for gas price calculation
* @return an Optional containing the data gas price for data if the transaction type supports
* @return an Optional containing the blob gas price for data if the transaction type supports
* blobs, otherwise returns an empty Optional
*/
private Optional<Wei> getDataGasPrice(
private Optional<Wei> getBlobGasPrice(
final Transaction transaction, final BlockHeader header, final ProtocolSpec protocolSpec) {
if (transaction.getType().supportsBlob()) {
return blockchain
@@ -695,8 +695,8 @@ public class BlockchainQueries {
parentHeader ->
protocolSpec
.getFeeMarket()
.dataPricePerGas(
calculateExcessDataGasForParent(protocolSpec, parentHeader)));
.blobGasPricePerGas(
calculateExcessBlobGasForParent(protocolSpec, parentHeader)));
}
return Optional.empty();
}

View File

@@ -30,8 +30,8 @@ public class TransactionReceiptWithMetadata {
private final long blockNumber;
private final Hash blockHash;
private final Transaction transaction;
private final Optional<Long> dataGasUsed;
private final Optional<Wei> dataGasPrice;
private final Optional<Long> blobGasUsed;
private final Optional<Wei> blobGasPrice;
private TransactionReceiptWithMetadata(
final TransactionReceipt receipt,
@@ -42,8 +42,8 @@ public class TransactionReceiptWithMetadata {
final Optional<Wei> baseFee,
final Hash blockHash,
final long blockNumber,
final Optional<Long> dataGasUsed,
final Optional<Wei> dataGasPrice) {
final Optional<Long> blobGasUsed,
final Optional<Wei> blobGasPrice) {
this.receipt = receipt;
this.transactionHash = transactionHash;
this.transactionIndex = transactionIndex;
@@ -52,8 +52,8 @@ public class TransactionReceiptWithMetadata {
this.blockHash = blockHash;
this.blockNumber = blockNumber;
this.transaction = transaction;
this.dataGasUsed = dataGasUsed;
this.dataGasPrice = dataGasPrice;
this.blobGasUsed = blobGasUsed;
this.blobGasPrice = blobGasPrice;
}
public static TransactionReceiptWithMetadata create(
@@ -65,8 +65,8 @@ public class TransactionReceiptWithMetadata {
final Optional<Wei> baseFee,
final Hash blockHash,
final long blockNumber,
final Optional<Long> dataGasUsed,
final Optional<Wei> dataGasPrice) {
final Optional<Long> blobGasUsed,
final Optional<Wei> blobGasPrice) {
return new TransactionReceiptWithMetadata(
receipt,
transaction,
@@ -76,8 +76,8 @@ public class TransactionReceiptWithMetadata {
baseFee,
blockHash,
blockNumber,
dataGasUsed,
dataGasPrice);
blobGasUsed,
blobGasPrice);
}
public TransactionReceipt getReceipt() {
@@ -114,11 +114,11 @@ public class TransactionReceiptWithMetadata {
return baseFee;
}
public Optional<Long> getDataGasUsed() {
return dataGasUsed;
public Optional<Long> getBlobGasUsed() {
return blobGasUsed;
}
public Optional<Wei> getDataGasPrice() {
return dataGasPrice;
public Optional<Wei> getBlobGasPrice() {
return blobGasPrice;
}
}

View File

@@ -45,8 +45,7 @@ public class EthJsonRpcHttpServiceTest extends AbstractJsonRpcHttpServiceTest {
@Test
public void getFilterChanges_noBlocks() throws Exception {
startService();
final String expectedRespBody =
String.format("{%n \"jsonrpc\" : \"2.0\",%n \"id\" : 2,%n \"result\" : [ ]%n}");
final String expectedRespBody = String.format("{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":[]}");
final ResponseBody body = ethNewBlockFilter(1).body();
final String result = getResult(body);
body.close();
@@ -60,7 +59,7 @@ public class EthJsonRpcHttpServiceTest extends AbstractJsonRpcHttpServiceTest {
BlockchainSetupUtil blockchainSetupUtil = startServiceWithEmptyChain(DataStorageFormat.FOREST);
final String expectedRespBody =
String.format(
"{%n \"jsonrpc\" : \"2.0\",%n \"id\" : 2,%n \"result\" : [ \"0x10aaf14a53caf27552325374429d3558398a36d3682ede6603c2c6511896e9f9\" ]%n}");
"{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":[\"0x10aaf14a53caf27552325374429d3558398a36d3682ede6603c2c6511896e9f9\"]}");
final ResponseBody body = ethNewBlockFilter(1).body();
final String result = getResult(body);
body.close();
@@ -75,8 +74,7 @@ public class EthJsonRpcHttpServiceTest extends AbstractJsonRpcHttpServiceTest {
@Test
public void getFilterChanges_noTransactions() throws Exception {
startService();
final String expectedRespBody =
String.format("{%n \"jsonrpc\" : \"2.0\",%n \"id\" : 2,%n \"result\" : [ ]%n}");
final String expectedRespBody = String.format("{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":[]}");
final ResponseBody body = ethNewPendingTransactionFilter(1).body();
final String result = getResult(body);
body.close();
@@ -96,18 +94,14 @@ public class EthJsonRpcHttpServiceTest extends AbstractJsonRpcHttpServiceTest {
final Response resp = ethGetFilterChanges(2, result);
assertThat(resp.code()).isEqualTo(200);
final String expectedRespBody =
String.format(
"{%n \"jsonrpc\" : \"2.0\",%n \"id\" : 2,%n \"result\" : [ \""
+ transactionHash
+ "\" ]%n}");
String.format("{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":[\"" + transactionHash + "\"]}");
assertThat(resp.body().string()).isEqualTo(expectedRespBody);
}
@Test
public void uninstallFilter() throws Exception {
startService();
final String expectedRespBody =
String.format("{%n \"jsonrpc\" : \"2.0\",%n \"id\" : 2,%n \"result\" : true%n}");
final String expectedRespBody = String.format("{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":true}");
final ResponseBody body = ethNewBlockFilter(1).body();
final String result = getResult(body);
body.close();

View File

@@ -23,6 +23,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
@@ -43,7 +44,6 @@ import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.evm.tracing.AccessListOperationTracer;
import java.util.ArrayList;

View File

@@ -165,6 +165,7 @@ public class EthGasPriceTest {
null,
null,
null,
null,
null),
new BlockBody(
List.of(
@@ -206,6 +207,7 @@ public class EthGasPriceTest {
null,
null,
null,
null,
null),
new BlockBody(List.of(), List.of())));
}

View File

@@ -23,7 +23,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
@@ -266,11 +266,11 @@ public class EthGetTransactionReceiptTest {
}
/**
* Test case to verify that the TransactionReceiptStatusResult contains data gas used and data gas
* Test case to verify that the TransactionReceiptStatusResult contains blob gas used and blob gas
* price when the transaction type is TransactionType#BLOB
*/
@Test
public void shouldContainDataGasUsedAndDataGasPriceWhenBlobTransaction() {
public void shouldContainBlobGasUsedAndBlobGasPriceWhenBlobTransaction() {
var hash = Hash.wrap(Bytes32.random());
mockBlockWithBlobTransaction(hash, 1L);
@@ -285,8 +285,8 @@ public class EthGetTransactionReceiptTest {
(TransactionReceiptStatusResult) response.getResult();
assertThat(result.getType()).isEqualTo("0x3");
assertThat(result.getDataGasUsed()).isEqualTo("0x20000");
assertThat(result.getDataGasPrice()).isEqualTo("0x1");
assertThat(result.getBlobGasUsed()).isEqualTo("0x20000");
assertThat(result.getBlobGasPrice()).isEqualTo("0x1");
}
private void mockBlockWithBlobTransaction(final Hash blockHash, final long blockNumber) {
@@ -306,7 +306,7 @@ public class EthGetTransactionReceiptTest {
when(block.getBody()).thenReturn(body);
when(body.getTransactions())
.thenReturn(List.of(new BlockDataGenerator().transaction(TransactionType.BLOB)));
when(parentHeader.getExcessDataGas()).thenReturn(Optional.of(DataGas.of(1000)));
when(parentHeader.getExcessBlobGas()).thenReturn(Optional.of(BlobGas.of(1000)));
when(blockchain.getBlockByHash(blockHash)).thenReturn(Optional.of(block));
mockProtocolSpec(header);
when(blockchain.getTransactionLocation(receiptHash))
@@ -315,7 +315,7 @@ public class EthGetTransactionReceiptTest {
private void mockProtocolSpec(final BlockHeader blockHeader) {
FeeMarket feeMarket = mock(CancunFeeMarket.class);
when(feeMarket.dataPricePerGas(any())).thenCallRealMethod();
when(feeMarket.blobGasPricePerGas(any())).thenCallRealMethod();
ProtocolSpec spec = mock(ProtocolSpec.class);
when(spec.getFeeMarket()).thenReturn(feeMarket);
when(spec.getGasCalculator()).thenReturn(new CancunGasCalculator());

View File

@@ -243,6 +243,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(System.currentTimeMillis()),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
null,
null);
var mockPayloadId =
PayloadIdentifier.forPayloadParams(
@@ -257,6 +258,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
Address.ECREC,
Optional.empty(),
Optional.empty()))
.thenReturn(mockPayloadId);
@@ -432,6 +434,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(System.currentTimeMillis()),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
null,
null);
var resp =
@@ -443,7 +446,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
var forkchoiceRes = (EngineUpdateForkchoiceResult) resp.getResult();
verify(mergeCoordinator, never()).preparePayload(any(), any(), any(), any(), any());
verify(mergeCoordinator, never()).preparePayload(any(), any(), any(), any(), any(), any());
assertThat(forkchoiceRes.getPayloadStatus().getStatus()).isEqualTo(VALID);
assertThat(forkchoiceRes.getPayloadStatus().getError()).isNull();
@@ -468,7 +471,8 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(timestampNotGreaterThanHead),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
emptyList());
emptyList(),
null);
var resp =
resp(
@@ -492,7 +496,8 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(System.currentTimeMillis()),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
emptyList());
emptyList(),
null);
var resp =
resp(
@@ -516,6 +521,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(System.currentTimeMillis()),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
null,
null);
var mockPayloadId =
@@ -531,6 +537,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
Address.ECREC,
Optional.empty(),
Optional.empty()))
.thenReturn(mockPayloadId);
@@ -557,6 +564,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(System.currentTimeMillis()),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
null,
null);
var resp =
@@ -592,7 +600,8 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(System.currentTimeMillis()),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
withdrawalParameters);
withdrawalParameters,
null);
final Optional<List<Withdrawal>> withdrawals =
Optional.of(
@@ -613,7 +622,8 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
Address.ECREC,
withdrawals))
withdrawals,
Optional.empty()))
.thenReturn(mockPayloadId);
assertSuccessWithPayloadForForkchoiceResult(
@@ -638,6 +648,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
String.valueOf(System.currentTimeMillis()),
Bytes32.fromHexStringLenient("0xDEADBEEF").toHexString(),
Address.ECREC.toString(),
null,
null);
var mockPayloadId =
@@ -653,6 +664,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
Address.ECREC,
Optional.empty(),
Optional.empty()))
.thenReturn(mockPayloadId);

View File

@@ -31,7 +31,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.merge.MergeContext;
import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
@@ -98,6 +98,7 @@ public abstract class AbstractEngineNewPayloadTest {
new ScheduledProtocolSpec.Hardfork("Cancun", 30);
protected final ScheduledProtocolSpec.Hardfork experimentalHardfork =
new ScheduledProtocolSpec.Hardfork("Experimental", 40);
protected Optional<Bytes32> maybeParentBeaconBlockRoot = Optional.empty();
@FunctionalInterface
interface MethodFactory {
@@ -183,7 +184,7 @@ public abstract class AbstractEngineNewPayloadTest {
lenient()
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
.thenReturn(Optional.of(mock(BlockHeader.class)));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
assertValidResponse(mockHeader, resp);
}
@@ -196,7 +197,7 @@ public abstract class AbstractEngineNewPayloadTest {
lenient()
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
.thenReturn(Optional.of(mock(BlockHeader.class)));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash().get()).isEqualTo(mockHash);
@@ -219,7 +220,7 @@ public abstract class AbstractEngineNewPayloadTest {
.thenReturn(true);
}
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash()).isEmpty();
@@ -236,7 +237,7 @@ public abstract class AbstractEngineNewPayloadTest {
when(blockchain.getBlockByHash(any())).thenReturn(Optional.of(mockBlock));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
assertValidResponse(mockHeader, resp);
}
@@ -251,7 +252,7 @@ public abstract class AbstractEngineNewPayloadTest {
when(mergeCoordinator.getLatestValidHashOfBadBlock(mockHeader.getHash()))
.thenReturn(Optional.of(latestValidHash));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash()).isEqualTo(Optional.of(latestValidHash));
@@ -269,7 +270,7 @@ public abstract class AbstractEngineNewPayloadTest {
lenient()
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
.thenReturn(Optional.of(mock(BlockHeader.class)));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
fromErrorResp(resp);
verify(engineCallListener, times(1)).executionEngineCalled();
@@ -288,7 +289,7 @@ public abstract class AbstractEngineNewPayloadTest {
lenient()
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
.thenReturn(Optional.of(mock(BlockHeader.class)));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
verify(engineCallListener, times(1)).executionEngineCalled();
verify(mergeCoordinator, times(0)).addBadBlock(any(), any());
@@ -311,7 +312,7 @@ public abstract class AbstractEngineNewPayloadTest {
}
when(mergeCoordinator.rememberBlock(any())).thenThrow(new MerkleTrieException("missing leaf"));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
verify(engineCallListener, times(1)).executionEngineCalled();
verify(mergeCoordinator, never()).addBadBlock(any(), any());
@@ -332,7 +333,7 @@ public abstract class AbstractEngineNewPayloadTest {
.when(mergeCoordinator.latestValidAncestorDescendsFromTerminal(any(BlockHeader.class)))
.thenReturn(true);
lenient().when(mockHeader.getHash()).thenReturn(Hash.fromHexStringLenient("0x1337"));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getStatusAsString()).isEqualTo(getExpectedInvalidBlockHashStatus().name());
@@ -345,7 +346,7 @@ public abstract class AbstractEngineNewPayloadTest {
BlockHeader paramHeader = spy(realHeader);
when(paramHeader.getHash()).thenReturn(Hash.fromHexStringLenient("0x1337"));
var resp = resp(mockPayload(paramHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(paramHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash()).isEmpty();
@@ -359,7 +360,7 @@ public abstract class AbstractEngineNewPayloadTest {
when(mergeCoordinator.getLatestValidAncestor(any(Hash.class)))
.thenReturn(Optional.of(mockHash));
var resp = resp(mockPayload(mockHeader, List.of("0xDEAD", "0xBEEF")));
var resp = resp(mockEnginePayload(mockHeader, List.of("0xDEAD", "0xBEEF")));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash().get()).isEqualTo(mockHash);
@@ -372,7 +373,7 @@ public abstract class AbstractEngineNewPayloadTest {
public void shouldRespondWithSyncingDuringForwardSync() {
BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty());
when(mergeContext.isSyncing()).thenReturn(Boolean.TRUE);
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getError()).isNull();
@@ -386,7 +387,7 @@ public abstract class AbstractEngineNewPayloadTest {
BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty());
when(mergeCoordinator.appendNewPayloadToSync(any()))
.thenReturn(CompletableFuture.completedFuture(null));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash()).isEmpty();
@@ -402,7 +403,7 @@ public abstract class AbstractEngineNewPayloadTest {
when(paramHeader.getHash()).thenReturn(Hash.fromHexStringLenient("0x1337"));
when(paramHeader.getExtraData().toHexString()).thenReturn(null);
var resp = resp(mockPayload(paramHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(paramHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash()).isEmpty();
@@ -415,7 +416,7 @@ public abstract class AbstractEngineNewPayloadTest {
public void shouldReturnInvalidWhenBadBlock() {
when(mergeCoordinator.isBadBlock(any(Hash.class))).thenReturn(true);
BlockHeader mockHeader = createBlockHeader(Optional.empty(), Optional.empty());
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
when(protocolSpec.getWithdrawalsValidator())
.thenReturn(new WithdrawalsValidator.AllowedWithdrawals());
EnginePayloadStatusResult res = fromSuccessResp(resp);
@@ -436,27 +437,31 @@ public abstract class AbstractEngineNewPayloadTest {
lenient()
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
.thenReturn(Optional.of(mock(BlockHeader.class)));
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
assertValidResponse(mockHeader, resp);
}
protected JsonRpcResponse resp(final EnginePayloadParameter payload) {
Object[] params =
maybeParentBeaconBlockRoot
.map(bytes32 -> new Object[] {payload, null, bytes32.toHexString()})
.orElseGet(() -> new Object[] {payload});
return method.response(
new JsonRpcRequestContext(
new JsonRpcRequest("2.0", this.method.getName(), new Object[] {payload})));
new JsonRpcRequestContext(new JsonRpcRequest("2.0", this.method.getName(), params)));
}
protected EnginePayloadParameter mockPayload(final BlockHeader header, final List<String> txs) {
return mockPayload(header, txs, null, null, null);
protected EnginePayloadParameter mockEnginePayload(
final BlockHeader header, final List<String> txs) {
return mockEnginePayload(header, txs, null, null, null);
}
protected EnginePayloadParameter mockPayload(
protected EnginePayloadParameter mockEnginePayload(
final BlockHeader header,
final List<String> txs,
final List<WithdrawalParameter> withdrawals,
final List<DepositParameter> deposits) {
return mockPayload(
return mockEnginePayload(
header,
txs,
withdrawals,
@@ -464,7 +469,7 @@ public abstract class AbstractEngineNewPayloadTest {
List.of(VersionedHash.DEFAULT_VERSIONED_HASH.toBytes()));
}
protected EnginePayloadParameter mockPayload(
protected EnginePayloadParameter mockEnginePayload(
final BlockHeader header,
final List<String> txs,
final List<WithdrawalParameter> withdrawals,
@@ -486,8 +491,8 @@ public abstract class AbstractEngineNewPayloadTest {
header.getPrevRandao().map(Bytes32::toHexString).orElse("0x0"),
txs,
withdrawals,
header.getDataGasUsed().map(UnsignedLongParameter::new).orElse(null),
header.getExcessDataGas().map(DataGas::toHexString).orElse(null),
header.getBlobGasUsed().map(UnsignedLongParameter::new).orElse(null),
header.getExcessBlobGas().map(BlobGas::toHexString).orElse(null),
versionedHashes,
deposits);
}
@@ -550,6 +555,7 @@ public abstract class AbstractEngineNewPayloadTest {
.timestamp(parentBlockHeader.getTimestamp() + 1)
.withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null))
.depositsRoot(maybeDeposits.map(BodyValidation::depositsRoot).orElse(null))
.parentBeaconBlockRoot(maybeParentBeaconBlockRoot)
.buildHeader();
return mockHeader;
}

View File

@@ -253,6 +253,7 @@ public class EngineExchangeTransitionConfigurationTest {
null,
null,
null,
null,
new BlockHeaderFunctions() {
@Override
public Hash hash(final BlockHeader header) {

View File

@@ -24,8 +24,8 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.merge.blockcreation.PayloadIdentifier;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
@@ -100,7 +100,7 @@ public class EngineGetPayloadV3Test extends AbstractEngineGetPayloadTest {
new BlockHeaderTestFixture()
.prevRandao(Bytes32.random())
.timestamp(CANCUN_AT + 1)
.excessDataGas(DataGas.of(10L))
.excessBlobGas(BlobGas.of(10L))
.buildHeader();
// should return withdrawals and excessGas for a post-cancun block
PayloadIdentifier postCancunPid =
@@ -119,7 +119,7 @@ public class EngineGetPayloadV3Test extends AbstractEngineGetPayloadTest {
.type(TransactionType.BLOB)
.chainId(Optional.of(BigInteger.ONE))
.maxFeePerGas(Optional.of(Wei.of(15)))
.maxFeePerDataGas(Optional.of(Wei.of(128)))
.maxFeePerBlobGas(Optional.of(Wei.of(128)))
.maxPriorityFeePerGas(Optional.of(Wei.of(1)))
.blobsWithCommitments(Optional.of(bwc))
.versionedHashes(Optional.of(bwc.getVersionedHashes()))
@@ -153,10 +153,10 @@ public class EngineGetPayloadV3Test extends AbstractEngineGetPayloadTest {
assertThat(res.getBlockValue()).isEqualTo(Quantity.create(0));
assertThat(res.getExecutionPayload().getPrevRandao())
.isEqualTo(cancunHeader.getPrevRandao().map(Bytes32::toString).orElse(""));
// excessDataGas: QUANTITY, 256 bits
// excessBlobGas: QUANTITY, 256 bits
String expectedQuantityOf10 = Bytes32.leftPad(Bytes.of(10)).toQuantityHexString();
assertThat(res.getExecutionPayload().getExcessDataGas()).isNotEmpty();
assertThat(res.getExecutionPayload().getExcessDataGas())
assertThat(res.getExecutionPayload().getExcessBlobGas()).isNotEmpty();
assertThat(res.getExecutionPayload().getExcessBlobGas())
.isEqualTo(expectedQuantityOf10);
});
verify(engineCallListener, times(1)).executionEngineCalled();

View File

@@ -26,7 +26,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.BlockProcessingOutputs;
import org.hyperledger.besu.ethereum.BlockProcessingResult;
@@ -44,6 +44,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -60,6 +61,7 @@ public class EngineNewPayloadEIP6110Test extends EngineNewPayloadV3Test {
@Override
public void before() {
super.before();
maybeParentBeaconBlockRoot = Optional.of(Bytes32.ZERO);
this.method =
new EngineNewPayloadV3(
vertx,
@@ -96,7 +98,7 @@ public class EngineNewPayloadEIP6110Test extends EngineNewPayloadV3Test {
.thenReturn(Optional.of(mockHeader.getHash()));
when(mergeCoordinator.latestValidAncestorDescendsFromTerminal(mockHeader)).thenReturn(true);
var resp = resp(mockPayload(mockHeader, Collections.emptyList(), null, deposits, null));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, deposits, null));
assertValidResponse(mockHeader, resp);
}
@@ -110,7 +112,7 @@ public class EngineNewPayloadEIP6110Test extends EngineNewPayloadV3Test {
var resp =
resp(
mockPayload(
mockEnginePayload(
createBlockHeader(Optional.empty(), Optional.empty()),
Collections.emptyList(),
null,
@@ -136,7 +138,7 @@ public class EngineNewPayloadEIP6110Test extends EngineNewPayloadV3Test {
when(mergeCoordinator.getLatestValidAncestor(mockHeader))
.thenReturn(Optional.of(mockHeader.getHash()));
when(mergeCoordinator.latestValidAncestorDescendsFromTerminal(mockHeader)).thenReturn(true);
var resp = resp(mockPayload(mockHeader, Collections.emptyList(), null, depositsParam));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList(), null, depositsParam));
assertValidResponse(mockHeader, resp);
}
@@ -150,7 +152,7 @@ public class EngineNewPayloadEIP6110Test extends EngineNewPayloadV3Test {
var resp =
resp(
mockPayload(
mockEnginePayload(
createBlockHeader(Optional.empty(), Optional.of(Collections.emptyList())),
Collections.emptyList(),
null,
@@ -169,8 +171,8 @@ public class EngineNewPayloadEIP6110Test extends EngineNewPayloadV3Test {
new BlockHeaderTestFixture()
.baseFeePerGas(Wei.ONE)
.timestamp(super.experimentalHardfork.milestone())
.excessDataGas(DataGas.ZERO)
.dataGasUsed(100L)
.excessBlobGas(BlobGas.ZERO)
.blobGasUsed(100L)
.buildHeader();
BlockHeader mockHeader =
@@ -180,9 +182,11 @@ public class EngineNewPayloadEIP6110Test extends EngineNewPayloadV3Test {
.number(parentBlockHeader.getNumber() + 1)
.timestamp(parentBlockHeader.getTimestamp() + 1)
.withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null))
.excessDataGas(DataGas.ZERO)
.dataGasUsed(100L)
.excessBlobGas(BlobGas.ZERO)
.blobGasUsed(100L)
.depositsRoot(maybeDeposits.map(BodyValidation::depositsRoot).orElse(null))
.parentBeaconBlockRoot(
maybeParentBeaconBlockRoot.isPresent() ? maybeParentBeaconBlockRoot : null)
.buildHeader();
return mockHeader;
}

View File

@@ -74,7 +74,7 @@ public class EngineNewPayloadV1Test extends AbstractEngineNewPayloadTest {
when(mergeCoordinator.latestValidAncestorDescendsFromTerminal(any(BlockHeader.class)))
.thenReturn(false);
var resp = resp(mockPayload(mockHeader, Collections.emptyList()));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList()));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getLatestValidHash()).isEqualTo(Optional.of(Hash.ZERO));

View File

@@ -84,7 +84,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
lenient()
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
.thenReturn(Optional.of(mock(BlockHeader.class)));
var resp = resp(mockPayload(mockHeader, Collections.emptyList(), withdrawalsParam, null));
var resp = resp(mockEnginePayload(mockHeader, Collections.emptyList(), withdrawalsParam, null));
assertValidResponse(mockHeader, resp);
}
@@ -102,7 +102,8 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
lenient()
.when(blockchain.getBlockHeader(mockHeader.getParentHash()))
.thenReturn(Optional.of(mock(BlockHeader.class)));
var resp = resp(mockPayload(mockHeader, Collections.emptyList(), withdrawals, null, null));
var resp =
resp(mockEnginePayload(mockHeader, Collections.emptyList(), withdrawals, null, null));
assertValidResponse(mockHeader, resp);
}
@@ -116,7 +117,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
var resp =
resp(
mockPayload(
mockEnginePayload(
createBlockHeader(Optional.of(Collections.emptyList()), Optional.empty()),
Collections.emptyList(),
withdrawals,
@@ -136,7 +137,7 @@ public class EngineNewPayloadV2Test extends AbstractEngineNewPayloadTest {
var resp =
resp(
mockPayload(
mockEnginePayload(
createBlockHeader(Optional.empty(), Optional.empty()),
Collections.emptyList(),
withdrawals,

View File

@@ -20,7 +20,7 @@ import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
@@ -39,6 +39,7 @@ import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -59,6 +60,7 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
@Override
public void before() {
super.before();
maybeParentBeaconBlockRoot = Optional.of(Bytes32.ZERO);
this.method =
new EngineNewPayloadV3(
vertx,
@@ -73,14 +75,23 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
@Test
public void shouldInvalidPayloadOnShortVersionedHash() {
Bytes shortHash = Bytes.fromHexString("0x" + "69".repeat(31));
EnginePayloadParameter payload = mock(EnginePayloadParameter.class);
when(payload.getTimestamp()).thenReturn(30l);
when(payload.getExcessBlobGas()).thenReturn("99");
when(payload.getBlobGasUsed()).thenReturn(9l);
JsonRpcResponse badParam =
method.response(
new JsonRpcRequestContext(
new JsonRpcRequest(
"2.0",
RpcMethod.ENGINE_NEW_PAYLOAD_V3.getMethodName(),
new Object[] {payload, List.of(shortHash.toHexString())})));
new Object[] {
payload,
List.of(shortHash.toHexString()),
"0x0000000000000000000000000000000000000000000000000000000000000000"
})));
EnginePayloadStatusResult res = fromSuccessResp(badParam);
assertThat(res.getStatusAsString()).isEqualTo(INVALID.name());
assertThat(res.getError()).isEqualTo("Invalid versionedHash");
@@ -95,7 +106,7 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
.baseFeePerGas(Wei.ONE)
.timestamp(super.cancunHardfork.milestone())
.buildHeader();
// protocolContext.getBlockchain().getBlockHeader(blockParam.getParentHash());
when(blockchain.getBlockHeader(parentBlockHeader.getBlockHash()))
.thenReturn(Optional.of(parentBlockHeader));
when(protocolContext.getBlockchain()).thenReturn(blockchain);
@@ -107,8 +118,10 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
.timestamp(parentBlockHeader.getTimestamp() + 12)
.withdrawalsRoot(maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null))
.depositsRoot(maybeDeposits.map(BodyValidation::depositsRoot).orElse(null))
.excessDataGas(DataGas.ZERO)
.dataGasUsed(0L)
.excessBlobGas(BlobGas.ZERO)
.blobGasUsed(0L)
.parentBeaconBlockRoot(
maybeParentBeaconBlockRoot.isPresent() ? maybeParentBeaconBlockRoot : null)
.buildHeader();
return mockHeader;
}

View File

@@ -99,12 +99,14 @@ public class EnginePayloadAttributesParameterTest {
private EnginePayloadAttributesParameter parameterWithdrawalsOmitted() {
return new EnginePayloadAttributesParameter(
TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, null);
TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, null, null);
}
private EnginePayloadAttributesParameter parameterWithdrawalsPresent() {
final List<WithdrawalParameter> withdrawals = List.of(WITHDRAWAL_PARAM_1, WITHDRAWAL_PARAM_2);
return new EnginePayloadAttributesParameter(
TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, withdrawals);
TIMESTAMP, PREV_RANDAO, SUGGESTED_FEE_RECIPIENT_ADDRESS, withdrawals, null);
}
// TODO: add a parent beacon block root test here
}

View File

@@ -120,7 +120,7 @@ public class TransactionTracerTest {
when(blockchain.getChainHeadHeader()).thenReturn(blockHeader);
when(protocolSpec.getBadBlocksManager()).thenReturn(new BadBlockManager());
when(protocolSpec.getGasCalculator()).thenReturn(gasCalculator);
lenient().when(gasCalculator.computeExcessDataGas(anyLong(), anyInt())).thenReturn(0L);
lenient().when(gasCalculator.computeExcessBlobGas(anyLong(), anyInt())).thenReturn(0L);
}
@Test

View File

@@ -117,6 +117,7 @@ public class BlockchainQueriesLogCacheTest {
null,
null,
null,
null,
new MainnetBlockHeaderFunctions());
testHash = fakeHeader.getHash();
final BlockBody fakeBody = new BlockBody(Collections.emptyList(), Collections.emptyList());

View File

@@ -109,6 +109,7 @@ public class TransactionLogBloomCacherTest {
null,
null,
null,
null,
new MainnetBlockHeaderFunctions());
testHash = fakeHeader.getHash();
when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(fakeHeader));
@@ -283,6 +284,7 @@ public class TransactionLogBloomCacherTest {
null,
null,
null,
null,
new MainnetBlockHeaderFunctions());
testHash = fakeHeader.getHash();
when(blockchain.getBlockHeader(number)).thenReturn(Optional.of(fakeHeader));

View File

@@ -18,13 +18,13 @@ package org.hyperledger.besu.ethereum.api.util;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.evm.AccessListEntry;
import java.math.BigInteger;
import java.util.List;

View File

@@ -14,10 +14,10 @@
*/
package org.hyperledger.besu.ethereum.blockcreation;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator.calculateExcessDataGasForParent;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
@@ -42,11 +42,13 @@ import org.hyperledger.besu.ethereum.mainnet.BodyValidation;
import org.hyperledger.besu.ethereum.mainnet.DepositsValidator;
import org.hyperledger.besu.ethereum.mainnet.DifficultyCalculator;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ParentBeaconBlockRootHelper;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.WithdrawalsProcessor;
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.evm.account.EvmAccount;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
@@ -152,7 +154,13 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final Optional<List<BlockHeader>> maybeOmmers,
final long timestamp) {
return createBlock(
maybeTransactions, maybeOmmers, Optional.empty(), Optional.empty(), timestamp, true);
maybeTransactions,
maybeOmmers,
Optional.empty(),
Optional.empty(),
Optional.empty(),
timestamp,
true);
}
protected BlockCreationResult createBlock(
@@ -160,6 +168,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final Optional<List<BlockHeader>> maybeOmmers,
final Optional<List<Withdrawal>> maybeWithdrawals,
final Optional<Bytes32> maybePrevRandao,
final Optional<Bytes32> maybeParentBeaconBlockRoot,
final long timestamp,
boolean rewardCoinbase) {
@@ -168,18 +177,24 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
protocolSchedule.getForNextBlockHeader(parentHeader, timestamp);
final ProcessableBlockHeader processableBlockHeader =
createPendingBlockHeader(timestamp, maybePrevRandao, newProtocolSpec);
createPendingBlockHeader(
timestamp, maybePrevRandao, maybeParentBeaconBlockRoot, newProtocolSpec);
final Address miningBeneficiary =
miningBeneficiaryCalculator.getMiningBeneficiary(processableBlockHeader.getNumber());
Wei dataGasPrice =
Wei blobGasPrice =
newProtocolSpec
.getFeeMarket()
.dataPricePerGas(calculateExcessDataGasForParent(newProtocolSpec, parentHeader));
.blobGasPricePerGas(calculateExcessBlobGasForParent(newProtocolSpec, parentHeader));
throwIfStopped();
final List<BlockHeader> ommers = maybeOmmers.orElse(selectOmmers());
if (maybeParentBeaconBlockRoot.isPresent()) {
ParentBeaconBlockRootHelper.storeParentBeaconBlockRoot(
disposableWorldState.updater(), timestamp, maybeParentBeaconBlockRoot.get());
}
throwIfStopped();
final TransactionSelectionResults transactionResults =
selectTransactions(
@@ -187,7 +202,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
disposableWorldState,
maybeTransactions,
miningBeneficiary,
dataGasPrice,
blobGasPrice,
newProtocolSpec);
transactionResults.logSelectionStats();
@@ -230,7 +245,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
throwIfStopped();
final GasUsage usage = computeExcessDataGas(transactionResults, newProtocolSpec);
final GasUsage usage = computeExcessBlobGas(transactionResults, newProtocolSpec);
throwIfStopped();
@@ -251,7 +266,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
: null)
.depositsRoot(maybeDeposits.map(BodyValidation::depositsRoot).orElse(null));
if (usage != null) {
builder.dataGasUsed(usage.used.toLong()).excessDataGas(usage.excessDataGas);
builder.blobGasUsed(usage.used.toLong()).excessBlobGas(usage.excessBlobGas);
}
final SealableBlockHeader sealableBlockHeader = builder.buildSealableBlockHeader();
@@ -288,10 +303,9 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
.toList();
}
record GasUsage(DataGas excessDataGas, DataGas used) {}
;
record GasUsage(BlobGas excessBlobGas, BlobGas used) {}
private GasUsage computeExcessDataGas(
private GasUsage computeExcessBlobGas(
final TransactionSelectionResults transactionResults, final ProtocolSpec newProtocolSpec) {
if (newProtocolSpec.getFeeMarket().implementsDataFee()) {
@@ -301,14 +315,12 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
.map(tx -> tx.getVersionedHashes().orElseThrow())
.mapToInt(List::size)
.sum();
// casting parent excess data gas to long since for the moment it should be well below that
// casting parent excess blob gas to long since for the moment it should be well below that
// limit
DataGas excessDataGas =
DataGas.of(
gasCalculator.computeExcessDataGas(
parentHeader.getExcessDataGas().map(DataGas::toLong).orElse(0L), newBlobsCount));
DataGas used = DataGas.of(gasCalculator.dataGasCost(newBlobsCount));
return new GasUsage(excessDataGas, used);
BlobGas excessBlobGas =
ExcessBlobGasCalculator.calculateExcessBlobGasForParent(newProtocolSpec, parentHeader);
BlobGas used = BlobGas.of(gasCalculator.blobGasCost(newBlobsCount));
return new GasUsage(excessBlobGas, used);
}
return null;
}
@@ -318,7 +330,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final MutableWorldState disposableWorldState,
final Optional<List<Transaction>> transactions,
final Address miningBeneficiary,
final Wei dataGasPrice,
final Wei blobGasPrice,
final ProtocolSpec protocolSpec)
throws RuntimeException {
final MainnetTransactionProcessor transactionProcessor = protocolSpec.getTransactionProcessor();
@@ -338,7 +350,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
minBlockOccupancyRatio,
isCancelled::get,
miningBeneficiary,
dataGasPrice,
blobGasPrice,
protocolSpec.getFeeMarket(),
protocolSpec.getGasCalculator(),
protocolSpec.getGasLimitCalculator(),
@@ -374,6 +386,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
private ProcessableBlockHeader createPendingBlockHeader(
final long timestamp,
final Optional<Bytes32> maybePrevRandao,
final Optional<Bytes32> maybeParentBeaconBlockRoot,
final ProtocolSpec protocolSpec) {
final long newBlockNumber = parentHeader.getNumber() + 1;
long gasLimit =
@@ -402,6 +415,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
.orElse(null);
final Bytes32 prevRandao = maybePrevRandao.orElse(null);
final Bytes32 parentBeaconBlockRoot = maybeParentBeaconBlockRoot.orElse(null);
return BlockHeaderBuilder.create()
.parentHash(parentHeader.getHash())
.coinbase(coinbase)
@@ -411,6 +425,7 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
.timestamp(timestamp)
.baseFee(baseFee)
.prevRandao(prevRandao)
.parentBeaconBlockRoot(parentBeaconBlockRoot)
.buildProcessableBlockHeader();
}

View File

@@ -88,27 +88,27 @@ public class BlockTransactionSelector {
private final Map<Transaction, TransactionSelectionResult> notSelectedTransactions =
new HashMap<>();
private long cumulativeGasUsed = 0;
private long cumulativeDataGasUsed = 0;
private long cumulativeBlobGasUsed = 0;
private void updateSelected(
final Transaction transaction,
final TransactionReceipt receipt,
final long gasUsed,
final long dataGasUsed) {
final long blobGasUsed) {
selectedTransactions.add(transaction);
transactionsByType
.computeIfAbsent(transaction.getType(), type -> new ArrayList<>())
.add(transaction);
receipts.add(receipt);
cumulativeGasUsed += gasUsed;
cumulativeDataGasUsed += dataGasUsed;
cumulativeBlobGasUsed += blobGasUsed;
LOG.atTrace()
.setMessage(
"New selected transaction {}, total transactions {}, cumulative gas used {}, cumulative data gas used {}")
"New selected transaction {}, total transactions {}, cumulative gas used {}, cumulative blob gas used {}")
.addArgument(transaction::toTraceLog)
.addArgument(selectedTransactions::size)
.addArgument(cumulativeGasUsed)
.addArgument(cumulativeDataGasUsed)
.addArgument(cumulativeBlobGasUsed)
.log();
}
@@ -133,8 +133,8 @@ public class BlockTransactionSelector {
return cumulativeGasUsed;
}
public long getCumulativeDataGasUsed() {
return cumulativeDataGasUsed;
public long getCumulativeBlobGasUsed() {
return cumulativeBlobGasUsed;
}
public Map<Transaction, TransactionSelectionResult> getNotSelectedTransactions() {
@@ -174,7 +174,7 @@ public class BlockTransactionSelector {
}
TransactionSelectionResults that = (TransactionSelectionResults) o;
return cumulativeGasUsed == that.cumulativeGasUsed
&& cumulativeDataGasUsed == that.cumulativeDataGasUsed
&& cumulativeBlobGasUsed == that.cumulativeBlobGasUsed
&& selectedTransactions.equals(that.selectedTransactions)
&& notSelectedTransactions.equals(that.notSelectedTransactions)
&& receipts.equals(that.receipts);
@@ -187,14 +187,14 @@ public class BlockTransactionSelector {
notSelectedTransactions,
receipts,
cumulativeGasUsed,
cumulativeDataGasUsed);
cumulativeBlobGasUsed);
}
public String toTraceLog() {
return "cumulativeGasUsed="
+ cumulativeGasUsed
+ ", cumulativeDataGasUsed="
+ cumulativeDataGasUsed
+ ", cumulativeBlobGasUsed="
+ cumulativeBlobGasUsed
+ ", selectedTransactions="
+ selectedTransactions.stream()
.map(Transaction::toTraceLog)
@@ -219,7 +219,7 @@ public class BlockTransactionSelector {
private final TransactionPool transactionPool;
private final AbstractBlockProcessor.TransactionReceiptFactory transactionReceiptFactory;
private final Address miningBeneficiary;
private final Wei dataGasPrice;
private final Wei blobGasPrice;
private final FeeMarket feeMarket;
private final GasCalculator gasCalculator;
private final GasLimitCalculator gasLimitCalculator;
@@ -238,7 +238,7 @@ public class BlockTransactionSelector {
final Double minBlockOccupancyRatio,
final Supplier<Boolean> isCancelled,
final Address miningBeneficiary,
final Wei dataGasPrice,
final Wei blobGasPrice,
final FeeMarket feeMarket,
final GasCalculator gasCalculator,
final GasLimitCalculator gasLimitCalculator,
@@ -253,7 +253,7 @@ public class BlockTransactionSelector {
this.minTransactionGasPrice = minTransactionGasPrice;
this.minBlockOccupancyRatio = minBlockOccupancyRatio;
this.miningBeneficiary = miningBeneficiary;
this.dataGasPrice = dataGasPrice;
this.blobGasPrice = blobGasPrice;
this.feeMarket = feeMarket;
this.gasCalculator = gasCalculator;
this.gasLimitCalculator = gasLimitCalculator;
@@ -354,7 +354,7 @@ public class BlockTransactionSelector {
blockHashLookup,
false,
TransactionValidationParams.mining(),
dataGasPrice);
blobGasPrice);
if (!effectiveResult.isInvalid()) {
@@ -379,10 +379,10 @@ public class BlockTransactionSelector {
transactionReceiptFactory.create(
transaction.getType(), effectiveResult, worldState, cumulativeGasUsed);
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
final long blobGasUsed = gasCalculator.blobGasCost(transaction.getBlobCount());
transactionSelectionResults.updateSelected(
transaction, receipt, gasUsedByTransaction, dataGasUsed);
transaction, receipt, gasUsedByTransaction, blobGasUsed);
LOG.atTrace()
.setMessage("Selected {} for block creation")
@@ -406,7 +406,7 @@ public class BlockTransactionSelector {
private boolean transactionDataPriceBelowMin(final Transaction transaction) {
if (transaction.getType().supportsBlob()) {
if (transaction.getMaxFeePerDataGas().orElseThrow().lessThan(dataGasPrice)) {
if (transaction.getMaxFeePerBlobGas().orElseThrow().lessThan(blobGasPrice)) {
return true;
}
}
@@ -469,15 +469,15 @@ public class BlockTransactionSelector {
}
private boolean transactionTooLargeForBlock(final Transaction transaction) {
final long dataGasUsed = gasCalculator.dataGasCost(transaction.getBlobCount());
final long blobGasUsed = gasCalculator.blobGasCost(transaction.getBlobCount());
if (dataGasUsed
> gasLimitCalculator.currentDataGasLimit()
- transactionSelectionResults.getCumulativeDataGasUsed()) {
if (blobGasUsed
> gasLimitCalculator.currentBlobGasLimit()
- transactionSelectionResults.getCumulativeBlobGasUsed()) {
return true;
}
return transaction.getGasLimit() + dataGasUsed
return transaction.getGasLimit() + blobGasUsed
> processableBlockHeader.getGasLimit() - transactionSelectionResults.getCumulativeGasUsed();
}

View File

@@ -32,8 +32,8 @@ import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.BLSPublicKey;
import org.hyperledger.besu.datatypes.BLSSignature;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.GWei;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.TransactionType;
@@ -146,6 +146,7 @@ abstract class AbstractBlockCreatorTest {
Optional.empty(),
Optional.of(emptyList()),
Optional.empty(),
Optional.empty(),
1L,
false);
@@ -165,6 +166,7 @@ abstract class AbstractBlockCreatorTest {
Optional.empty(),
Optional.of(emptyList()),
Optional.empty(),
Optional.empty(),
1L,
false);
@@ -182,6 +184,7 @@ abstract class AbstractBlockCreatorTest {
Optional.empty(),
Optional.of(emptyList()),
Optional.empty(),
Optional.empty(),
1L,
false);
@@ -214,7 +217,13 @@ abstract class AbstractBlockCreatorTest {
final AbstractBlockCreator blockCreator = blockCreatorWithWithdrawalsProcessor();
final BlockCreationResult blockCreationResult =
blockCreator.createBlock(
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), 1L, false);
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
1L,
false);
verify(withdrawalsProcessor, never()).processWithdrawals(any(), any());
assertThat(blockCreationResult.getBlock().getHeader().getWithdrawalsRoot()).isEmpty();
assertThat(blockCreationResult.getBlock().getBody().getWithdrawals()).isEmpty();
@@ -225,7 +234,13 @@ abstract class AbstractBlockCreatorTest {
final AbstractBlockCreator blockCreator = blockCreatorWithoutWithdrawalsProcessor();
final BlockCreationResult blockCreationResult =
blockCreator.createBlock(
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), 1L, false);
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
1L,
false);
verify(withdrawalsProcessor, never()).processWithdrawals(any(), any());
assertThat(blockCreationResult.getBlock().getHeader().getWithdrawalsRoot()).isEmpty();
assertThat(blockCreationResult.getBlock().getBody().getWithdrawals()).isEmpty();
@@ -242,6 +257,7 @@ abstract class AbstractBlockCreatorTest {
Optional.empty(),
Optional.of(withdrawals),
Optional.empty(),
Optional.empty(),
1L,
false);
@@ -263,6 +279,7 @@ abstract class AbstractBlockCreatorTest {
Optional.empty(),
Optional.of(withdrawals),
Optional.empty(),
Optional.empty(),
1L,
false);
verify(withdrawalsProcessor, never()).processWithdrawals(any(), any());
@@ -274,7 +291,7 @@ abstract class AbstractBlockCreatorTest {
@Test
public void computesGasUsageFromIncludedTransactions() {
final KeyPair senderKeys = SignatureAlgorithmFactory.getInstance().generateKeyPair();
final AbstractBlockCreator blockCreator = blockCreatorWithDataGasSupport();
final AbstractBlockCreator blockCreator = blockCreatorWithBlobGasSupport();
BlobTestFixture blobTestFixture = new BlobTestFixture();
BlobsWithCommitments bwc = blobTestFixture.createBlobsWithCommitments(6);
TransactionTestFixture ttf = new TransactionTestFixture();
@@ -283,7 +300,7 @@ abstract class AbstractBlockCreatorTest {
.type(TransactionType.BLOB)
.chainId(Optional.of(BigInteger.valueOf(42)))
.maxFeePerGas(Optional.of(Wei.of(15)))
.maxFeePerDataGas(Optional.of(Wei.of(128)))
.maxFeePerBlobGas(Optional.of(Wei.of(128)))
.maxPriorityFeePerGas(Optional.of(Wei.of(1)))
.versionedHashes(Optional.of(bwc.getVersionedHashes()))
.createTransaction(senderKeys);
@@ -295,15 +312,16 @@ abstract class AbstractBlockCreatorTest {
Optional.empty(),
Optional.empty(),
Optional.empty(),
Optional.empty(),
1L,
false);
long dataGasUsage = blockCreationResult.getBlock().getHeader().getGasUsed();
assertThat(dataGasUsage).isNotZero();
DataGas excessDataGas = blockCreationResult.getBlock().getHeader().getExcessDataGas().get();
assertThat(excessDataGas).isNotNull();
long blobGasUsage = blockCreationResult.getBlock().getHeader().getGasUsed();
assertThat(blobGasUsage).isNotZero();
BlobGas excessBlobGas = blockCreationResult.getBlock().getHeader().getExcessBlobGas().get();
assertThat(excessBlobGas).isNotNull();
}
private AbstractBlockCreator blockCreatorWithDataGasSupport() {
private AbstractBlockCreator blockCreatorWithBlobGasSupport() {
final ProtocolSpecAdapters protocolSpecAdapters =
ProtocolSpecAdapters.create(
0,

View File

@@ -634,7 +634,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
final ProcessableBlockHeader blockHeader,
final Wei minGasPrice,
final Address miningBeneficiary,
final Wei dataGasPrice,
final Wei blobGasPrice,
final double minBlockOccupancyRatio) {
final BlockTransactionSelector selector =
new BlockTransactionSelector(
@@ -648,7 +648,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
minBlockOccupancyRatio,
this::isCancelled,
miningBeneficiary,
dataGasPrice,
blobGasPrice,
getFeeMarket(),
new LondonGasCalculator(),
GasLimitCalculator.constant(),
@@ -662,7 +662,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
final ProcessableBlockHeader blockHeader,
final Wei minGasPrice,
final Address miningBeneficiary,
final Wei dataGasPrice,
final Wei blobGasPrice,
final double minBlockOccupancyRatio,
final TransactionSelectorFactory transactionSelectorFactory) {
final BlockTransactionSelector selector =
@@ -677,7 +677,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
minBlockOccupancyRatio,
this::isCancelled,
miningBeneficiary,
dataGasPrice,
blobGasPrice,
getFeeMarket(),
new LondonGasCalculator(),
GasLimitCalculator.constant(),

View File

@@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum;
public interface GasLimitCalculator {
static final long DATA_GAS_LIMIT = 786432;
static final long BLOB_GAS_LIMIT = 786432;
long nextGasLimit(long currentGasLimit, long targetGasLimit, long newBlockNumber);
@@ -24,7 +24,7 @@ public interface GasLimitCalculator {
return (currentGasLimit, targetGasLimit, newBlockNumber) -> currentGasLimit;
}
default long currentDataGasLimit() {
return DATA_GAS_LIMIT;
default long currentBlobGasLimit() {
return BLOB_GAS_LIMIT;
}
}

View File

@@ -95,6 +95,11 @@ public class BonsaiSnapshotWorldStateKeyValueStorage extends BonsaiWorldStateKey
return isClosedGet() ? Optional.empty() : super.getAccountStateTrieNode(location, nodeHash);
}
@Override
public Optional<Bytes> getTrieNodeUnsafe(final Bytes key) {
return isClosedGet() ? Optional.empty() : super.getTrieNodeUnsafe(key);
}
@Override
public Optional<Bytes> getAccountStorageTrieNode(
final Hash accountHash, final Bytes location, final Bytes32 nodeHash) {

View File

@@ -166,32 +166,24 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoC
}
}
/**
* Retrieves the storage trie node associated with the specified account and location, if
* available.
*
* @param accountHash The hash of the account.
* @param location The location within the storage trie.
* @param maybeNodeHash The optional hash of the storage trie node to validate the retrieved data
* against.
* @return The optional bytes of the storage trie node.
*/
@Override
public Optional<Bytes> getAccountStorageTrieNode(
final Hash accountHash, final Bytes location, final Optional<Bytes32> maybeNodeHash) {
if (maybeNodeHash.filter(hash -> hash.equals(MerkleTrie.EMPTY_TRIE_NODE_HASH)).isPresent()) {
final Hash accountHash, final Bytes location, final Bytes32 nodeHash) {
if (nodeHash.equals(MerkleTrie.EMPTY_TRIE_NODE_HASH)) {
return Optional.of(MerkleTrie.EMPTY_TRIE_NODE);
} else {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, Bytes.concatenate(accountHash, location).toArrayUnsafe())
.map(Bytes::wrap)
.filter(data -> maybeNodeHash.map(hash -> Hash.hash(data).equals(hash)).orElse(true));
.filter(b -> Hash.hash(b).equals(nodeHash));
}
}
@Override
public Optional<Bytes> getAccountStorageTrieNode(
final Hash accountHash, final Bytes location, final Bytes32 nodeHash) {
return getAccountStorageTrieNode(accountHash, location, Optional.ofNullable(nodeHash));
public Optional<Bytes> getTrieNodeUnsafe(final Bytes key) {
return composedWorldStateStorage
.get(TRIE_BRANCH_STORAGE, Bytes.concatenate(key).toArrayUnsafe())
.map(Bytes::wrap);
}
public Optional<byte[]> getTrieLog(final Hash blockHash) {

View File

@@ -19,7 +19,7 @@ import static java.util.Collections.emptyList;
import org.hyperledger.besu.config.GenesisAllocation;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Block;
@@ -53,6 +53,7 @@ import java.util.stream.Stream;
import com.google.common.base.MoreObjects;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
public final class GenesisState {
@@ -168,8 +169,10 @@ public final class GenesisState {
.blockHeaderFunctions(ScheduleBasedBlockHeaderFunctions.create(protocolSchedule))
.baseFee(genesis.getGenesisBaseFeePerGas().orElse(null))
.withdrawalsRoot(isShanghaiAtGenesis(genesis) ? Hash.EMPTY_TRIE_HASH : null)
.dataGasUsed(isCancunAtGenesis(genesis) ? parseDataGasUsed(genesis) : null)
.excessDataGas(isCancunAtGenesis(genesis) ? parseExcessDataGas(genesis) : null)
.blobGasUsed(isCancunAtGenesis(genesis) ? parseBlobGasUsed(genesis) : null)
.excessBlobGas(isCancunAtGenesis(genesis) ? parseExcessBlobGas(genesis) : null)
.parentBeaconBlockRoot(
(isCancunAtGenesis(genesis) ? parseParentBeaconBlockRoot(genesis) : null))
.depositsRoot(isExperimentalEipsTimeAtGenesis(genesis) ? Hash.EMPTY_TRIE_HASH : null)
.buildBlockHeader();
}
@@ -220,16 +223,21 @@ public final class GenesisState {
return withNiceErrorMessage("nonce", genesis.getNonce(), GenesisState::parseUnsignedLong);
}
private static long parseDataGasUsed(final GenesisConfigFile genesis) {
private static long parseBlobGasUsed(final GenesisConfigFile genesis) {
return withNiceErrorMessage(
"dataGasUsed", genesis.getDataGasUsed(), GenesisState::parseUnsignedLong);
"blobGasUsed", genesis.getBlobGasUsed(), GenesisState::parseUnsignedLong);
}
private static DataGas parseExcessDataGas(final GenesisConfigFile genesis) {
long excessDataGas =
private static BlobGas parseExcessBlobGas(final GenesisConfigFile genesis) {
long excessBlobGas =
withNiceErrorMessage(
"excessDataGas", genesis.getExcessDataGas(), GenesisState::parseUnsignedLong);
return DataGas.of(excessDataGas);
"excessBlobGas", genesis.getExcessBlobGas(), GenesisState::parseUnsignedLong);
return BlobGas.of(excessBlobGas);
}
private static Bytes32 parseParentBeaconBlockRoot(final GenesisConfigFile genesis) {
return withNiceErrorMessage(
"parentBeaconBlockRoot", genesis.getParentBeaconBlockRoot(), Bytes32::fromHexString);
}
private static long parseUnsignedLong(final String value) {

View File

@@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.core;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
@@ -23,7 +23,6 @@ import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.evm.log.LogsBloomFilter;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
@@ -62,56 +61,9 @@ public class BlockHeader extends SealableBlockHeader
final Bytes32 mixHashOrPrevRandao,
final long nonce,
final Hash withdrawalsRoot,
final long dataGasUsed,
final DataGas excessDataGas,
final Hash depositsRoot,
final BlockHeaderFunctions blockHeaderFunctions,
final Optional<LogsBloomFilter> privateLogsBloom) {
super(
parentHash,
ommersHash,
coinbase,
stateRoot,
transactionsRoot,
receiptsRoot,
logsBloom,
difficulty,
number,
gasLimit,
gasUsed,
timestamp,
extraData,
baseFee,
mixHashOrPrevRandao,
withdrawalsRoot,
dataGasUsed,
excessDataGas,
depositsRoot);
this.nonce = nonce;
this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this));
this.parsedExtraData = Suppliers.memoize(() -> blockHeaderFunctions.parseExtraData(this));
}
public BlockHeader(
final Hash parentHash,
final Hash ommersHash,
final Address coinbase,
final Hash stateRoot,
final Hash transactionsRoot,
final Hash receiptsRoot,
final LogsBloomFilter logsBloom,
final Difficulty difficulty,
final long number,
final long gasLimit,
final long gasUsed,
final long timestamp,
final Bytes extraData,
final Wei baseFee,
final Bytes32 mixHashOrPrevRandao,
final long nonce,
final Hash withdrawalsRoot,
final Long dataGasUsed,
final DataGas excessDataGas,
final Long blobGasUsed,
final BlobGas excessBlobGas,
final Bytes32 parentBeaconBlockRoot,
final Hash depositsRoot,
final BlockHeaderFunctions blockHeaderFunctions) {
super(
@@ -131,8 +83,9 @@ public class BlockHeader extends SealableBlockHeader
baseFee,
mixHashOrPrevRandao,
withdrawalsRoot,
dataGasUsed,
excessDataGas,
blobGasUsed,
excessBlobGas,
parentBeaconBlockRoot,
depositsRoot);
this.nonce = nonce;
this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this));
@@ -216,9 +169,12 @@ public class BlockHeader extends SealableBlockHeader
if (withdrawalsRoot != null) {
out.writeBytes(withdrawalsRoot);
}
if (excessDataGas.isPresent() && dataGasUsed.isPresent()) {
out.writeLongScalar(dataGasUsed.get());
out.writeUInt64Scalar(excessDataGas.get());
if (excessBlobGas.isPresent() && blobGasUsed.isPresent()) {
out.writeLongScalar(blobGasUsed.get());
out.writeUInt64Scalar(excessBlobGas.get());
}
if (parentBeaconBlockRoot != null) {
out.writeBytes(parentBeaconBlockRoot);
}
if (depositsRoot != null) {
out.writeBytes(depositsRoot);
@@ -249,9 +205,10 @@ public class BlockHeader extends SealableBlockHeader
!(input.isEndOfCurrentList() || input.isZeroLengthString())
? Hash.wrap(input.readBytes32())
: null;
final Long dataGasUsed = !input.isEndOfCurrentList() ? input.readLongScalar() : null;
final DataGas excessDataGas =
!input.isEndOfCurrentList() ? DataGas.of(input.readLongScalar()) : null;
final Long blobGasUsed = !input.isEndOfCurrentList() ? input.readLongScalar() : null;
final BlobGas excessBlobGas =
!input.isEndOfCurrentList() ? BlobGas.of(input.readLongScalar()) : null;
final Bytes32 parentBeaconBlockRoot = !input.isEndOfCurrentList() ? input.readBytes32() : null;
final Hash depositHashRoot =
!input.isEndOfCurrentList() ? Hash.wrap(input.readBytes32()) : null;
input.leaveList();
@@ -273,8 +230,9 @@ public class BlockHeader extends SealableBlockHeader
mixHashOrPrevRandao,
nonce,
withdrawalHashRoot,
dataGasUsed,
excessDataGas,
blobGasUsed,
excessBlobGas,
parentBeaconBlockRoot,
depositHashRoot,
blockHeaderFunctions);
}
@@ -320,8 +278,11 @@ public class BlockHeader extends SealableBlockHeader
if (withdrawalsRoot != null) {
sb.append("withdrawalsRoot=").append(withdrawalsRoot).append(", ");
}
dataGasUsed.ifPresent(aLong -> sb.append("dataGasUsed=").append(aLong).append(", "));
excessDataGas.ifPresent(dataGas -> sb.append("excessDataGas=").append(dataGas).append(", "));
blobGasUsed.ifPresent(aLong -> sb.append("blobGasUsed=").append(aLong).append(", "));
excessBlobGas.ifPresent(blobGas -> sb.append("excessBlobGas=").append(blobGas).append(", "));
if (parentBeaconBlockRoot != null) {
sb.append("parentBeaconBlockRoot=").append(parentBeaconBlockRoot).append(", ");
}
if (depositsRoot != null) {
sb.append("depositsRoot=").append(depositsRoot);
}
@@ -352,8 +313,9 @@ public class BlockHeader extends SealableBlockHeader
.getWithdrawalsRoot()
.map(h -> Hash.fromHexString(h.toHexString()))
.orElse(null),
pluginBlockHeader.getDataGasUsed().map(Long::longValue).orElse(null),
pluginBlockHeader.getExcessDataGas().map(DataGas::fromQuantity).orElse(null),
pluginBlockHeader.getBlobGasUsed().map(Long::longValue).orElse(null),
pluginBlockHeader.getExcessBlobGas().map(BlobGas::fromQuantity).orElse(null),
pluginBlockHeader.getParentBeaconBlockRoot().orElse(null),
pluginBlockHeader
.getDepositsRoot()
.map(h -> Hash.fromHexString(h.toHexString()))

View File

@@ -19,7 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
@@ -73,8 +73,9 @@ public class BlockHeaderBuilder {
// instead of an invalid identifier such as -1.
private OptionalLong nonce = OptionalLong.empty();
private Long dataGasUsed = null;
private DataGas excessDataGas = null;
private Long blobGasUsed = null;
private BlobGas excessBlobGas = null;
private Bytes32 parentBeaconBlockRoot = null;
public static BlockHeaderBuilder create() {
return new BlockHeaderBuilder();
@@ -120,8 +121,9 @@ public class BlockHeaderBuilder {
.nonce(header.getNonce())
.prevRandao(header.getPrevRandao().orElse(null))
.withdrawalsRoot(header.getWithdrawalsRoot().orElse(null))
.dataGasUsed(header.getDataGasUsed().orElse(null))
.excessDataGas(header.getExcessDataGas().orElse(null))
.blobGasUsed(header.getBlobGasUsed().orElse(null))
.excessBlobGas(header.getExcessBlobGas().orElse(null))
.parentBeaconBlockRoot(header.getParentBeaconBlockRoot().orElse(null))
.depositsRoot(header.getDepositsRoot().orElse(null));
}
@@ -144,7 +146,8 @@ public class BlockHeaderBuilder {
.baseFee(fromBuilder.baseFee)
.prevRandao(fromBuilder.mixHashOrPrevRandao)
.withdrawalsRoot(fromBuilder.withdrawalsRoot)
.excessDataGas(fromBuilder.excessDataGas)
.excessBlobGas(fromBuilder.excessBlobGas)
.parentBeaconBlockRoot(fromBuilder.parentBeaconBlockRoot)
.depositsRoot(fromBuilder.depositsRoot)
.blockHeaderFunctions(fromBuilder.blockHeaderFunctions);
toBuilder.nonce = fromBuilder.nonce;
@@ -172,8 +175,9 @@ public class BlockHeaderBuilder {
mixHashOrPrevRandao,
nonce.getAsLong(),
withdrawalsRoot,
dataGasUsed,
excessDataGas,
blobGasUsed,
excessBlobGas,
parentBeaconBlockRoot,
depositsRoot,
blockHeaderFunctions);
}
@@ -190,8 +194,9 @@ public class BlockHeaderBuilder {
timestamp,
baseFee,
mixHashOrPrevRandao,
dataGasUsed,
excessDataGas);
blobGasUsed,
excessBlobGas,
parentBeaconBlockRoot);
}
public SealableBlockHeader buildSealableBlockHeader() {
@@ -214,8 +219,9 @@ public class BlockHeaderBuilder {
baseFee,
mixHashOrPrevRandao,
withdrawalsRoot,
dataGasUsed,
excessDataGas,
blobGasUsed,
excessBlobGas,
parentBeaconBlockRoot,
depositsRoot);
}
@@ -256,8 +262,9 @@ public class BlockHeaderBuilder {
timestamp(processableBlockHeader.getTimestamp());
baseFee(processableBlockHeader.getBaseFee().orElse(null));
processableBlockHeader.getPrevRandao().ifPresent(this::prevRandao);
processableBlockHeader.getDataGasUsed().ifPresent(this::dataGasUsed);
processableBlockHeader.getExcessDataGas().ifPresent(this::excessDataGas);
processableBlockHeader.getBlobGasUsed().ifPresent(this::blobGasUsed);
processableBlockHeader.getExcessBlobGas().ifPresent(this::excessBlobGas);
processableBlockHeader.getParentBeaconBlockRoot().ifPresent(this::parentBeaconBlockRoot);
return this;
}
@@ -279,8 +286,9 @@ public class BlockHeaderBuilder {
baseFee(sealableBlockHeader.getBaseFee().orElse(null));
sealableBlockHeader.getPrevRandao().ifPresent(this::prevRandao);
withdrawalsRoot(sealableBlockHeader.getWithdrawalsRoot().orElse(null));
sealableBlockHeader.getDataGasUsed().ifPresent(this::dataGasUsed);
sealableBlockHeader.getExcessDataGas().ifPresent(this::excessDataGas);
sealableBlockHeader.getBlobGasUsed().ifPresent(this::blobGasUsed);
sealableBlockHeader.getExcessBlobGas().ifPresent(this::excessBlobGas);
sealableBlockHeader.getParentBeaconBlockRoot().ifPresent(this::parentBeaconBlockRoot);
depositsRoot(sealableBlockHeader.getDepositsRoot().orElse(null));
return this;
}
@@ -402,13 +410,18 @@ public class BlockHeaderBuilder {
return this;
}
public BlockHeaderBuilder excessDataGas(final DataGas excessDataGas) {
this.excessDataGas = excessDataGas;
public BlockHeaderBuilder excessBlobGas(final BlobGas excessBlobGas) {
this.excessBlobGas = excessBlobGas;
return this;
}
public BlockHeaderBuilder dataGasUsed(final Long dataGasUsed) {
this.dataGasUsed = dataGasUsed;
public BlockHeaderBuilder blobGasUsed(final Long blobGasUsed) {
this.blobGasUsed = blobGasUsed;
return this;
}
public BlockHeaderBuilder parentBeaconBlockRoot(final Bytes32 parentBeaconBlockRoot) {
this.parentBeaconBlockRoot = parentBeaconBlockRoot;
return this;
}
}

View File

@@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.core;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.frame.BlockValues;
@@ -44,10 +44,12 @@ public class ProcessableBlockHeader implements BlockValues {
protected final Wei baseFee;
// prevRandao is included for post-merge blocks
protected final Bytes32 mixHashOrPrevRandao;
// dataGasUsed is included for Cancun
protected final Optional<Long> dataGasUsed;
// excessDataGas is included for Cancun
protected final Optional<DataGas> excessDataGas;
// blobGasUsed is included for Cancun
protected final Optional<Long> blobGasUsed;
// excessBlogGas is included for Cancun
protected final Optional<BlobGas> excessBlobGas;
// parentBeaconBlockRoot is included for Cancun
protected final Bytes32 parentBeaconBlockRoot;
protected ProcessableBlockHeader(
final Hash parentHash,
@@ -58,8 +60,9 @@ public class ProcessableBlockHeader implements BlockValues {
final long timestamp,
final Wei baseFee,
final Bytes32 mixHashOrPrevRandao,
final Long dataGasUsed,
final DataGas excessDataGas) {
final Long blobGasUsed,
final BlobGas excessBlobGas,
final Bytes32 parentBeaconBlockRoot) {
this.parentHash = parentHash;
this.coinbase = coinbase;
this.difficulty = difficulty;
@@ -68,8 +71,9 @@ public class ProcessableBlockHeader implements BlockValues {
this.timestamp = timestamp;
this.baseFee = baseFee;
this.mixHashOrPrevRandao = mixHashOrPrevRandao;
this.dataGasUsed = Optional.ofNullable(dataGasUsed);
this.excessDataGas = Optional.ofNullable(excessDataGas);
this.blobGasUsed = Optional.ofNullable(blobGasUsed);
this.excessBlobGas = Optional.ofNullable(excessBlobGas);
this.parentBeaconBlockRoot = parentBeaconBlockRoot;
}
/**
@@ -168,12 +172,16 @@ public class ProcessableBlockHeader implements BlockValues {
return Optional.ofNullable(mixHashOrPrevRandao);
}
public Optional<DataGas> getExcessDataGas() {
return excessDataGas;
public Optional<BlobGas> getExcessBlobGas() {
return excessBlobGas;
}
public Optional<Long> getDataGasUsed() {
return dataGasUsed;
public Optional<Long> getBlobGasUsed() {
return blobGasUsed;
}
public Optional<Bytes32> getParentBeaconBlockRoot() {
return Optional.ofNullable(parentBeaconBlockRoot);
}
public String toLogString() {

View File

@@ -15,7 +15,7 @@
package org.hyperledger.besu.ethereum.core;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.log.LogsBloomFilter;
@@ -62,8 +62,9 @@ public class SealableBlockHeader extends ProcessableBlockHeader {
final Wei baseFee,
final Bytes32 mixHashOrPrevRandao,
final Hash withdrawalsRoot,
final Long dataGasUsed,
final DataGas excessDataGas,
final Long blobGasUsed,
final BlobGas excessBlobGas,
final Bytes32 parentBeaconBlockRoot,
final Hash depositsRoot) {
super(
parentHash,
@@ -74,8 +75,9 @@ public class SealableBlockHeader extends ProcessableBlockHeader {
timestamp,
baseFee,
mixHashOrPrevRandao,
dataGasUsed,
excessDataGas);
blobGasUsed,
excessBlobGas,
parentBeaconBlockRoot);
this.ommersHash = ommersHash;
this.stateRoot = stateRoot;
this.transactionsRoot = transactionsRoot;

View File

@@ -24,13 +24,13 @@ import org.hyperledger.besu.crypto.SECPPublicKey;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Blob;
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.KZGCommitment;
import org.hyperledger.besu.datatypes.KZGProof;
import org.hyperledger.besu.datatypes.Quantity;
import org.hyperledger.besu.datatypes.Sha256Hash;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.VersionedHash;
@@ -42,10 +42,8 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.evm.AccessListEntry;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -83,7 +81,7 @@ public class Transaction
private final Optional<Wei> maxPriorityFeePerGas;
private final Optional<Wei> maxFeePerGas;
private final Optional<Wei> maxFeePerDataGas;
private final Optional<Wei> maxFeePerBlobGas;
private final long gasLimit;
@@ -139,7 +137,7 @@ public class Transaction
* @param gasPrice the gas price
* @param maxPriorityFeePerGas the max priority fee per gas
* @param maxFeePerGas the max fee per gas
* @param maxFeePerDataGas the max fee per data gas
* @param maxFeePerBlobGas the max fee per blob gas
* @param gasLimit the gas limit
* @param to the transaction recipient
* @param value the value being transferred to the recipient
@@ -160,7 +158,7 @@ public class Transaction
final Optional<Wei> gasPrice,
final Optional<Wei> maxPriorityFeePerGas,
final Optional<Wei> maxFeePerGas,
final Optional<Wei> maxFeePerDataGas,
final Optional<Wei> maxFeePerBlobGas,
final long gasLimit,
final Optional<Address> to,
final Wei value,
@@ -188,10 +186,10 @@ public class Transaction
maybeAccessList.isPresent(), "Must specify access list for access list transaction");
}
if (versionedHashes.isPresent() || maxFeePerDataGas.isPresent()) {
if (versionedHashes.isPresent() || maxFeePerBlobGas.isPresent()) {
checkArgument(
transactionType.supportsBlob(),
"Must not specify blob versioned hashes of max fee per data gas for transaction not supporting it");
"Must not specify blob versioned hashes of max fee per blob gas for transaction not supporting it");
}
if (transactionType.supportsBlob()) {
@@ -200,7 +198,7 @@ public class Transaction
checkArgument(
!versionedHashes.get().isEmpty(), "Blob transaction must have at least one blob");
checkArgument(
maxFeePerDataGas.isPresent(), "Must specify max fee per data gas for blob transaction");
maxFeePerBlobGas.isPresent(), "Must specify max fee per blob gas for blob transaction");
}
this.transactionType = transactionType;
@@ -208,7 +206,7 @@ public class Transaction
this.gasPrice = gasPrice;
this.maxPriorityFeePerGas = maxPriorityFeePerGas;
this.maxFeePerGas = maxFeePerGas;
this.maxFeePerDataGas = maxFeePerDataGas;
this.maxFeePerBlobGas = maxFeePerBlobGas;
this.gasLimit = gasLimit;
this.to = to;
this.value = value;
@@ -230,7 +228,7 @@ public class Transaction
final Optional<Wei> gasPrice,
final Optional<Wei> maxPriorityFeePerGas,
final Optional<Wei> maxFeePerGas,
final Optional<Wei> maxFeePerDataGas,
final Optional<Wei> maxFeePerBlobGas,
final long gasLimit,
final Optional<Address> to,
final Wei value,
@@ -246,7 +244,7 @@ public class Transaction
gasPrice,
maxPriorityFeePerGas,
maxFeePerGas,
maxFeePerDataGas,
maxFeePerBlobGas,
gasLimit,
to,
value,
@@ -361,7 +359,7 @@ public class Transaction
final Bytes payload,
final Address sender,
final Optional<BigInteger> chainId,
final Optional<Wei> maxFeePerDataGas,
final Optional<Wei> maxFeePerBlobGas,
final Optional<List<VersionedHash>> versionedHashes,
final Optional<BlobsWithCommitments> blobsWithCommitments) {
this(
@@ -369,7 +367,7 @@ public class Transaction
Optional.of(gasPrice),
Optional.empty(),
Optional.empty(),
maxFeePerDataGas,
maxFeePerBlobGas,
gasLimit,
to,
value,
@@ -422,30 +420,21 @@ public class Transaction
}
/**
* Return the transaction max fee per data gas.
* Return the transaction max fee per blob gas.
*
* @return the transaction max fee per data gas
* @return the transaction max fee per blob gas
*/
@Override
public Optional<Wei> getMaxFeePerDataGas() {
return maxFeePerDataGas;
public Optional<Wei> getMaxFeePerBlobGas() {
return maxFeePerBlobGas;
}
/**
* Boolean which indicates the transaction has associated cost data, whether gas price or 1559 fee
* market parameters.
* Return the effective priority fee per gas for this transaction.
*
* @return whether cost params are present
* @param maybeBaseFee base fee in case of EIP-1559 transaction
* @return priority fee per gas in wei
*/
public boolean hasCostParams() {
return Arrays.asList(
getGasPrice(), getMaxFeePerGas(), getMaxPriorityFeePerGas(), getMaxFeePerDataGas())
.stream()
.flatMap(Optional::stream)
.map(Quantity::getAsBigInteger)
.anyMatch(q -> q.longValue() > 0L);
}
public Wei getEffectivePriorityFeePerGas(final Optional<Wei> maybeBaseFee) {
return maybeBaseFee
.map(
@@ -547,6 +536,7 @@ public class Transaction
return getTo().isPresent() ? Optional.of(payload) : Optional.empty();
}
@Override
public Optional<List<AccessListEntry>> getAccessList() {
return maybeAccessList;
}
@@ -604,7 +594,7 @@ public class Transaction
gasPrice.orElse(null),
maxPriorityFeePerGas.orElse(null),
maxFeePerGas.orElse(null),
maxFeePerDataGas.orElse(null),
maxFeePerBlobGas.orElse(null),
gasLimit,
to,
value,
@@ -625,6 +615,13 @@ public class Transaction
TransactionEncoder.encodeForWire(this, out);
}
@Override
public Bytes encoded() {
final BytesValueRLPOutput rplOutput = new BytesValueRLPOutput();
writeTo(rplOutput);
return rplOutput.encoded();
}
@Override
public BigInteger getR() {
return signature.getR();
@@ -706,9 +703,9 @@ public class Transaction
*
* @return the max up-front cost for the gas the transaction can use.
*/
private Wei getMaxUpfrontGasCost(final long dataGasPerBlock) {
private Wei getMaxUpfrontGasCost(final long blobGasPerBlock) {
return getUpfrontGasCost(
getMaxGasPrice(), getMaxFeePerDataGas().orElse(Wei.ZERO), dataGasPerBlock);
getMaxGasPrice(), getMaxFeePerBlobGas().orElse(Wei.ZERO), blobGasPerBlock);
}
/**
@@ -721,19 +718,19 @@ public class Transaction
}
/**
* Calculates the up-front cost for the gas and data gas the transaction can use.
* Calculates the up-front cost for the gas and blob gas the transaction can use.
*
* @param gasPrice the gas price to use
* @param dataGasPrice the data gas price to use
* @param blobGasPrice the blob gas price to use
* @return the up-front cost for the gas the transaction can use.
*/
public Wei getUpfrontGasCost(
final Wei gasPrice, final Wei dataGasPrice, final long totalDataGas) {
final Wei gasPrice, final Wei blobGasPrice, final long totalBlobGas) {
if (gasPrice == null || gasPrice.isZero()) {
return Wei.ZERO;
}
final var cost = calculateUpfrontGasCost(gasPrice, dataGasPrice, totalDataGas);
final var cost = calculateUpfrontGasCost(gasPrice, blobGasPrice, totalBlobGas);
if (cost.bitLength() > 256) {
return Wei.MAX_WEI;
@@ -743,12 +740,12 @@ public class Transaction
}
private BigInteger calculateUpfrontGasCost(
final Wei gasPrice, final Wei dataGasPrice, final long totalDataGas) {
final Wei gasPrice, final Wei blobGasPrice, final long totalBlobGas) {
var cost =
new BigInteger(1, Longs.toByteArray(getGasLimit())).multiply(gasPrice.getAsBigInteger());
if (transactionType.supportsBlob()) {
cost = cost.add(dataGasPrice.getAsBigInteger().multiply(BigInteger.valueOf(totalDataGas)));
cost = cost.add(blobGasPrice.getAsBigInteger().multiply(BigInteger.valueOf(totalBlobGas)));
}
return cost;
@@ -763,8 +760,8 @@ public class Transaction
*
* @return the up-front gas cost for the transaction
*/
public Wei getUpfrontCost(final long totalDataGas) {
return getMaxUpfrontGasCost(totalDataGas).addExact(getValue());
public Wei getUpfrontCost(final long totalBlobGas) {
return getMaxUpfrontGasCost(totalBlobGas).addExact(getValue());
}
/**
@@ -780,6 +777,7 @@ public class Transaction
new IllegalStateException(
"Transaction requires either gasPrice or maxFeePerGas")));
}
/**
* Calculates the effectiveGasPrice of a transaction on the basis of an {@code Optional<Long>}
* baseFee and handles unwrapping Optional fee parameters. If baseFee is present, effective gas is
@@ -801,10 +799,12 @@ public class Transaction
return this.transactionType;
}
@Override
public Optional<List<VersionedHash>> getVersionedHashes() {
return versionedHashes;
}
@Override
public Optional<BlobsWithCommitments> getBlobsWithCommitments() {
return blobsWithCommitments;
}
@@ -826,7 +826,7 @@ public class Transaction
final Wei gasPrice,
final Wei maxPriorityFeePerGas,
final Wei maxFeePerGas,
final Wei maxFeePerDataGas,
final Wei maxFeePerBlobGas,
final long gasLimit,
final Optional<Address> to,
final Wei value,
@@ -861,7 +861,7 @@ public class Transaction
nonce,
maxPriorityFeePerGas,
maxFeePerGas,
maxFeePerDataGas,
maxFeePerBlobGas,
gasLimit,
to,
value,
@@ -974,7 +974,7 @@ public class Transaction
final long nonce,
final Wei maxPriorityFeePerGas,
final Wei maxFeePerGas,
final Wei maxFeePerDataGas,
final Wei maxFeePerBlobGas,
final long gasLimit,
final Optional<Address> to,
final Wei value,
@@ -998,7 +998,7 @@ public class Transaction
chainId,
accessList,
rlpOutput);
rlpOutput.writeUInt256Scalar(maxFeePerDataGas);
rlpOutput.writeUInt256Scalar(maxFeePerBlobGas);
BlobTransactionEncoder.writeBlobVersionedHashes(rlpOutput, versionedHashes);
rlpOutput.endList();
});
@@ -1036,7 +1036,7 @@ public class Transaction
&& Objects.equals(this.gasPrice, that.gasPrice)
&& Objects.equals(this.maxPriorityFeePerGas, that.maxPriorityFeePerGas)
&& Objects.equals(this.maxFeePerGas, that.maxFeePerGas)
&& Objects.equals(this.maxFeePerDataGas, that.maxFeePerDataGas)
&& Objects.equals(this.maxFeePerBlobGas, that.maxFeePerBlobGas)
&& this.nonce == that.nonce
&& Objects.equals(this.payload, that.payload)
&& Objects.equals(this.signature, that.signature)
@@ -1052,7 +1052,7 @@ public class Transaction
gasPrice,
maxPriorityFeePerGas,
maxFeePerGas,
maxFeePerDataGas,
maxFeePerBlobGas,
gasLimit,
to,
value,
@@ -1081,9 +1081,9 @@ public class Transaction
sb.append("maxFeePerGas=")
.append(getMaxFeePerGas().map(Wei::toShortHexString).get())
.append(", ");
getMaxFeePerDataGas()
getMaxFeePerBlobGas()
.ifPresent(
wei -> sb.append("maxFeePerDataGas=").append(wei.toShortHexString()).append(", "));
wei -> sb.append("maxFeePerBlobGas=").append(wei.toShortHexString()).append(", "));
}
sb.append("gasLimit=").append(getGasLimit()).append(", ");
if (getTo().isPresent()) sb.append("to=").append(getTo().get()).append(", ");
@@ -1118,7 +1118,7 @@ public class Transaction
sb.append("pf: ")
.append(getMaxPriorityFeePerGas().map(Wei::toHumanReadableString).get())
.append(", ");
getMaxFeePerDataGas()
getMaxFeePerBlobGas()
.ifPresent(wei -> sb.append("df: ").append(wei.toHumanReadableString()).append(", "));
}
sb.append("gl: ").append(getGasLimit()).append(", ");
@@ -1127,6 +1127,7 @@ public class Transaction
return sb.append("}").toString();
}
@Override
public Optional<Address> contractAddress() {
if (isContractCreation()) {
return Optional.of(Address.contractAddress(getSender(), getNonce()));
@@ -1146,7 +1147,7 @@ public class Transaction
protected Wei maxPriorityFeePerGas;
protected Wei maxFeePerGas;
protected Wei maxFeePerDataGas;
protected Wei maxFeePerBlobGas;
protected long gasLimit = -1L;
@@ -1197,8 +1198,8 @@ public class Transaction
return this;
}
public Builder maxFeePerDataGas(final Wei maxFeePerDataGas) {
this.maxFeePerDataGas = maxFeePerDataGas;
public Builder maxFeePerBlobGas(final Wei maxFeePerBlobGas) {
this.maxFeePerBlobGas = maxFeePerBlobGas;
return this;
}
@@ -1275,7 +1276,7 @@ public class Transaction
Optional.ofNullable(gasPrice),
Optional.ofNullable(maxPriorityFeePerGas),
Optional.ofNullable(maxFeePerGas),
Optional.ofNullable(maxFeePerDataGas),
Optional.ofNullable(maxFeePerBlobGas),
gasLimit,
to,
value,
@@ -1305,7 +1306,7 @@ public class Transaction
gasPrice,
maxPriorityFeePerGas,
maxFeePerGas,
maxFeePerDataGas,
maxFeePerBlobGas,
gasLimit,
to,
value,

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.core.encoding;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Blob;
import org.hyperledger.besu.datatypes.KZGCommitment;
@@ -25,7 +26,6 @@ import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.evm.AccessListEntry;
import java.util.List;
import java.util.function.Supplier;
@@ -79,7 +79,7 @@ public class BlobTransactionDecoder {
accessListEntryRLPInput.leaveList();
return accessListEntry;
}))
.maxFeePerDataGas(Wei.of(input.readUInt256Scalar()))
.maxFeePerBlobGas(Wei.of(input.readUInt256Scalar()))
.versionedHashes(
input.readList(versionedHashes -> new VersionedHash(versionedHashes.readBytes32())));

View File

@@ -43,7 +43,7 @@ public class BlobTransactionEncoder {
out.writeUInt256Scalar(transaction.getValue());
out.writeBytes(transaction.getPayload());
TransactionEncoder.writeAccessList(out, transaction.getAccessList());
out.writeUInt256Scalar(transaction.getMaxFeePerDataGas().orElseThrow());
out.writeUInt256Scalar(transaction.getMaxFeePerBlobGas().orElseThrow());
out.startList();
transaction
.getVersionedHashes()

View File

@@ -24,13 +24,13 @@ import static org.hyperledger.besu.ethereum.core.Transaction.TWO;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.evm.AccessListEntry;
import java.math.BigInteger;
import java.util.Optional;

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.core.encoding;
import static com.google.common.base.Preconditions.checkNotNull;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
@@ -23,7 +24,6 @@ import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.evm.AccessListEntry;
import java.math.BigInteger;
import java.util.List;
@@ -178,9 +178,9 @@ public class TransactionEncoder {
accessListEntries.get(),
(accessListEntry, accessListEntryRLPOutput) -> {
accessListEntryRLPOutput.startList();
out.writeBytes(accessListEntry.getAddress());
out.writeBytes(accessListEntry.address());
out.writeList(
accessListEntry.getStorageKeys(),
accessListEntry.storageKeys(),
(storageKeyBytes, storageKeyBytesRLPOutput) ->
storageKeyBytesRLPOutput.writeBytes(storageKeyBytes));
accessListEntryRLPOutput.endList();

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.ethereum.core.feemarket;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
@@ -62,18 +62,18 @@ public interface TransactionPriceCalculator {
return output.divide(denominator);
}
static TransactionPriceCalculator dataGas(
final int minDataGasPrice,
final int dataGasPriceUpdateFraction,
final DataGas excessDataGas) {
static TransactionPriceCalculator blobGas(
final int minBlobGasPrice,
final int blobGasPriceUpdateFraction,
final BlobGas excessBlobGas) {
return ((transaction, baseFee) -> {
final var dataGasPrice =
final var blobGasPrice =
Wei.of(
fakeExponential(
BigInteger.valueOf(minDataGasPrice),
excessDataGas.toBigInteger(),
BigInteger.valueOf(dataGasPriceUpdateFraction)));
return dataGasPrice;
BigInteger.valueOf(minBlobGasPrice),
excessBlobGas.toBigInteger(),
BigInteger.valueOf(blobGasPriceUpdateFraction)));
return blobGasPrice;
});
}
}

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.ethereum.mainnet;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessDataGasCalculator.calculateExcessDataGasForParent;
import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
@@ -104,12 +104,19 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(blockHeader);
if (blockHeader.getParentBeaconBlockRoot().isPresent()) {
final WorldUpdater updater = worldState.updater();
ParentBeaconBlockRootHelper.storeParentBeaconBlockRoot(
updater, blockHeader.getTimestamp(), blockHeader.getParentBeaconBlockRoot().get());
}
for (final Transaction transaction : transactions) {
if (!hasAvailableBlockBudget(blockHeader, transaction, currentGasUsed)) {
return new BlockProcessingResult(Optional.empty(), "provided gas insufficient");
}
final WorldUpdater worldStateUpdater = worldState.updater();
final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(blockHeader, blockchain);
final Address miningBeneficiary =
miningBeneficiaryCalculator.calculateBeneficiary(blockHeader);
@@ -117,14 +124,14 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(blockHeader.getParentHash());
Wei dataGasPrice =
Wei blobGasPrice =
maybeParentHeader
.map(
(parentHeader) ->
protocolSpec
.getFeeMarket()
.dataPricePerGas(
calculateExcessDataGasForParent(protocolSpec, parentHeader)))
.blobGasPricePerGas(
calculateExcessBlobGasForParent(protocolSpec, parentHeader)))
.orElse(Wei.ZERO);
final TransactionProcessingResult result =
@@ -139,7 +146,7 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
true,
TransactionValidationParams.processingBlock(),
privateMetadataUpdater,
dataGasPrice);
blobGasPrice);
if (result.isInvalid()) {
String errorMessage =
MessageFormat.format(

View File

@@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
public class CancunTargetingGasLimitCalculator extends LondonTargetingGasLimitCalculator {
private static final long MAX_DATA_GAS_PER_BLOCK = 786432L;
private static final long MAX_BLOB_GAS_PER_BLOCK = 786432L;
public CancunTargetingGasLimitCalculator(
final long londonForkBlock, final BaseFeeMarket feeMarket) {
@@ -25,7 +25,7 @@ public class CancunTargetingGasLimitCalculator extends LondonTargetingGasLimitCa
}
@Override
public long currentDataGasLimit() {
return MAX_DATA_GAS_PER_BLOCK;
public long currentBlobGasLimit() {
return MAX_BLOB_GAS_PER_BLOCK;
}
}

View File

@@ -20,10 +20,10 @@ import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.AncestryValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.BaseFeeMarketBlockHeaderGasPriceValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.BlobGasValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.CalculatedDifficultyValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantFieldValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ConstantOmmersHashRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.DataGasValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ExtraDataMaxLengthValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasLimitRangeAndDeltaValidationRule;
import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.GasUsageValidationRule;
@@ -200,6 +200,6 @@ public final class MainnetBlockHeaderValidator {
public static BlockHeaderValidator.Builder cancunBlockHeaderValidator(final FeeMarket feeMarket) {
return mergeBlockHeaderValidator(feeMarket)
.addRule(new DataGasValidationRule(new CancunGasCalculator()));
.addRule(new BlobGasValidationRule(new CancunGasCalculator()));
}
}

View File

@@ -656,9 +656,9 @@ public abstract class MainnetProtocolSpecs {
genesisConfigOptions,
evmConfiguration)
.feeMarket(cancunFeeMarket)
// gas calculator for EIP-4844 data gas
// gas calculator for EIP-4844 blob gas
.gasCalculator(CancunGasCalculator::new)
// gas limit with EIP-4844 max data gas per block
// gas limit with EIP-4844 max blob gas per block
.gasLimitCalculatorBuilder(
feeMarket ->
new CancunTargetingGasLimitCalculator(
@@ -696,7 +696,7 @@ public abstract class MainnetProtocolSpecs {
stackSizeLimit,
feeMarket,
CoinbaseFeePriceCalculator.eip1559()))
// change to check for max data gas per block for EIP-4844
// change to check for max blob gas per block for EIP-4844
.transactionValidatorFactoryBuilder(
(gasCalculator, gasLimitCalculator, feeMarket) ->
new TransactionValidatorFactory(

View File

@@ -19,6 +19,7 @@ import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVAT
import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION;
import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.chain.Blockchain;
@@ -31,7 +32,6 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.EvmAccount;
import org.hyperledger.besu.evm.account.MutableAccount;
@@ -124,7 +124,7 @@ public class MainnetTransactionProcessor {
final BlockHashLookup blockHashLookup,
final Boolean isPersistingPrivateState,
final TransactionValidationParams transactionValidationParams,
final Wei dataGasPrice) {
final Wei blobGasPrice) {
return processTransaction(
blockchain,
worldState,
@@ -136,7 +136,7 @@ public class MainnetTransactionProcessor {
isPersistingPrivateState,
transactionValidationParams,
null,
dataGasPrice);
blobGasPrice);
}
/**
@@ -166,7 +166,7 @@ public class MainnetTransactionProcessor {
final Boolean isPersistingPrivateState,
final TransactionValidationParams transactionValidationParams,
final OperationTracer operationTracer,
final Wei dataGasPrice) {
final Wei blobGasPrice) {
return processTransaction(
blockchain,
worldState,
@@ -178,7 +178,7 @@ public class MainnetTransactionProcessor {
isPersistingPrivateState,
transactionValidationParams,
null,
dataGasPrice);
blobGasPrice);
}
/**
@@ -203,7 +203,7 @@ public class MainnetTransactionProcessor {
final OperationTracer operationTracer,
final BlockHashLookup blockHashLookup,
final Boolean isPersistingPrivateState,
final Wei dataGasPrice) {
final Wei blobGasPrice) {
return processTransaction(
blockchain,
worldState,
@@ -215,7 +215,7 @@ public class MainnetTransactionProcessor {
isPersistingPrivateState,
ImmutableTransactionValidationParams.builder().build(),
null,
dataGasPrice);
blobGasPrice);
}
/**
@@ -242,7 +242,7 @@ public class MainnetTransactionProcessor {
final BlockHashLookup blockHashLookup,
final Boolean isPersistingPrivateState,
final TransactionValidationParams transactionValidationParams,
final Wei dataGasPrice) {
final Wei blobGasPrice) {
return processTransaction(
blockchain,
worldState,
@@ -254,7 +254,7 @@ public class MainnetTransactionProcessor {
isPersistingPrivateState,
transactionValidationParams,
null,
dataGasPrice);
blobGasPrice);
}
public TransactionProcessingResult processTransaction(
@@ -268,7 +268,7 @@ public class MainnetTransactionProcessor {
final Boolean isPersistingPrivateState,
final TransactionValidationParams transactionValidationParams,
final PrivateMetadataUpdater privateMetadataUpdater,
final Wei dataGasPrice) {
final Wei blobGasPrice) {
try {
final var transactionValidator = transactionValidatorFactory.get();
LOG.trace("Starting execution of {}", transaction);
@@ -305,10 +305,10 @@ public class MainnetTransactionProcessor {
final Wei transactionGasPrice =
feeMarket.getTransactionPriceCalculator().price(transaction, blockHeader.getBaseFee());
final long dataGas = gasCalculator.dataGasCost(transaction.getBlobCount());
final long blobGas = gasCalculator.blobGasCost(transaction.getBlobCount());
final Wei upfrontGasCost =
transaction.getUpfrontGasCost(transactionGasPrice, dataGasPrice, dataGas);
transaction.getUpfrontGasCost(transactionGasPrice, blobGasPrice, blobGas);
final Wei previousBalance = senderMutableAccount.decrementBalance(upfrontGasCost);
LOG.trace(
"Deducted sender {} upfront gas cost {} ({} -> {})",
@@ -324,9 +324,9 @@ public class MainnetTransactionProcessor {
final Multimap<Address, Bytes32> storageList = HashMultimap.create();
int accessListStorageCount = 0;
for (final var entry : accessListEntries) {
final Address address = entry.getAddress();
final Address address = entry.address();
addressList.add(address);
final List<Bytes32> storageKeys = entry.getStorageKeys();
final List<Bytes32> storageKeys = entry.storageKeys();
storageList.putAll(address, storageKeys);
accessListStorageCount += storageKeys.size();
}
@@ -346,7 +346,7 @@ public class MainnetTransactionProcessor {
transaction.getGasLimit(),
intrinsicGas,
accessListGas,
dataGas);
blobGas);
final WorldUpdater worldUpdater = worldState.updater();
final ImmutableMap.Builder<String, Object> contextVariablesBuilder =

View File

@@ -51,7 +51,7 @@ import org.bouncycastle.crypto.digests.SHA256Digest;
*/
public class MainnetTransactionValidator implements TransactionValidator {
private final byte BLOB_COMMITMENT_VERSION_KZG = 0x01;
private static final byte BLOB_COMMITMENT_VERSION_KZG = 0x01;
private final GasCalculator gasCalculator;
private final GasLimitCalculator gasLimitCalculator;
@@ -93,11 +93,19 @@ public class MainnetTransactionValidator implements TransactionValidator {
return signatureResult;
}
if (transaction.getType().supportsBlob() && transaction.getBlobsWithCommitments().isPresent()) {
final ValidationResult<TransactionInvalidReason> blobsResult =
validateTransactionsBlobs(transaction);
if (!blobsResult.isValid()) {
return blobsResult;
if (transaction.getType().supportsBlob()) {
final ValidationResult<TransactionInvalidReason> blobTransactionResult =
validateBlobTransaction(transaction);
if (!blobTransactionResult.isValid()) {
return blobTransactionResult;
}
if (transaction.getBlobsWithCommitments().isPresent()) {
final ValidationResult<TransactionInvalidReason> blobsResult =
validateTransactionsBlobs(transaction);
if (!blobsResult.isValid()) {
return blobsResult;
}
}
}
@@ -155,24 +163,24 @@ public class MainnetTransactionValidator implements TransactionValidator {
}
if (transaction.getType().supportsBlob()) {
final long txTotalDataGas = gasCalculator.dataGasCost(transaction.getBlobCount());
if (txTotalDataGas > gasLimitCalculator.currentDataGasLimit()) {
final long txTotalBlobGas = gasCalculator.blobGasCost(transaction.getBlobCount());
if (txTotalBlobGas > gasLimitCalculator.currentBlobGasLimit()) {
return ValidationResult.invalid(
TransactionInvalidReason.TOTAL_DATA_GAS_TOO_HIGH,
TransactionInvalidReason.TOTAL_BLOB_GAS_TOO_HIGH,
String.format(
"total data gas %d exceeds max data gas per block %d",
txTotalDataGas, gasLimitCalculator.currentDataGasLimit()));
"total blob gas %d exceeds max blob gas per block %d",
txTotalBlobGas, gasLimitCalculator.currentBlobGasLimit()));
}
}
if (transaction.getType().supportsBlob()) {
final long txTotalDataGas = gasCalculator.dataGasCost(transaction.getBlobCount());
if (txTotalDataGas > gasLimitCalculator.currentDataGasLimit()) {
final long txTotalBlobGas = gasCalculator.blobGasCost(transaction.getBlobCount());
if (txTotalBlobGas > gasLimitCalculator.currentBlobGasLimit()) {
return ValidationResult.invalid(
TransactionInvalidReason.TOTAL_DATA_GAS_TOO_HIGH,
TransactionInvalidReason.TOTAL_BLOB_GAS_TOO_HIGH,
String.format(
"total data gas %d exceeds max data gas per block %d",
txTotalDataGas, gasLimitCalculator.currentDataGasLimit()));
"total blob gas %d exceeds max blob gas per block %d",
txTotalBlobGas, gasLimitCalculator.currentBlobGasLimit()));
}
}
@@ -207,7 +215,7 @@ public class MainnetTransactionValidator implements TransactionValidator {
}
final Wei upfrontCost =
transaction.getUpfrontCost(gasCalculator.dataGasCost(transaction.getBlobCount()));
transaction.getUpfrontCost(gasCalculator.blobGasCost(transaction.getBlobCount()));
if (upfrontCost.compareTo(senderBalance) > 0) {
return ValidationResult.invalid(
TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE,
@@ -282,7 +290,7 @@ public class MainnetTransactionValidator implements TransactionValidator {
return ValidationResult.valid();
}
public ValidationResult<TransactionInvalidReason> validateTransactionsBlobs(
public ValidationResult<TransactionInvalidReason> validateBlobTransaction(
final Transaction transaction) {
if (transaction.getType().supportsBlob() && transaction.getTo().isEmpty()) {
@@ -291,6 +299,18 @@ public class MainnetTransactionValidator implements TransactionValidator {
"transaction blob transactions cannot have a to address");
}
if (transaction.getVersionedHashes().isEmpty()) {
return ValidationResult.invalid(
TransactionInvalidReason.INVALID_BLOBS,
"transaction blob transactions must specify one or more versioned hashes");
}
return ValidationResult.valid();
}
public ValidationResult<TransactionInvalidReason> validateTransactionsBlobs(
final Transaction transaction) {
if (transaction.getBlobsWithCommitments().isEmpty()) {
return ValidationResult.invalid(
TransactionInvalidReason.INVALID_BLOBS,

View File

@@ -0,0 +1,60 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.mainnet;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
/** A helper class to store the parent beacon block root. */
public class ParentBeaconBlockRootHelper {
// Modulus use to for the timestamp to store the root
public static final long HISTORICAL_ROOTS_MODULUS = 98304;
// Address of the system user, that is used to call the contract for storing the root
// public static final Address SYSTEM_ADDRESS =
// Address.fromHexString("0xfffffffffffffffffffffffffffffffffffffffe");
// The address of the contract that stores the roots
// public static final Address BEACON_ROOTS_ADDRESS =
// Address.fromHexString("0x89e64Be8700cC37EB34f9209c96466DEEDc0d8a6");
public static void storeParentBeaconBlockRoot(
final WorldUpdater worldUpdater, final long timestamp, final Bytes32 root) {
/*
pseudo code from EIP 4788:
timestamp_as_uint256 = to_uint256_be(block_header.timestamp)
parent_beacon_block_root = block_header.parent_beacon_block_root
sstore(HISTORY_STORAGE_ADDRESS, timestamp_index, timestamp_as_uint256)
sstore(HISTORY_STORAGE_ADDRESS, root_index, parent_beacon_block_root)
*/
final long timestampReduced = timestamp % HISTORICAL_ROOTS_MODULUS;
final long timestampExtended = timestampReduced + HISTORICAL_ROOTS_MODULUS;
final UInt256 timestampIndex = UInt256.valueOf(timestampReduced);
final UInt256 rootIndex = UInt256.valueOf(timestampExtended);
final MutableAccount account =
worldUpdater.getOrCreate(Address.PARENT_BEACON_BLOCK_ROOT_REGISTRY).getMutable();
account.setStorageValue(timestampIndex, UInt256.valueOf(timestamp));
account.setStorageValue(rootIndex, UInt256.fromBytes(root));
worldUpdater.commit();
}
}

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.ethereum.mainnet.feemarket;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
import java.math.BigInteger;
@@ -25,8 +25,8 @@ import org.slf4j.LoggerFactory;
public class CancunFeeMarket extends LondonFeeMarket {
private static final Logger LOG = LoggerFactory.getLogger(CancunFeeMarket.class);
private static final BigInteger MIN_DATA_GAS_PRICE = BigInteger.ONE;
private static final BigInteger DATA_GAS_PRICE_UPDATE_FRACTION = BigInteger.valueOf(3338477);
private static final BigInteger BLOB_GAS_PRICE = BigInteger.ONE;
private static final BigInteger BLOB_GAS_PRICE_UPDATE_FRACTION = BigInteger.valueOf(3338477);
public CancunFeeMarket(
final long londonForkBlockNumber, final Optional<Wei> baseFeePerGasOverride) {
@@ -39,18 +39,18 @@ public class CancunFeeMarket extends LondonFeeMarket {
}
@Override
public Wei dataPricePerGas(final DataGas excessDataGas) {
final var dataGasPrice =
public Wei blobGasPricePerGas(final BlobGas excessBlobGas) {
final var blobGasPrice =
Wei.of(
fakeExponential(
MIN_DATA_GAS_PRICE, excessDataGas.toBigInteger(), DATA_GAS_PRICE_UPDATE_FRACTION));
BLOB_GAS_PRICE, excessBlobGas.toBigInteger(), BLOB_GAS_PRICE_UPDATE_FRACTION));
LOG.atTrace()
.setMessage("parentExcessDataGas: {} dataGasPrice: {}")
.addArgument(excessDataGas::toShortHexString)
.addArgument(dataGasPrice::toHexString)
.setMessage("parentExcessBlobGas: {} blobGasPrice: {}")
.addArgument(excessBlobGas::toShortHexString)
.addArgument(blobGasPrice::toHexString)
.log();
return dataGasPrice;
return blobGasPrice;
}
private BigInteger fakeExponential(

View File

@@ -14,29 +14,29 @@
*/
package org.hyperledger.besu.ethereum.mainnet.feemarket;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
/** Calculates the excess data gas for a parent block header. */
public class ExcessDataGasCalculator {
/** Calculates the excess blob gas for a parent block header. */
public class ExcessBlobGasCalculator {
/**
* public class ExcessDataGasCalculator { /** Calculates the excess data gas for a parent block
* public class ExcessBlobGasCalculator { /** Calculates the excess blob gas for a parent block
* header.
*
* @param protocolSpec The protocol specification.
* @param parentHeader The parent block header.
* @return The excess data gas.
* @return The excess blob gas.
*/
public static DataGas calculateExcessDataGasForParent(
public static BlobGas calculateExcessBlobGasForParent(
final ProtocolSpec protocolSpec, final BlockHeader parentHeader) {
// Blob Data Excess
long headerExcess =
protocolSpec
.getGasCalculator()
.computeExcessDataGas(
parentHeader.getExcessDataGas().map(DataGas::toLong).orElse(0L),
parentHeader.getDataGasUsed().orElse(0L));
return DataGas.of(headerExcess);
.computeExcessBlobGas(
parentHeader.getExcessBlobGas().map(BlobGas::toLong).orElse(0L),
parentHeader.getBlobGasUsed().orElse(0L));
return BlobGas.of(headerExcess);
}
}

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.ethereum.mainnet.feemarket;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.feemarket.TransactionPriceCalculator;
@@ -57,7 +57,7 @@ public interface FeeMarket {
return new LegacyFeeMarket();
}
default Wei dataPricePerGas(final DataGas excessDataGas) {
default Wei blobGasPricePerGas(final BlobGas excessBlobGas) {
return Wei.ZERO;
}
}

View File

@@ -14,7 +14,7 @@
*/
package org.hyperledger.besu.ethereum.mainnet.headervalidationrules;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
@@ -22,35 +22,35 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Validation rule to check if the block header's excess data gas matches the calculated value. */
public class DataGasValidationRule implements DetachedBlockHeaderValidationRule {
/** Validation rule to check if the block header's excess blob gas matches the calculated value. */
public class BlobGasValidationRule implements DetachedBlockHeaderValidationRule {
private static final Logger LOG = LoggerFactory.getLogger(DataGasValidationRule.class);
private static final Logger LOG = LoggerFactory.getLogger(BlobGasValidationRule.class);
private final GasCalculator gasCalculator;
public DataGasValidationRule(final GasCalculator gasCalculator) {
public BlobGasValidationRule(final GasCalculator gasCalculator) {
this.gasCalculator = gasCalculator;
}
/**
* Validates the block header by checking if the header's excess data gas matches the calculated
* Validates the block header by checking if the header's excess blob gas matches the calculated
* value based on the parent header.
*/
@Override
public boolean validate(final BlockHeader header, final BlockHeader parent) {
long headerExcessDataGas = header.getExcessDataGas().map(DataGas::toLong).orElse(0L);
long parentExcessDataGas = parent.getExcessDataGas().map(DataGas::toLong).orElse(0L);
long parentDataGasUsed = parent.getDataGasUsed().orElse(0L);
long headerExcessBlobGas = header.getExcessBlobGas().map(BlobGas::toLong).orElse(0L);
long parentExcessBlobGas = parent.getExcessBlobGas().map(BlobGas::toLong).orElse(0L);
long parentBlobGasUsed = parent.getBlobGasUsed().orElse(0L);
long calculatedExcessDataGas =
gasCalculator.computeExcessDataGas(parentExcessDataGas, parentDataGasUsed);
long calculatedExcessBlobGas =
gasCalculator.computeExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed);
if (headerExcessDataGas != calculatedExcessDataGas) {
if (headerExcessBlobGas != calculatedExcessBlobGas) {
LOG.info(
"Invalid block header: header excessDataGas {} and calculated excessDataGas {} do not match",
headerExcessDataGas,
calculatedExcessDataGas);
"Invalid block header: header excessBlobGas {} and calculated excessBlobGas {} do not match",
headerExcessBlobGas,
calculatedExcessBlobGas);
return false;
}
return true;

View File

@@ -78,6 +78,11 @@ public class WorldStateKeyValueStorage implements WorldStateStorage {
}
}
@Override
public Optional<Bytes> getTrieNodeUnsafe(final Bytes key) {
return keyValueStorage.get(key.toArrayUnsafe()).map(Bytes::wrap);
}
@Override
public FlatDbMode getFlatDbMode() {
return FlatDbMode.NO_FLATTENED;

Some files were not shown because too many files have changed in this diff Show More