New excess_data_gas block header field (#4958)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
pull/4971/head
Fabio Di Fabio 2 years ago committed by GitHub
parent 857db71e8b
commit 6e8e24874f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 1
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/BlockUtils.java
  3. 2
      besu/src/test/java/org/hyperledger/besu/services/BesuEventsImplTest.java
  4. 147
      datatypes/src/main/java/org/hyperledger/besu/datatypes/DataGas.java
  5. 1
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java
  6. 1
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java
  7. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGasPriceTest.java
  8. 1
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java
  9. 1
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesLogCacheTest.java
  10. 1
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/GoQuorumPrivateTxBloomBlockchainQueriesTest.java
  11. 1
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/GoQuorumPrivateTransactionLogBloomCacherTest.java
  12. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/cache/TransactionLogBloomCacherTest.java
  13. 21
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java
  14. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java
  15. 10
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java
  16. 7
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java
  17. 5
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/NonBesuBlockHeader.java
  18. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/bonsai/LogRollingTests.java
  19. 8
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/KeccakHasherTest.java
  20. 1
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/MessageWrapperTest.java
  21. 3
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java
  22. 3
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java
  23. 1
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java
  24. 2
      plugin-api/build.gradle
  25. 8
      plugin-api/src/main/java/org/hyperledger/besu/plugin/data/BlockHeader.java

@ -17,6 +17,7 @@
### Breaking Changes
### Additions and Improvements
- Add `excess_data_gas` field to block header [#4958](https://github.com/hyperledger/besu/pull/4958)
### Bug Fixes
- Mitigation fix for stale bonsai code storage leading to log rolling issues on contract recreates [#4906](https://github.com/hyperledger/besu/pull/4906)

@ -54,6 +54,7 @@ public class BlockUtils {
mixHash,
new BigInteger(block.getNonceRaw().substring(2), 16).longValue(),
null,
null,
blockHeaderFunctions);
}
}

@ -193,7 +193,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));
}
private void clearSyncTarget() {

@ -0,0 +1,147 @@
/*
* Copyright contributors to Hyperledger Besu
*
* 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.datatypes;
import org.hyperledger.besu.plugin.data.Quantity;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.BaseUInt256Value;
import org.apache.tuweni.units.bigints.UInt256;
/** A particular quantity of DataGas */
public final class DataGas extends BaseUInt256Value<DataGas> implements Quantity {
/** The constant ZERO. */
public static final DataGas ZERO = of(0);
/** The constant ONE. */
public static final DataGas ONE = of(1);
/** The constant MAX_DATA_GAS. */
public static final DataGas MAX_DATA_GAS = of(UInt256.MAX_VALUE);
/**
* Instantiates a new DataGas.
*
* @param value the value
*/
DataGas(final UInt256 value) {
super(value, DataGas::new);
}
private DataGas(final long v) {
this(UInt256.valueOf(v));
}
private DataGas(final BigInteger v) {
this(UInt256.valueOf(v));
}
private DataGas(final String hexString) {
this(UInt256.fromHexString(hexString));
}
/**
* data gas of value.
*
* @param value the value
* @return the data gas
*/
public static DataGas of(final long value) {
return new DataGas(value);
}
/**
* data gas of value.
*
* @param value the value
* @return the data gas
*/
public static DataGas of(final BigInteger value) {
return new DataGas(value);
}
/**
* data gas of value.
*
* @param value the value
* @return the data gas
*/
public static DataGas of(final UInt256 value) {
return new DataGas(value);
}
/**
* data gas of value.
*
* @param value the value
* @return the data gas
*/
public static DataGas ofNumber(final Number value) {
return new DataGas((BigInteger) value);
}
/**
* Wrap data gas.
*
* @param value the value
* @return the data gas
*/
public static DataGas wrap(final Bytes value) {
return new DataGas(UInt256.fromBytes(value));
}
/**
* From hex string to data gas.
*
* @param str the str
* @return the data gas
*/
public static DataGas fromHexString(final String str) {
return new DataGas(str);
}
@Override
public Number getValue() {
return getAsBigInteger();
}
@Override
public BigInteger getAsBigInteger() {
return toBigInteger();
}
@Override
public String toHexString() {
return super.toHexString();
}
@Override
public String toShortHexString() {
return super.isZero() ? "0x0" : super.toShortHexString();
}
/**
* From quantity to data gas.
*
* @param quantity the quantity
* @return the data gas
*/
public static DataGas fromQuantity(final Quantity quantity) {
return DataGas.wrap((Bytes) quantity);
}
}

@ -124,6 +124,7 @@ public class JsonRpcResponseUtils {
mixHash,
nonce,
withdrawalsRoot,
null, // ToDo 4844: set with the value of excess_data_gas field
blockHeaderFunctions);
return new JsonRpcSuccessResponse(

@ -156,6 +156,7 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
blockParam.getPrevRandao(),
0,
null,
null,
headerFunctions);
// ensure the block hash matches the blockParam hash

@ -162,6 +162,7 @@ public class EthGasPriceTest {
Hash.EMPTY,
0,
null,
null,
null),
new BlockBody(
List.of(
@ -199,6 +200,7 @@ public class EthGasPriceTest {
Hash.EMPTY,
0,
null,
null,
null),
new BlockBody(List.of(), List.of())));
}

