payload_builder

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 8, 2026 License: GPL-3.0 Imports: 30 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultCacheSize is the number of slots to keep in the cache.
	DefaultCacheSize = 1000
)

Variables

This section is empty.

Functions

func ModifyPayloadExtraData

func ModifyPayloadExtraData(
	p *engineall.ExecutionPayload,
	executionRequests []prague.ExecutionRequest,
	extraDataPrefix []byte,
	parentBeaconBlockRoot common.Hash,
) (common.Hash, error)

ModifyPayloadExtraData rewrites the extraData field of a built execution payload in place, prepending the given prefix (truncating the original to stay within the 32-byte limit), recomputes the block hash, updates the payload's BlockHash field, and returns the new hash.

The parentBeaconBlockRoot is required because it is part of the block header (and therefore affects the block hash) but is not carried in the execution payload itself.

executionRequests carries the EIP-7685 execution requests from the engine API response (Electra/Prague+); they are needed to compute the requestsHash header field. Pass nil for pre-Electra payloads.

The function first verifies it can reconstruct the original block hash from the payload fields. If verification fails (e.g. an unhandled fork added new header fields) it returns an error rather than producing an incorrect hash.

func ParseExecutionRequests

func ParseExecutionRequests(raw []prague.ExecutionRequest, dataVersion version.DataVersion) (*eth2all.ExecutionRequests, error)

ParseExecutionRequests decodes raw EIP-7685 execution request bytes from the Engine API into a versioned eth2all.ExecutionRequests.

Each element in raw is: [type_prefix_byte || request_1 || request_2 || ...] where all requests of the same type are concatenated after a single prefix byte. Builder deposit (0x03) and builder exit (0x04) requests are only valid from Gloas onwards.

Types

type BidRecord

type BidRecord struct {
	Transport        BidTransport
	Value            phase0.Gwei
	ExecutionPayment phase0.Gwei
	At               time.Time
}

BidRecord is a lightweight record of a bid produced for this payload (not the heavy payload itself).

type BidTransport

type BidTransport string

BidTransport identifies which submitter produced a bid or reveal.

const (
	// BidTransportP2P is the ePBS p2p gossip submitter.
	BidTransportP2P BidTransport = "p2p"
	// BidTransportBuilderAPI is the HTTP Builder API submitter.
	BidTransportBuilderAPI BidTransport = "builder-api"
)

type BlobsBundle

type BlobsBundle struct {
	Commitments []deneb.KZGCommitment `json:"commitments"`
	Proofs      []deneb.KZGProof      `json:"proofs"`
	Blobs       []deneb.Blob          `json:"blobs"`
}

BlobsBundle holds the blobs, KZG commitments and proofs produced alongside a payload, in beacon (deneb) types. The engine API bundle is converted to this once in the builder (see beaconBlobsBundleFromEngine) so downstream consumers use the beacon types directly instead of re-converting at every call site.

func (*BlobsBundle) BlobsAsBytes

func (b *BlobsBundle) BlobsAsBytes() [][]byte

BlobsAsBytes returns the blobs as raw byte slices for beacon submission. Nil-safe: returns nil for a nil bundle.

func (*BlobsBundle) MarshalJSON

func (b *BlobsBundle) MarshalJSON() ([]byte, error)

MarshalJSON renders the bundle as {commitments, proofs, blobs} hex arrays. Nil-safe: a nil bundle marshals to JSON null.

func (*BlobsBundle) ProofsAsBytes

func (b *BlobsBundle) ProofsAsBytes() [][]byte

ProofsAsBytes returns the KZG proofs as raw byte slices for beacon submission. Nil-safe: returns nil for a nil bundle.

type BuilderStats

type BuilderStats struct {
	SlotsBuilt     uint64
	BidsSubmitted  uint64
	BidsWon        uint64
	BlocksIncluded uint64 // Blocks where our payload was included
	TotalPaid      uint64 // Gwei paid for won bids
	RevealsSuccess uint64
	RevealsFailed  uint64
	RevealsSkipped uint64
}

BuilderStats tracks statistics for builder operations.

type ELClientVersion

type ELClientVersion struct {
	Code    string
	Name    string
	Version string
	Commit  string
}

ELClientVersion is the execution client's identification, as returned by engine_getClientVersionV1, in display-friendly string form.

type EngineClient

