payload_bidder

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: 26 Imported by: 0

Documentation

Overview

Package payload_bidder holds the shared, transport-independent mechanics for post-Gloas builder participation: constructing and signing execution payload bids and the corresponding execution payload envelope (reveal). Both the ePBS p2p submitter and the HTTP Builder API build on it; each supplies its own economics (bid value, execution payment) while the construction, hash-tree- root (always via dynamic-ssz so preset-dependent sizes resolve), signing domain, and fork handling live here.

Everything is fork-agnostic: bids and envelopes use the go-eth2-client spec/all union types and read the active fork from the payload, so adding a future fork is confined to the spec/all view tables.

Index

Constants

View Source
const (
	WonBlockSourceBuilderAPI = "builder_api"
	WonBlockSourceEPBS       = "epbs"
)

WonBlockSource identifies which subsystem delivered a won block.

View Source
const ProposerPreferencesNamespace = "proposer_preferences"

ProposerPreferencesNamespace is the kv_store namespace holding the cached proposer preferences.

View Source
const WonBlocksNamespace = "won_blocks"

WonBlocksNamespace is the kv_store namespace holding the persisted won-block records, owned by the InclusionTracker.

Variables

View Source
var DomainBeaconBuilder = phase0.DomainType{0x0B, 0x00, 0x00, 0x00}

DomainBeaconBuilder is DOMAIN_BEACON_BUILDER — the signing domain for execution payload bids and execution payload envelopes.

Functions

func BuildSignedBid

func BuildSignedBid(
	p *payload_builder.Payload,
	params BidParams,
	s *Signer,
	forkVersion phase0.Version,
	genesisValidatorsRoot phase0.Root,
) (*eth2all.SignedExecutionPayloadBid, error)

BuildSignedBid constructs and signs a fork-agnostic SignedExecutionPayloadBid for the given payload. The fork is read from the payload; all payload-derived fields (parent hashes, block hash, randao, gas limit, commitments, execution requests root, slot) are filled here, and only the transport's economics + identity come in via params.

func BuildSignedEnvelope

func BuildSignedEnvelope(
	p *payload_builder.Payload,
	rc RevealContext,
	s *Signer,
	forkVersion phase0.Version,
	genesisValidatorsRoot phase0.Root,
) (signed *eth2all.SignedExecutionPayloadEnvelope, blobs, proofs [][]byte, err error)

BuildSignedEnvelope constructs and signs a fork-agnostic SignedExecutionPayloadEnvelope for the given payload, and returns the blobs and KZG proofs to publish alongside it. The fork-agnostic envelope embeds the canonical payload directly (no per-fork conversion needed).

Types

type BidParams

type BidParams struct {
	BuilderIndex     uint64
	FeeRecipient     bellatrix.ExecutionAddress
	Value            phase0.Gwei
	ExecutionPayment phase0.Gwei
}

BidParams are the policy-decided inputs a transport supplies for a bid. The transport owns the economics (value, execution payment) and identity (builder index, fee recipient); every other bid field is derived from the payload.

type InclusionTracker added in v0.0.2

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

InclusionTracker watches head events and detects inclusion of our payloads. It records the payment obligation, requests the payload reveal, records won blocks (it is the single owner of won-block records, covering both flows and all forks), and checks the follow-up block to detect orphaned (unrevealed) payloads. Shared by both the p2p and Builder API flows.

func NewInclusionTracker added in v0.0.2

func NewInclusionTracker(
	clClient *beacon.Client,
	chainSvc chain.Service,
	builderSvc *payload_builder.Service,
	revealSvc *RevealService,
	payments *PaymentTracker,
	log logrus.FieldLogger,
) *InclusionTracker

NewInclusionTracker creates a new inclusion tracker. revealSvc and payments may be nil (pre-Gloas networks); the tracker then only persists won blocks and fires inclusion events.

func (*InclusionTracker) GetWonBlocks added in v0.0.2

func (t *InclusionTracker) GetWonBlocks(offset, limit int) ([]*WonBlock, int)

GetWonBlocks returns a page of won-block records sorted by slot descending (newest first) plus the total record count.

func (*InclusionTracker) SetStateDB added in v0.0.2

func (t *InclusionTracker) SetStateDB(stateDB *db.Database)

SetStateDB sets the optional state-db used to persist won blocks (attached to the won-block store on Start). When unset, won blocks are kept in memory only.

func (*InclusionTracker) Start added in v0.0.2

func (t *InclusionTracker) Start(ctx context.Context) error

Start starts the inclusion tracker's main loop. When a state-db was set it first attaches the won-block store's persistence, rehydrating wins recorded in prior runs.

func (*InclusionTracker) Stop added in v0.0.2

func (t *InclusionTracker) Stop()

Stop stops the inclusion tracker, waits for the main loop to exit, and flushes the won-block store. Must run before the state-db closes (run.go registers the tracker's Stop defer after the state-db's close defer, so LIFO ordering guarantees this).

func (*InclusionTracker) SubscribeIncluded added in v0.0.2

func (t *InclusionTracker) SubscribeIncluded(capacity int) *utils.Subscription[*PayloadIncludedEvent]

SubscribeIncluded subscribes to payload inclusion events.

type PayloadIncludedEvent added in v0.0.2

type PayloadIncludedEvent struct {
	Payload      *payload_builder.Payload
	BlockInfo    *beacon.BlockInfo
	BidValueGwei uint64
	WonBlock     *WonBlock // the recorded won-block entry for this inclusion
}

PayloadIncludedEvent is fired when a beacon block committing to one of our payloads is observed at the head (consumed by the WebUI).

type PaymentTracker added in v0.0.2

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

PaymentTracker tracks the builder's payment obligations and live balance adjustments across both bid flows (p2p and Builder API). Fed by the InclusionTracker (won bids) and RevealService (reveals); consumed by the lifecycle manager (top-ups) and the WebUI. Passive and thread-safe: it runs no goroutine of its own.

func NewPaymentTracker added in v0.0.2

func NewPaymentTracker(chainSvc chain.Service, log logrus.FieldLogger) *PaymentTracker

NewPaymentTracker creates a new payment tracker.

func (*PaymentTracker) AddDeposit added in v0.0.2

func (t *PaymentTracker) AddDeposit(amount uint64)

AddDeposit adds a deposit/topup amount to the balance adjustment. Topups take effect immediately (no finalization delay).

func (*PaymentTracker) GetBalanceAdjustment added in v0.0.2

func (t *PaymentTracker) GetBalanceAdjustment() int64

GetBalanceAdjustment returns the cumulative balance adjustment since last state refresh.

func (*PaymentTracker) GetTotalPendingPayments added in v0.0.2

func (t *PaymentTracker) GetTotalPendingPayments() uint64

GetTotalPendingPayments returns the sum of unrevealed won bid obligations.

func (*PaymentTracker) MarkRevealed added in v0.0.2

func (t *PaymentTracker) MarkRevealed(slot phase0.Slot)

MarkRevealed moves a won bid from pending to an immediate balance deduction. The payment is removed from pending and subtracted from the balance adjustment.

func (*PaymentTracker) PruneExpiredPayments added in v0.0.2

func (t *PaymentTracker) PruneExpiredPayments(currentEpoch phase0.Epoch)

PruneExpiredPayments removes pending payments older than 2 epochs.

func (*PaymentTracker) RecordWonBid added in v0.0.2

func (t *PaymentTracker) RecordWonBid(slot phase0.Slot, value uint64)

RecordWonBid records a won bid as a pending payment (unrevealed). Called when our bid is included in a beacon block. If we later reveal, call MarkRevealed to move it from pending to a balance deduction. If we don't reveal, it stays pending for 2 epochs then expires.

func (*PaymentTracker) ResetBalanceAdjustment added in v0.0.2

func (t *PaymentTracker) ResetBalanceAdjustment()

ResetBalanceAdjustment resets the adjustment to 0. Called when the chain state refreshes and the balance is up to date.

type PendingPayment added in v0.0.2

type PendingPayment struct {
	Slot  phase0.Slot
	Epoch phase0.Epoch
	Value uint64 // Gwei
}

PendingPayment records an unrevealed won bid that may be deducted later.

type ProposerPreferencesCodec added in v0.0.2

type ProposerPreferencesCodec struct{}

ProposerPreferencesCodec translates the proposer preference store's entries to their persisted form: decimal slot string keys, SSZ-encoded values.

func (ProposerPreferencesCodec) DecodeKey added in v0.0.2

func (ProposerPreferencesCodec) DecodeKey(key string) (phase0.Slot, error)

DecodeKey parses a decimal slot string.

func (ProposerPreferencesCodec) DecodeValue added in v0.0.2

DecodeValue SSZ-decodes a signed proposer preference.

func (ProposerPreferencesCodec) EncodeKey added in v0.0.2

func (ProposerPreferencesCodec) EncodeKey(slot phase0.Slot) string

EncodeKey encodes a slot as its decimal string form.

func (ProposerPreferencesCodec) EncodeValue added in v0.0.2

EncodeValue SSZ-encodes a signed proposer preference.

type ProposerPreferencesService added in v0.0.2

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

ProposerPreferencesService listens to the beacon node's proposer_preferences SSE topic, caches the first valid preference per slot, prunes old slots on epoch transitions, and resolves proposer settings for Gloas+ payload builds (it implements payload_builder.ProposerSettingsResolver).

func NewProposerPreferencesService added in v0.0.2

func NewProposerPreferencesService(clClient *beacon.Client, chainSvc chain.Service,
	log logrus.FieldLogger) *ProposerPreferencesService

NewProposerPreferencesService creates a new proposer preferences service. The backing store keeps the first valid preference per slot (subsequent preferences for the same slot are ignored).

func (*ProposerPreferencesService) GetStore added in v0.0.2

GetStore returns the underlying per-slot preference store for direct access (bid gating, bid construction, WebUI listing).

func (*ProposerPreferencesService) ResolveProposerSettings added in v0.0.2

ResolveProposerSettings resolves the proposer's announced settings for a build from the cached gossip preference. Self-scoped: it only applies from the Gloas fork onwards and returns false when no preference is cached for the slot.

func (*ProposerPreferencesService) Start added in v0.0.2

Start subscribes to the proposer_preferences SSE topic and to epoch stats (for pruning) and begins processing events in the service's own loop.

func (*ProposerPreferencesService) Stop added in v0.0.2

func (s *ProposerPreferencesService) Stop()

Stop stops the service and waits for the main loop to exit.

type RevealContext

type RevealContext struct {
	BuilderIndex          uint64
	BeaconBlockRoot       phase0.Root
	ParentBeaconBlockRoot phase0.Root
}

RevealContext are the inputs a transport supplies for a payload reveal that aren't carried by the payload: the builder index and the beacon block roots the envelope is bound to.

type RevealRequest added in v0.0.2

type RevealRequest struct {
	Payload   *payload_builder.Payload
	BlockInfo *beacon.BlockInfo // root + parent root of the committing beacon block
	Transport payload_builder.BidTransport
}

RevealRequest asks the RevealService to publish a payload's envelope at the configured reveal time. Both flows submit these; the service dedupes by slot.

type RevealResult added in v0.0.2

type RevealResult struct {
	Slot        phase0.Slot
	Transport   payload_builder.BidTransport
	Success     bool
	Skipped     bool   // request arrived after the slot's reveal deadline
	Error       string // failure reason (when Success is false)
	Attempt     int    // 1-based
	MaxAttempts int
}

RevealResult reports the outcome of a reveal attempt.

type RevealService added in v0.0.2

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

RevealService publishes execution payload envelopes at the slot-relative reveal time. It runs its own main loop: requests arrive on a channel, due times are awaited with a timer (no polling), reveals are deduped per slot (the first request wins regardless of transport), and failed publishes are retried a bounded number of times. It is independent of the p2p bidder and Builder API modules and their enable flags.

func NewRevealService added in v0.0.2

func NewRevealService(
	cfg *config.Config,
	signer *Signer,
	publisher envelopePublisher,
	chainSvc chain.Service,
	builderSvc *payload_builder.Service,
	payments *PaymentTracker,
	log logrus.FieldLogger,
) *RevealService

NewRevealService creates a new reveal service.

func (*RevealService) RequestReveal added in v0.0.2

func (s *RevealService) RequestReveal(req *RevealRequest)

RequestReveal enqueues a reveal request; non-blocking: a full queue is logged and dropped (at most one reveal per slot, so the 16 buffer is generous).

func (*RevealService) SetBuilderIndex added in v0.0.2

func (s *RevealService) SetBuilderIndex(index uint64)

SetBuilderIndex updates the builder index used when signing envelopes.

func (*RevealService) Start added in v0.0.2

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

Start starts the reveal service's main loop.

func (*RevealService) Stop added in v0.0.2

func (s *RevealService) Stop()

Stop stops the reveal service and waits for the main loop to exit.

func (*RevealService) SubscribeResults added in v0.0.2

func (s *RevealService) SubscribeResults(capacity int) *utils.Subscription[*RevealResult]

SubscribeResults subscribes to reveal results (consumed by the WebUI).

type Signer

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

Signer signs execution payload bids and envelopes with the builder's BLS key.

func NewSigner

func NewSigner(blsSigner *signer.BLSSigner) *Signer

NewSigner creates a new payload bidder signer.

func (*Signer) SignBid

func (s *Signer) SignBid(
	bid *eth2all.ExecutionPayloadBid,
	forkVersion phase0.Version,
	genesisValidatorsRoot phase0.Root,
) (phase0.BLSSignature, error)

SignBid signs an execution payload bid. forkVersion must be the fork version the consensus client verifies against (the Gloas fork version).

func (*Signer) SignEnvelope

func (s *Signer) SignEnvelope(
	envelope *eth2all.ExecutionPayloadEnvelope,
	forkVersion phase0.Version,
	genesisValidatorsRoot phase0.Root,
) (phase0.BLSSignature, error)

SignEnvelope signs an execution payload envelope.

type WonBlock added in v0.0.2

type WonBlock struct {
	Source          string `json:"source"`
	Slot            uint64 `json:"slot"`
	BlockHash       string `json:"block_hash"`
	NumTransactions int    `json:"num_transactions"`
	NumBlobs        int    `json:"num_blobs"`
	ValueWei        string `json:"value_wei"`
	ValueETH        string `json:"value_eth"`
	Timestamp       int64  `json:"timestamp"` // Unix milliseconds at inclusion time
}

WonBlock is a block of ours that was included in a beacon block, won via either the Builder API or p2p ePBS bidding. The JSON tags are the wire shape consumed by the WebUI (bids-won REST endpoint and bid_won SSE event) — do not change them.

type WonBlockCodec added in v0.0.2

type WonBlockCodec struct{}

WonBlockCodec translates the won-block store's entries to their persisted form: decimal slot string keys, JSON-encoded values. JSON is deliberate: WonBlock is a local aggregate (not a spec SSZ type), and the kv_store value is an opaque blob either way.

func (WonBlockCodec) DecodeKey added in v0.0.2

func (WonBlockCodec) DecodeKey(key string) (phase0.Slot, error)

DecodeKey parses a decimal slot string.

func (WonBlockCodec) DecodeValue added in v0.0.2

func (WonBlockCodec) DecodeValue(value []byte) (*WonBlock, error)

DecodeValue JSON-decodes a won block.

func (WonBlockCodec) EncodeKey added in v0.0.2

func (WonBlockCodec) EncodeKey(slot phase0.Slot) string

EncodeKey encodes a slot as its decimal string form.

func (WonBlockCodec) EncodeValue added in v0.0.2

func (WonBlockCodec) EncodeValue(wonBlock *WonBlock) ([]byte, error)

EncodeValue JSON-encodes a won block.

Jump to

Keyboard shortcuts

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