Skip to content

feat: add GLOAS (Glamsterdam) signing support - #1192

Open
usmansaleem wants to merge 15 commits into
Consensys-Incorporated:masterfrom
usmansaleem:glamsterdam_changes
Open

feat: add GLOAS (Glamsterdam) signing support#1192
usmansaleem wants to merge 15 commits into
Consensys-Incorporated:masterfrom
usmansaleem:glamsterdam_changes

Conversation

@usmansaleem

@usmansaleem usmansaleem commented May 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds eth2 signing support for the upcoming Glamsterdam (ePBS / GLOAS) fork — five new signing types matching ethereum/remote-signing-api#28, plus CLI and schema support:

Type Domain Description
EXECUTION_PAYLOAD_BID BEACON_BUILDER (0x0B000000) Builder execution payload bid
EXECUTION_PAYLOAD_ENVELOPE BEACON_BUILDER (0x0B000000) Builder execution payload envelope
PAYLOAD_ATTESTATION_MESSAGE PTC_ATTESTER (0x0C000000) Payload attestation committee (PTC) message
PROPOSER_PREFERENCES PROPOSER_PREFERENCES (0x0D000000) Proposer preferences
BUILDER_REQUEST_AUTH BUILDER_REQUEST_AUTH (0x0B000001) Out-of-protocol builder-API auth

What's Included:

  • New Schema POJOs:
    • Under core/.../signing/eth2/schema/gloas/: ExecutionPayloadBid, ExecutionPayloadEnvelope, ExecutionPayloadGloas (extending ExecutionPayloadDeneb with block_access_list and slot_number), PayloadAttestationData, ProposerPreferences, and BuilderRequestAuth.
    • Under core/.../signing/eth2/schema/electra/: BuilderDepositRequest, BuilderExitRequest, and updated ExecutionRequests (EIP-8282).
  • Fork-Versioned Requests (VersionedRequest<T>):
    • Every Gloas payload uses the versioned envelope format {"version": "GLOAS", "data": {...}}, ensuring the signer resolves the SSZ schema from the declared milestone and validates that the milestone is scheduled on the configured network.
    • BLOCK_V2 and AGGREGATE_AND_PROOF_V2 also updated to accept version: GLOAS.
  • Serialization:
    • Added Jackson serializers/deserializers for UInt256 and KZGCommitment in SigningObjectMapperFactory and SigningMetadataModule.
  • CLI:
    • Added hidden experimental option --Xnetwork-gloas-fork-epoch to Eth2SubCommand for overriding the Gloas fork epoch.
  • OpenAPI:
  • Acceptance Tests:
    • Fixtures (Eth2RequestUtils, Eth2SigningRequestBodyBuilder) updated.
    • BlsSigningAcceptanceTest covers all five new signing types under SpecMilestone.GLOAS.
    • Eth2BlockSigningAcceptanceTest and Eth2AggregateAndProofSigningAcceptanceTest cover GLOAS BLOCK_V2 / AGGREGATE_AND_PROOF_V2.

Note: Slashing protection is intentionally omitted for the new types — per consensus spec and Teku's SlashingProtectedSigner, only blocks and attestations are slashable.

⚠️ Teku Dependency & Subject to Change

  • Temporarily points to Teku's develop snapshot in gradle/versions.gradle.
  • build.gradle is configured to treat Teku develop as a changing module and bypass the 24h cache so builds continuously resolve the latest develop build until a formal release is cut.
  • Once Teku cuts its next release, Teku will be pinned to that release version and the changing module configuration will be removed before taking this PR out of draft.

Test Plan

  • ./gradlew spotlessApply spotlessCheck checkLicense
  • ./gradlew :core:compileJava :acceptance-tests:compileTestJava
  • ./gradlew test (unit tests)
  • ./gradlew :acceptance-tests:acceptanceTest --tests "tech.pegasys.web3signer.tests.signing.*"
  • GitHub Actions CI passed (all matrix jobs and Docker builds)
  • Re-pin Teku to a fixed release once available
  • Cross-validate against a Teku build with external signing enabled

Adds four new signing types for the upcoming Glamsterdam (ePBS) fork:
EXECUTION_PAYLOAD_BID, EXECUTION_PAYLOAD_ENVELOPE,
PAYLOAD_ATTESTATION_MESSAGE, and PROPOSER_PREFERENCES.

Bumps Teku to the develop snapshot as the GLOAS schemas (e.g.
ExecutionPayloadBid added execution_requests_root, ExecutionPayloadEnvelope
dropped slot/state_root, new ExecutionPayloadGloas) are still evolving
post-26.4.0. Should pin to a stable Teku version once the next release is cut.

Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
@sonarqubecloud

sonarqubecloud Bot commented May 6, 2026

Copy link
Copy Markdown

@eth2353

eth2353 commented Jul 10, 2026

Copy link
Copy Markdown

Hi Usman, could you please publish a Docker image w/ Glamsterdam support somewhere to aid in testing validator client <-> remote signer interactions? Thank you!

…R_REQUEST_AUTH

Teku's Gloas data structures moved forward since this branch was last synced:

- ExecutionRequestsSchema moved from execution.versions.electra to the base
  execution package, and gained builder_deposits/builder_exits (EIP-8282,
  Gloas). ExecutionRequests now builds via ExecutionRequestsBuilder (schema
  no longer exposes a fixed-arity create()); electra callers are unaffected
  since Electra's builder no-ops the new builder fields.