@ -250,6 +250,7 @@ public class EngineExchangeTransitionConfigurationTest {
Bytes32.ZERO,
0,
null,
null,
new BlockHeaderFunctions() {
@Override
public Hash hash(final BlockHeader header) {

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

@ -93,6 +93,7 @@ public class GoQuorumPrivateTxBloomBlockchainQueriesTest {
Hash.EMPTY,
0,
null,
null,
new MainnetBlockHeaderFunctions(),
Optional.of(testLogsBloomFilter));
testHash = fakeHeader.getHash();

@ -169,6 +169,7 @@ public class GoQuorumPrivateTransactionLogBloomCacherTest {
Hash.EMPTY,
0,
null,
null,
new MainnetBlockHeaderFunctions(),
Optional.of(testLogsBloomFilter));
return fakeHeader;

@ -101,6 +101,7 @@ public class TransactionLogBloomCacherTest {
Hash.EMPTY,
0,
null,
null,
new MainnetBlockHeaderFunctions());
testHash = fakeHeader.getHash();
when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.of(fakeHeader));
@ -266,6 +267,7 @@ public class TransactionLogBloomCacherTest {
Hash.EMPTY,
0,
null,
null,
new MainnetBlockHeaderFunctions());
testHash = fakeHeader.getHash();
when(blockchain.getBlockHeader(number)).thenReturn(Optional.of(fakeHeader));

@ -15,6 +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.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
@ -63,6 +64,7 @@ public class BlockHeader extends SealableBlockHeader
final Bytes32 mixHashOrPrevRandao,
final long nonce,
final Hash withdrawalsRoot,
final DataGas excessDataGas,
final BlockHeaderFunctions blockHeaderFunctions,
final Optional<LogsBloomFilter> privateLogsBloom) {
super(
@ -81,7 +83,8 @@ public class BlockHeader extends SealableBlockHeader
extraData,
baseFee,
mixHashOrPrevRandao,
withdrawalsRoot);
withdrawalsRoot,
excessDataGas);
this.nonce = nonce;
this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this));
this.parsedExtraData = Suppliers.memoize(() -> blockHeaderFunctions.parseExtraData(this));
@ -106,6 +109,7 @@ public class BlockHeader extends SealableBlockHeader
final Bytes32 mixHashOrPrevRandao,
final long nonce,
final Hash withdrawalsRoot,
final DataGas excessDataGas,
final BlockHeaderFunctions blockHeaderFunctions) {
super(
parentHash,
@ -123,7 +127,8 @@ public class BlockHeader extends SealableBlockHeader
extraData,
baseFee,
mixHashOrPrevRandao,
withdrawalsRoot);
withdrawalsRoot,
excessDataGas);
this.nonce = nonce;
this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this));
this.parsedExtraData = Suppliers.memoize(() -> blockHeaderFunctions.parseExtraData(this));
@ -232,6 +237,9 @@ public class BlockHeader extends SealableBlockHeader
if (withdrawalsRoot != null) {
out.writeBytes(withdrawalsRoot);
}
if (excessDataGas != null) {
out.writeUInt256Scalar(excessDataGas);
}
out.endList();
}
@ -256,6 +264,8 @@ public class BlockHeader extends SealableBlockHeader
final Wei baseFee = !input.isEndOfCurrentList() ? Wei.of(input.readUInt256Scalar()) : null;
final Hash withdrawalHashRoot =
!input.isEndOfCurrentList() ? Hash.wrap(input.readBytes32()) : null;
final DataGas excessDataGas =
!input.isEndOfCurrentList() ? DataGas.of(input.readUInt256Scalar()) : null;
input.leaveList();
return new BlockHeader(
parentHash,
@ -275,6 +285,7 @@ public class BlockHeader extends SealableBlockHeader
mixHashOrPrevRandao,
nonce,
withdrawalHashRoot,
excessDataGas,
blockHeaderFunctions);
}
@ -315,10 +326,13 @@ public class BlockHeader extends SealableBlockHeader
sb.append("extraData=").append(extraData).append(", ");
sb.append("baseFee=").append(baseFee).append(", ");
sb.append("mixHashOrPrevRandao=").append(mixHashOrPrevRandao).append(", ");
sb.append("nonce=").append(nonce);
sb.append("nonce=").append(nonce).append(", ");
if (withdrawalsRoot != null) {
sb.append("withdrawalsRoot=").append(withdrawalsRoot).append(", ");
}
if (excessDataGas != null) {
sb.append("excessDataGas=").append(excessDataGas);
}
return sb.append("}").toString();
}
@ -346,6 +360,7 @@ public class BlockHeader extends SealableBlockHeader
.getWithdrawalsRoot()
.map(h -> Hash.fromHexString(h.toHexString()))
.orElse(null),
pluginBlockHeader.getExcessDataGas().map(DataGas::fromQuantity).orElse(null),
blockHeaderFunctions);
}

@ -19,6 +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.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
@ -71,6 +72,8 @@ public class BlockHeaderBuilder {
// instead of an invalid identifier such as -1.
private OptionalLong nonce = OptionalLong.empty();
private DataGas excessDataGas = null;
public static BlockHeaderBuilder create() {
return new BlockHeaderBuilder();
}
@ -114,7 +117,8 @@ public class BlockHeaderBuilder {
.mixHash(header.getMixHash())
.nonce(header.getNonce())
.prevRandao(header.getPrevRandao().orElse(null))
.withdrawalsRoot(header.getWithdrawalsRoot().orElse(null));
.withdrawalsRoot(header.getWithdrawalsRoot().orElse(null))
.excessDataGas(header.getExcessDataGas().orElse(null));
}
public static BlockHeaderBuilder fromBuilder(final BlockHeaderBuilder fromBuilder) {
@ -136,6 +140,7 @@ public class BlockHeaderBuilder {
.baseFee(fromBuilder.baseFee)
.prevRandao(fromBuilder.mixHashOrPrevRandao)
.withdrawalsRoot(fromBuilder.withdrawalsRoot)
.excessDataGas(fromBuilder.excessDataGas)
.blockHeaderFunctions(fromBuilder.blockHeaderFunctions);
toBuilder.nonce = fromBuilder.nonce;
return toBuilder;
@ -162,6 +167,7 @@ public class BlockHeaderBuilder {
mixHashOrPrevRandao,
nonce.getAsLong(),
withdrawalsRoot,
excessDataGas,
blockHeaderFunctions);
}
@ -176,7 +182,8 @@ public class BlockHeaderBuilder {
gasLimit,
timestamp,
baseFee,
mixHashOrPrevRandao);
mixHashOrPrevRandao,
excessDataGas);
}
public SealableBlockHeader buildSealableBlockHeader() {
@ -198,7 +205,8 @@ public class BlockHeaderBuilder {
extraData,
baseFee,
mixHashOrPrevRandao,
withdrawalsRoot);
withdrawalsRoot,
excessDataGas);
}
private void validateBlockHeader() {
@ -238,6 +246,7 @@ public class BlockHeaderBuilder {
timestamp(processableBlockHeader.getTimestamp());
baseFee(processableBlockHeader.getBaseFee().orElse(null));
processableBlockHeader.getPrevRandao().ifPresent(this::prevRandao);
processableBlockHeader.getExcessDataGas().ifPresent(this::excessDataGas);
return this;
}
@ -259,6 +268,7 @@ public class BlockHeaderBuilder {
baseFee(sealableBlockHeader.getBaseFee().orElse(null));
sealableBlockHeader.getPrevRandao().ifPresent(this::prevRandao);
withdrawalsRoot(sealableBlockHeader.getWithdrawalsRoot().orElse(null));
sealableBlockHeader.getExcessDataGas().ifPresent(this::excessDataGas);
return this;
}
@ -373,4 +383,10 @@ public class BlockHeaderBuilder {
this.withdrawalsRoot = hash;
return this;
}
public BlockHeaderBuilder excessDataGas(final DataGas excessDataGas) {
checkArgument(gasLimit >= 0L);
this.excessDataGas = excessDataGas;
return this;
}
}

