Documentation
¶
Overview ¶
Package chain provides epoch-level state management and builder information caching.
Index ¶
- Constants
- Variables
- func BeaconVersion(v enginev.DataVersion) (version.DataVersion, error)
- func EngineVersion(v version.DataVersion) (enginev.DataVersion, error)
- func HasBuilderExited(info *BuilderInfo) bool
- func IsBuilderActive(info *BuilderInfo, finalizedEpoch uint64) bool
- func IsValidCandidateKey(key string) bool
- type ActiveIndiceIndex
- type BlobScheduleEntry
- type BuilderInfo
- type CandidateKey
- type CandidateParent
- type ChainSpec
- func (s *ChainSpec) GetForkEpoch(fork version.DataVersion) phase0.Epoch
- func (s *ChainSpec) GetForkVersion(fork version.DataVersion) (phase0.Version, error)
- func (s *ChainSpec) IsForkActive(fork version.DataVersion, epoch phase0.Epoch) bool
- func (s *ChainSpec) IsForkScheduled(fork version.DataVersion) bool
- type DutyState
- type EpochStats
- type ForkSchedule
- type HeadChangeEvent
- type HeadTracker
- func (h *HeadTracker) CurrentHead() *beacon.BlockInfo
- func (h *HeadTracker) FinalityInfo() *beacon.FinalityInfo
- func (h *HeadTracker) GetBlock(ctx context.Context, root phase0.Root) (*beacon.BlockInfo, error)
- func (h *HeadTracker) GetPayloadStatus(root phase0.Root) PayloadStatus
- func (h *HeadTracker) IsCanonical(ctx context.Context, root phase0.Root) bool
- func (h *HeadTracker) LookupBlock(root phase0.Root) (*beacon.BlockInfo, bool)
- func (h *HeadTracker) LookupELParentMeta(ctx context.Context, fromRoot phase0.Root, execHash phase0.Hash32) (number, gasLimit uint64)
- func (h *HeadTracker) PrimeBlock(info *beacon.BlockInfo)
- func (h *HeadTracker) PrimeHead(info *beacon.BlockInfo)
- func (h *HeadTracker) ResolveCandidates(ctx context.Context, slot phase0.Slot) ([]*CandidateParent, error)
- func (h *HeadTracker) ResolveELParentMeta(ctx context.Context, fromRoot phase0.Root, execHash phase0.Hash32) (number, gasLimit uint64)
- func (h *HeadTracker) Start(ctx context.Context)
- func (h *HeadTracker) Stop()
- func (h *HeadTracker) SubscribeHeadChanges() *utils.Subscription[*HeadChangeEvent]
- type HeadVoteTracker
- func (t *HeadVoteTracker) GetParticipation(slot phase0.Slot, root phase0.Root) (HeadVoteUpdate, bool)
- func (t *HeadVoteTracker) GetSubnetCoverage() SubnetCoverage
- func (t *HeadVoteTracker) GetVoteDetail(slot phase0.Slot, root phase0.Root) (VoteDetail, bool)
- func (t *HeadVoteTracker) Start(ctx context.Context)
- func (t *HeadVoteTracker) Stop()
- func (t *HeadVoteTracker) SubscribeBlocks() *utils.Subscription[*eth2all.SignedBeaconBlock]
- func (t *HeadVoteTracker) SubscribeCoverage() *utils.Subscription[*SubnetCoverage]
- func (t *HeadVoteTracker) SubscribeUpdates() *utils.Subscription[*HeadVoteUpdate]
- type HeadVoteUpdate
- type PayloadStatus
- type PendingDepositInfo
- type Service
- type SubnetCoverage
- type VoteAttester
- type VoteDetail
Constants ¶
const BuilderIndexFlag uint64 = 1 << 40
const ( // EtherGweiFactor is the number of Gwei in 1 ETH. EtherGweiFactor = phase0.Gwei(1_000_000_000) )
const FarFutureEpoch = uint64(0xFFFFFFFFFFFFFFFF)
FarFutureEpoch is the sentinel value indicating a builder/validator has not exited.
Variables ¶
var AllCandidateKeys = []CandidateKey{ CandidateParentFull, CandidateParentEmpty, CandidateGrandparentFull, CandidateGrandparentEmpty, }
AllCandidateKeys lists every candidate key in canonical priority order.
Functions ¶
func BeaconVersion ¶
func BeaconVersion(v enginev.DataVersion) (version.DataVersion, error)
BeaconVersion maps an Engine API (execution) data version back to the canonical beacon (consensus) fork that introduced it.
func EngineVersion ¶
func EngineVersion(v version.DataVersion) (enginev.DataVersion, error)
EngineVersion maps a beacon (consensus) fork to the Engine API (execution) data version whose payload structures it carries. It errors for pre-merge forks (phase0/altair), which have no execution payload.
func HasBuilderExited ¶ added in v0.0.3
func HasBuilderExited(info *BuilderInfo) bool
HasBuilderExited returns true when the builder's exit has been initiated (withdrawable epoch set). Per the Gloas spec an exited builder can never be reactivated: a deposit for its pubkey only tops up the exited entry and is withdrawn back to the execution address by the sweep (pushing the withdrawable epoch out by MIN_BUILDER_WITHDRAWABILITY_DELAY if the entry was already swept). The pubkey only becomes depositable again once the entry's index is reused by a different builder's deposit and the pubkey leaves the registry (info == nil).
func IsBuilderActive ¶
func IsBuilderActive(info *BuilderInfo, finalizedEpoch uint64) bool
IsBuilderActive returns true when a builder's deposit has been finalized and the builder has not exited. Pass the result of GetBuilderByPubkey and GetFinalizedEpoch.
func IsValidCandidateKey ¶ added in v0.0.3
IsValidCandidateKey reports whether the given string names a candidate key.
Types ¶
type ActiveIndiceIndex ¶
type ActiveIndiceIndex uint32
ActiveIndiceIndex is a uint32 index into the active validators array.
type BlobScheduleEntry ¶
BlobScheduleEntry represents a single entry in the BLOB_SCHEDULE.
type BuilderInfo ¶
type BuilderInfo struct {
Index uint64
Pubkey phase0.BLSPubKey
Balance uint64
Active bool
DepositEpoch uint64
WithdrawableEpoch uint64
PendingPayments uint64 // Sum of pending payments from BuilderPendingPayments in state
}
BuilderInfo represents information about a builder from the beacon state.
type CandidateKey ¶ added in v0.0.3
type CandidateKey string
CandidateKey identifies a build-parent candidate for a slot: which beacon block and which execution payload the build extends. "parent" and "grandparent" are positions on the canonical head chain at resolution time, so after missed slots they name the last existing blocks, not fixed slot offsets.
const ( // CandidateParentFull: build on the head block and its committed payload. CandidateParentFull CandidateKey = "parent_full" // CandidateParentEmpty: build on the head block but on the execution // payload it built upon (the head block's own payload treated as // withheld). Gloas+ only. CandidateParentEmpty CandidateKey = "parent_empty" // CandidateGrandparentFull: build on the head block's parent and its // committed payload (a deliberate reorg of the head block). CandidateGrandparentFull CandidateKey = "grandparent_full" // CandidateGrandparentEmpty: build on the head block's parent but on the // payload it built upon (reorg of the head block combined with the // grandparent's payload treated as withheld). Gloas+ only. CandidateGrandparentEmpty CandidateKey = "grandparent_empty" )
type CandidateParent ¶ added in v0.0.3
type CandidateParent struct {
Key CandidateKey
ParentBlockRoot phase0.Root
ParentSlot phase0.Slot
ParentBlockHash phase0.Hash32
// ELParentGasLimit is the gas limit of the execution block identified by
// ParentBlockHash (0 = unknown). Committed gas limits come from the bid
// (Gloas) or the embedded payload (pre-Gloas).
ELParentGasLimit uint64
// ELParentNumber is the block number of the execution block identified by
// ParentBlockHash (0 = unknown; Gloas blocks require the revealed
// envelope to learn it).
ELParentNumber uint64
// ParentPayloadStatus is the reveal status of the beacon parent block's
// own committed payload. Full candidates are only viable when it is (or
// becomes) revealed; empty candidates when it stays withheld.
ParentPayloadStatus PayloadStatus
}
CandidateParent is one resolved build-parent candidate for a slot.
type ChainSpec ¶
type ChainSpec struct {
// SecondsPerSlot is the slot duration, taken from SLOT_DURATION_MS when the
// beacon node serves it (EIP-7782 networks keep serving a stale
// SECONDS_PER_SLOT preset default alongside it) and from SECONDS_PER_SLOT
// otherwise.
SecondsPerSlot time.Duration
SlotsPerEpoch uint64
// Duty calculation parameters
ShuffleRoundCount uint64
TargetCommitteeSize uint64
MaxCommitteesPerSlot uint64
MaxEffectiveBalance uint64
MaxEffectiveBalanceElectra uint64
EpochsPerHistoricalVector uint64
MinSeedLookahead uint64
// Pending-deposit processing parameters (Electra). Used to estimate how many
// pending deposits drain per epoch when timing the pre-Gloas early onboarding
// deposit (see pkg/lifecycle pending-deposit simulation).
MinPerEpochChurnLimit uint64
ChurnLimitQuotient uint64
MaxPerEpochActivationExitChurnLimit uint64
MaxPendingDepositsPerEpoch uint64
MinActivationBalance uint64
EffectiveBalanceIncrement uint64
MaxWithdrawalsPerPayload uint64
// Domain types
DomainBeaconProposer phase0.DomainType
DomainBeaconAttester phase0.DomainType
DomainPtcAttester phase0.DomainType
DomainProposerPreferences phase0.DomainType
// Fork epochs and versions (nil if not configured)
ForkSchedule []ForkSchedule
// Blob schedule (BPO - Blob Parameters Only)
BlobSchedule []BlobScheduleEntry
// ePBS parameters
PtcSize uint64
// PAYLOAD_DUE_BPS: the builder payload reveal deadline as basis points of
// the slot duration (Gloas). A block whose payload has not been seen by
// this offset is treated as empty by payload timeliness voting.
PayloadDueBps uint64
// Deposit contract
DepositContractAddress *common.Address
}
ChainSpec holds chain specification parameters.
func ParseChainSpec ¶
func ParseChainSpec(specData map[string]string, rawData map[string]json.RawMessage) (*ChainSpec, error)
ParseChainSpec parses the chain specification from the spec data.
func (*ChainSpec) GetForkEpoch ¶
func (s *ChainSpec) GetForkEpoch(fork version.DataVersion) phase0.Epoch
GetForkEpoch returns the epoch of a given fork.
func (*ChainSpec) GetForkVersion ¶
GetForkVersion returns the fork version for a given fork.
func (*ChainSpec) IsForkActive ¶
IsForkActive checks if a fork is active for a given epoch.
func (*ChainSpec) IsForkScheduled ¶
func (s *ChainSpec) IsForkScheduled(fork version.DataVersion) bool
IsForkScheduled checks if a fork is scheduled.
type DutyState ¶
type DutyState struct {
RandaoMix *phase0.Hash32
NextRandaoMix *phase0.Hash32
GetRandaoMixes func() []phase0.Root
GetActiveCount func() uint64
GetEffectiveBalance func(index ActiveIndiceIndex) phase0.Gwei
}
DutyState holds the state data needed for duty calculations.
type EpochStats ¶
type EpochStats struct {
Version version.DataVersion
Epoch phase0.Epoch
FinalizedEpoch phase0.Epoch
StateSlot phase0.Slot
// Validator data
ActiveValidators uint64
ValidatorCount uint64
ActiveIndices []phase0.ValidatorIndex
EffectiveBalances []uint32 // Effective balance in full ETH units
// Builder data (for lifecycle management, Gloas only).
// Populated (possibly empty) for any Gloas+ state; nil for pre-Gloas epochs.
Builders []*BuilderInfo
// Total active effective balance (gwei). Used to estimate the activation-exit
// churn limit for pending-deposit processing (early-onboarding timing).
TotalActiveBalance uint64
// Pending-deposit queue data (Electra+). Used to time the pre-Gloas early
// onboarding deposit so it is still queued at the fork boundary.
PendingDeposits []PendingDepositInfo
DepositBalanceToConsume uint64 // gwei
Eth1DepositIndex uint64
DepositRequestsStartIndex uint64
// Pre-computed duties
RandaoMix phase0.Hash32
NextRandaoMix phase0.Hash32
ProposerDuties []phase0.ValidatorIndex // [slot_index] -> validator index
AttesterDuties [][][]ActiveIndiceIndex // [slot_index][committee_index][member] -> active indice index
PtcDuties [][]ActiveIndiceIndex // [slot_index][ptc_member] -> active indice index (Gloas only)
}
EpochStats holds cached statistics for an epoch computed from beacon state.
type ForkSchedule ¶
type HeadChangeEvent ¶ added in v0.0.3
type HeadChangeEvent struct {
Old *beacon.BlockInfo // nil on the first observed head
New *beacon.BlockInfo
ReorgDepth uint64
CommonAncestor phase0.Root
}
HeadChangeEvent is fired for every accepted head switch. ReorgDepth is 0 for a normal chain extension; for a reorg it is the number of slots between the old head and the common ancestor. CommonAncestor is zero when the fork point is deeper than the scan window.
type HeadTracker ¶ added in v0.0.3
type HeadTracker struct {
// contains filtered or unexported fields
}
HeadTracker maintains buildoor's own view of the canonical chain: the current head, a bounded block-by-root ancestry cache, and per-block payload reveal status (Gloas). It is the validation oracle for payload-attributes sanitization and the source of build-parent candidates.
func NewHeadTracker ¶ added in v0.0.3
func NewHeadTracker( clClient *beacon.Client, chainSpec *ChainSpec, genesis *beacon.Genesis, log logrus.FieldLogger, ) *HeadTracker
NewHeadTracker creates a new head tracker.
func (*HeadTracker) CurrentHead ¶ added in v0.0.3
func (h *HeadTracker) CurrentHead() *beacon.BlockInfo
CurrentHead returns the most recently observed head block (nil until the first head event resolves).
func (*HeadTracker) FinalityInfo ¶ added in v0.0.3
func (h *HeadTracker) FinalityInfo() *beacon.FinalityInfo
FinalityInfo returns the finality checkpoint execution hashes cached for the current head (nil until the first refresh completes). Refreshed once per head change, so build paths never pay the beacon-API round trips.
func (*HeadTracker) GetBlock ¶ added in v0.0.3
GetBlock resolves a block by root through the shared ancestry cache, fetching from the beacon node on a miss.
func (*HeadTracker) GetPayloadStatus ¶ added in v0.0.3
func (h *HeadTracker) GetPayloadStatus(root phase0.Root) PayloadStatus
GetPayloadStatus returns the reveal status of the block's committed payload. Unknown blocks report Pending. Pre-Gloas blocks are always Revealed (the payload is embedded in the block).
func (*HeadTracker) IsCanonical ¶ added in v0.0.3
IsCanonical reports whether the given root is on the current head's ancestry within the retention window.
func (*HeadTracker) LookupBlock ¶ added in v0.0.3
LookupBlock returns a cached block by root without ever fetching, for callers that must not block (UI event assembly, hot paths).
func (*HeadTracker) LookupELParentMeta ¶ added in v0.0.3
func (h *HeadTracker) LookupELParentMeta( ctx context.Context, fromRoot phase0.Root, execHash phase0.Hash32, ) (number, gasLimit uint64)
LookupELParentMeta returns the block number and gas limit of the execution block identified by execHash from already-known data only: the committing beacon block's own fields and the envelope-metadata cache. It never performs a beacon-API fetch, so build hot paths never block on one (payload-available events prefetch the metadata in the background).
func (*HeadTracker) PrimeBlock ¶ added in v0.0.3
func (h *HeadTracker) PrimeBlock(info *beacon.BlockInfo)
PrimeBlock contributes an already-resolved block to the shared ancestry cache (also derives payload-status evidence for its parent).
func (*HeadTracker) PrimeHead ¶ added in v0.0.3
func (h *HeadTracker) PrimeHead(info *beacon.BlockInfo)
PrimeHead seeds the tracker with an already-resolved head block (cached and adopted as current head unless an equal-or-newer head is known). Live head events take over from the first processed event.
func (*HeadTracker) ResolveCandidates ¶ added in v0.0.3
func (h *HeadTracker) ResolveCandidates(ctx context.Context, slot phase0.Slot) ([]*CandidateParent, error)
ResolveCandidates derives the build-parent candidates for the given slot from the current head chain. The head must be older than the target slot. Empty variants are only produced under Gloas; a variant whose parent tuple duplicates another is dropped.
func (*HeadTracker) ResolveELParentMeta ¶ added in v0.0.3
func (h *HeadTracker) ResolveELParentMeta( ctx context.Context, fromRoot phase0.Root, execHash phase0.Hash32, ) (number, gasLimit uint64)
ResolveELParentMeta resolves the block number and gas limit of the execution block identified by execHash, walking the beacon ancestry from fromRoot to find the block that committed it (best-effort; zeros when unknown). May fetch from the beacon node — do not call from build hot paths; use LookupELParentMeta there.
func (*HeadTracker) Start ¶ added in v0.0.3
func (h *HeadTracker) Start(ctx context.Context)
Start starts the head tracker's event loop.
func (*HeadTracker) Stop ¶ added in v0.0.3
func (h *HeadTracker) Stop()
Stop stops the head tracker and waits for its loop to exit.
func (*HeadTracker) SubscribeHeadChanges ¶ added in v0.0.3
func (h *HeadTracker) SubscribeHeadChanges() *utils.Subscription[*HeadChangeEvent]
SubscribeHeadChanges returns a subscription for head switch events (including reorgs).
type HeadVoteTracker ¶
type HeadVoteTracker struct {
// contains filtered or unexported fields
}
HeadVoteTracker tracks per-slot attestation participation by aggregating raw single_attestation events (streaming in from the Gloas attester deadline at 25% of the slot) into per-root bitmaps against locally computed attester duties. Raw singles are the ONLY participation source — aggregates are deliberately not subscribed (they arrive at the 50% aggregate deadline, which is also the payload reveal deadline, far too late to be useful). Instead, every imported block's attestations serve as the ground truth to measure how much of the vote our singles view actually covered: a node without subscribe-all-subnets only sees singles on its duty subnets, and a sustained miss flags the tracking as unreliable. Updates are throttled to percent-steps on a flush interval; crossing the configured participation threshold fires immediately.
func NewHeadVoteTracker ¶
func NewHeadVoteTracker( cfg *config.Config, chainSvc Service, clClient *beacon.Client, log logrus.FieldLogger, ) *HeadVoteTracker
NewHeadVoteTracker creates a new head vote tracker.
func (*HeadVoteTracker) GetParticipation ¶ added in v0.0.3
func (t *HeadVoteTracker) GetParticipation(slot phase0.Slot, root phase0.Root) (HeadVoteUpdate, bool)
GetParticipation returns the current participation snapshot for a tracked (slot, beacon block root) pair; ok is false when the pair is not tracked.
func (*HeadVoteTracker) GetSubnetCoverage ¶ added in v0.0.3
func (t *HeadVoteTracker) GetSubnetCoverage() SubnetCoverage
GetSubnetCoverage returns the current subnet coverage summary.
func (*HeadVoteTracker) GetVoteDetail ¶ added in v0.0.3
func (t *HeadVoteTracker) GetVoteDetail(slot phase0.Slot, root phase0.Root) (VoteDetail, bool)
GetVoteDetail returns the per-attester vote detail for a slot. A zero root resolves the slot's primary root. ok is false when the (slot, root) pair is not tracked.
func (*HeadVoteTracker) Start ¶
func (t *HeadVoteTracker) Start(ctx context.Context)
Start starts the head vote tracker.
func (*HeadVoteTracker) SubscribeBlocks ¶ added in v0.0.3
func (t *HeadVoteTracker) SubscribeBlocks() *utils.Subscription[*eth2all.SignedBeaconBlock]
SubscribeBlocks returns a subscription for imported blocks (the full fork-agnostic signed block — a byproduct of the coverage measurement's block fetch; at most one per imported block, none while a fetch is still in flight). Consumers reduce it to whatever shape they need.
func (*HeadVoteTracker) SubscribeCoverage ¶ added in v0.0.3
func (t *HeadVoteTracker) SubscribeCoverage() *utils.Subscription[*SubnetCoverage]
SubscribeCoverage returns a subscription for subnet coverage updates (at most one per imported block).
func (*HeadVoteTracker) SubscribeUpdates ¶
func (t *HeadVoteTracker) SubscribeUpdates() *utils.Subscription[*HeadVoteUpdate]
SubscribeUpdates returns a subscription for head vote updates.
type HeadVoteUpdate ¶
type HeadVoteUpdate struct {
Slot phase0.Slot
BlockRoot phase0.Root
ParticipationPct float64
ParticipationETH uint64
TotalSlotETH uint64
VoteCount int
TotalMembers int
ThresholdPct float64 // effective threshold at fire time (0 = disabled)
ThresholdMet bool
Timestamp int64
}
HeadVoteUpdate is dispatched when head vote participation changes.
type PayloadStatus ¶ added in v0.0.3
type PayloadStatus string
PayloadStatus is the reveal status of a Gloas block's committed execution payload. Pre-Gloas blocks embed their payload and are always Revealed.
const ( // PayloadStatusPending: no reveal evidence yet and the reveal deadline has // not passed. PayloadStatusPending PayloadStatus = "pending" // PayloadStatusRevealed: the payload was seen (payload-available event or // a child block built on it). PayloadStatusRevealed PayloadStatus = "revealed" // PayloadStatusEmpty: the payload is treated as withheld — either a child // block built past it, or the reveal deadline passed without evidence // (provisional until contrary evidence arrives). PayloadStatusEmpty PayloadStatus = "empty" )
type PendingDepositInfo ¶
PendingDepositInfo is a single entry of the beacon state's pending_deposits queue, reduced to the fields needed to model Electra deposit-queue draining and to identify our own (early-onboarding) deposit after a restart.
type Service ¶
type Service interface {
Start(ctx context.Context) error
Stop() error
// Chain state accessors
GetChainSpec() *ChainSpec
GetGenesis() *beacon.Genesis
SlotToTime(slot phase0.Slot) time.Time
TimeToSlot(t time.Time) phase0.Slot
GetCurrentEpoch() phase0.Epoch
GetCurrentSlot() phase0.Slot
GetCurrentFork() version.DataVersion
ActiveForkAtEpoch(epoch phase0.Epoch) version.DataVersion
GetForkVersion() (phase0.Version, error)
GetEpochOfSlot(slot phase0.Slot) phase0.Epoch
// Epoch stats access
GetCurrentEpochStats() *EpochStats
GetEpochStats(epoch phase0.Epoch) *EpochStats
// Subscriptions
SubscribeEpochStats() *utils.Subscription[*EpochStats]
// Head vote tracking
GetHeadVoteTracker() *HeadVoteTracker
// Canonical head / ancestry / payload-status view
GetHeadTracker() *HeadTracker
// Finality
GetFinalizedEpoch() phase0.Epoch
// Builder access
GetBuilderByIndex(index uint64) *BuilderInfo
GetBuilderByPubkey(pubkey phase0.BLSPubKey) *BuilderInfo
GetBuilders() []*BuilderInfo
// Validator access
GetValidatorPubkeyByIndex(index phase0.ValidatorIndex) *phase0.BLSPubKey
// RefreshBuilders re-fetches the beacon state to pick up new builder registrations.
RefreshBuilders(ctx context.Context) error
}
Service interface defines the chain service operations.
type SubnetCoverage ¶ added in v0.0.3
type SubnetCoverage struct {
Slots int // measured blocks in the window
Attesters int // total attesters counted across the window
SeenPct float64 // percent of those attesters seen as singles beforehand
Low bool // sustained miss above coverageMissThreshold
}
SubnetCoverage summarizes how many of the attesters that landed in recent blocks were previously seen as raw single attestations.
type VoteAttester ¶ added in v0.0.3
type VoteAttester struct {
Index phase0.ValidatorIndex
SeenAtMs int32 // ms offset from slot start; -1 = never seen as a raw single
InBlock bool // attested on chain per the next-block ground truth
}
VoteAttester is one committee member's vote observation.
type VoteDetail ¶ added in v0.0.3
type VoteDetail struct {
Slot phase0.Slot
BlockRoot phase0.Root
TotalMembers int
Attesters []VoteAttester
}
VoteDetail is a per-attester snapshot of one (slot, root) vote state, consumed by the WebUI's vote-arrival heatmap.