From 9e2f4713800351b2778026f78c2b928483352583 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Fri, 16 Feb 2024 11:24:00 -0700 Subject: [PATCH] Apply Reference tests v13.1 (#6574) Update to new reference tests for cancun. * Init KZG as part of ReferenceTestProtocolSchedules * fix unsigned long errors * block validation on borked blobGasUsed Signed-off-by: Justin Florentine Signed-off-by: Danno Ferrin Signed-off-by: Sally MacFarlane Co-authored-by: Justin Florentine Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 1 + .../besu/ethereum/core/BlockHeader.java | 10 ++------- .../mainnet/AbstractBlockProcessor.java | 19 +++++++++++++++-- .../BlobGasValidationRule.java | 10 ++++++++- ethereum/referencetests/build.gradle | 2 +- .../referencetests/ReferenceTestEnv.java | 3 ++- .../ReferenceTestProtocolSchedules.java | 3 +++ .../src/reference-test/external-resources | 2 +- .../hyperledger/besu/evm/internal/Words.java | 21 +++++++++++++++++++ 9 files changed, 57 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e8352f0a65..d166031ce68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ - More accurate column size `storage rocksdb usage` subcommand [#6540](https://github.com/hyperledger/besu/pull/6540) - Adds `storage rocksdb x-stats` subcommand [#6540](https://github.com/hyperledger/besu/pull/6540) - New `eth_blobBaseFee`JSON-RPC method [#6581](https://github.com/hyperledger/besu/pull/6581) +- Upgrade reference tests to version 13.1 [#6574](https://github.com/hyperledger/besu/pull/6574) ### Bug fixes - Fix the way an advertised host configured with `--p2p-host` is treated when communicating with the originator of a PING packet [#6225](https://github.com/hyperledger/besu/pull/6225) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java index 7aa5770f3fc..7f06e6c821e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java @@ -102,11 +102,6 @@ public Hash getMixHash() { return Hash.wrap(mixHashOrPrevRandao); } - @Override - public Bytes32 getMixHashOrPrevRandao() { - return mixHashOrPrevRandao; - } - /** * Returns the block nonce. * @@ -207,7 +202,7 @@ public static BlockHeader readFrom( : null; final Long blobGasUsed = !input.isEndOfCurrentList() ? input.readLongScalar() : null; final BlobGas excessBlobGas = - !input.isEndOfCurrentList() ? BlobGas.of(input.readLongScalar()) : null; + !input.isEndOfCurrentList() ? BlobGas.of(input.readUInt64Scalar()) : null; final Bytes32 parentBeaconBlockRoot = !input.isEndOfCurrentList() ? input.readBytes32() : null; final Hash depositHashRoot = !input.isEndOfCurrentList() ? Hash.wrap(input.readBytes32()) : null; @@ -242,10 +237,9 @@ public boolean equals(final Object obj) { if (obj == this) { return true; } - if (!(obj instanceof BlockHeader)) { + if (!(obj instanceof BlockHeader other)) { return false; } - final BlockHeader other = (BlockHeader) obj; return getHash().equals(other.getHash()); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java index 8f1b01a50c1..1a70ce49381 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java @@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.trie.bonsai.worldview.BonsaiWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; +import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldState; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -101,6 +102,7 @@ public BlockProcessingResult processBlock( final PrivateMetadataUpdater privateMetadataUpdater) { final List receipts = new ArrayList<>(); long currentGasUsed = 0; + long currentBlobGasUsed = 0; final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(blockHeader); @@ -127,7 +129,7 @@ public BlockProcessingResult processBlock( Wei blobGasPrice = maybeParentHeader .map( - (parentHeader) -> + parentHeader -> protocolSpec .getFeeMarket() .blobGasPricePerGas( @@ -163,12 +165,25 @@ public BlockProcessingResult processBlock( worldStateUpdater.commit(); currentGasUsed += transaction.getGasLimit() - result.getGasRemaining(); + if (transaction.getVersionedHashes().isPresent()) { + currentBlobGasUsed += + (transaction.getVersionedHashes().get().size() * CancunGasCalculator.BLOB_GAS_PER_BLOB); + } + final TransactionReceipt transactionReceipt = transactionReceiptFactory.create( transaction.getType(), result, worldState, currentGasUsed); receipts.add(transactionReceipt); } - + if (blockHeader.getBlobGasUsed().isPresent() + && currentBlobGasUsed != blockHeader.getBlobGasUsed().get()) { + String errorMessage = + String.format( + "block did not consume expected blob gas: header %d, transactions %d", + blockHeader.getBlobGasUsed().get(), currentBlobGasUsed); + LOG.error(errorMessage); + return new BlockProcessingResult(Optional.empty(), errorMessage); + } final Optional maybeWithdrawalsProcessor = protocolSpec.getWithdrawalsProcessor(); if (maybeWithdrawalsProcessor.isPresent() && maybeWithdrawals.isPresent()) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java index e58d378562f..f5c22a710b3 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java @@ -17,6 +17,7 @@ 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.CancunGasCalculator; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.slf4j.Logger; @@ -35,7 +36,7 @@ public BlobGasValidationRule(final GasCalculator gasCalculator) { /** * Validates the block header by checking if the header's excess blob gas matches the calculated - * value based on the parent header. + * value based on the parent header, as well that the used blobGas is a multiple of GAS_PER_BLOB. */ @Override public boolean validate(final BlockHeader header, final BlockHeader parent) { @@ -53,6 +54,13 @@ public boolean validate(final BlockHeader header, final BlockHeader parent) { calculatedExcessBlobGas); return false; } + long headerBlobGasUsed = header.getBlobGasUsed().orElse(0L); + if (headerBlobGasUsed % CancunGasCalculator.BLOB_GAS_PER_BLOB != 0) { + LOG.info( + "blob gas used must be multiple of GAS_PER_BLOB ({})", + CancunGasCalculator.BLOB_GAS_PER_BLOB); + return false; + } return true; } } diff --git a/ethereum/referencetests/build.gradle b/ethereum/referencetests/build.gradle index a30317f5d3f..8bbda83eb14 100644 --- a/ethereum/referencetests/build.gradle +++ b/ethereum/referencetests/build.gradle @@ -198,7 +198,7 @@ tasks.register('validateReferenceTestSubmodule') { description = "Checks that the reference tests submodule is not accidentally changed" doLast { def result = new ByteArrayOutputStream() - def expectedHash = '428f218d7d6f4a52544e12684afbfe6e2882ffbf' + def expectedHash = '853b1e03b1078d370614002851ba1ee9803d9fcf ' def submodulePath = java.nio.file.Path.of("${rootProject.projectDir}", "ethereum/referencetests/src/reference-test/external-resources").toAbsolutePath() try { exec { diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java index 2daf1893ba4..c7e726d03ff 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.referencetests; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.hyperledger.besu.evm.internal.Words.decodeUnsignedLong; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; @@ -138,7 +139,7 @@ public ReferenceTestEnv( number == null ? 0 : Long.decode(number), gasLimit == null ? 15_000_000L : Long.decode(gasLimit), 0L, - timestamp == null ? 0L : Long.decode(timestamp), + timestamp == null ? 0L : decodeUnsignedLong(timestamp), Bytes.EMPTY, Optional.ofNullable(baseFee).map(Wei::fromHexString).orElse(null), Optional.ofNullable(random).map(Difficulty::fromHexString).orElse(Difficulty.ZERO), diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java index df4a5722721..77c9be2037b 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.evm.precompile.KZGPointEvalPrecompiledContract; import java.math.BigInteger; import java.util.Arrays; @@ -78,6 +79,8 @@ public static ReferenceTestProtocolSchedules create(final StubGenesisConfigOptio "ShanghaiToCancunAtTime15k", createSchedule(genesisStub.clone().shanghaiTime(0).cancunTime(15000))); builder.put("Cancun", createSchedule(genesisStub.clone().cancunTime(0))); + // also load KZG file for mainnet + KZGPointEvalPrecompiledContract.init(); builder.put("Prague", createSchedule(genesisStub.clone().pragueTime(0))); builder.put("Future_EIPs", createSchedule(genesisStub.clone().futureEipsTime(0))); builder.put("Experimental_EIPs", createSchedule(genesisStub.clone().experimentalEipsTime(0))); diff --git a/ethereum/referencetests/src/reference-test/external-resources b/ethereum/referencetests/src/reference-test/external-resources index 428f218d7d6..853b1e03b10 160000 --- a/ethereum/referencetests/src/reference-test/external-resources +++ b/ethereum/referencetests/src/reference-test/external-resources @@ -1 +1 @@ -Subproject commit 428f218d7d6f4a52544e12684afbfe6e2882ffbf +Subproject commit 853b1e03b1078d370614002851ba1ee9803d9fcf diff --git a/evm/src/main/java/org/hyperledger/besu/evm/internal/Words.java b/evm/src/main/java/org/hyperledger/besu/evm/internal/Words.java index 821406c8aa4..7a8308431a6 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/internal/Words.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/internal/Words.java @@ -16,6 +16,8 @@ import org.hyperledger.besu.datatypes.Address; +import java.math.BigInteger; + import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.MutableBytes; @@ -213,4 +215,23 @@ static Bytes longBytes(final long value) { (byte) (value >>> 8), (byte) value); } + + static long decodeUnsignedLong(final String number) { + String parsable = number; + int radix = 10; + if (number.startsWith("0x")) { + radix = 16; + parsable = number.substring(2); + } else if (!number.matches("\\d+")) { + // presume naked hex + radix = 16; + } + + BigInteger bi = new BigInteger(parsable, radix); + if (bi.bitCount() > 64) { + throw new NumberFormatException("Number larger than uint64"); + } + + return bi.longValue(); + } }