@ -15,6 +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.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.frame.BlockValues;
@ -43,6 +44,7 @@ public class ProcessableBlockHeader implements BlockValues {
protected final Wei baseFee;
// prevRandao is included for post-merge blocks
protected final Bytes32 mixHashOrPrevRandao;
protected final DataGas excessDataGas;
protected ProcessableBlockHeader(
final Hash parentHash,
@ -52,7 +54,8 @@ public class ProcessableBlockHeader implements BlockValues {
final long gasLimit,
final long timestamp,
final Wei baseFee,
final Bytes32 mixHashOrPrevRandao) {
final Bytes32 mixHashOrPrevRandao,
final DataGas excessDataGas) {
this.parentHash = parentHash;
this.coinbase = coinbase;
this.difficulty = difficulty;
@ -61,6 +64,7 @@ public class ProcessableBlockHeader implements BlockValues {
this.timestamp = timestamp;
this.baseFee = baseFee;
this.mixHashOrPrevRandao = mixHashOrPrevRandao;
this.excessDataGas = excessDataGas;
}
/**
@ -159,6 +163,10 @@ public class ProcessableBlockHeader implements BlockValues {
return Optional.ofNullable(mixHashOrPrevRandao);
}
public Optional<DataGas> getExcessDataGas() {
return Optional.ofNullable(excessDataGas);
}
public String toLogString() {
return getNumber() + " (time: " + getTimestamp() + ")";
}

@ -15,6 +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.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.evm.log.LogsBloomFilter;
@ -58,7 +59,8 @@ public class SealableBlockHeader extends ProcessableBlockHeader {
final Bytes extraData,
final Wei baseFee,
final Bytes32 mixHashOrPrevRandao,
final Hash withdrawalsRoot) {
final Hash withdrawalsRoot,
final DataGas excessDataGas) {
super(
parentHash,
coinbase,
@ -67,7 +69,8 @@ public class SealableBlockHeader extends ProcessableBlockHeader {
gasLimit,
timestamp,
baseFee,
mixHashOrPrevRandao);
mixHashOrPrevRandao,
excessDataGas);
this.ommersHash = ommersHash;
this.stateRoot = stateRoot;
this.transactionsRoot = transactionsRoot;

@ -117,4 +117,9 @@ public class NonBesuBlockHeader implements BlockHeader {
public Hash getBlockHash() {
return blockHash;
}
@Override
public Optional<? extends Quantity> getExcessDataGas() {
return Optional.empty();
}
}

@ -87,6 +87,7 @@ public class LogRollingTests {
Hash.ZERO,
0,
null,
null,
new MainnetBlockHeaderFunctions());
private static final BlockHeader headerTwo =
new BlockHeader(
@ -107,6 +108,7 @@ public class LogRollingTests {
Hash.ZERO,
0,
null,
null,
new MainnetBlockHeaderFunctions());
@Before

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.mainnet;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Difficulty;
@ -47,7 +48,8 @@ public class KeccakHasherTest {
final Bytes extraData,
final Wei baseFee,
final Bytes32 random,
final Hash withdrawalsRoot) {
final Hash withdrawalsRoot,
final DataGas excessDataGas) {
super(
parentHash,
ommersHash,
@ -64,7 +66,8 @@ public class KeccakHasherTest {
extraData,
baseFee,
random,
withdrawalsRoot);
withdrawalsRoot,
excessDataGas);
}
}
@ -111,6 +114,7 @@ public class KeccakHasherTest {
Bytes.fromHexString("0xd88301080f846765746888676f312e31302e31856c696e7578"),
null,
null,
null,
null);
PoWSolution result =

@ -327,6 +327,7 @@ public class MessageWrapperTest {
Hash.fromHexString(mixHash),
Bytes.fromHexStringLenient(nonce).toLong(),
null,
null,
new MainnetBlockHeaderFunctions());
}
}

@ -57,6 +57,7 @@ public class ChainForTestCreator {
Hash.EMPTY,
0,
null,
null,
new MainnetBlockHeaderFunctions());
}
@ -81,6 +82,7 @@ public class ChainForTestCreator {
blockHeader.getMixHash(),
blockHeader.getNonce(),
blockHeader.getWithdrawalsRoot().orElse(null),
blockHeader.getExcessDataGas().orElse(null),
new MainnetBlockHeaderFunctions());
}
@ -127,6 +129,7 @@ public class ChainForTestCreator {
Hash.EMPTY,
0,
null,
null,
new MainnetBlockHeaderFunctions());
}
}

@ -18,6 +18,7 @@ package org.hyperledger.besu.ethereum.referencetests;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.DataGas;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.ProtocolContext;
@ -158,6 +159,7 @@ public class BlockchainReferenceTestCaseSpec {
@JsonProperty("mixHash") final String mixHash,
@JsonProperty("nonce") final String nonce,
@JsonProperty("withdrawalsRoot") final String withdrawalsRoot,
@JsonProperty("excessDataGas") final String excessDataGas,
@JsonProperty("hash") final String hash) {
super(
Hash.fromHexString(parentHash), // parentHash
@ -177,6 +179,7 @@ public class BlockchainReferenceTestCaseSpec {
Hash.fromHexString(mixHash), // mixHash
Bytes.fromHexStringLenient(nonce).toLong(),
withdrawalsRoot != null ? Hash.fromHexString(withdrawalsRoot) : null,
excessDataGas != null ? DataGas.fromHexString(excessDataGas) : null,
new BlockHeaderFunctions() {
@Override
public Hash hash(final BlockHeader header) {

@ -75,6 +75,7 @@ public class ReferenceTestEnv extends BlockHeader {
Optional.ofNullable(random).map(Difficulty::fromHexString).orElse(Difficulty.ZERO),
0L,
null, // withdrawalsRoot
null,
new MainnetBlockHeaderFunctions());
}

@ -66,7 +66,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files
knownHash = 'YkTh76Ko7+iMzVlaAEBR+qw8ct5gRHMQmVRyTI1qhBI='
knownHash = '3JnYE8JbJPkPsNkmlUUFCaUU8Rk1IdfJ8lMuJOBpt5s='
}
check.dependsOn('checkAPIChanges')

@ -187,4 +187,12 @@ public interface BlockHeader {
* withdrawal in the withdrawal list portion of the block.
*/
Optional<? extends Hash> getWithdrawalsRoot();
/**
* The excess_data_gas of this header.
*
* @return The excess_data_gas of this header.
*/
@Unstable
Optional<? extends Quantity> getExcessDataGas();
}

Loading…
Cancel
Save