type EngineClient interface {
	// ForkchoiceUpdatedAgnostic updates the forkchoice and optionally starts a
	// payload build, using the fork-agnostic request union.
	ForkchoiceUpdatedAgnostic(
		ctx context.Context,
		request *engineall.ForkchoiceUpdatedRequest,
	) (*paris.ForkchoiceUpdatedResponse, error)

	// GetPayloadAgnostic retrieves a built payload as the fork-agnostic union,
	// dispatching to the engine_getPayload version implied by dataVersion.
	GetPayloadAgnostic(
		ctx context.Context,
		dataVersion enginev.DataVersion,
		payloadID paris.PayloadID,
	) (*engineall.GetPayloadResponse, error)

	// ClientVersion exchanges client identity via engine_getClientVersionV1.
	ClientVersion(
		ctx context.Context,
		clientVersion *identification.ClientVersion,
	) ([]*identification.ClientVersion, error)
}

EngineClient is the subset of the go-eth-engine-client JSON-RPC service used by buildoor. It dispatches each fork-agnostic request to the matching versioned engine_* method internally. The jsonrpc.Service satisfies it.

type Payload

type Payload struct {
	// Attributes is the payload_attributes event this build was triggered by.
	Attributes *beacon.PayloadAttributesEvent
	// ExecutionPayload is the fork-agnostic beacon execution payload.
	ExecutionPayload *eth2all.ExecutionPayload
	// BlobsBundle holds the blobs/commitments/proofs (Deneb+), nil if none.
	BlobsBundle *BlobsBundle
	// ExecutionRequests are the parsed execution requests (Electra+), versioned for the active fork.
	ExecutionRequests *eth2all.ExecutionRequests

	// Metadata not carried by the objects above.
	BlockHash    phase0.Hash32  // block hash after extra-data injection
	FeeRecipient common.Address // resolved proposer fee recipient for the bid
	BlockValue   *big.Int       // EL-reported block value (wei)
	ReadyAt      time.Time      // when the payload became ready
	// contains filtered or unexported fields
}

Payload is the canonical built payload, produced once by the builder and referenced (never copied) throughout the stack — it is a large object (blobs, transactions), so downstream consumers hold the same *Payload rather than copying it. The build outputs are immutable; the bid/reveal activity log is appended by the payload_bidder as bids are produced and the payload revealed.

Anything derivable from the build objects (slot, parent hashes, timestamp, gas limit, ...) is read through them rather than duplicated here.

func (*Payload) AddBid

func (p *Payload) AddBid(rec BidRecord)

AddBid appends a bid record to the payload's activity log.

func (*Payload) Bids

func (p *Payload) Bids() []BidRecord

Bids returns a snapshot copy of the bids recorded for this payload.

func (*Payload) MarkRevealed

func (p *Payload) MarkRevealed(rec RevealRecord)

MarkRevealed records the reveal of this payload's envelope. The first reveal wins; subsequent calls are ignored.

func (*Payload) Reveal

func (p *Payload) Reveal() *RevealRecord

Reveal returns the reveal record if the payload has been revealed, else nil.

type PayloadBuildFailedEvent

type PayloadBuildFailedEvent struct {
	Slot     phase0.Slot
	Error    string    // Failure reason
	FailedAt time.Time // When the build failed
}

PayloadBuildFailedEvent is emitted when a payload build fails. Subscribers (e.g. the WebUI) use it to mark the in-progress build as failed instead of leaving it rendered as perpetually building.

type PayloadBuildStartedEvent

type PayloadBuildStartedEvent struct {
	Slot      phase0.Slot
	StartedAt time.Time // When the build started
}

PayloadBuildStartedEvent is emitted when payload building begins for a slot, before the build has completed. Subscribers (e.g. the WebUI) use it to render the build as in-progress rather than waiting for the payload to be ready.

type PayloadBuilder

type PayloadBuilder struct {
	// contains filtered or unexported fields
}

PayloadBuilder handles execution payload building via the Engine API.

func NewPayloadBuilder

func NewPayloadBuilder(
	clClient *beacon.Client,
	engineClient EngineClient,
	chainSvc chain.Service,
	feeRecipient common.Address,
	cfg *config.Config,
	log logrus.FieldLogger,
	settingsResolvers []ProposerSettingsResolver,
) *PayloadBuilder