- ProposerPreferencesSchema gained a dependent_root field and renamed
  gas_limit to target_gas_limit.
- ExecutionPayloadEnvelopeSchema gained a parent_beacon_block_root field.

Also add BUILDER_REQUEST_AUTH signing support per builder-specs (Gloas):
a proposer-signed BuilderRequestAuth{data, slot} authenticating per-request
builder-API calls, domain DOMAIN_BUILDER_REQUEST_AUTH (0x0B000001). Signed
with the genesis fork version (no fork_info), like the deprecated
ValidatorRegistrationV1 flow, since Teku has not yet wired this domain name
end-to-end (still exposed as Domain.REQUEST_AUTH in teku:develop).

Mirrors remote-signing-api PR Consensys-Incorporated#28 review feedback (james-prysm,
JasonVranek): the bid/proposer handshake needs a signed request-auth
message, not just a signed bid.

Also fix acceptanceTest Gradle task: the Gradle 8->9 upgrade dropped
implicit convention-based testClassesDirs/classpath wiring for custom
Test-type tasks, silently turning every acceptanceTest run into a
no-op (NO-SOURCE). Wire it explicitly.

Known pre-existing gap (unrelated to this change): the acceptance test
harness's setForkEpochs() has no GLOAS case, so the EXECUTION_PAYLOAD_BID/
EXECUTION_PAYLOAD_ENVELOPE/PAYLOAD_ATTESTATION_MESSAGE/PROPOSER_PREFERENCES
parameterized tests fail with "Setting manual fork epoch is not yet
implemented for GLOAS". BUILDER_REQUEST_AUTH is unaffected (falls back to
PHASE0 setup, like VALIDATOR_REGISTRATION, since its domain is genesis-only).
Wires GLOAS fork-epoch activation end-to-end, following the existing
per-fork CLI option pattern:
- Eth2SubCommand: --Xnetwork-gloas-fork-epoch -> Eth2NetworkConfiguration
  .Builder.gloasForkEpoch() (already present in Teku).
- Acceptance-test DSL: SignerConfiguration/SignerConfigurationBuilder,
  CmdLineParamsConfigFileImpl/CmdLineParamsDefaultImpl.
- SigningAcceptanceTestBase.setForkEpochs(): added the missing GLOAS case
  (this previously threw "Setting manual fork epoch is not yet
  implemented for GLOAS" for every GLOAS-milestone acceptance test).

With GLOAS acceptance tests actually running end-to-end for the first
time, three more dormant bugs surfaced (all pre-existing, never
exercised because the acceptanceTest task was NO-SOURCE until the
previous commit):
- KZGCommitment had no Jackson (de)serializer at all -> added, mirroring
  the BLSPubKey/BLSSignature hex-string convention.
- UInt256 (base_fee_per_gas) had no (de)serializer -> Jackson fell back
  to an implicit UInt256.valueOf(long) creator and blew up on values
  exceeding Long.MAX_VALUE. Added explicit decimal-string (de)serializer,
  matching the OpenAPI spec's "UInt256 decimal" description.
- Raw Teku BLSPublicKey (used directly, unwrapped, by WithdrawalRequest,
  ConsolidationRequest, PendingDeposit and now BuilderExitRequest) had no
  deserializer -> added to SigningMetadataModule and wired into
  SigningObjectMapperFactory.

BlsSigningAcceptanceTest now passes all 84 parameterized cases,
including every GLOAS type and BUILDER_REQUEST_AUTH. Full acceptanceTest
suite: 288 tests, only pre-existing unrelated Besu/Eth1 failures remain
(besu version/environment mismatch, predates this branch).
…estAuth

State the actual mechanic (genesis fork version + zero
genesis_validators_root, no fork_info) instead of comparing to
ValidatorRegistrationV1, which is a different, unrelated, deprecated
concept (superseded by ProposerPreferences) and only shares the
genesis-only domain computation with BuilderRequestAuth.
@sonarqubecloud

Copy link
Copy Markdown

Sync openapi-specs/eth2 with ethereum/remote-signing-api@8742bd7 and
update the implementation to match:

- EXECUTION_PAYLOAD_BID, EXECUTION_PAYLOAD_ENVELOPE,
  PAYLOAD_ATTESTATION_MESSAGE, PROPOSER_PREFERENCES and
  BUILDER_REQUEST_AUTH now carry {version, data} like BLOCK_V2.
  New generic VersionedRequest<T> record; handler resolves the
  SpecVersion from the declared milestone instead of the slot and
  rejects milestones not scheduled on the configured network.
- BLOCK_V2 / AGGREGATE_AND_PROOF_V2 acceptance tests cover GLOAS.
- BUILDER_REQUEST_AUTH acceptance test now runs against a GLOAS spec.
- CHANGELOG: note the versioned shape supersedes the 26.7.0 draft.
…he refresh

- Update BuilderRequestAuth and signing root resolution to match Teku's
  renamed classes and methods (BuilderRequestAuth, BUILDER_REQUEST_AUTH_SCHEMA,
  signingRootForSignBuilderRequestAuth).
- Update acceptance test data generator to use randomBuilderRequestAuth().
- Configure Gradle to treat Teku develop artifacts as changing modules and
  bypass changing module cache so builds always pick up latest Teku develop
  until the next release is pinned.
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