Documentation
¶
Overview ¶
Package config handles configuration loading and validation for buildoor.
Index ¶
Constants ¶
const ( SourceDefault = "default" SourceCLI = "cli" SourceUI = "ui" )
Source identifies which layer currently wins for a setting.
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 ¶
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: 5000ms @12s (e.g. 2500ms @6s)
RevealTime (41.7% of the slot) is anchored to the Gloas/EIP-7732 deadlines: it sits after the attestation deadline (ATTESTATION_DUE_BPS_GLOAS, 25%) — so the builder has seen attestation weight on the block before committing to reveal — and comfortably before the hard payload deadline (PAYLOAD_DUE_BPS, 50% since consensus-specs#5414), after which the PTC votes the payload absent. The ~8% (1s @12s) margin before that deadline lets the envelope gossip to PTC members, who attest at 75% (PAYLOAD_ATTESTATION_DUE_BPS).
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.
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 ¶
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.
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.