Documentation
¶
Overview ¶
Package chainselection implements multi-peer chain selection. It tracks the tip reported by each connected peer and, for Shelley-family headers, uses the Praos select view projected from the observed header: longer chain first, then the reference implementation's equal-length opcert/VRF tiebreaker when it is armed.
Genesis selection mode can be enabled at startup. The selector's rolling observed density ranks peers during bootstrap; when fetched candidates fork, ledger resolution performs the authoritative density comparison from their exact common intersection. Both automatically fall back to Praos once the local tip is close enough to the best observed peer tip.
ChainSelector is the top-level type. It consumes PeerTipUpdateEvent events from chainsync, compares peer tips against the local tip, and emits ChainSwitchEvent on the EventBus when the selected peer changes. The node's Run loop listens for those events and repoints the active chainsync stream at the new best peer.
This package does not perform any block validation; it only selects which peer's chain to follow. Validation happens downstream in the ledger package after blocks are fetched from the selected peer.
Index ¶
- Constants
- func DensityFromIntersection(intersectionSlot uint64, window uint64, slots []uint64) uint64
- func GenesisWindowSlotsForParams(securityParam uint64, activeSlotsCoeff float64) uint64
- func GetVRFOutput(header gledger.BlockHeader) []byte
- func PreferPraosCandidate(ours, cand PraosTiebreakerView) bool
- type CandidateFragment
- type ChainComparisonResult
- type ChainSelectedNoneEvent
- type ChainSelectionEvent
- type ChainSelector
- func (cs *ChainSelector) CandidateFragments() map[ouroboros.ConnectionId]CandidateFragment
- func (cs *ChainSelector) EvaluateAndSwitch() bool
- func (cs *ChainSelector) GenesisCorroborationActive() bool
- func (cs *ChainSelector) GenesisSelectionState() (bool, uint64)
- func (cs *ChainSelector) GenesisStatus() GenesisStatus
- func (cs *ChainSelector) GenesisWindowSlots() uint64
- func (cs *ChainSelector) GetAllPeerTips() map[ouroboros.ConnectionId]*PeerChainTip
- func (cs *ChainSelector) GetBestPeer() *ouroboros.ConnectionId
- func (cs *ChainSelector) GetCandidateFragment(connId ouroboros.ConnectionId) (CandidateFragment, bool)
- func (cs *ChainSelector) GetPeerSyncTarget(connId ouroboros.ConnectionId) (ochainsync.Tip, bool)
- func (cs *ChainSelector) GetPeerTip(connId ouroboros.ConnectionId) *PeerChainTip
- func (cs *ChainSelector) HandlePeerActivityEvent(evt event.Event)
- func (cs *ChainSelector) HandlePeerRollbackEvent(evt event.Event)
- func (cs *ChainSelector) HandlePeerTipUpdateEvent(evt event.Event)
- func (cs *ChainSelector) PeerCount() int
- func (cs *ChainSelector) RemovePeer(connId ouroboros.ConnectionId)
- func (cs *ChainSelector) SelectBestChain() *ouroboros.ConnectionId
- func (cs *ChainSelector) SelectionMode() SelectionMode
- func (cs *ChainSelector) SetConnectionEligible(connId ouroboros.ConnectionId, eligible bool)
- func (cs *ChainSelector) SetConnectionPriority(connId ouroboros.ConnectionId, priority int)
- func (cs *ChainSelector) SetLocalTip(tip ochainsync.Tip)
- func (cs *ChainSelector) SetSecurityParam(k uint64)
- func (cs *ChainSelector) ShouldApplyIngress(connId ouroboros.ConnectionId) bool
- func (cs *ChainSelector) Start(ctx context.Context) error
- func (cs *ChainSelector) Stop()
- func (cs *ChainSelector) SyncTargetForPeerTipUpdate(update PeerTipUpdateEvent) (ochainsync.Tip, bool)
- func (cs *ChainSelector) TouchPeerActivity(connId ouroboros.ConnectionId)
- func (cs *ChainSelector) UpdatePeerTip(connId ouroboros.ConnectionId, tip ochainsync.Tip, vrfOutput []byte) bool
- type ChainSelectorConfig
- type ChainSwitchEvent
- type EvaluationPanicEvent
- type GenesisCorroborationFailedEvent
- type GenesisModeExitedEvent
- type GenesisPeerStatus
- type GenesisStatus
- type PeerActivityEvent
- type PeerChainTip
- func (p *PeerChainTip) ApplyRollback(point ocommon.Point, tip ochainsync.Tip)
- func (p *PeerChainTip) CandidateFragment() CandidateFragment
- func (p *PeerChainTip) IsStale(threshold time.Duration) bool
- func (p *PeerChainTip) SelectionTip() ochainsync.Tip
- func (p *PeerChainTip) Touch()
- func (p *PeerChainTip) UpdateTip(tip ochainsync.Tip, vrfOutput []byte)
- func (p *PeerChainTip) UpdateTipWithObserved(tip ochainsync.Tip, observedTip ochainsync.Tip, vrfOutput []byte)
- func (p *PeerChainTip) UpdateTipWithObservedPraosView(tip ochainsync.Tip, observedTip ochainsync.Tip, vrfOutput []byte, ...)
- type PeerEvictedEvent
- type PeerRollbackEvent
- type PeerRollbackHandlerPanicEvent
- type PeerTipUpdateEvent
- type PraosTiebreakerConfig
- type PraosTiebreakerFlavor
- type PraosTiebreakerView
- func GetPraosTiebreakerView(header gledger.BlockHeader) (PraosTiebreakerView, bool)
- func NewPraosTiebreakerViewFull(tip ochainsync.Tip, issuer []byte, issueNo uint64, vrfOutput []byte, ...) PraosTiebreakerView
- func PraosTiebreakerViewFromTip(tip ochainsync.Tip, vrfOutput []byte, config PraosTiebreakerConfig) PraosTiebreakerView
- type SelectionMode
Constants ¶
const ( ChainEqual = praos.ChainEqual ChainABetter = praos.ChainABetter ChainBBetter = praos.ChainBBetter ChainComparisonUnknown = praos.ChainComparisonUnknown )
const ( PeerTipUpdateEventType event.EventType = "chainselection.peer_tip_update" PeerActivityEventType event.EventType = "chainselection.peer_activity" PeerRollbackEventType event.EventType = "chainselection.peer_rollback" ChainSwitchEventType event.EventType = "chainselection.chain_switch" ChainSelectionEventType event.EventType = "chainselection.selection" PeerEvictedEventType event.EventType = "chainselection.peer_evicted" // GenesisCorroborationFailedEventType is published when the densest // Genesis fast source cannot be corroborated by the configured minimum // number of independent peers, so it is denied chain selection (stalls) // rather than steering the local chain. Subscribers (peer governance, // operators) can use this to demote or investigate the source. GenesisCorroborationFailedEventType event.EventType = "chainselection.genesis_corroboration_failed" // GenesisModeExitedEventType is published when the selector transitions // from Genesis density-based selection back to Praos selection because the // local tip has caught up to within the Genesis window of the best known // peer tip. GenesisModeExitedEventType event.EventType = "chainselection.genesis_mode_exited" // ChainSelectedNoneEventType is published when the selector transitions to // having no selectable best peer (e.g. an uncorroborated Genesis fast source // is denied). It is the explicit selected-to-none transition that the // ChainSwitchEvent (which always carries a non-nil replacement) cannot // express, so subscribers can observe that selection has stalled. Ledger // application from uncorroborated peers is separately gated via // ShouldApplyIngress; this event is for observability of the stall. ChainSelectedNoneEventType event.EventType = "chainselection.selected_none" // PeerRollbackHandlerPanicEventType is published when the // PeerRollbackEvent handler registered in NewChainSelector panics. The // EventBus subscription that delivers PeerRollbackEvent is torn down // immediately afterward (see event.EventBus.SubscribeFuncStrict), so // this is the durable signal that rollback handling for this selector // has stopped rather than a swallowed panic followed by business as // usual. PeerRollbackHandlerPanicEventType event.EventType = "chainselection.peer_rollback_handler_panic" // EvaluationPanicEventType is published when a background evaluation // tick or triggered evaluation panics. The evaluation loop itself keeps // running (see ChainSelector.recoverEvaluationPanic), but the specific // best-peer transition that evaluation would have produced is dropped; // this event is the only remaining signal that it happened. EvaluationPanicEventType event.EventType = "chainselection.evaluation_panic" )
const ( PraosTiebreakerUnknown = praos.PraosTiebreakerUnknown PraosTiebreakerUnrestricted = praos.PraosTiebreakerUnrestricted PraosTiebreakerRestricted = praos.PraosTiebreakerRestricted )
const ( // DefaultMaxTrackedPeers is the maximum number of peers tracked by // the ChainSelector. When a new peer is added and the limit is reached, // the least-recently-updated peer is evicted. This bounds memory usage // and CPU cost of chain selection, preventing Sybil-based resource // exhaustion. DefaultMaxTrackedPeers = 200 )
const VRFOutputSize = praos.VRFOutputSize
VRFOutputSize is re-exported from consensus/praos.
Variables ¶
This section is empty.
Functions ¶
func DensityFromIntersection ¶ added in v0.69.0
DensityFromIntersection counts candidate blocks in the Genesis window that starts immediately after the common intersection and ends at intersectionSlot+window, inclusive. The intersection block itself belongs to both candidates and is therefore excluded.
Slots must describe one candidate path in ascending order. Values outside the window are ignored so callers may pass the complete fetched fragment.
func GenesisWindowSlotsForParams ¶ added in v0.37.0
GenesisWindowSlotsForParams returns the Genesis density window in slots. Shelley-style networks use 3k/f, where k is the security parameter and f is the active slot coefficient.
func GetVRFOutput ¶
func GetVRFOutput(header gledger.BlockHeader) []byte
GetVRFOutput delegates to consensus/praos.
func PreferPraosCandidate ¶ added in v0.46.0
func PreferPraosCandidate( ours, cand PraosTiebreakerView, ) bool
PreferPraosCandidate delegates to consensus/praos.
Types ¶
type CandidateFragment ¶ added in v0.70.6
type CandidateFragment struct {
// contains filtered or unexported fields
}
CandidateFragment is a bounded, immutable snapshot of the chain fragment a chainsync-eligible peer has actually delivered, ordered from its anchor (the oldest retained point) to its most recently delivered point.
This is Dingo's analogue of the upstream consensus interface readCandidateChains :: STM m (Map peer (AnchoredFragment header)); see ARCHITECTURE.md's "Ouroboros Genesis trust model" section. As with the upstream contract, entries are derived only from headers that have already passed chain-selection observation (see LedgerState.ValidateChainSelectionHeaderCrypto in ARCHITECTURE.md), the fragment may hold fewer than k+1 points, and its anchor is not required to intersect the primary chain or any other peer's fragment.
The fragment reuses PeerChainTip's existing delivered-tip history (recordObservedTipHistory), which is already updated once per delivered header and bounded to k+1 entries for rollback restoration, and exposes it as a first-class, independently owned value with an anchor and a pairwise intersection primitive. Entries are kept in strictly ascending slot order.
func (CandidateFragment) Anchor ¶ added in v0.70.6
func (f CandidateFragment) Anchor() ocommon.Point
Anchor returns the fragment's oldest retained point. Per the upstream AnchoredFragment contract, the anchor is not guaranteed to intersect the primary chain or any other peer's fragment — it is simply the oldest point this snapshot still remembers. Anchor returns the zero Point when the fragment is empty.
func (CandidateFragment) HeadPoint ¶ added in v0.70.6
func (f CandidateFragment) HeadPoint() ocommon.Point
HeadPoint returns the fragment's most recently delivered point, or the zero Point when the fragment is empty.
func (CandidateFragment) Intersect ¶ added in v0.70.6
func (f CandidateFragment) Intersect( other CandidateFragment, ) (ocommon.Point, bool)
Intersect returns the highest point present in both fragments, comparing by (slot, hash). Both fragments must already be in ascending slot order, which recordObservedTipHistory guarantees. This is the primitive the Limit on Eagerness and the Genesis Density Disconnector need to compute the intersection across candidate fragments (see ARCHITECTURE.md); it does not itself implement either.
func (CandidateFragment) Len ¶ added in v0.70.6
func (f CandidateFragment) Len() int
Len returns the number of points retained in the fragment.
func (CandidateFragment) Points ¶ added in v0.70.6
func (f CandidateFragment) Points() []ocommon.Point
Points returns the fragment's retained points, including the anchor, in ascending slot order. The caller receives an independent copy.
type ChainComparisonResult ¶
type ChainComparisonResult = praos.ChainComparisonResult
ChainComparisonResult is aliased from consensus/praos.
func ComparePraosTips ¶ added in v0.46.0
func ComparePraosTips( tipA, tipB ochainsync.Tip, viewA, viewB PraosTiebreakerView, ) ChainComparisonResult
ComparePraosTips delegates to consensus/praos.
func CompareVRFOutputs ¶
func CompareVRFOutputs(vrfA, vrfB []byte) ChainComparisonResult
CompareVRFOutputs delegates to consensus/praos.
type ChainSelectedNoneEvent ¶ added in v0.67.0
type ChainSelectedNoneEvent struct {
PreviousConnectionId ouroboros.ConnectionId
GenesisCorroboration bool
}
ChainSelectedNoneEvent is published when best-peer selection transitions from some peer to none (selection stalled).
Fields:
- PreviousConnectionId: the peer that was selected before the stall (zero value if none was selected).
- GenesisCorroboration: true when the stall is due to the Genesis corroboration gate (no corroborated peer), as opposed to simply having no eligible peers.
type ChainSelectionEvent ¶
type ChainSelectionEvent struct {
BestConnectionId ouroboros.ConnectionId
BestTip ochainsync.Tip
PeerCount int
SwitchOccurred bool
}
ChainSelectionEvent is published when chain selection evaluation completes.
type ChainSelector ¶
type ChainSelector struct {
// contains filtered or unexported fields
}
ChainSelector tracks chain tips from multiple peers and selects the best chain using the active mode's comparison rules.
func NewChainSelector ¶
func NewChainSelector(cfg ChainSelectorConfig) *ChainSelector
NewChainSelector creates a new ChainSelector with the given configuration.
func (*ChainSelector) CandidateFragments ¶ added in v0.70.6
func (cs *ChainSelector) CandidateFragments() map[ouroboros.ConnectionId]CandidateFragment
CandidateFragments returns a snapshot of the candidate chain fragment maintained for every currently tracked peer. This is the Dingo equivalent of the upstream readCandidateChains query: a fragment exists only while its peer's connection is tracked (i.e. chainsync-eligible per peer governance, the sole gate on entry into peerTips — see ouroboros/chainsync.go), and RemovePeer drops it along with the rest of that peer's state.
This intentionally does not consult the eligible map (SetConnectionEligible / isConnectionEligible): that flag disqualifies a peer from being chosen as best peer or counted as a corroboration witness, but it is not a disconnect and does not stop the peer from chainsyncing or being tracked here, so filtering on it would hide a still-connected candidate's fragment and would make this accessor inconsistent with its sibling GetAllPeerTips, which does not filter on it either. A future consumer that needs only selection-eligible fragments can intersect this result with isConnectionEligible/GetPeerTip itself.
func (*ChainSelector) EvaluateAndSwitch ¶
func (cs *ChainSelector) EvaluateAndSwitch() bool
EvaluateAndSwitch evaluates all peer tips and switches to the best chain if it differs from the current best. Returns true if a switch occurred.
func (*ChainSelector) GenesisCorroborationActive ¶ added in v0.67.0
func (cs *ChainSelector) GenesisCorroborationActive() bool
GenesisCorroborationActive reports whether the Genesis corroboration gate is currently in effect. Callers use it to decide whether tip observation must be ordered synchronously with the apply-eligibility gate (see ShouldApplyIngress): the gate is only non-trivial while corroboration is active.
func (*ChainSelector) GenesisSelectionState ¶ added in v0.69.0
func (cs *ChainSelector) GenesisSelectionState() (bool, uint64)
GenesisSelectionState returns an atomic snapshot of whether Genesis selection is active and the density window it is using. Composition code injects this narrow state query into fork resolution so the authoritative local decision follows the selector's one-way Genesis-to-Praos transition.
func (*ChainSelector) GenesisStatus ¶ added in v0.67.0
func (cs *ChainSelector) GenesisStatus() GenesisStatus
GenesisStatus returns a snapshot of current selection mode, Genesis window, selected fast source, and per-peer density/corroboration for observability.
func (*ChainSelector) GenesisWindowSlots ¶ added in v0.37.0
func (cs *ChainSelector) GenesisWindowSlots() uint64
GenesisWindowSlots returns the slot window used for Genesis density checks.
func (*ChainSelector) GetAllPeerTips ¶
func (cs *ChainSelector) GetAllPeerTips() map[ouroboros.ConnectionId]*PeerChainTip
GetAllPeerTips returns a deep copy of all tracked peer tips.
func (*ChainSelector) GetBestPeer ¶
func (cs *ChainSelector) GetBestPeer() *ouroboros.ConnectionId
GetBestPeer returns the connection ID of the peer with the best chain, or nil if no suitable peer is available.
func (*ChainSelector) GetCandidateFragment ¶ added in v0.70.6
func (cs *ChainSelector) GetCandidateFragment( connId ouroboros.ConnectionId, ) (CandidateFragment, bool)
GetCandidateFragment returns the candidate chain fragment for a specific peer. The second return value is false when the peer is not tracked (never observed, or removed on disconnect).
func (*ChainSelector) GetPeerSyncTarget ¶ added in v0.70.3
func (cs *ChainSelector) GetPeerSyncTarget( connId ouroboros.ConnectionId, ) (ochainsync.Tip, bool)
GetPeerSyncTarget returns a peer's advertised head only after its delivered frontier is close enough to corroborate that advertisement.
func (*ChainSelector) GetPeerTip ¶
func (cs *ChainSelector) GetPeerTip( connId ouroboros.ConnectionId, ) *PeerChainTip
GetPeerTip returns a deep copy of the chain tip for a specific peer. Returns nil if the peer is not tracked.
func (*ChainSelector) HandlePeerActivityEvent ¶ added in v0.27.7
func (cs *ChainSelector) HandlePeerActivityEvent(evt event.Event)
HandlePeerActivityEvent refreshes a peer's liveness on non-tip protocol activity such as keepalive responses.
func (*ChainSelector) HandlePeerRollbackEvent ¶ added in v0.61.2
func (cs *ChainSelector) HandlePeerRollbackEvent(evt event.Event)
HandlePeerRollbackEvent trims Genesis observed history and refreshes the tracked peer tip after a rollback.
func (*ChainSelector) HandlePeerTipUpdateEvent ¶
func (cs *ChainSelector) HandlePeerTipUpdateEvent(evt event.Event)
HandlePeerTipUpdateEvent handles PeerTipUpdateEvent from the event bus.
func (*ChainSelector) PeerCount ¶
func (cs *ChainSelector) PeerCount() int
PeerCount returns the number of peers being tracked.
func (*ChainSelector) RemovePeer ¶
func (cs *ChainSelector) RemovePeer(connId ouroboros.ConnectionId)
RemovePeer removes a peer from tracking.
func (*ChainSelector) SelectBestChain ¶
func (cs *ChainSelector) SelectBestChain() *ouroboros.ConnectionId
SelectBestChain evaluates all peer tips and returns the connection ID of the peer with the best chain.
func (*ChainSelector) SelectionMode ¶ added in v0.37.0
func (cs *ChainSelector) SelectionMode() SelectionMode
SelectionMode returns the selector's current mode.
func (*ChainSelector) SetConnectionEligible ¶ added in v0.55.0
func (cs *ChainSelector) SetConnectionEligible( connId ouroboros.ConnectionId, eligible bool, )
SetConnectionEligible marks whether a peer connection is eligible for chain selection. Ineligible peers are skipped during best-peer evaluation. Calling this triggers a re-evaluation of the best peer.
eligible=true is the default (absent key), so we delete instead of storing it. This prevents a stale entry when an out-of-order eligible=true event arrives after RemovePeer has already cleaned up the maps.
func (*ChainSelector) SetConnectionPriority ¶ added in v0.55.0
func (cs *ChainSelector) SetConnectionPriority( connId ouroboros.ConnectionId, priority int, )
SetConnectionPriority sets the selection priority for a peer connection. When two peers advertise the same chain tip, the peer with the higher priority wins. Calling this triggers a re-evaluation of the best peer.
priority=0 is the default (absent key), so we delete instead of storing it. This prevents a stale entry when an out-of-order priority=0 event arrives after RemovePeer has already cleaned up the maps.
func (*ChainSelector) SetLocalTip ¶
func (cs *ChainSelector) SetLocalTip(tip ochainsync.Tip)
SetLocalTip updates the local chain tip for comparison.
It also records the last time the APPLIED local tip moved FORWARD (its block number advanced). The anti-flap incumbent pin uses this timestamp as a progress-aware escape: if the applied tip stops advancing while the pin is engaged, the pin releases. Same-tip updates and rollbacks deliberately do NOT reset the stall clock, so a stalled incumbent cannot keep the pin alive by re-reporting an unchanged tip. Forward progress after a rollback does reset the clock because the comparison is against the previous applied tip, not an all-time high-water mark.
func (*ChainSelector) SetSecurityParam ¶
func (cs *ChainSelector) SetSecurityParam(k uint64)
SetSecurityParam updates the security parameter (k) dynamically. This allows the selector to use protocol parameters for density-based comparison.
func (*ChainSelector) ShouldApplyIngress ¶ added in v0.67.0
func (cs *ChainSelector) ShouldApplyIngress( connId ouroboros.ConnectionId, ) bool
ShouldApplyIngress reports whether headers/blocks from connId may be applied to the ledger. It returns false only while Genesis corroboration is active (Genesis mode with a positive threshold) and the peer is not corroborated, so an uncorroborated or divergent fast source is OBSERVED — its tips still feed corroboration via PeerTipUpdateEvent — but its blocks are not applied and it cannot steer the ledger. Enforcing the stall here (ledger application) rather than only at peer selection is required because ingress is gated on peer- governance eligibility, independent of the selected best peer: clearing the active chainsync driver alone would not stop an eligible uncorroborated peer's headers from being applied.
An unknown peer (no tips observed yet) is treated as uncorroborated and denied while the gate is active — fail closed until corroboration forms. Outside Genesis corroboration it always returns true (no behavior change).
func (*ChainSelector) Start ¶
func (cs *ChainSelector) Start(ctx context.Context) error
Start begins the chain selector's background evaluation loop and subscribes to relevant events.
func (*ChainSelector) SyncTargetForPeerTipUpdate ¶ added in v0.70.3
func (cs *ChainSelector) SyncTargetForPeerTipUpdate( update PeerTipUpdateEvent, ) (ochainsync.Tip, bool)
SyncTargetForPeerTipUpdate applies the bounded-target policy to the exact observed/advertised pair carried by one chainsync event. It intentionally does not read the mutable per-peer tip map.
func (*ChainSelector) TouchPeerActivity ¶ added in v0.27.7
func (cs *ChainSelector) TouchPeerActivity(connId ouroboros.ConnectionId)
func (*ChainSelector) UpdatePeerTip ¶
func (cs *ChainSelector) UpdatePeerTip( connId ouroboros.ConnectionId, tip ochainsync.Tip, vrfOutput []byte, ) bool
UpdatePeerTip updates the chain tip for a specific peer and triggers evaluation if needed. The vrfOutput parameter is the VRF output from the tip block header, used for tie-breaking when chains have equal block number and slot.
Returns true if the tip was accepted, false if its delivered frontier was rejected as implausible. The remote advertised tip is untrusted and may be arbitrarily far ahead while the peer legitimately serves the next block the node needs, so plausibility is checked against the locally observed header. For known peers, the reference is the peer's previous observed frontier; for new peers, it is the best observed peer frontier. This avoids rejecting legitimate peers during sync while still bounding delivered block-number jumps.
type ChainSelectorConfig ¶
type ChainSelectorConfig struct {
Logger *slog.Logger
EventBus *event.EventBus
EvaluationInterval time.Duration
StaleTipThreshold time.Duration
SecurityParam uint64
GenesisMode bool
GenesisWindowSlots uint64
// MinCorroboratingPeers is the number of distinct other eligible peers
// that must report the same recent blocks as a candidate before that
// candidate can drive chain selection in Genesis mode. It implements the
// Ouroboros Genesis trust property that a fast (shallow) block source is
// followed only while corroborated by independent peers. 0 disables
// corroboration (density-only Genesis selection, the historical default).
MinCorroboratingPeers int
ConnectionLive func(ouroboros.ConnectionId) bool
ConnectionEligible func(ouroboros.ConnectionId) bool
ConnectionPriority func(ouroboros.ConnectionId) int
MaxTrackedPeers int // 0 means use DefaultMaxTrackedPeers
// DisableEventSubscriptions leaves EventBus configured for publishing
// selector events but skips automatic input subscriptions. This is useful
// for deterministic replay harnesses that feed input events synchronously.
DisableEventSubscriptions bool
// BlockfetchLatency returns the EWMA first-block latency for a
// connection and whether any samples exist. Used only to choose a
// peer when two peers advertise the exact same selected block.
BlockfetchLatency func(ouroboros.ConnectionId) (time.Duration, bool)
}
ChainSelectorConfig holds configuration for the ChainSelector.
type ChainSwitchEvent ¶
type ChainSwitchEvent struct {
PreviousConnectionId ouroboros.ConnectionId
NewConnectionId ouroboros.ConnectionId
NewTip ochainsync.Tip
PreviousTip ochainsync.Tip
NewObservedTip ochainsync.Tip
NewObservedTipSet bool
PreviousObservedTip ochainsync.Tip
ComparisonResult ChainComparisonResult
BlockDifference int64
}
ChainSwitchEvent is published when the chain selector decides to switch to a different peer's chain.
Fields:
- PreviousConnectionId: The connection ID of the peer we were following.
- NewConnectionId: The connection ID of the peer we are now following.
- NewTip: The advertised chain tip of the new peer.
- PreviousTip: The advertised chain tip of the previous peer at switch time.
- NewObservedTip: The delivered frontier of the new peer. A zero value means the peer delivered nothing, which is distinct from absent.
- NewObservedTipSet: Whether NewObservedTip was populated. Producers in this package always set it. Events built elsewhere (older producers, direct unit-test and integration constructors) leave it false, and only those fall back to the advertised NewTip.
- PreviousObservedTip: The delivered frontier of the previous peer.
- ComparisonResult: Why the new chain is better than the previous chain.
- BlockDifference: NewTip.BlockNumber - PreviousTip.BlockNumber.
type EvaluationPanicEvent ¶ added in v0.70.5
EvaluationPanicEvent is published when a background evaluation tick or triggered evaluation panics.
Fields:
- Panic: the recovered panic value, for diagnostics.
- Triggered: true when the panic occurred in runTriggeredEvaluation (the evaluationLoop select case draining evaluationTrigger, fed by SetConnectionEligible/SetConnectionPriority's triggerEvaluation calls); false for the periodic ticker tick (runEvaluationTick), which also runs cleanupStalePeers first. Panics from EvaluateAndSwitch called directly outside evaluationLoop (e.g. from UpdatePeerTip, RemovePeer, SetLocalTip, or an event handler) are not covered by this event -- only the two evaluationLoop paths recover and surface panics here.
type GenesisCorroborationFailedEvent ¶ added in v0.67.0
type GenesisCorroborationFailedEvent struct {
ConnectionId ouroboros.ConnectionId
ObservedDensity uint64
CorroboratingPeers int
RequiredPeers int
GenesisWindowSlots uint64
}
GenesisCorroborationFailedEvent is published when the densest Genesis fast source lacks the configured minimum corroboration from independent peers.
Fields:
- ConnectionId: the uncorroborated fast source that was denied selection.
- ObservedDensity: its observed block density within the Genesis window.
- CorroboratingPeers: how many independent peers actually corroborate it.
- RequiredPeers: the configured MinCorroboratingPeers threshold.
- GenesisWindowSlots: the active Genesis density window in slots.
type GenesisModeExitedEvent ¶ added in v0.67.0
type GenesisModeExitedEvent struct {
LocalSlot uint64
BestKnownSlot uint64
GenesisWindowSlots uint64
}
GenesisModeExitedEvent is published when the selector leaves Genesis mode.
Fields:
- LocalSlot: the local tip slot at the time of exit.
- BestKnownSlot: the best known selectable peer tip slot.
- GenesisWindowSlots: the active Genesis density window in slots.
type GenesisPeerStatus ¶ added in v0.67.0
type GenesisPeerStatus struct {
ConnectionId ouroboros.ConnectionId
ObservedDensity uint64
CorroboratingPeers int
Corroborated bool
Selectable bool
}
GenesisPeerStatus is the per-peer Genesis observability snapshot.
type GenesisStatus ¶ added in v0.67.0
type GenesisStatus struct {
Mode SelectionMode
WindowSlots uint64
MinCorroboratingPeers int
BestSource *ouroboros.ConnectionId
Peers []GenesisPeerStatus
}
GenesisStatus is a point-in-time snapshot of Genesis selection state for observability (metrics, logs, operator tooling).
type PeerActivityEvent ¶ added in v0.27.7
type PeerActivityEvent struct {
ConnectionId ouroboros.ConnectionId
}
PeerActivityEvent is published when a peer has recent protocol activity (for example, a keepalive response) without a tip change. This refreshes selector liveness for healthy but temporarily quiet peers.
type PeerChainTip ¶
type PeerChainTip struct {
ConnectionId ouroboros.ConnectionId
// Tip is the remote peer's advertised chain tip. It is untrusted and may
// be far ahead of the headers the peer has actually delivered.
Tip ochainsync.Tip
// ObservedTip is the latest header locally delivered by this peer. Chain
// comparison and handoff decisions use this frontier.
ObservedTip ochainsync.Tip
VRFOutput []byte // VRF output from tip block for tie-breaking
PraosView PraosTiebreakerView
LastUpdated time.Time
// contains filtered or unexported fields
}
PeerChainTip tracks the chain tip reported by a specific peer.
func NewPeerChainTip ¶
func NewPeerChainTip( connId ouroboros.ConnectionId, tip ochainsync.Tip, vrfOutput []byte, ) *PeerChainTip
NewPeerChainTip creates a new PeerChainTip with the given connection ID, tip, and VRF output.
func (*PeerChainTip) ApplyRollback ¶ added in v0.37.0
func (p *PeerChainTip) ApplyRollback( point ocommon.Point, tip ochainsync.Tip, )
ApplyRollback trims observed history at the rollback point and refreshes the peer tip to the chainsync tip reported with the rollback.
func (*PeerChainTip) CandidateFragment ¶ added in v0.70.6
func (p *PeerChainTip) CandidateFragment() CandidateFragment
CandidateFragment returns a snapshot of this peer's candidate chain fragment. The caller receives an independent copy.
func (*PeerChainTip) IsStale ¶
func (p *PeerChainTip) IsStale(threshold time.Duration) bool
IsStale returns true if the peer's tip hasn't been updated within the given duration.
func (*PeerChainTip) SelectionTip ¶ added in v0.27.7
func (p *PeerChainTip) SelectionTip() ochainsync.Tip
SelectionTip returns the best locally observed frontier for this peer. When available, prefer the latest block the peer has actually delivered to us over its remote advertised tip. This avoids switching to peers whose far-end tip is high while their chainsync cursor is still lagging.
func (*PeerChainTip) Touch ¶ added in v0.27.7
func (p *PeerChainTip) Touch()
Touch marks the peer as recently active without changing its advertised tip.
func (*PeerChainTip) UpdateTip ¶
func (p *PeerChainTip) UpdateTip(tip ochainsync.Tip, vrfOutput []byte)
UpdateTip updates the peer's chain tip, VRF output, and last updated timestamp.
func (*PeerChainTip) UpdateTipWithObserved ¶ added in v0.27.7
func (p *PeerChainTip) UpdateTipWithObserved( tip ochainsync.Tip, observedTip ochainsync.Tip, vrfOutput []byte, )
UpdateTipWithObserved updates both the remote advertised tip and the latest locally observed frontier for the peer.
func (*PeerChainTip) UpdateTipWithObservedPraosView ¶ added in v0.46.0
func (p *PeerChainTip) UpdateTipWithObservedPraosView( tip ochainsync.Tip, observedTip ochainsync.Tip, vrfOutput []byte, praosView PraosTiebreakerView, )
UpdateTipWithObservedPraosView updates the remote advertised tip, the latest locally observed frontier, the VRF output, and the Praos tiebreaker view for the peer. Callers must provide a PraosTiebreakerView derived from observedTip and the supplied vrfOutput when that VRF output participates in the view. The view is stored as supplied; this method does not validate consistency, so an inconsistent view can make later chain-selection comparisons incorrect.
type PeerEvictedEvent ¶ added in v0.22.0
type PeerEvictedEvent struct {
ConnectionId ouroboros.ConnectionId
}
PeerEvictedEvent is published when a tracked peer is evicted from the chain selector to make room for a new peer. Subscribers (e.g. connection manager) can use this to close the evicted peer's connection.
type PeerRollbackEvent ¶ added in v0.37.0
type PeerRollbackEvent struct {
ConnectionId ouroboros.ConnectionId
Point ocommon.Point
Tip ochainsync.Tip
}
PeerRollbackEvent is published when an ingress-eligible chainsync peer reports a rollback. Point is the rollback point; Tip is the peer's current chainsync tip after the rollback.
type PeerRollbackHandlerPanicEvent ¶ added in v0.70.5
type PeerRollbackHandlerPanicEvent struct {
Panic any
}
PeerRollbackHandlerPanicEvent is published when HandlePeerRollbackEvent panics. Panic carries the recovered panic value for diagnostics.
type PeerTipUpdateEvent ¶
type PeerTipUpdateEvent struct {
ConnectionId ouroboros.ConnectionId
// Tip is the untrusted remote advertised tip.
Tip ochainsync.Tip
// ObservedTip is the header frontier actually delivered by the peer.
ObservedTip ochainsync.Tip
VRFOutput []byte // VRF output from observed block header for tie-breaking
PraosView PraosTiebreakerView
}
PeerTipUpdateEvent is published when a peer's chain tip is updated via chainsync roll forward.
type PraosTiebreakerConfig ¶ added in v0.46.0
type PraosTiebreakerConfig = praos.PraosTiebreakerConfig
PraosTiebreakerConfig is aliased from consensus/praos.
func PraosTiebreakerConfigBeforeConway ¶ added in v0.46.0
func PraosTiebreakerConfigBeforeConway() PraosTiebreakerConfig
PraosTiebreakerConfigBeforeConway delegates to consensus/praos.
func PraosTiebreakerConfigConway ¶ added in v0.46.0
func PraosTiebreakerConfigConway() PraosTiebreakerConfig
PraosTiebreakerConfigConway delegates to consensus/praos.
func PraosTiebreakerConfigUnknown ¶ added in v0.46.0
func PraosTiebreakerConfigUnknown() PraosTiebreakerConfig
PraosTiebreakerConfigUnknown delegates to consensus/praos.
type PraosTiebreakerFlavor ¶ added in v0.46.0
type PraosTiebreakerFlavor = praos.PraosTiebreakerFlavor
PraosTiebreakerFlavor and its constants are type-aliased from consensus/praos so that chainselection.PraosTiebreakerFlavor and praos.PraosTiebreakerFlavor are the same type.
type PraosTiebreakerView ¶ added in v0.46.0
type PraosTiebreakerView = praos.PraosTiebreakerView
PraosTiebreakerView is aliased from consensus/praos.
func GetPraosTiebreakerView ¶ added in v0.46.0
func GetPraosTiebreakerView( header gledger.BlockHeader, ) (PraosTiebreakerView, bool)
GetPraosTiebreakerView delegates to consensus/praos.
func NewPraosTiebreakerViewFull ¶ added in v0.55.0
func NewPraosTiebreakerViewFull( tip ochainsync.Tip, issuer []byte, issueNo uint64, vrfOutput []byte, config PraosTiebreakerConfig, ) PraosTiebreakerView
NewPraosTiebreakerViewFull delegates to consensus/praos.
func PraosTiebreakerViewFromTip ¶ added in v0.46.0
func PraosTiebreakerViewFromTip( tip ochainsync.Tip, vrfOutput []byte, config PraosTiebreakerConfig, ) PraosTiebreakerView
PraosTiebreakerViewFromTip delegates to consensus/praos.
type SelectionMode ¶ added in v0.37.0
type SelectionMode uint8
SelectionMode describes the chain-selection strategy currently in use.
const ( SelectionModePraos SelectionMode = iota SelectionModeGenesis )
func (SelectionMode) String ¶ added in v0.37.0
func (m SelectionMode) String() string