NewPayloadBuilder creates a new payload builder. cfg is the shared config pointer; mutable settings (e.g. PayloadBuildTime) are read live from it. settingsResolvers are asked in order for the proposer's announced fee recipient and gas limit; the first match wins.

func (*PayloadBuilder) AbortBuild

func (b *PayloadBuilder) AbortBuild(slot phase0.Slot)

AbortBuild aborts any active build for the given slot.

func (*PayloadBuilder) BuildPayloadFromAttributes

func (b *PayloadBuilder) BuildPayloadFromAttributes(
	ctx context.Context,
	attrs *beacon.PayloadAttributesEvent,
) (*Payload, error)

BuildPayloadFromAttributes builds a payload using data from a payload_attributes event. This is the primary build path, triggered when the beacon node emits payload_attributes. The event contains all necessary information: timestamp, randao, withdrawals, etc.

type PayloadCache

type PayloadCache struct {
	// contains filtered or unexported fields
}

PayloadCache stores built payloads for a limited number of slots. It uses a simple LRU-like approach, keeping only the most recent slots.

func NewPayloadCache

func NewPayloadCache(maxSlots int) *PayloadCache

NewPayloadCache creates a new payload cache with the specified maximum slots.

func (*PayloadCache) Cleanup

func (c *PayloadCache) Cleanup(olderThan phase0.Slot)

Cleanup removes payloads older than the given slot.

func (*PayloadCache) Delete

func (c *PayloadCache) Delete(slot phase0.Slot)

Delete removes a payload for the given slot.

func (*PayloadCache) Get

func (c *PayloadCache) Get(slot phase0.Slot) *Payload

Get retrieves a payload for the given slot.

func (*PayloadCache) GetAll

func (c *PayloadCache) GetAll() []*Payload

GetAll returns all cached payloads.

func (*PayloadCache) GetByBlockHash

func (c *PayloadCache) GetByBlockHash(blockHash phase0.Hash32) *Payload

GetByBlockHash retrieves a payload by its block hash.

func (*PayloadCache) Size

func (c *PayloadCache) Size() int

Size returns the number of payloads in the cache.

func (*PayloadCache) Store

func (c *PayloadCache) Store(event *Payload)

Store stores a payload in the cache. It automatically evicts old payloads to maintain the size limit.

type ProposerSettings added in v0.0.2

type ProposerSettings struct {
	FeeRecipient   common.Address
	TargetGasLimit uint64 // 0 = not announced
}

ProposerSettings are the proposer-announced build parameters for a slot.

type ProposerSettingsResolver added in v0.0.2

type ProposerSettingsResolver interface {
	ResolveProposerSettings(slot phase0.Slot, proposerIndex phase0.ValidatorIndex) (ProposerSettings, bool)
}

ProposerSettingsResolver resolves the proposer's announced settings for a build. Implementations self-scope: they return false when they don't apply to the slot's fork or hold no data (gossip preferences post-Gloas in payload_bidder; Builder API validator registrations pre-Gloas in the legacy dialect).

type RevealRecord

type RevealRecord struct {
	Transport       BidTransport
	BeaconBlockRoot phase0.Root
	At              time.Time
}

RevealRecord records that the payload's execution envelope was revealed.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is the standalone builder service that handles payload building. It does NOT handle ePBS bidding or revealing - those are handled by the epbs package.

Fork-aware building: - Electra/Fulu: Build on parent block (payload is in the block) - Gloas: Build on last known payload (payload is separate from block)

Building is triggered by payload_attributes events from the beacon node, which contain all the information needed to build a payload.

func NewService

func NewService(
	cfg *config.Config,
	clClient *beacon.Client,
	chainSvc chain.Service,
	engineClient EngineClient,
	feeRecipient common.Address,
	log logrus.FieldLogger,
) (*Service, error)

NewService creates a new builder service. Proposer settings (fee recipient, target gas limit) are resolved through the resolvers registered via AddProposerSettingsResolver before Start.

func (*Service) AddProposerSettingsResolver added in v0.0.2

func (s *Service) AddProposerSettingsResolver(r ProposerSettingsResolver)

AddProposerSettingsResolver appends a resolver; the builder asks each registered resolver in order and uses the first match. Register before Start().

func (*Service) GetCLClient

func (s *Service) GetCLClient() *beacon.Client

GetCLClient returns the consensus layer client.

func (*Service) GetChainSpec

func (s *Service) GetChainSpec() *chain.ChainSpec

GetChainSpec returns the chain specification.

func (*Service) GetConfig

func (s *Service) GetConfig() *config.Config

GetConfig returns the current configuration.

func (*Service) GetCurrentSlot

func (s *Service) GetCurrentSlot() phase0.Slot

GetCurrentSlot returns the current slot.

func (*Service) GetELClientVersion

func (s *Service) GetELClientVersion() *ELClientVersion

GetELClientVersion returns the cached EL client identification. Returns nil if the EL has not yet responded or does not support engine_getClientVersionV1.

func (*Service) GetGenesis

func (s *Service) GetGenesis() *beacon.Genesis

GetGenesis returns the genesis information.

func (*Service) GetPayloadCache

func (s *Service) GetPayloadCache() *PayloadCache

GetPayloadCache returns the payload cache for direct access.

func (*Service) GetStats

func (s *Service) GetStats() BuilderStats

GetStats returns the current builder statistics.

func (*Service) IncrementBidsSubmitted

func (s *Service) IncrementBidsSubmitted()

IncrementBidsSubmitted increments the bids submitted counter. Called by the ePBS service when a bid is submitted.

func (*Service) IncrementBlocksIncluded

func (s *Service) IncrementBlocksIncluded()

IncrementBlocksIncluded increments the blocks included and bids won counters. Called by the ePBS service when our payload is included in a beacon block.

func (*Service) IncrementRevealsFailed

func (s *Service) IncrementRevealsFailed()

IncrementRevealsFailed increments the failed reveals counter.

func (*Service) IncrementRevealsSkipped

func (s *Service) IncrementRevealsSkipped()

IncrementRevealsSkipped increments the skipped reveals counter.

func (*Service) IncrementRevealsSuccess

func (s *Service) IncrementRevealsSuccess()

IncrementRevealsSuccess increments the successful reveals counter.

func (*Service) Start

func (s *Service) Start(ctx context.Context) error

Start initializes and starts the builder service.

func (*Service) Stop

func (s *Service) Stop()

Stop stops the builder service.

func (*Service) SubscribePayloadBuildFailed

func (s *Service) SubscribePayloadBuildFailed(
	capacity int,
) *utils.Subscription[*PayloadBuildFailedEvent]

SubscribePayloadBuildFailed subscribes to payload build failed events. Consumers (like the WebUI) use this to mark in-progress builds as failed.

func (*Service) SubscribePayloadBuildStarted

func (s *Service) SubscribePayloadBuildStarted(
	capacity int,
) *utils.Subscription[*PayloadBuildStartedEvent]

SubscribePayloadBuildStarted subscribes to payload build started events. Consumers (like the WebUI) use this to render builds as in-progress.

func (*Service) SubscribePayloadReady

func (s *Service) SubscribePayloadReady(capacity int) *utils.Subscription[*Payload]

SubscribePayloadReady subscribes to payload ready events. Consumers (like the ePBS service) use this to receive built payloads.

func (*Service) UpdateConfig

func (s *Service) UpdateConfig(cfg *config.Config) error

UpdateConfig updates the service configuration at runtime.

type SlotManager

type SlotManager struct {
	// contains filtered or unexported fields
}

SlotManager handles slot scheduling decisions.

func NewSlotManager

func NewSlotManager(cfg *config.Config) *SlotManager

NewSlotManager creates a new slot manager.

func (*SlotManager) GetCurrentSlot

func (m *SlotManager) GetCurrentSlot() phase0.Slot

GetCurrentSlot returns the current slot.

func (*SlotManager) GetSlotsBuilt

func (m *SlotManager) GetSlotsBuilt() uint64

GetSlotsBuilt returns the number of slots built.

func (*SlotManager) GetSlotsRemaining

func (m *SlotManager) GetSlotsRemaining() int

GetSlotsRemaining returns the number of slots remaining to build. Returns -1 if unlimited.

func (*SlotManager) OnSlotBuilt

func (m *SlotManager) OnSlotBuilt(slot phase0.Slot)

OnSlotBuilt records that a slot was built.

func (*SlotManager) ShouldBuildForSlot

func (m *SlotManager) ShouldBuildForSlot(slot phase0.Slot) bool

ShouldBuildForSlot returns true if we should build for the given slot.

func (*SlotManager) UpdateConfig

func (m *SlotManager) UpdateConfig(cfg *config.Config)

UpdateConfig updates the slot manager configuration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL