Documentation
¶
Overview ¶
Package p2p_bidder implements the active p2p bidding flow of ePBS (bid windows, bid submission, competitor tracking, registration state).
Index ¶
- Constants
- func RegistrationStateName(state int32) string
- type BidCreator
- type BidSubmissionEvent
- type BidTracker
- func (t *BidTracker) Cleanup(olderThan phase0.Slot)
- func (t *BidTracker) GetHighestBid(slot phase0.Slot) *TrackedBid
- func (t *BidTracker) GetHighestCompetitorBid(slot phase0.Slot, parentHash phase0.Hash32) (uint64, bool)
- func (t *BidTracker) GetOurBid(slot phase0.Slot) *TrackedBid
- func (t *BidTracker) GetSlotBids(slot phase0.Slot) *SlotBids
- func (t *BidTracker) IsOurs(builderIndex uint64) bool
- func (t *BidTracker) TrackBid(bid *ExecutionPayloadBid, isOurs bool)
- type ExecutionPayloadBid
- type Scheduler
- func (s *Scheduler) Cleanup(olderThan phase0.Slot)
- func (s *Scheduler) GetBidTracker() *BidTracker
- func (s *Scheduler) OnHeadChange(ctx context.Context, change *chain.HeadChangeEvent)
- func (s *Scheduler) OnHeadEvent(event *beacon.HeadEvent)
- func (s *Scheduler) ProcessTick(ctx context.Context)
- func (s *Scheduler) Wait()
- type Service
- func (s *Service) FireBidSubmission(event *BidSubmissionEvent)
- func (s *Service) GetBidTracker() *BidTracker
- func (s *Service) GetBuilderIndex() uint64
- func (s *Service) GetBuilderPubkey() phase0.BLSPubKey
- func (s *Service) GetRegistrationState() int32
- func (s *Service) IsActive() bool
- func (s *Service) IsEnabled() bool
- func (s *Service) IsRegistered() bool
- func (s *Service) RefreshRegistrationState()
- func (s *Service) Registry() *builder_keys.Registry
- func (s *Service) SetBuilderRegistered(index uint64)
- func (s *Service) SetEnabled(enabled bool)
- func (s *Service) SetRegistrationPending()
- func (s *Service) Start(ctx context.Context, builderSvc *payload_builder.Service) error
- func (s *Service) Stop()
- func (s *Service) SubscribeBidSubmissions(capacity int, blocking bool) *utils.Subscription[*BidSubmissionEvent]
- type SlotBids
- type SlotState
- type TrackedBid
Constants ¶
const ( RegistrationStateUnknown int32 = 0 // Not checked yet RegistrationStatePending int32 = 1 // Deposit submitted, waiting for inclusion in beacon state RegistrationStateRegistered int32 = 2 // Builder registered and deposit epoch finalized RegistrationStateWaitingGloas int32 = 3 // Waiting for Gloas fork activation RegistrationStatePendingFinalization int32 = 4 // Builder in beacon state but deposit epoch not finalized RegistrationStateExiting int32 = 5 // Exit submitted, withdrawable epoch set but not reached RegistrationStateExited int32 = 6 // Withdrawable epoch passed, builder has exited RegistrationStateUnregistered int32 = 7 // Builder not in beacon state and no deposit in progress )
Registration state constants for the p2p bidder service.
const ( // BidStatusSubmitted means the bid was constructed and gossiped. BidStatusSubmitted = "submitted" // BidStatusConstructed means the bid was built and signed, but the network // submission failed. BidStatusConstructed = "constructed" // BidStatusFailed means bid construction itself failed. BidStatusFailed = "failed" )
Bid submission statuses reported via BidSubmissionEvent.Status.
Variables ¶
This section is empty.
Functions ¶
func RegistrationStateName ¶
RegistrationStateName returns the string name for a registration state.
Types ¶
type BidCreator ¶
type BidCreator struct {
// contains filtered or unexported fields
}
BidCreator builds ePBS bids via the shared payload_bidder and gossips them over p2p. It owns the p2p transport and the (caller-computed) bid economics; the bid construction and signing live in payload_bidder. The builder identity comes in per bid: which of the managed keys signs is a scheduler decision.
func NewBidCreator ¶
func NewBidCreator( clClient bidSubmitter, chainSvc chain.Service, log logrus.FieldLogger, ) *BidCreator
NewBidCreator creates a new bid creator.
func (*BidCreator) CreateAndSubmitBid ¶
func (c *BidCreator) CreateAndSubmitBid( ctx context.Context, key *builder_keys.Key, payload *payload_builder.Payload, bidValue uint64, bidTransform string, ) (*eth2all.SignedExecutionPayloadBid, error)
CreateAndSubmitBid builds, signs, and gossips a bid for the given payload at the supplied value, from the given builder key. The competitive bid value is decided by the scheduler; the ePBS p2p path takes no execution payment. The constructed signed bid is returned even when the network submission fails so callers can record the exact object that was built; it is nil only when construction itself failed.
type BidSubmissionEvent ¶
type BidSubmissionEvent struct {
Slot phase0.Slot
BlockHash [32]byte
Value uint64
BidCount int
Success bool
Warning string // Non-fatal warning (e.g. "no proposer preferences")
Error string
// Status is one of BidStatusSubmitted/BidStatusConstructed/BidStatusFailed
// for submission attempts (empty for pre-construction skip events).
Status string
// SignedBid is the constructed signed bid; nil when construction failed
// (or for pre-construction skip events).
SignedBid *eth2all.SignedExecutionPayloadBid
// CompetitorHighGwei is the highest competitor bid known for the slot at
// fire time (our own builder index excluded); nil when none is known.
CompetitorHighGwei *uint64
}
BidSubmissionEvent represents a bid submission attempt (success or failure).
type BidTracker ¶
type BidTracker struct {
// contains filtered or unexported fields
}
BidTracker tracks bids observed on the p2p network for competition analysis.
func NewBidTracker ¶
func NewBidTracker(registry *builder_keys.Registry, log logrus.FieldLogger) *BidTracker
NewBidTracker creates a new bid tracker. The key registry identifies which gossiped bids are ours: with several managed keys bidding the same slot, any of their builder indices must be excluded from competitor comparisons.
func (*BidTracker) Cleanup ¶
func (t *BidTracker) Cleanup(olderThan phase0.Slot)
Cleanup removes old slot data.
func (*BidTracker) GetHighestBid ¶
func (t *BidTracker) GetHighestBid(slot phase0.Slot) *TrackedBid
GetHighestBid returns the highest bid for a slot.
func (*BidTracker) GetHighestCompetitorBid ¶ added in v0.0.3
func (t *BidTracker) GetHighestCompetitorBid( slot phase0.Slot, parentHash phase0.Hash32, ) (uint64, bool)
GetHighestCompetitorBid returns the highest tracked bid value (gwei) for the slot excluding every key of ours, and whether any competitor bid is known. Unlike GetHighestBid it can never report one of our own bids back to us — which matters once several managed keys bid the same slot. A non-zero parentHash restricts the comparison to bids committing to the same execution parent (bids on other forks are not competing).
func (*BidTracker) GetOurBid ¶
func (t *BidTracker) GetOurBid(slot phase0.Slot) *TrackedBid
GetOurBid returns our bid for a slot.
func (*BidTracker) GetSlotBids ¶
func (t *BidTracker) GetSlotBids(slot phase0.Slot) *SlotBids
GetSlotBids returns all bids for a slot.
func (*BidTracker) IsOurs ¶ added in v0.0.3
func (t *BidTracker) IsOurs(builderIndex uint64) bool
IsOurs reports whether a gossiped bid's builder index belongs to the managed key set.
func (*BidTracker) TrackBid ¶
func (t *BidTracker) TrackBid(bid *ExecutionPayloadBid, isOurs bool)
TrackBid adds a bid to the tracker.
type ExecutionPayloadBid ¶
type ExecutionPayloadBid struct {
ParentBlockHash phase0.Hash32
ParentBlockRoot phase0.Root
BlockHash phase0.Hash32
FeeRecipient [20]byte
GasLimit uint64
BuilderIndex uint64
Slot phase0.Slot
Value uint64 // Gwei
ExecutionPayment uint64 // Gwei
}
ExecutionPayloadBid represents a bid for an execution payload.
type Scheduler ¶
type Scheduler struct {
// contains filtered or unexported fields
}
Scheduler handles time-based bid scheduling. It uses a simple loop that checks current time and triggers actions.
func NewScheduler ¶
func NewScheduler( chainSvc chain.Service, bidCreator *BidCreator, bidTracker *BidTracker, payloadCache *payload_builder.PayloadCache, service *Service, registry *builder_keys.Registry, propPrefsStore *memstore.Store[phase0.Slot, *gloasspec.SignedProposerPreferences], planSvc *action_plan.PlanService, cfg *config.Config, log logrus.FieldLogger, ) *Scheduler
NewScheduler creates a new scheduler. planSvc is the mandatory per-slot action plan service: every bid setting the scheduler acts on comes from its frozen slot snapshots, never from the live config — except the bid candidate selection, which is deliberately live (the whole point is choosing at bid time, after the plan froze).
func (*Scheduler) GetBidTracker ¶
func (s *Scheduler) GetBidTracker() *BidTracker
GetBidTracker returns the bid tracker.
func (*Scheduler) OnHeadChange ¶ added in v0.0.3
func (s *Scheduler) OnHeadChange(ctx context.Context, change *chain.HeadChangeEvent)
OnHeadChange reopens bidding for slots whose closing block was reorged out: with the block gone, the slot's proposer opportunity is live again for the rest of its bid window.
func (*Scheduler) OnHeadEvent ¶
OnHeadEvent closes bidding for the slot — once a block is produced, no more bids can make it.
func (*Scheduler) ProcessTick ¶
ProcessTick is called frequently to check if any bids are due.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the p2p bidder orchestrator that handles time-scheduled bidding. It submits bids during the slot's bid window, tracks competitor bids from the gossip stream, and maintains the builder's registration state. Once a slot's block is produced (head event), the bidder is done with that slot — reveals, inclusion tracking, and payment accounting live in the shared payload_bidder services.
func NewService ¶
func NewService( clClient *beacon.Client, chainSvc chain.Service, registry *builder_keys.Registry, propPrefsStore *memstore.Store[phase0.Slot, *gloasspec.SignedProposerPreferences], planSvc *action_plan.PlanService, log logrus.FieldLogger, ) (*Service, error)
NewService creates a new p2p bidder service. propPrefsStore is the shared per-slot proposer preferences store (owned by payload_bidder.ProposerPreferencesService); it gates bidding — slots without a cached preference are skipped. It may be nil, in which case no bids are submitted. planSvc is the mandatory per-slot action plan service — the single scheduling/settings authority: the scheduler freezes each slot's plan on first evaluation and the frozen snapshot alone decides whether and how the slot is bid on (a plan may activate bidding for a slot even when ePBS is globally disabled).
func (*Service) FireBidSubmission ¶
func (s *Service) FireBidSubmission(event *BidSubmissionEvent)
FireBidSubmission fires a bid submission event.
func (*Service) GetBidTracker ¶
func (s *Service) GetBidTracker() *BidTracker
GetBidTracker returns the bid tracker.
func (*Service) GetBuilderIndex ¶
GetBuilderIndex returns the primary key's on-chain builder index (0 when it is not registered). Status reporting only — bids carry the index of the key that signed them.
func (*Service) GetBuilderPubkey ¶
GetBuilderPubkey returns the primary key's public key.
func (*Service) GetRegistrationState ¶
GetRegistrationState returns the current registration state.
func (*Service) IsActive ¶
IsActive returns whether the builder can actively participate (registered or pending finalization).
func (*Service) IsEnabled ¶
IsEnabled returns whether the p2p bidder service is enabled (status reporting only; not consulted by the bid scheduler).
func (*Service) IsRegistered ¶
IsRegistered returns whether the builder has a valid index and its deposit is finalized.
func (*Service) RefreshRegistrationState ¶
func (s *Service) RefreshRegistrationState()
RefreshRegistrationState re-evaluates the registration state from the chain service. Called periodically to detect state transitions (e.g. finalization, exit).
func (*Service) Registry ¶ added in v0.0.3
func (s *Service) Registry() *builder_keys.Registry
Registry returns the managed builder key set.
func (*Service) SetBuilderRegistered ¶
SetBuilderRegistered re-evaluates the reported registration state when the lifecycle manager detects a registration. The builder index itself lives on the key registry; this only drives the status reporting.
func (*Service) SetEnabled ¶
SetEnabled sets the enabled state of the p2p bidder service. The flag is status reporting only (WebUI/API); the per-slot bid decision comes solely from the action plan's frozen snapshots.
func (*Service) SetRegistrationPending ¶
func (s *Service) SetRegistrationPending()
SetRegistrationPending marks the builder as having a deposit in flight. Called by the lifecycle manager when a deposit is submitted.
A deposit only says something about the key it funds. Once any key of the fleet is active the builder can bid, so a deposit for some other key must not pull the reported state back to pending — the scheduler gates bidding on it, and a fleet ramping toward its target deposits continuously, which would otherwise suppress bidding for the whole ramp.
func (*Service) SubscribeBidSubmissions ¶
func (s *Service) SubscribeBidSubmissions(capacity int, blocking bool) *utils.Subscription[*BidSubmissionEvent]
SubscribeBidSubmissions subscribes to bid submission events. Blocking subscriptions never drop events (authoritative consumers, e.g. the slot results tracker); non-blocking ones drop on a full buffer (e.g. the WebUI SSE bridge).
type SlotBids ¶
type SlotBids struct {
Slot phase0.Slot
Bids map[uint64]*TrackedBid // BuilderIndex -> Bid
HighestBid *TrackedBid
OurBid *TrackedBid
WinningBid *TrackedBid // Set after block inclusion
}
SlotBids holds all bids for a specific slot.
func NewSlotBids ¶
NewSlotBids creates a new SlotBids instance for the given slot.
type SlotState ¶
type SlotState struct {
LastBidTime time.Time
LastBidHash phase0.Hash32
BidCount int
BidsClosed bool // Block received, no more bids possible
ClosedByRoot phase0.Root // block root that closed bidding (reopens if orphaned)
NoPrefsWarnedFor bool // Missing-preferences skip already reported for this slot
NoKeyWarnedFor bool // No-ready-key skip already reported for this slot
// PayloadBids tracks each payload's own bid progress, so multi-candidate
// bidding ("all") does not starve the other candidates behind one payload's
// interval gate.
PayloadBids map[phase0.Hash32]*payloadBidState
// BidCandidate is the candidate the auto selection committed to on the
// first bid of the slot (sticky unless candidate switching is enabled).
BidCandidate chain.CandidateKey
BidCandidateSet bool
// UsedKeys holds the keys that already gossiped a bid for this slot. The
// gossip rules ignore every bid a builder makes after its first for a slot,
// so a key is SPENT once one of its bids reached the network — every later
// bid, including an escalated re-bid of the very same payload, has to come
// from a key that has not bid yet or it never propagates.
UsedKeys map[uint64]struct{}
// Frozen is the slot's immutable action-plan snapshot, resolved on the
// first scheduler evaluation of the slot (nil until then).
Frozen *action_plan.FrozenPlan
}
SlotState tracks the bidding state for a single slot.
type TrackedBid ¶
type TrackedBid struct {
Bid *ExecutionPayloadBid
BuilderIndex uint64
ReceivedAt time.Time
IsOurs bool
}
TrackedBid represents a bid being tracked for competition analysis.