Skip to content

Add Gloas beacon state package#15611

Merged
terencechain merged 9 commits intodevelopfrom
add-gloas-state
Nov 18, 2025
Merged

Add Gloas beacon state package#15611
terencechain merged 9 commits intodevelopfrom
add-gloas-state

Conversation

@terencechain
Copy link
Copy Markdown
Collaborator

@terencechain terencechain commented Aug 20, 2025

This PR adds minimal support for the Gloas beacon state package. It ensures that the custom hash tree root function passes the SSZ vector spec test. Getters and setters are not included in this PR and will be added in follow-up PRs as needed. This implementation covers initialization and ensures the package can be used in future tests

Note to the reviewer: please double check InitializeFromProtoUnsafeGloas which i have pending payments and withdrawals as shared reference. It's not clear to me if they should be shared or not, please correct me if i am wrong here:

	b.sharedFieldReferences[types.BuilderPendingPayments] = stateutil.NewRef(1)    // New in Gloas.
	b.sharedFieldReferences[types.BuilderPendingWithdrawals] = stateutil.NewRef(1) // New in Gloas.

@terencechain terencechain force-pushed the add-gloas-state branch 3 times, most recently from 4864197 to 442588a Compare August 26, 2025 02:11
@terencechain terencechain force-pushed the add-gloas-state branch 3 times, most recently from a02c7b6 to 0d06b2f Compare August 31, 2025 03:16
@terencechain terencechain force-pushed the add-gloas-state branch 5 times, most recently from 77937de to 1089cb3 Compare September 24, 2025 21:13
@terencechain terencechain changed the base branch from develop to add-gloas-protobufs September 24, 2025 21:13
@terencechain terencechain force-pushed the add-gloas-state branch 5 times, most recently from 197d571 to 89fef62 Compare September 24, 2025 22:31
@terencechain terencechain marked this pull request as ready for review September 24, 2025 22:31
@terencechain terencechain force-pushed the add-gloas-state branch 3 times, most recently from dbb6439 to 31e7558 Compare September 25, 2025 15:00
@terencechain terencechain force-pushed the add-gloas-protobufs branch 2 times, most recently from 7ad2960 to ffa57b7 Compare October 9, 2025 20:46
BuilderPendingWithdrawals: b.builderPendingWithdrawals,
LatestBlockHash: b.latestBlockHash,
LatestWithdrawalsRoot: b.latestWithdrawalsRoot,
LatestExecutionPayloadBid: b.executionPayloadbid,
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.

Maybe change executionPayloadBid to latestExecutionPayloadBid to unify naming in both types?


