config

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 24, 2026 License: GPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package config handles configuration loading and validation for buildoor.

Index

Constants

View Source
const (
	SourceDefault = "default"
	SourceCLI     = "cli"
	SourceUI      = "ui"
)

Source identifies which layer currently wins for a setting.

View Source
const (
	KeyScheduleMode      = "schedule.mode"
	KeyScheduleEveryNth  = "schedule.every_nth"
	KeyScheduleNextN     = "schedule.next_n"
	KeyScheduleStartSlot = "schedule.start_slot"

	KeyEPBSBuildStartTime = "epbs.build_start_time"
	KeyEPBSBidStartTime   = "epbs.bid_start_time"
	KeyEPBSBidEndTime     = "epbs.bid_end_time"
	KeyEPBSRevealTime     = "epbs.reveal_time"
	KeyEPBSBidMinAmount   = "epbs.bid_min_amount"
	KeyEPBSBidIncrease    = "epbs.bid_increase"
	KeyEPBSBidInterval    = "epbs.bid_interval"
	KeyEPBSBidSubsidy     = "epbs.bid_subsidy"

	KeyPayloadBuildTime  = "payload_build_time"
	KeyExtraData         = "extra_data"
	KeyBuilderAPISubsidy = "builder_api.block_value_subsidy_gwei"

	KeyDepositAmount  = "deposit_amount"
	KeyTopupThreshold = "topup_threshold"
	KeyTopupAmount    = "topup_amount"

	KeyEPBSEnabled       = "epbs_enabled"
	KeyBuilderAPIEnabled = "builder_api_enabled"
	KeyLifecycleEnabled  = "lifecycle_enabled"
)

Canonical settings keys. These are the persisted/override keys and are shared between the field registry (fields.go) and the API handlers that apply UI overrides, so the two never drift.

Variables

This section is empty.

Functions

This section is empty.

Types

type BuilderAPIConfig

type BuilderAPIConfig struct {
	// BuilderURL is this builder's publicly reachable URL (e.g. "https://builder.example.com").
	// Used to verify the auth.message.data field (set to the builder URL) in
	// SignedRequestAuthV1 messages from proposers. If empty, this validation is skipped.
	BuilderURL string `yaml:"builder_url" json:"builder_url"`

	// RequireRequestAuth controls whether a SignedRequestAuthV1 body is mandatory on
	// getExecutionPayloadBid requests. When true, requests without an auth body are
	// rejected with 401. When false (default), auth is optional — but if supplied it
	// is always fully validated.
	RequireRequestAuth bool `yaml:"require_request_auth" json:"require_request_auth"`

	// BlockValueSubsidyGwei is added to the bid value so the proposer sees a higher bid:
	// to the getHeader bid value in the Fulu Builder API, and to the block value that
	// forms bid.ExecutionPayment/Value in Gloas getExecutionPayloadBid calls.
	BlockValueSubsidyGwei uint64 `yaml:"block_value_subsidy_gwei" json:"block_value_subsidy_gwei"`
}

BuilderAPIConfig defines configuration for the traditional Builder API (pre-ePBS).

type BuilderState

type BuilderState struct {
	Pubkey            []byte
	Index             uint64
	IsRegistered      bool
	Balance           uint64 // Gwei
	DepositEpoch      uint64
	WithdrawableEpoch uint64
}

BuilderState represents the current state of a builder in the beacon chain.

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 Config

type Config struct {
	BuilderPrivkey string `yaml:"builder_privkey" json:"builder_privkey,omitempty"`
	// BuilderMnemonic, when set, derives the builder BLS key from this BIP-39 mnemonic and
	// BuilderKeyIndex using the standard validator key path m/12381/3600/{index}/0/0.
	// Mutually exclusive with BuilderPrivkey. json:"-" keeps the secret out of every JSON
	// serialization path (WebUI REST + SSE); YAML config loading is unaffected.
	BuilderMnemonic   string           `yaml:"builder_mnemonic" json:"-"`
	BuilderKeyIndex   uint64           `yaml:"builder_key_index" json:"builder_key_index"`
	CLClient          string           `yaml:"cl_client" json:"cl_client,omitempty"`
	ELEngineAPI       string           `yaml:"el_engine_api" json:"el_engine_api,omitempty"`   // Engine API URL (required for payload building)
	ELJWTSecret       string           `yaml:"el_jwt_secret" json:"el_jwt_secret,omitempty"`   // Path to JWT secret file for engine API auth
	ELRPC             string           `yaml:"el_rpc" json:"el_rpc,omitempty"`                 // Optional: EL JSON-RPC for transactions (lifecycle only)
	WalletPrivkey     string           `yaml:"wallet_privkey" json:"wallet_privkey,omitempty"` // Optional: only if lifecycle enabled
	APIPort           int              `yaml:"api_port" json:"api_port"`                       // Optional, 0 = disabled
	AuthProviderURL   string           `yaml:"auth_provider_url" json:"auth_provider_url"`     // Optional: authenticatoor URL; when set, API requests must carry a JWT verified against the authenticatoor's JWKS. When empty, the API is unauthenticated.
	InjectHeadHTML    string           `yaml:"inject_head_html" json:"inject_head_html"`       // Optional: raw HTML snippet (e.g. analytics tags) injected into <head> of the served SPA. Falls back to BUILDOOR_INJECT_HEAD_HTML env var when empty.
	OverviewURL       string           `yaml:"overview_url" json:"overview_url"`               // Optional: URL of the multi-instance overview UI. When set, the dashboard renders an "Overview" entry in the top nav so operators get consistent navigation across instances.
	LifecycleEnabled  bool             `yaml:"lifecycle_enabled" json:"lifecycle_enabled"`
	EPBSEnabled       bool             `yaml:"epbs_enabled" json:"epbs_enabled"`               // Initial enabled state for ePBS (service available if Gloas fork is scheduled)
	BuilderAPIEnabled bool             `yaml:"builder_api_enabled" json:"builder_api_enabled"` // Initial enabled state for Builder API
	BuilderAPI        BuilderAPIConfig `yaml:"builder_api" json:"builder_api"`                 // Builder API configuration
	DepositAmount     uint64           `yaml:"deposit_amount" json:"deposit_amount"`           // Gwei, default 10 ETH
	TopupThreshold    uint64           `yaml:"topup_threshold" json:"topup_threshold"`         // Gwei
	TopupAmount       uint64           `yaml:"topup_amount" json:"topup_amount"`               // Gwei
	DepositMaxFeeGwei uint64           `yaml:"deposit_max_fee" json:"deposit_max_fee"`
	Schedule          ScheduleConfig   `yaml:"schedule" json:"schedule"`
	EPBS              EPBSConfig       `yaml:"epbs" json:"epbs"` // Time-scheduled ePBS config
	Debug             bool             `yaml:"debug" json:"debug"`
	Pprof             bool             `yaml:"pprof" json:"pprof"`
	PayloadBuildTime  uint64           `yaml:"payload_build_time" json:"payload_build_time"` // The time given to the EL to build the payload after triggering the payload build via fcu (in ms)
	// ExtraData is the prefix injected into the built payload's extra-data field
	// (then padded with the EL's original extra data, truncated to 32 bytes). Used
	// to mark blocks built by this builder. Defaulted to "buildoor/" when empty.
	ExtraData       string                `yaml:"extra_data" json:"extra_data"`
	ValidatorRanges ValidatorRangesConfig `yaml:"validator_ranges" json:"validator_ranges"`
	// StateDBPath, when set, enables the optional SQLite state-db at this path.
	// It persists UI setting overrides, won blocks, validator registrations,
	// proposer preferences and an audit log across restarts. Startup-only and
	// never itself persisted. Empty disables persistence (in-memory only).
	StateDBPath string `yaml:"state_db" json:"state_db,omitempty"`
}

Config represents the complete configuration for the buildoor application.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a configuration with sensible defaults. Timing fields default to 0, which means "auto-compute from slot time". Call ApplySlotDefaults after loading the chain spec to fill them in.

func (*Config) ApplySlotDefaults

func (c *Config) ApplySlotDefaults(slotTimeMs int64)

ApplySlotDefaults fills in zero-valued timing fields with slot-relative defaults. This is called after the chain spec is loaded so the slot duration is known.

Timing fields are tuned for a 12s slot and scaled linearly to the actual slot time (value = reference@12s * slotTimeMs / 12000):

BuildStartTime:  -2900ms @12s  (e.g. -1450ms @6s)
PayloadBuildTime: 2100ms @12s  (e.g.  1050ms @6s)
BidStartTime:     -400ms @12s  (e.g.  -200ms @6s)
BidEndTime:       -100ms @12s  (e.g.   -50ms @6s)
RevealTime:       7000ms @12s  (e.g.  3500ms @6s)

RevealTime (58.3% of the slot) is anchored to the Gloas/EIP-7732 deadlines: it sits after the attestation-aggregate deadline (AGGREGATE_DUE_BPS_GLOAS, 50%) — so the builder has seen enough attestation weight to know the block is the canonical head before committing to reveal — and comfortably before the hard payload deadline (PAYLOAD_DUE_BPS / PAYLOAD_ATTESTATION_DUE_BPS, 75%), after which the PTC votes the payload absent. The ~17% (2s @12s) margin lets the envelope gossip to PTC members before they attest at 75%.

type EPBSConfig

type EPBSConfig struct {
	// BuildStartTime is milliseconds relative to the proposal slot start when we
	// start building. Negative values mean before the slot starts (e.g. -3000 =
	// 3 seconds before slot start). Positive values mean after slot start.
	// Set to 0 to build immediately when payload_attributes is received.
	// Default: -3000.
	BuildStartTime int64 `yaml:"build_start_time" json:"build_start_time"`

	// BidStartTime is milliseconds relative to slot start for first bid.
	// Can be negative to bid before slot starts.
	BidStartTime int64 `yaml:"bid_start_time" json:"bid_start_time"`

	// BidEndTime is milliseconds relative to slot start for last bid.
	BidEndTime int64 `yaml:"bid_end_time" json:"bid_end_time"`

	// RevealTime is milliseconds relative to slot start for reveal.
	RevealTime int64 `yaml:"reveal_time" json:"reveal_time"`

	// BidMinAmount is the minimum bid amount in gwei.
	// Bids use max(blockValue, BidMinAmount) as the starting bid value.
	BidMinAmount uint64 `yaml:"bid_min_amount" json:"bid_min_amount"`

	// BidIncrease is the amount to increase bid per subsequent bid in gwei.
	BidIncrease uint64 `yaml:"bid_increase" json:"bid_increase"`

	// BidInterval is milliseconds between bids. 0 means single bid.
	BidInterval int64 `yaml:"bid_interval" json:"bid_interval"`

	// BidSubsidy is added to every bid in gwei so the bid clears the proposer's
	// local-EL threshold (the BN otherwise self-builds when its local EL value is higher).
	BidSubsidy uint64 `yaml:"bid_subsidy" json:"bid_subsidy"`
}

EPBSConfig defines time-scheduled bidding parameters for ePBS.

type Field

type Field struct {
	// Key is the canonical persisted/override key, e.g. "epbs.bid_subsidy".
	Key string
	// FlagKey is the viper flag key, e.g. "epbs-bid-subsidy", used with
	// viper.IsSet for CLI-change detection.
	FlagKey string
	// contains filtered or unexported fields
}

Field describes a single mutable setting: how to read and write it on a Config, its canonical storage key, and the viper flag key used to detect operator-supplied (CLI/env/config) changes across restarts.

Only mutable settings are registered. Immutable startup-only fields (keys, client URLs, ports, the state-db path) are intentionally absent: they are never overridable via the UI and never persisted.

func Fields

func Fields() []Field

Fields returns the registry of all mutable settings, including the per-module enable flags (which are configured via CLI flags exactly like other settings and therefore follow the same default/cli/ui resolution).

func (Field) Decode

func (f Field) Decode(raw json.RawMessage) (any, error)

Decode parses a JSON value into the field's Go type.

func (Field) Encode

func (f Field) Encode(v any) (json.RawMessage, error)

Encode serialises a typed value to JSON for storage.

func (Field) Equal

func (f Field) Equal(a, b any) bool

Equal reports whether two typed values of this field are equal.

func (Field) Get

func (f Field) Get(c *Config) any

Get reads the field's value from c.

func (Field) Set

func (f Field) Set(c *Config, v any) error

Set writes v into the field on c (in place).

type ScheduleConfig

type ScheduleConfig struct {
	Mode      ScheduleMode `yaml:"mode" json:"mode"`             // all, every_nth, next_n
	EveryNth  uint64       `yaml:"every_nth" json:"every_nth"`   // For every_nth mode
	NextN     uint64       `yaml:"next_n" json:"next_n"`         // For next_n mode
	StartSlot uint64       `yaml:"start_slot" json:"start_slot"` // Optional start slot
}

ScheduleConfig defines when the builder should build blocks.

type ScheduleMode

type ScheduleMode string

ScheduleMode represents the scheduling strategy for block building.

const (
	// ScheduleModeAll builds for all slots.
	ScheduleModeAll ScheduleMode = "all"
	// ScheduleModeEveryN builds for every Nth slot.
	ScheduleModeEveryN ScheduleMode = "every_nth"
	// ScheduleModeNextN builds for the next N slots then stops.
	ScheduleModeNextN ScheduleMode = "next_n"
)

type Service

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

Service is the central authority for buildoor's mutable runtime configuration. It owns the effective Config every module reads and is the single writer, layering three sources: hardcoded defaults < CLI-supplied < UI override. CLI and UI are resolved by recency (a monotonic seq), not a fixed priority: a CLI value that changed since the last run wins over an older UI override, while an unchanged CLI flag lets a newer UI override win. UI overrides persist across restarts via the optional state-db. The effective Config is the same pointer handed to every module, so writes (applied in place under the service lock) are observed live by all readers.

func NewService

func NewService(effective, defaults *Config, supplied map[string]bool, store *db.Database, log logrus.FieldLogger) (*Service, error)

New constructs the settings service.

  • effective is the resolved operator config (defaults + flags/env/file, already slot-adjusted); it becomes the shared config modules read and is mutated in place to apply overrides.
  • defaults is a pristine, slot-adjusted default Config used as the floor.
  • supplied maps each field key to whether the operator explicitly provided it (viper.IsSet); only supplied keys form the CLI layer.
  • store is the optional state-db (may be disabled).

func (*Service) Load

func (s *Service) Load() *Config

Load returns the effective The returned pointer is the shared config modules read; callers must treat it as read-only.

func (*Service) OnChange

func (s *Service) OnChange(fn func())

OnChange registers a callback invoked (outside the service lock) after every applied change. Used to trigger module-side resets and re-reads.

func (*Service) Set

func (s *Service) Set(key string, raw json.RawMessage, actor string) error

Set applies a single UI override.

func (*Service) SetMany

func (s *Service) SetMany(updates map[string]json.RawMessage, actor string) error

SetMany applies a batch of UI overrides atomically: all values are validated and decoded first, then applied, persisted, and the effective config recomputed before subscribers are notified once.

type ValidatorRangesConfig

type ValidatorRangesConfig struct {
	// File is a path to a YAML file in the format produced by ethereum-package:
	//   "0-127": "01-geth-lighthouse"
	//   "128-255": "02-nethermind-teku"
	File string `yaml:"file" json:"file,omitempty"`

	// URL is fetched on startup and refreshed every 5 minutes.
	// Expected JSON: {"ranges": {"0-199": "prysm-ethrex-1", ...}}
	// Template: https://config.<network>.ethpandaops.io/api/v1/nodes/validator-ranges
	URL string `yaml:"url" json:"url,omitempty"`
}

ValidatorRangesConfig configures how to load validator index → client name mappings. If both are set, URL takes precedence.

Jump to

Keyboard shortcuts

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