Skip to content

fix(evmtool): use excessBlobGas from test environment in state-test#9545

Merged
macfarla merged 6 commits intobesu-eth:mainfrom
bshastry:fix/evmtool-state-test-excess-blob-gas
Dec 11, 2025
Merged

fix(evmtool): use excessBlobGas from test environment in state-test#9545
macfarla merged 6 commits intobesu-eth:mainfrom
bshastry:fix/evmtool-state-test-excess-blob-gas

Conversation

@bshastry
Copy link
Copy Markdown
Contributor

@bshastry bshastry commented Dec 6, 2025

Summary

Fix evmtool state-test command to correctly use currentExcessBlobGas from the test environment when calculating blob gas price, instead of always using zero.

Fixed Issue(s)

N/A - This fix addresses a consensus divergence (only via the statetest interface) discovered during differential fuzzing with goevmlab.


Thanks for sending a pull request! Have you done the following?

  • Checked out our contribution guidelines?
  • Considered documentation and added the doc-change-required label to this PR if updates are required.
  • Considered the changelog and included an update if required. (evmtool fix, not user-facing)
  • For database changes (e.g. KeyValueSegmentIdentifier) considered compatibility and performed forwards and backwards compatibility tests (N/A - no database changes)

Locally, you can run these tests to catch failures early:

  • spotless: ./gradlew spotlessApply
  • unit tests: ./gradlew :ethereum:evmtool:test --tests StateTestSubCommandTest
  • acceptance tests: ./gradlew acceptanceTest (not required for evmtool changes)
  • integration tests: ./gradlew integrationTest (not required for evmtool changes)
  • reference tests: ./gradlew ethereum:referenceTests:referenceTests (not applicable)
  • hive tests: Engine or other RPCs modified? (N/A - evmtool only)

Description

The StateTestSubCommand was hardcoding BlobGas.ZERO when calculating blob gas price for EIP-4844 transaction validation:

// Before (incorrect):
final Wei blobGasPrice = protocolSpec.getFeeMarket().blobGasPricePerGas(BlobGas.ZERO);

// After (correct):
final BlobGas excessBlobGas = blockHeader.getExcessBlobGas().orElse(BlobGas.ZERO);
final Wei blobGasPrice = protocolSpec.getFeeMarket().blobGasPricePerGas(excessBlobGas);

This caused the BLOBBASEFEE opcode (0x4a) to always return 1 (minimum blob gas price) regardless of what currentExcessBlobGas was specified in the test environment.

Impact

With excessBlobGas=0x240000 (2,359,296) and Cancun's blob fee update fraction (3,338,477):

  • Before fix: BLOBBASEFEE returns 1 (using zero excess blob gas)
  • After fix: BLOBBASEFEE correctly returns 2 (using actual excess blob gas)

This affects:

  • State test execution producing incorrect state roots when tests use non-zero currentExcessBlobGas
  • Blob transaction validation using incorrect blob gas prices
  • Differential testing against geth showing false positives

Test Plan

  • Added unit test shouldUseExcessBlobGasFromEnvironment that verifies correct blob gas price calculation
  • Verified state root matches geth output for test with currentExcessBlobGas=0x240000
  • All existing StateTestSubCommandTest tests pass

Notes

  • This is a developer tooling fix for evmtool, not a change to core Besu consensus
  • The fix mirrors how GeneralStateReferenceTestTools correctly handles excess blob gas
  • Similar fix was applied to REVM (commit 652419e6) for the same class of bug

The state-test command was hardcoding BlobGas.ZERO when calculating
blob gas price, ignoring the currentExcessBlobGas from the test
environment. This caused incorrect BLOBBASEFEE opcode results and
state root divergence with geth.

With excessBlobGas=0x240000 and Cancun blob fee fraction:
- Before: BLOBBASEFEE returns 1 (using zero)
- After: BLOBBASEFEE returns 2 (using actual value)

Signed-off-by: Bhargava Shastry <bhargava.shastry@ethereum.org>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@macfarla macfarla enabled auto-merge (squash) December 8, 2025 23:48
@macfarla macfarla disabled auto-merge December 9, 2025 02:48
@macfarla
Copy link
Copy Markdown
Contributor

macfarla commented Dec 9, 2025

Thanks for the fix @bshastry - there is one EvmToolSpecTests failing -

Cannot invoke "com.fasterxml.jackson.databind.JsonNode.isTextual()" because "cliNode" is null
java.lang.NullPointerException: Cannot invoke "com.fasterxml.jackson.databind.JsonNode.isTextual()" because "cliNode" is null
	at org.hyperledger.besu.evmtool.EvmToolSpecTests.testBySpec(EvmToolSpecTests.java:138)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)

@macfarla macfarla marked this pull request as draft December 9, 2025 02:53
…cTests

The excess-blob-gas.json file was in raw state test format but placed in
the state-test/ directory which is scanned by EvmToolSpecTests. This caused
a NullPointerException because EvmToolSpecTests expects a spec wrapper format
with cli, stdin, stdout fields.

- Convert state-test/excess-blob-gas.json to spec wrapper format
- Create separate excess-blob-gas.json in parent directory for StateTestSubCommandTest
- Update StateTestSubCommandTest to reference the new file location

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Bhargava Shastry <bhargava.shastry@ethereum.org>
@bshastry bshastry force-pushed the fix/evmtool-state-test-excess-blob-gas branch from 55942c6 to 49dee27 Compare December 10, 2025 10:24
@bshastry bshastry marked this pull request as ready for review December 10, 2025 10:24
@bshastry
Copy link
Copy Markdown
Contributor Author

Thanks for the fix @bshastry - there is one EvmToolSpecTests failing -

Cannot invoke "com.fasterxml.jackson.databind.JsonNode.isTextual()" because "cliNode" is null
java.lang.NullPointerException: Cannot invoke "com.fasterxml.jackson.databind.JsonNode.isTextual()" because "cliNode" is null
	at org.hyperledger.besu.evmtool.EvmToolSpecTests.testBySpec(EvmToolSpecTests.java:138)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)

I fixed it in the later commit. Hopefully, this should pass all checks 🙏

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
@macfarla macfarla merged commit b256243 into besu-eth:main Dec 11, 2025
46 checks passed
@github-project-automation github-project-automation bot moved this from Open PRs to Done in RC 25.12.0 Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants