Enforce EIP-7928 BAL item budget per transaction in processing and mining#10250
Conversation
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
fab-10
left a comment
There was a problem hiding this comment.
LGTM, just a couple of minor things
There was a problem hiding this comment.
Since the code has been moved to a selector, tests can be moved as well for uniformity
There was a problem hiding this comment.
I think this one still make sens but I will add another one for the selector
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Enforces EIP-7928 Block Access List (BAL) item-budget checks consistently during both block import/execution and block building/transaction selection, keeping mining and validation aligned.
Changes:
- Add EIP-7928 BAL item counting utilities (
eip7928ItemCount) + replay support (mergeFrom) for BAL builders/lists. - Wire fork-specific
BlockAccessListValidatorintoProtocolSpecand enforce per-transaction (fail-fast) + post-build validations inAbstractBlockProcessor. - Add a mining selector (
BlockAccessListItemBudgetTransactionSelector) and newTransactionSelectionResultto reject txs that would exceed the BAL item budget, with Amsterdam-focused tests.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| plugin-api/src/main/java/org/hyperledger/besu/plugin/data/TransactionSelectionResult.java | Adds a selection result for BAL item-budget rejection during mining. |
| plugin-api/build.gradle | Updates the plugin API hash to reflect the API change. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/block/access/list/BlockAccessList.java | Adds EIP-7928 item counting and a builder replay (mergeFrom) + builder item counting. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockAccessListValidator.java | Centralizes BAL item-budget validation and post-build hash/size checks. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockAccessListValidator.java | Expands validator API with execution-time size checks and post-build validation. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpec.java | Stores a fork-specific BlockAccessListValidator directly on the spec. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolSpecBuilder.java | Wires blockAccessListValidator into ProtocolSpec construction. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java | Enforces per-tx BAL item-budget fail-fast and delegates post-build BAL validation. |
| ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/BlockAccessListValidationError.java | Adds a structured error container for execution-time BAL validation failures. |
| ethereum/blockcreation/src/main/java/.../BlockTransactionSelector.java | Adds the BAL item-budget selector into the mining selector pipeline. |
| ethereum/blockcreation/src/main/java/.../BlockAccessListItemBudgetTransactionSelector.java | Implements mining-time BAL item-budget rejection logic. |
| ethereum/core/src/test/java/.../MainnetBlockAccessListValidatorTest.java | Adds unit tests for helper methods + post-build size/hash ordering behavior. |
| ethereum/core/src/test/java/.../BlockAccessListBuilderEip7928Test.java | Adds tests validating item counting and merge replay equivalency. |
| ethereum/core/src/test/java/.../AbstractBlockProcessorBalValidationTest.java | Adds tests for per-tx fail-fast and post-build BAL validation in processing. |
| ethereum/blockcreation/src/test/java/.../BlockAccessListItemBudgetTransactionSelectorTest.java | Unit tests for mining selector behavior under budget constraints. |
| ethereum/blockcreation/src/test/java/.../AmsterdamBalBlockTransactionSelectorTest.java | Integration-style selector tests using an Amsterdam genesis config. |
| ethereum/blockcreation/src/test/resources/.../amsterdam-genesis.json | Adds an Amsterdam genesis for BAL-relevant tx selection tests. |
| ethereum/blockcreation/src/test/java/.../AbstractBlockTransactionSelectorTest.java | Extends selector factory to pass optional BAL builder; makes Sender public for reuse. |
| ethereum/core/src/test/java/.../SyncBlockBodyTest.java | Updates ProtocolSpec construction to pass a BlockAccessListValidator. |
| ethereum/api/src/test/java/.../EthGetTransactionReceiptTest.java | Updates ProtocolSpec construction to pass a BlockAccessListValidator. |
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
fab-10
left a comment
There was a problem hiding this comment.
suggestions to replace the use of instanceof with a method that expose if the check is without the budget or not
Signed-off-by: Karim Taam <karim.t2am@gmail.com>
b3c6a01 to
6c28b84
Compare
this way the switch is not needed at all Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
6c28b84 to
4c87595
Compare
|
also tested to build block on Sepolia to be sure there is no regression |
* Refactor and fixes for JMH benchmarks regarding signed values (#10269) Summary of changes: - There was a lot of duplicate setup code in all of the arithmetic opcodes (DIV, SDIV, MOD, ...). All this copy pasting didn't help and the definition of enums with the byte sizes manually creates a source for errors and duplicate effort. - Names are also now consistent within each benchmark following OPCODE_BIT-SIZE_BIT-SIZE structure for easy copy pasting of results and interpretation. - Removed enum case definition in most cases to avoid redundancy. - Some issues were also fixed around negation of inputs for testing signed opcodes (SMOD was missing negation!). Inputs are now correctly negated and compared with their absolute values for swapping them. - Generation of 256 bit negative numbers is now limited to 255 bits to make sure we leave MSB for two complement representation. * Publish besu-evm as an API dependency from plugin-api (#10262) Signed-off-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com> * Header download progress (#10275) * Save and resume header download progress on pipeline restart Track the lowest imported block number in ImportHeadersStep and persist it to ChainSyncState so that backward header downloads can resume from where they left off after an error, rather than restarting from the pivot. - Add ChainSyncState.withHeaderProgress() to update the header progress - Track lowestImportedBlock in ImportHeadersStep - Return BackwardHeaderPipelineResult record from pipeline factory - Call saveHeaderProgress() in SnapSyncChainDownloader on error Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net> * Enforce EIP-7928 BAL item budget per transaction in processing and mining (#10250) Signed-off-by: Karim Taam <karim.t2am@gmail.com> Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Take empty block period seconds out of experimental (#10264) * Take empty block period seconds out of experimental Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Tidy up changelog Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Typo Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Review comments Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> --------- Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Add ChaindId, Coinbase, Gaslimit and PrevRandao to EVM v2 (#10298) * Add ChaindId, Coinbase, Gaslimit and PrevRandao to EVM v2 Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> * Address comments Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> --------- Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> * Rename InvalidSystemCallAddressException to SystemCallNoCodeAtAddressException (#10305) * Rename InvalidSystemCallAddressException to SystemCallNoCodeAtAddressException The exception is thrown when no code exists at the address, not because the address is invalid. Updated all usages. Fixes #10281 Signed-off-by: Liberty S <694522458@qq.com> * Fix missing reference to renamed exception Signed-off-by: Liberty S <694522458@qq.com> --------- Signed-off-by: Liberty S <694522458@qq.com> Co-authored-by: daniellehrner <daniel.lehrner@consensys.net> * Publish Guava as an API dependency from plugin-api (#10248) Signed-off-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> * clean stop bws if world state unavailable (#10021) * clean stop bws if world state unavailable * immutable field Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> * Reject Status with mismatched protocolVersion vs layout (#10241) * Reject Status with mismatched protocolVersion vs layout A Besu peer build (seen in production as `besu/v26.2-develop-73d07f9`) advertises eth/69 in Hello but sends the eth/68 Status layout `[version, networkId, totalDifficulty, bestHash, genesisHash, forkId]` with `version=69` stamped on the wire. Spec-strict EL clients (e.g. Nimbus) reject this with `protocol breach` every 30 seconds. Besu's current decoder uses shape auto-detection (checks whether the fourth element is a list) and only discovers the inconsistency inside the EthStatus constructor via `checkArgument`, which throws `IllegalArgumentException`. That type is not caught by `EthProtocolManager.handleStatusMessage`'s `try/catch (RLPException)`, so the exception escapes the message dispatcher instead of producing a clean `SUBPROTOCOL_TRIGGERED_UNPARSABLE_STATUS` disconnect. Validate version/layout consistency inline in `EthStatus.readFrom` and throw `RLPException` instead. Add tests for both mismatch directions, including the exact malformed bytes captured from the broken peer in bal-devnet-3. Signed-off-by: qu0b <st3f4n.s@gmail.com> Signed-off-by: qu0b <stefan@starflinger.eu> * Remove redundant comment on shape/version enforcement Addresses review from @pinges: the code is self-explanatory. Signed-off-by: Stefan <stefan@starflinger.eu> --------- Signed-off-by: qu0b <st3f4n.s@gmail.com> Signed-off-by: qu0b <stefan@starflinger.eu> Signed-off-by: Stefan <stefan@starflinger.eu> Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> * Flaky BackwardSyncContextTest: remove broken Awaitility pattern (#10303) * Fix flaky BackwardSyncContextTest by removing broken Awaitility pattern Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Matilda-Clerke <matilda.clerke@consensys.net> * Add MulOperationV2 (#10291) Add MulOperationV2, units and benchmark Uses UInt256.mul same as MulOperationOptimized Signed-off-by: Simon Dudley <simon.dudley@consensys.net> * Feat/reenable dynamic cpsb calculation (#10295) * reenable dynamic costPerStateByte calculation Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * fix AbstractBlockProcessorIntegrationTest Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> --------- Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * add eip 7976 to Amsterdam (#10296) Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * Add EIP-7981 to bal-devnet-4 (#10297) * add eip 7981 to Amsterdam Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * fix AbstractBlockProcessorIntegrationTest Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> --------- Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> --------- Signed-off-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net> Signed-off-by: Karim Taam <karim.t2am@gmail.com> Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> Signed-off-by: Liberty S <694522458@qq.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Signed-off-by: qu0b <st3f4n.s@gmail.com> Signed-off-by: qu0b <stefan@starflinger.eu> Signed-off-by: Stefan <stefan@starflinger.eu> Signed-off-by: Simon Dudley <simon.dudley@consensys.net> Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> Co-authored-by: Luis Pinto <luis.pinto@consensys.net> Co-authored-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com> Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Karim Taam <karim.t2am@gmail.com> Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net> Co-authored-by: Matt Whitehead <matthew.whitehead@kaleido.io> Co-authored-by: ahamlat <ameziane.hamlat@consensys.net> Co-authored-by: Liberty-Swine <694522458@qq.com> Co-authored-by: Stefan <22667037+qu0b@users.noreply.github.com> Co-authored-by: Matilda-Clerke <matilda.clerke@consensys.net> Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
* Refactor and fixes for JMH benchmarks regarding signed values (besu-eth#10269) Summary of changes: - There was a lot of duplicate setup code in all of the arithmetic opcodes (DIV, SDIV, MOD, ...). All this copy pasting didn't help and the definition of enums with the byte sizes manually creates a source for errors and duplicate effort. - Names are also now consistent within each benchmark following OPCODE_BIT-SIZE_BIT-SIZE structure for easy copy pasting of results and interpretation. - Removed enum case definition in most cases to avoid redundancy. - Some issues were also fixed around negation of inputs for testing signed opcodes (SMOD was missing negation!). Inputs are now correctly negated and compared with their absolute values for swapping them. - Generation of 256 bit negative numbers is now limited to 255 bits to make sure we leave MSB for two complement representation. * Publish besu-evm as an API dependency from plugin-api (besu-eth#10262) Signed-off-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com> * Header download progress (besu-eth#10275) * Save and resume header download progress on pipeline restart Track the lowest imported block number in ImportHeadersStep and persist it to ChainSyncState so that backward header downloads can resume from where they left off after an error, rather than restarting from the pivot. - Add ChainSyncState.withHeaderProgress() to update the header progress - Track lowestImportedBlock in ImportHeadersStep - Return BackwardHeaderPipelineResult record from pipeline factory - Call saveHeaderProgress() in SnapSyncChainDownloader on error Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net> * Enforce EIP-7928 BAL item budget per transaction in processing and mining (besu-eth#10250) Signed-off-by: Karim Taam <karim.t2am@gmail.com> Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Take empty block period seconds out of experimental (besu-eth#10264) * Take empty block period seconds out of experimental Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Tidy up changelog Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Typo Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Review comments Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> --------- Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> * Add ChaindId, Coinbase, Gaslimit and PrevRandao to EVM v2 (besu-eth#10298) * Add ChaindId, Coinbase, Gaslimit and PrevRandao to EVM v2 Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> * Address comments Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> --------- Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> * Rename InvalidSystemCallAddressException to SystemCallNoCodeAtAddressException (besu-eth#10305) * Rename InvalidSystemCallAddressException to SystemCallNoCodeAtAddressException The exception is thrown when no code exists at the address, not because the address is invalid. Updated all usages. Fixes besu-eth#10281 Signed-off-by: Liberty S <694522458@qq.com> * Fix missing reference to renamed exception Signed-off-by: Liberty S <694522458@qq.com> --------- Signed-off-by: Liberty S <694522458@qq.com> Co-authored-by: daniellehrner <daniel.lehrner@consensys.net> * Publish Guava as an API dependency from plugin-api (besu-eth#10248) Signed-off-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> * clean stop bws if world state unavailable (besu-eth#10021) * clean stop bws if world state unavailable * immutable field Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> * Reject Status with mismatched protocolVersion vs layout (besu-eth#10241) * Reject Status with mismatched protocolVersion vs layout A Besu peer build (seen in production as `besu/v26.2-develop-73d07f9`) advertises eth/69 in Hello but sends the eth/68 Status layout `[version, networkId, totalDifficulty, bestHash, genesisHash, forkId]` with `version=69` stamped on the wire. Spec-strict EL clients (e.g. Nimbus) reject this with `protocol breach` every 30 seconds. Besu's current decoder uses shape auto-detection (checks whether the fourth element is a list) and only discovers the inconsistency inside the EthStatus constructor via `checkArgument`, which throws `IllegalArgumentException`. That type is not caught by `EthProtocolManager.handleStatusMessage`'s `try/catch (RLPException)`, so the exception escapes the message dispatcher instead of producing a clean `SUBPROTOCOL_TRIGGERED_UNPARSABLE_STATUS` disconnect. Validate version/layout consistency inline in `EthStatus.readFrom` and throw `RLPException` instead. Add tests for both mismatch directions, including the exact malformed bytes captured from the broken peer in bal-devnet-3. Signed-off-by: qu0b <st3f4n.s@gmail.com> Signed-off-by: qu0b <stefan@starflinger.eu> * Remove redundant comment on shape/version enforcement Addresses review from @pinges: the code is self-explanatory. Signed-off-by: Stefan <stefan@starflinger.eu> --------- Signed-off-by: qu0b <st3f4n.s@gmail.com> Signed-off-by: qu0b <stefan@starflinger.eu> Signed-off-by: Stefan <stefan@starflinger.eu> Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> * Flaky BackwardSyncContextTest: remove broken Awaitility pattern (besu-eth#10303) * Fix flaky BackwardSyncContextTest by removing broken Awaitility pattern Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Matilda-Clerke <matilda.clerke@consensys.net> * Add MulOperationV2 (besu-eth#10291) Add MulOperationV2, units and benchmark Uses UInt256.mul same as MulOperationOptimized Signed-off-by: Simon Dudley <simon.dudley@consensys.net> * Feat/reenable dynamic cpsb calculation (besu-eth#10295) * reenable dynamic costPerStateByte calculation Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * fix AbstractBlockProcessorIntegrationTest Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> --------- Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * add eip 7976 to Amsterdam (besu-eth#10296) Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * Add EIP-7981 to bal-devnet-4 (besu-eth#10297) * add eip 7981 to Amsterdam Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> * fix AbstractBlockProcessorIntegrationTest Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> --------- Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> --------- Signed-off-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> Signed-off-by: stefan.pingel@consensys.net <stefan.pingel@consensys.net> Signed-off-by: Karim Taam <karim.t2am@gmail.com> Signed-off-by: Matthew Whitehead <matthew.whitehead@kaleido.io> Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net> Signed-off-by: Liberty S <694522458@qq.com> Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> Signed-off-by: qu0b <st3f4n.s@gmail.com> Signed-off-by: qu0b <stefan@starflinger.eu> Signed-off-by: Stefan <stefan@starflinger.eu> Signed-off-by: Simon Dudley <simon.dudley@consensys.net> Signed-off-by: daniellehrner <daniel.lehrner@consensys.net> Co-authored-by: Luis Pinto <luis.pinto@consensys.net> Co-authored-by: Alejandro <26930485+alejandroGM0@users.noreply.github.com> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com> Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Karim Taam <karim.t2am@gmail.com> Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net> Co-authored-by: Matt Whitehead <matthew.whitehead@kaleido.io> Co-authored-by: ahamlat <ameziane.hamlat@consensys.net> Co-authored-by: Liberty-Swine <694522458@qq.com> Co-authored-by: Stefan <22667037+qu0b@users.noreply.github.com> Co-authored-by: Matilda-Clerke <matilda.clerke@consensys.net> Co-authored-by: Simon Dudley <simon.dudley@consensys.net> Signed-off-by: daniellehrner <daniel.lehrner@consensys.net>
PR description
This change enforces the EIP-7928 block access list (BAL) item budget consistently in block processing (import / execution) and block building (mining / tx selection). After each transaction, we verify that merging that transaction’s BAL partial into the running block state would not exceed the limit derived from the block gas limit and the fork’s per-item cost. Mining and validation therefore share the same rule and stay aligned.
Motivation
The BAL for a block is built incrementally from per-transaction partials.
Without a per-tx check:
Block processing
After each transaction is applied to the BAL builder, the running item count is validated against the EIP-7928 budget.
Block building
During transaction selection, when a BAL builder is present for the pending block, a post-processing step rejects a candidate if merging its execution partial would exceed the same budget (same validator logic as processing).
Transaction index state used for BAL tracing is reset at the start of each selection run so indices stay correct if the selector is reused.
Tests
Amsterdam-based block transaction selector tests (BAL-relevant fork): budget exceeded vs both transactions selected
Thanks for sending a pull request! Have you done the following?
doc-change-requiredlabel to this PR if updates are required.Locally, you can run these tests to catch failures early:
./gradlew spotlessApply./gradlew build./gradlew acceptanceTest./gradlew integrationTest./gradlew ethereum:referenceTests:referenceTests