mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 21:17:54 -05:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
25
CHANGELOG.md
25
CHANGELOG.md
@@ -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
|
||||
|
||||
@@ -57,6 +57,7 @@ public class BlockUtils {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
blockHeaderFunctions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4073,6 +4073,6 @@
|
||||
"gasUsed": "0x0",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"baseFeePerGas": null,
|
||||
"dataGasUsed": null,
|
||||
"excessDataGas": null
|
||||
"blobGasUsed": null,
|
||||
"excessBlobGas": null
|
||||
}
|
||||
@@ -20,8 +20,8 @@
|
||||
"blockHash": "0x50c02dc77082fe2060b600cba0e6ce5a491af6d5323b2a90a7bc6359dd18e97b",
|
||||
"transactions": [],
|
||||
"withdrawals": [],
|
||||
"dataGasUsed": null,
|
||||
"excessDataGas": null
|
||||
"blobGasUsed": null,
|
||||
"excessBlobGas": null
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
"blockHash": "0x50c02dc77082fe2060b600cba0e6ce5a491af6d5323b2a90a7bc6359dd18e97b",
|
||||
"transactions": [],
|
||||
"withdrawals": [],
|
||||
"dataGasUsed": null,
|
||||
"excessDataGas": null
|
||||
"blobGasUsed": null,
|
||||
"excessBlobGas": null
|
||||
},
|
||||
null
|
||||
]
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
"blockHash": "0xc33d43425366d661ef70df12faf8ccd66ed7d0c6718d16d14868ba49e6786927",
|
||||
"transactions": [],
|
||||
"withdrawals": [],
|
||||
"dataGasUsed": "0x0",
|
||||
"excessDataGas": "0x0"
|
||||
"blobGasUsed": "0x0",
|
||||
"excessBlobGas": "0x0"
|
||||
},
|
||||
[]
|
||||
]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -253,6 +253,7 @@ public class EngineExchangeTransitionConfigurationTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new BlockHeaderFunctions() {
|
||||
@Override
|
||||
public Hash hash(final BlockHeader header) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())));
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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
Reference in New Issue
Block a user