Skip to content

execution: treat empty BAL as valid access list (EIP-7928)#20776

Merged
yperbasis merged 15 commits into
erigontech:mainfrom
Sahil-4555:fix/eip-7928-empty-bal-sidecar
May 19, 2026
Merged

execution: treat empty BAL as valid access list (EIP-7928)#20776
yperbasis merged 15 commits into
erigontech:mainfrom
Sahil-4555:fix/eip-7928-empty-bal-sidecar

Conversation

@Sahil-4555

@Sahil-4555 Sahil-4555 commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

This update aligns BAL handling with the requirements described in EIP-7928, which requires that even an empty BAL be recognized as a legitimate access list. According to the specification, the header should include the rlp.encode([]) hash, while the payload should have the standard empty RLP list (0xc0). Previously, even though the header hash was established correctly, the BAL bytes themselves were not saved. This effectively regarded an empty BAL as if it did not exist, contradicting the desired behavior indicated in the EIP.

With this change, empty BALs are now handled consistently like any other BAL. The RLP decoder now returns an initialized empty slice instead of nil, so 0xc0 naturally round-trips through the standard encode/decode path without special-case logic. The len(block.BlockAccessList) > 0 guard in the DB inserter correctly persists the []byte{0xc0} sidecar (length 1), and the engine API response encodes it back via standard RLP rules. The payload response path also retains the br.BlockAccessList != nil guard so that a genuinely missing BAL is never silently emitted as 0xc0. This removes any ambiguity between a valid empty BAL and cases where BAL data is missing or pruned.

@yperbasis yperbasis requested a review from taratorio April 24, 2026 09:08
@yperbasis yperbasis added the Glamsterdam https://eips.ethereum.org/EIPS/eip-7773 label Apr 24, 2026
@yperbasis yperbasis added this to the 3.6.0 milestone Apr 24, 2026
@yperbasis yperbasis requested a review from Copilot April 24, 2026 09:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Erigon’s execution/engine API and storage paths to treat an empty Block Access List (BAL) as a present and valid sidecar (per EIP-7928), ensuring it round-trips as canonical RLP 0xc0 rather than being dropped as “missing”.

Changes:

  • Persist BAL sidecars even when the BAL is empty (based on the empty BAL commitment hash).
  • Serve canonical empty BAL bytes (0xc0) when legacy data stored the empty hash but omitted the sidecar bytes.
  • Update engine payload assembly/newPayload handling and add a test to ensure empty BAL round-trips through getPayload.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
execution/execmodule/inserters.go Persists BAL sidecar when the header commitment indicates an empty BAL, normalizing empty bytes to canonical 0xc0.
execution/execmodule/getters.go Adds BAL read helper that recovers canonical empty BAL bytes when legacy inserts stored only the empty-hash commitment.
execution/engineapi/engine_server.go Normalizes empty BAL input to canonical bytes in newPayload, and always encodes BAL in payload responses when a commitment exists.
execution/engineapi/engine_server_getpayload_test.go Adds test asserting payload responses include canonical empty BAL bytes when header carries the empty commitment hash.
Comments suppressed due to low confidence (2)

execution/engineapi/engine_server.go:1079

  • assembledBlockToPayloadResponse now encodes and returns a BAL whenever header.BlockAccessListHash is non-nil, even if br.BlockAccessList is nil. If a non-empty BAL commitment is present but the in-memory BlockAccessList is missing (nil), this will incorrectly return the canonical empty bytes 0xc0, causing a commitment mismatch for the payload. Consider only encoding when br.BlockAccessList is non-nil/len>0, or when the header commitment equals empty.BlockAccessListHash (the one case where nil/empty is still valid).
	if header.BlockAccessListHash != nil {
		// NOTE(EIP-7928): an empty BAL still round-trips as the RLP bytes 0xc0, so
		// we encode even when br.BlockAccessList is nil/empty as long as the header
		// carries a BAL commitment.
		encoded, encErr := types.EncodeBlockAccessListBytes(br.BlockAccessList)
		if encErr == nil {
			ep.BlockAccessList = encoded
		}

execution/execmodule/inserters.go:129

  • The BAL sidecar write is still skipped when header.BlockAccessListHash is non-nil/non-empty but block.BlockAccessList is empty. That silently persists a header commitment without the corresponding sidecar bytes (similar to the empty-BAL issue, but for non-empty commitments). Consider explicitly erroring when header.BlockAccessListHash != nil and len(block.BlockAccessList)==0 unless the hash equals empty.BlockAccessListHash (in which case you can normalize to 0xc0).
		if len(block.BlockAccessList) > 0 || (header.BlockAccessListHash != nil && *header.BlockAccessListHash == empty.BlockAccessListHash) {
			if header.BlockAccessListHash == nil {
				return 0, fmt.Errorf("ethereumExecutionModule.InsertBlocks: block access list provided without hash for block %d", height)
			}
			balBytes := block.BlockAccessList
			if len(balBytes) == 0 {
				balBytes, err = types.EncodeBlockAccessListBytes(nil)
				if err != nil {
					return 0, fmt.Errorf("ethereumExecutionModule.InsertBlocks: encode empty block access list, block %d: %s", height, err)
				}
			}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread execution/execmodule/getters.go Outdated
Comment thread execution/engineapi/engine_server.go Outdated
@Sahil-4555 Sahil-4555 force-pushed the fix/eip-7928-empty-bal-sidecar branch 3 times, most recently from acb4fad to 20b6db3 Compare April 27, 2026 03:38
@AskAlexSharov AskAlexSharov requested a review from Copilot April 27, 2026 03:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

execution/engineapi/engine_server.go:1072

  • assembledBlockToPayloadResponse silently drops BlockAccessList if EncodeBlockAccessListBytes returns an error (it just leaves the field unset). For Gloas/Amsterdam+ payloads where BlockAccessListHash is present, returning a payload without blockAccessList can violate the Engine API expectations and makes debugging harder. Consider propagating the encoding error (return it from this function) or at least logging and failing the request when encoding/validation fails, since it indicates an inconsistent block state.
	if header.BlockAccessListHash != nil {
		// EIP-7928: encode even when br.BlockAccessList is nil/empty — an empty
		// BAL serializes to 0xc0 via standard RLP rules.
		encoded, encErr := types.EncodeBlockAccessListBytes(br.BlockAccessList)
		if encErr == nil {
			ep.BlockAccessList = encoded
		}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread execution/types/block_access_list.go Outdated
@Sahil-4555 Sahil-4555 force-pushed the fix/eip-7928-empty-bal-sidecar branch from 20b6db3 to a5121ec Compare April 27, 2026 04:07
@yperbasis yperbasis requested a review from Copilot May 5, 2026 11:02
@yperbasis yperbasis modified the milestones: 3.6.0, 3.5.0 May 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread execution/engineapi/engine_server.go
Comment thread execution/engineapi/engine_server.go Outdated
Comment thread execution/engineapi/engine_server_getpayload_test.go Outdated
@Sahil-4555 Sahil-4555 force-pushed the fix/eip-7928-empty-bal-sidecar branch from 0388a10 to 3142328 Compare May 5, 2026 12:00
@Sahil-4555 Sahil-4555 force-pushed the fix/eip-7928-empty-bal-sidecar branch from 3142328 to 613d4d6 Compare May 6, 2026 03:49
@yperbasis yperbasis modified the milestones: 3.5.0, 3.6.0 May 6, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

@yperbasis yperbasis added this pull request to the merge queue May 19, 2026
Merged via the queue into erigontech:main with commit ff3b684 May 19, 2026
69 of 70 checks passed
@Sahil-4555 Sahil-4555 deleted the fix/eip-7928-empty-bal-sidecar branch May 19, 2026 13:02
@yperbasis yperbasis modified the milestones: 3.6.0, 3.5.0 May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Glamsterdam https://eips.ethereum.org/EIPS/eip-7773

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants