Skip to content

Remove BeaconState proto message - #17535

Open
syjn99 wants to merge 17 commits into
developfrom
chore/remove-beaconstate-proto
Open

syjn99 wants to merge 17 commits into
developfrom
chore/remove-beaconstate-proto

Conversation

@syjn99

@syjn99 syjn99 commented Sep 22, 2026

Copy link
Copy Markdown
Member

What type of PR is this?

Other: (Very nice) cleanup

What does this PR do? Why is it needed?

This PR removes beacon_state.proto and automatically generated *.pb.go files corresponds to it. Instead, we now replaces all proto message definition of BeaconState{Fork} with native Go struct.

Before:

message BeaconState {
  // Versioning [1001-2000]
  uint64 genesis_time = 1001;
  // ... and so on
}
  • Add new BeaconState per fork in beacon_state.proto file
  • Run make gen for executing protoc, so that we have a Go struct.
  • This system enforces us to have few converter functions from/to proto, as well as slice type even though it is completely fine to use array type for fixed bytevector.

After:

// in beacon_state_mainnet.go
// BeaconState is the Phase0 SSZ state.
type BeaconState struct {
	GenesisTime                 uint64
	GenesisValidatorsRoot       []byte `ssz-size:"32"`
	Slot                        primitives.Slot
	Fork                        *Fork
	LatestBlockHeader           *BeaconBlockHeader
// and so on
  • Add new BeaconState per fork in beacon_state_{mainnet|minimal}.go file
  • No need to generate *.pb.go files related to the state. Plus we remove over 9K lines of generated files which is awesome.
  • Note that we don't need few entries in ssz_proto_library.bzl as it is now natively maintained in native Go struct definition.

Which issue(s) does this PR fix?

Fixes #17503

Other notes for review

How to review this PR

This PR is designed to review commit by commit. It consists of three parts:

Revisit the testing harness

Until fix(ssz): derive query field names without json tags, these are collections of groundwork for the later work. First commit (test(state): support non-protobuf states in SSZ harness) is note-worthy - as it touches our equality check. Main purpose is dropping proto dependency on equality check.

Mechanical change from Altair to Gloas, and then Phase0

From refactor(state): replace Altair protobuf with SSZ struct to refactor(state): replace Phase0 protobuf with SSZ struct,
each commit mechanically migrates to native struct per fork. Most of the diff of each commit is regenerated *.pb.go files and some equality check in our spectest runner.

Phase0 is deliberately done after Gloas as it has different wire format and pattern when saving in the storage.

Cleanups

From refactor(state): drop protobuf from beacon-chain/state, commits are mostly cleaning things up which are now unused or dead. refactor(proto): remove beacon_state.proto is note-worthy, as it retires beacon_state.proto and moves each proto message into separate parts in the codebase, so please read the description.

Production Risk

Before #17523, there was a very tiny production risk on DB migration, but now we don't have. I believe this PR doesn't bring any production risk and should work well without any problems, but here's some notes:

  • DB compatability: We save BeaconState in SSZ format, so it doesn't need to be considered. Same behavior.
  • CopySlice(nil) returns nil instead of [].
  • SSZ Query package changes are not considered as production IMO.

Follow-ups

  • Move state-related definition and function into dedicated package. proto/ package is not proper location now.
  • Rename *Proto* methods. I deliberately omitted it in this PR because it covers almost entire codebase.
  • Delegate SSZ List limit and SSZ Vector length to fieldparams configuration which is considered as canonical.
  • Better memory allocation and no more Proto conversion.
    • As methodical-ssz doesn't support yet for array type, we need a patch there.

Acknowledgements

  • I have read CONTRIBUTING.md.
  • I have included a uniquely named changelog fragment file.
  • I have added a description with sufficient context for reviewers to understand this PR.
  • I have tested that my changes work as expected and I added a testing plan to the PR description (if applicable).

@syjn99
syjn99 force-pushed the chore/remove-beaconstate-proto branch 5 times, most recently from 133d059 to 6d86111 Compare September 23, 2026 01:12
@syjn99 syjn99 added the cleanup PR improving code health label Sep 23, 2026
@syjn99
syjn99 marked this pull request as ready for review September 23, 2026 08:36
@syjn99
syjn99 requested review from a team, kasey and prestonvanloon as code owners September 23, 2026 08:36
@syjn99 syjn99 changed the title [WIP] Remove BeaconState proto message Remove BeaconState proto message Sep 23, 2026
The SSZ query analyzer took the spec field name from the json struct tag,
which only protobuf-generated structs carry. Hand-written SSZ containers
(the beacon states) have none, so fall back to the snake_case of the Go
field name. Both spellings come from the same words, so the derived names
match the ones protoc used to emit.
Every message left in the file was dead, SSZ-only, or needed by exactly
one other proto. Where each one went:

- CheckPtInfo: deleted, no references.
- StateSummary: moved to beacon_core_types.proto. Stays protobuf because
  db/kv stores it as protobuf bytes; field numbers and full name are
  unchanged, so existing databases decode as before.
- SyncAggregatorSelectionData: moved to sync_committee.proto. Stays
  protobuf because it is a SignRequest oneof member in keymanager.proto.
- PendingAttestation: moved to attestation.proto. Stays protobuf because
  the Att interface embeds proto.Message.
- HistoricalBatch: hand-written in beacon_state_{mainnet,minimal}.go,
  since the roots vector size differs per preset, with the same
  field-parity test the states have.
- SigningData, ForkData, DepositMessage, PowBlock: hand-written in
  beacon_state_types.go, preset-independent and SSZ-only.

beacon_state.pb.go and beacon_state.minimal.pb.go go with the file, and
block_roots.size/state_roots.size were the last preset tokens it used.
Regenerated *.ssz.go files are byte-identical.
beacon_state.proto is gone, so the spec references for BeaconState
(phase0..fulu), HistoricalBatch, DepositMessage, ForkData, SigningData
and PowBlock now search the hand-written Go structs, and
PendingAttestation / SyncAggregatorSelectionData follow their messages
to attestation.proto / sync_committee.proto. BeaconState#gloas stays an
exception as before.
- Make CI see normal go file in proto package
- Style change
- Run test in minimal config as well
@syjn99
syjn99 force-pushed the chore/remove-beaconstate-proto branch from 6d86111 to 2b4c717 Compare September 23, 2026 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cleanup PR improving code health

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove proto messages for BeaconStates

1 participant