payments := make([]*ethpb.BuilderPendingPayment, len(b.builderPendingPayments))
for i, payment := range b.builderPendingPayments {
if payment != nil {
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.

You already have a nil check inside Copy() so this check is technically not needed


withdrawals := make([]*ethpb.BuilderPendingWithdrawal, len(b.builderPendingWithdrawals))
for i, withdrawal := range b.builderPendingWithdrawals {
if withdrawal != nil {
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.

same here, no need to check

@@ -0,0 +1,78 @@
package state_native
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.

Having all Gloas logic in a gloas.go file is new, so far we have been splitting everything by functionality. For example latestWithdrawalsRootVal would go to getters_withdrawal.go.

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.

I like it better in the new fork specific file.

@terencechain terencechain force-pushed the add-gloas-state branch 2 times, most recently from c6279ec to 839c895 Compare November 14, 2025 23:19
rkapka
rkapka previously approved these changes Nov 15, 2025
case LatestExecutionPayloadHeaderDeneb:
return "latestExecutionPayloadHeaderDeneb"
case ExecutionPayloadBid:
return "executionPayloadBid"
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.

This is a little confusing in that the other fields are called by their names, should this be "latestExecutionPayloadBid"?


// Gloas fields
latestExecutionPayloadBid *ethpb.ExecutionPayloadBid
executionPayloadAvailability []byte
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.

JustificationBits is a bitvector, why is executionPayloadAvailability of type []byte?

PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"`
ProposerLookahead []primitives.ValidatorIndex `json:"proposer_look_ahead" yaml:"proposer_look_ahead"`
LatestExecutionPayloadBid *ethpb.ExecutionPayloadBid `json:"latest_execution_payload_bid" yaml:"latest_execution_payload_bid"`
ExecutionPayloadAvailability []byte `json:"execution_payload_availability" yaml:"execution_payload_availability"`
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.

Same here, justification bits is a Bitvector above.

BuilderPendingWithdrawals: b.builderPendingWithdrawals,
LatestBlockHash: b.latestBlockHash,
LatestWithdrawalsRoot: b.latestWithdrawalsRoot,
LatestExecutionPayloadBid: b.latestExecutionPayloadBid,
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.

should this be ordered as in the state?

BuilderPendingWithdrawals: b.builderPendingWithdrawalsVal(),
LatestBlockHash: b.latestBlockHashVal(),
LatestWithdrawalsRoot: b.latestWithdrawalsRootVal(),
LatestExecutionPayloadBid: b.latestExecutionPayloadBid.Copy(),
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.

Should this be ordered as in the state?


fieldRoots[types.BuilderPendingWithdrawals.RealPosition()] = bpwRoot[:]

lbhRoot := bytesutil.ToBytes32(state.latestBlockHash)
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.

Do we really need these copies? if there's any doubt I would rather keep these copies indeed.

types.PendingPartialWithdrawals,
types.PendingConsolidations,
types.ProposerLookahead,
types.ExecutionPayloadBid,
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.

Should this be ordered as in the state?, also perhaps it's better to add a list with the fields that are strictly added in deneb and use them both in the deneb field declaration and here.

denebSharedFieldRefCount = 7
electraSharedFieldRefCount = 10
fuluSharedFieldRefCount = 11
gloasSharedFieldRefCount = 12
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.

Probably add a comment with what is the field added here?

b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1)
b.sharedFieldReferences[types.ExecutionPayloadBid] = stateutil.NewRef(1) // New in Gloas.
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.

Why is this shared? In fact why is the execution payload header even shared in previous states? cc @rkapka

I'm pretty sure this was just copied/pasted from previous code, but this seems wrong to me.

)

// ExecutionPayloadAvailabilityRoot computes the merkle root of an execution payload availability bitvector.
func ExecutionPayloadAvailabilityRoot(bitvector []byte) ([32]byte, error) {
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.

Note to myself, this function needs to be optimized, copying here all the bytes and chunking doesn't make sense. For smaller bitfields it does make sense, but this will have 256 chunks

}

capellaFields = append(
append([]types.FieldIndex{}, altairFields...),
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.

This is a really weird pattern.

electraSharedFieldRefCount = 10
fuluSharedFieldRefCount = 11
gloasSharedFieldRefCount = 12
gloasSharedFieldRefCount = 12 // Adds LatestExecutionPayloadBid to the shared-ref set.
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.

If you remove the payload bid then this comment needs to change?

Copy link
Copy Markdown
Collaborator Author

@terencechain terencechain Nov 17, 2025

Choose a reason for hiding this comment

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

Sorry, i meant to say Adds pending builder withdrawals to the shared-ref set, not LatestExecutionPayloadBid

Comment on lines +93 to +95
denebFields = slices.Concat(
altairFields,
append([]types.FieldIndex{types.LatestExecutionPayloadHeaderDeneb}, withdrawalAndHistoricalSummaryFields...),
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.

concat takes several inputs, this can be written as

    denebFields = slices.Concat(
	altairFields,
	[]types.FieldIndex{types.LatestExecutionPayloadHeaderDeneb},
	withdrawalAndHistoricalSummaryFields,
)

electraSharedFieldRefCount = 10
fuluSharedFieldRefCount = 11
gloasSharedFieldRefCount = 12 // Adds LatestExecutionPayloadBid to the shared-ref set.
gloasSharedFieldRefCount = 12 // Adds pending builder withdrawals to the shared-ref set.
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.

gloasSharedFieldRefCount     = 12 // Adds pending builder withdrawals to the shared-ref set and LatestExecutionPayloadHeader is removed


capellaFields = slices.Concat(
altairFields,
append([]types.FieldIndex{types.LatestExecutionPayloadHeaderCapella}, withdrawalAndHistoricalSummaryFields...),
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.

Same here, the second append is not needed.

@terencechain terencechain added this pull request to the merge queue Nov 18, 2025
Merged via the queue into develop with commit bc0868e Nov 18, 2025
17 checks passed
@terencechain terencechain deleted the add-gloas-state branch November 18, 2025 15:37
@github-project-automation github-project-automation Bot moved this to Done in Gloas Feb 11, 2026
@terencechain terencechain assigned terencechain and unassigned potuz Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants