Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e70bb6b
port spec/gloas type surface + versioned wrappers + api/v1/gloas
AntiD2ta Jul 23, 2026
42f3afa
address local review findings (test coverage + cosmetic nits)
AntiD2ta Jul 23, 2026
6380a91
enable attgo current-year linter and refresh copyright headers to 2026
AntiD2ta Jul 23, 2026
ed3eb62
port spec/gloas ePBS transport surface (endpoints, events, client par…
AntiD2ta Jul 23, 2026
8ce030d
fix two JSON-path panics in spec/gloas ExecutionPayload codec
AntiD2ta Jul 26, 2026
f214eed
gloas-enable the mechanical versioned HTTP endpoints (beacon state, a…
AntiD2ta Jul 26, 2026
50beacf
validate decoded hex length before copy() in spec/gloas JSON unmarsha…
AntiD2ta Jul 28, 2026
3a612a9
guard nil BaseFeePerGas in the spec/gloas ExecutionPayload YAML marsh…
AntiD2ta Jul 28, 2026
2cc1984
register the seven Gloas SSE topics in SupportedEventTopics
AntiD2ta Jul 28, 2026
35e9662
retype the Gloas arms of the versioned aggregate-and-proof wrappers
AntiD2ta Jul 28, 2026
744b919
restore static-SSZ decode coverage in the http test suite
AntiD2ta Jul 28, 2026
5145a11
bounds-check the DataVersion string table on both of its readers
AntiD2ta Jul 28, 2026
6422b9f
add the PTC validator flow: duties, data, pool and submission
AntiD2ta Jul 29, 2026
bf361ea
de-duplicate the ePBS request marshal and the api/v1 hex decode
AntiD2ta Jul 29, 2026
adb7c3f
add the ePBS block-production types: gloas block contents and the pro…
AntiD2ta Jul 29, 2026
801d5c5
add the ePBS block-production transport: v4 proposals and the envelop…
AntiD2ta Jul 30, 2026
569b6f3
add preset-agnostic PTC participation accessors to gloas.PayloadAttes…
AntiD2ta Jul 31, 2026
2bfe4c0
fix multi.Events self-recursion and forward every event handler
AntiD2ta Jul 31, 2026
6a747d2
fetch full history for the lint job so attgo can resolve changed files
AntiD2ta Jul 31, 2026
1eae874
fix the gloas.BeaconState JSON codec's bitvector, and Builder's dropp…
AntiD2ta Jul 31, 2026
5442e8d
encode the proposal SSZ body at the node's preset, not mainnet's
AntiD2ta Jul 31, 2026
f9c44b2
give package http's internal tests one service constructor, so they s…
AntiD2ta Jul 31, 2026
4dea4d2
fork-gate the ePBS http tests, and run the suite against a second end…
AntiD2ta Jul 31, 2026
48d759b
skip the pre-Gloas envelope test on a node that knows the fork but se…
AntiD2ta Jul 31, 2026
7b9467a
give the gloas http job a bandwidth budget, not a hang timeout
AntiD2ta Jul 31, 2026
a2e1f05
stop three validator rows pulling the whole set to prove a state id r…
AntiD2ta Jul 31, 2026
6746c26
correct why the gloas http job needs a long timeout
AntiD2ta Jul 31, 2026
a42c6e1
say which node answered, before the suite starts
AntiD2ta Jul 31, 2026
8441a64
fix epbs proposal guard rejecting a conformant builder-bid response
AntiD2ta Jul 31, 2026
55bfa28
fix VersionedSignedProposal.ExecutionBlockHash for Gloas proposals
AntiD2ta Aug 1, 2026
a311189
add BodyRoot/ParentRoot/StateRoot to VersionedEPBSProposal
AntiD2ta Aug 3, 2026
fc18498
use ErrUnsupportedVersion for the unknown-version case
AntiD2ta Aug 3, 2026
3f63d54
accept the gloas payload-availability vote in attestation data
AntiD2ta Aug 3, 2026
7529615
fix: decode Gloas attestations in pool
AntiD2ta Aug 4, 2026
57f8007
remove stale indexed attestation validation comments
AntiD2ta Aug 4, 2026
c2ab3be
test: cover inherited Gloas SSZ roots
AntiD2ta Aug 4, 2026
5a52443
fix: tighten gloas follow-up quality
AntiD2ta Aug 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ jobs:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
# attgo's current-year analyzer resolves the changed-file set with
# `git diff origin/master...HEAD`. The default shallow checkout has no
# origin/master ref, so the analyzer fails open and checks every file in
# the repo rather than the ones this branch touches.
fetch-depth: 0

- uses: actions/setup-go@v5
with:
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/http-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,23 @@ jobs:
HTTP_TEST_CONCURRENCY: ${{ vars.HTTP_TEST_CONCURRENCY }}
HTTP_BEARER_TOKEN: ${{ secrets.HTTP_BEARER_TOKEN }}
run: go test -v -timeout=10m ./http/...

http-tests-gloas:
if: ${{ vars.HTTP_ADDRESS_GLOAS != '' }}
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.25.2'

- name: Run HTTP tests
env:
HTTP_ADDRESS: ${{ vars.HTTP_ADDRESS_GLOAS }}
HTTP_TEST_CONCURRENCY: ${{ vars.HTTP_TEST_CONCURRENCY }}
HTTP_BEARER_TOKEN: ${{ secrets.HTTP_BEARER_TOKEN_GLOAS }}
HTTP_REQUIRE_GLOAS: 'true'
run: go test -v -timeout=25m ./http/...
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
# Test binary, build with `go test -c`
*.test

# Custom golangci-lint binary built via `golangci-lint custom` (config: .custom-gcl.yml)
custom-gcl

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage.html
Expand Down
13 changes: 12 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ linters:
# HIGH PRIORITY
enable_no_pkg_logger: false
enable_enum_iota: true
enable_current_year: false
enable_current_year: true
# MEDIUM PRIORITY
enable_capital_comment: false
enable_func_opts: true
Expand All @@ -178,6 +178,17 @@ linters:
- third_party$ # Exclude third party code
- builtin$ # Exclude builtin code
- examples$ # Exclude example code
# Rule-based exclusions
rules:
# gloas ePBS type definitions carry long dynssz size-expression struct
# tags and require ssz-index tags for correct SSZ generation (removing
# them changes the generated SSZ). gofmt aligns these tags past the
# 132-char limit and struct tags cannot be wrapped, so exempt only the
# line-length checks for the gloas type packages.
- path: (spec|api/v1)/gloas/
text: "line is [0-9]+ characters"
linters:
- revive
# Formatters: Code formatting tools
formatters:
enable:
Expand Down
71 changes: 71 additions & 0 deletions api/epbsproposalopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright © 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"github.com/attestantio/go-eth2-client/spec/phase0"
)

// EPBSProposalOpts are the options for obtaining ePBS block proposals.
//
// Post-Gloas there is no blinded proposal: proposers commit to an execution
// payload bid rather than to a payload, so the axis that replaced blinded versus
// unblinded is IncludePayload — whether the execution payload envelope travels
// with the block or stays cached on the producing node.
type EPBSProposalOpts struct {
Common CommonOpts

// Slot is the slot for which the proposal should be fetched.
Slot phase0.Slot
// RandaoReveal is the RANDAO reveal for the proposal.
RandaoReveal phase0.BLSSignature
// Graffiti is the graffiti to be included in the beacon block body.
Graffiti [32]byte
// SkipRandaoVerification is true if we do not want the server to verify our RANDAO reveal.
// If this is set then the RANDAO reveal should be passed as the point at infinity (0xc0…00)
SkipRandaoVerification bool
// IncludePayload selects whether a self-built proposal carries its execution
// payload envelope and blobs.
//
// True asks a self-building node for the stateless form: everything needed to
// publish travels in the response, so any beacon node can publish the block.
// This is what multiple-beacon-node, distributed-validator and failover setups
// require. It is a request rather than a guarantee: a block built on an
// external builder's bid comes back with
// VersionedEPBSProposal.ExecutionPayloadIncluded false whatever was asked for,
// because the node does not hold the builder's payload, so those setups must
// read that field rather than assume this one describes what arrived.
//
// False is stateful: the producing node caches the envelope and blobs, so the
// block must be published via that same node, and the envelope retrieved from
// it with ExecutionPayloadEnvelope() — but only when the node self-built the
// block. An external builder's bid comes back excluded regardless of what was
// asked for, and the response alone does not say which case occurred; that is
// operational context the caller must already know.
//
// The spec marks this parameter required with no default, and the two choices
// carry materially different operational constraints, so it is a pointer:
// there is no safe value to assume on the caller's behalf, and leaving it
// unset is rejected rather than silently resolved to the constraining mode.
IncludePayload *bool
// BuilderBoostFactor is the relative weight of the builder payload versus a locally-produced
// payload, as per https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV4
//
// This is optional, and when it is not supplied the parameter is left off the
// request entirely, leaving the choice to the node. Note that differs from
// ProposalOpts, which materialises 100 client-side: the spec states no
// default for either endpoint, so sending nothing is what actually leaves the
// decision where the caller left it.
BuilderBoostFactor *uint64
}
40 changes: 39 additions & 1 deletion api/eventsopts.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2025 Attestant Limited.
// Copyright © 2025 - 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
Expand All @@ -21,6 +21,7 @@ import (
"github.com/attestantio/go-eth2-client/spec/altair"
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/attestantio/go-eth2-client/spec/electra"
"github.com/attestantio/go-eth2-client/spec/gloas"
"github.com/attestantio/go-eth2-client/spec/phase0"
)

Expand Down Expand Up @@ -53,12 +54,28 @@ type EventsOpts struct {
ContributionAndProofHandler ContributionAndProofEventHandlerFunc
// DataColumnSidecarHandler is a handler for the data_column_sidecar event.
DataColumnSidecarHandler DataColumnSidecarEventHandlerFunc
// ExecutionPayloadHandler is a handler for the execution_payload event
// (SignedExecutionPayloadEnvelope successfully imported on the fork-choice).
ExecutionPayloadHandler ExecutionPayloadEventHandlerFunc
// ExecutionPayloadAvailableHandler is a handler for the execution_payload_available event.
ExecutionPayloadAvailableHandler ExecutionPayloadAvailableEventHandlerFunc
// ExecutionPayloadBidHandler is a handler for the execution_payload_bid event.
ExecutionPayloadBidHandler ExecutionPayloadBidEventHandlerFunc
// ExecutionPayloadGossipHandler is a handler for the execution_payload_gossip event
// (SignedExecutionPayloadEnvelope passed gossip validation).
ExecutionPayloadGossipHandler ExecutionPayloadGossipEventHandlerFunc
// FastConfirmationHandler is a handler for the fast_confirmation event.
FastConfirmationHandler FastConfirmationEventHandlerFunc
// FinalizedCheckpointHandler is a handler for the finalized_checkpoint event.
FinalizedCheckpointHandler FinalizedCheckpointEventHandlerFunc
// HeadHandler is a handler for the head event.
HeadHandler HeadEventHandlerFunc
// PayloadAttestationMessageHandler is a handler for the payload_attestation_message event.
PayloadAttestationMessageHandler PayloadAttestationMessageEventHandlerFunc
// PayloadAttributesHandler is a handler for the payload_attributes event.
PayloadAttributesHandler PayloadAttributesEventHandlerFunc
// ProposerPreferencesHandler is a handler for the proposer_preferences event.
ProposerPreferencesHandler ProposerPreferencesEventHandlerFunc
// ProposerSlashingHandler is a handler for the proposer_slashing event.
ProposerSlashingHandler ProposerSlashingEventHandlerFunc
// SingleAttestationHandler is a handler for the single_attestation event.
Expand Down Expand Up @@ -114,3 +131,24 @@ type VoluntaryExitEventHandlerFunc func(context.Context, *phase0.SignedVoluntary

// DataColumnSidecarEventHandlerFunc is the handler for data_column_sidecar events.
type DataColumnSidecarEventHandlerFunc func(context.Context, *apiv1.DataColumnSidecarEvent)

// ExecutionPayloadEventHandlerFunc is the handler for execution_payload events.
type ExecutionPayloadEventHandlerFunc func(context.Context, *apiv1.ExecutionPayloadEvent)

// ExecutionPayloadAvailableEventHandlerFunc is the handler for execution_payload_available events.
type ExecutionPayloadAvailableEventHandlerFunc func(context.Context, *apiv1.ExecutionPayloadAvailableEvent)

// ExecutionPayloadBidEventHandlerFunc is the handler for execution_payload_bid events.
type ExecutionPayloadBidEventHandlerFunc func(context.Context, *gloas.SignedExecutionPayloadBid)

// ExecutionPayloadGossipEventHandlerFunc is the handler for execution_payload_gossip events.
type ExecutionPayloadGossipEventHandlerFunc func(context.Context, *apiv1.ExecutionPayloadEvent)

// FastConfirmationEventHandlerFunc is the handler for fast_confirmation events.
type FastConfirmationEventHandlerFunc func(context.Context, *apiv1.FastConfirmationEvent)

// PayloadAttestationMessageEventHandlerFunc is the handler for payload_attestation_message events.
type PayloadAttestationMessageEventHandlerFunc func(context.Context, *gloas.PayloadAttestationMessage)

// ProposerPreferencesEventHandlerFunc is the handler for proposer_preferences events.
type ProposerPreferencesEventHandlerFunc func(context.Context, *gloas.SignedProposerPreferences)
40 changes: 40 additions & 0 deletions api/executionpayloadenvelopeopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright © 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"github.com/attestantio/go-eth2-client/spec/phase0"
)

// ExecutionPayloadEnvelopeOpts are the options for obtaining the execution
// payload envelope a node cached while producing a block.
//
// This is the other half of asking for a proposal with the payload excluded: the
// node kept the envelope, and this is how the caller retrieves it to sign and
// publish.
type ExecutionPayloadEnvelopeOpts struct {
Common CommonOpts

// Slot is the slot for which the envelope was built.
Slot phase0.Slot
// BeaconBlockRoot is the root of the beacon block the envelope commits to.
//
// Passing it makes the lookup re-org resistant: if a re-org happens between
// producing the block and retrieving the envelope, the caller gets nothing
// rather than an envelope committed to a block that is no longer on the
// chain. The node is expected to check the cached envelope against it, and
// the returned envelope's own root is checked against it again here, so a
// node that does not is caught rather than trusted.
BeaconBlockRoot phase0.Root
}
24 changes: 24 additions & 0 deletions api/payloadattestationdataopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright © 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import "github.com/attestantio/go-eth2-client/spec/phase0"

// PayloadAttestationDataOpts are the options for obtaining payload attestation data.
type PayloadAttestationDataOpts struct {
Common CommonOpts

// Slot is the slot for which the data is obtained.
Slot phase0.Slot
}
26 changes: 26 additions & 0 deletions api/payloadattestationpoolopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright © 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import "github.com/attestantio/go-eth2-client/spec/phase0"

// PayloadAttestationPoolOpts are the options for obtaining the payload attestation pool.
type PayloadAttestationPoolOpts struct {
Common CommonOpts

// Slot is the slot for which the data is obtained. If not present then
// data for all slots will be obtained. Note that some beacon nodes
// require a slot and will reject a request without one.
Slot *phase0.Slot
}
26 changes: 26 additions & 0 deletions api/ptcdutiesopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright © 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import "github.com/attestantio/go-eth2-client/spec/phase0"

// PTCDutiesOpts are the options for obtaining payload timeliness committee duties.
type PTCDutiesOpts struct {
Common CommonOpts

// Epoch is the epoch for which the data is obtained.
Epoch phase0.Epoch
// Indices is a list of validators for which to obtain the duties.
Indices []phase0.ValidatorIndex
}
22 changes: 22 additions & 0 deletions api/signedexecutionpayloadenvelopeopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright © 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

// SignedExecutionPayloadEnvelopeOpts are the options for obtaining signed execution payload envelopes.
type SignedExecutionPayloadEnvelopeOpts struct {
Common CommonOpts

// Block is the ID of the block which the data is obtained.
Block string
}
28 changes: 28 additions & 0 deletions api/submitexecutionpayloadbidopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright © 2026 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
"github.com/attestantio/go-eth2-client/spec"
)

// SubmitExecutionPayloadBidOpts are the options for submitting execution
// payload bids.
type SubmitExecutionPayloadBidOpts struct {
Common CommonOpts

// SignedExecutionPayloadBid is the signed bid to publish. Its Version
// selects the wire schema and the consensus version header.
SignedExecutionPayloadBid *spec.VersionedSignedExecutionPayloadBid
}
Loading
Loading