Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Implementation of the GDD governor
The GDD governor is the component responsible for identifying and
disconnecting peers offering sparser chains than the best. This has the
effect of unblocking the Limit on Eagerness, since removing disagreeing
peers allows the current selection to advance. See
LoE
for more details.
The GDD governor, invoked with runGDDGovernor
, is supposed to run in a background
thread. It evaluates candidate chains whenever they change, or whenever a
peer claims to have no more headers, or whenever a peer starts sending
headers beyond the forecast horizon.
Whenever GDD disconnects peers, and as a result the youngest header present in all candidate fragments changes, the chain selection is updated.
Synopsis
- data DensityBounds blk = DensityBounds {}
- data GDDDebugInfo peer blk = GDDDebugInfo {
- bounds ∷ [(peer, DensityBounds blk)]
- curChain ∷ AnchoredFragment (Header blk)
- candidates ∷ [(peer, AnchoredFragment (Header blk))]
- candidateSuffixes ∷ [(peer, AnchoredFragment (Header blk))]
- losingPeers ∷ [peer]
- loeHead ∷ Anchor (Header blk)
- sgen ∷ GenesisWindow
- data GDDStateView m blk peer = GDDStateView {
- gddCtxCurChain ∷ AnchoredFragment (Header blk)
- gddCtxImmutableLedgerSt ∷ ExtLedgerState blk
- gddCtxKillActions ∷ Map peer (m ())
- gddCtxStates ∷ Map peer (ChainSyncState blk)
- data TraceGDDEvent peer blk
- = TraceGDDDisconnected (NonEmpty peer)
- | TraceGDDDebug (GDDDebugInfo peer blk)
- densityDisconnect ∷ (Ord peer, LedgerSupportsProtocol blk) ⇒ GenesisWindow → SecurityParam → Map peer (ChainSyncState blk) → [(peer, AnchoredFragment (Header blk))] → AnchoredFragment (Header blk) → ([peer], [(peer, DensityBounds blk)])
- gddWatcher ∷ ∀ m blk peer. (IOLike m, Ord peer, LedgerSupportsProtocol blk, HasHardForkHistory blk) ⇒ TopLevelConfig blk → Tracer m (TraceGDDEvent peer blk) → ChainDB m blk → STM m GsmState → STM m (Map peer (ChainSyncClientHandle m blk)) → StrictTVar m (AnchoredFragment (Header blk)) → Watcher m (GsmState, GDDStateView m blk peer) (Map peer (StrictMaybe (WithOrigin SlotNo), Bool))
- sharedCandidatePrefix ∷ GetHeader blk ⇒ AnchoredFragment (Header blk) → [(peer, AnchoredFragment (Header blk))] → (AnchoredFragment (Header blk), [(peer, AnchoredFragment (Header blk))])
Documentation
data DensityBounds blk Source #
Instances
(Show (Header blk), GetHeader blk) ⇒ Show (DensityBounds blk) Source # | |
Defined in Ouroboros.Consensus.Genesis.Governor showsPrec ∷ Int → DensityBounds blk → ShowS # show ∷ DensityBounds blk → String # showList ∷ [DensityBounds blk] → ShowS # |
data GDDDebugInfo peer blk Source #
GDDDebugInfo | |
|
Instances
(GetHeader blk, Show (Header blk), Show peer) ⇒ Show (GDDDebugInfo peer blk) Source # | |
Defined in Ouroboros.Consensus.Genesis.Governor showsPrec ∷ Int → GDDDebugInfo peer blk → ShowS # show ∷ GDDDebugInfo peer blk → String # showList ∷ [GDDDebugInfo peer blk] → ShowS # |
data GDDStateView m blk peer Source #
Pure snapshot of the dynamic data the GDD operates on.
GDDStateView | |
|
data TraceGDDEvent peer blk Source #
TraceGDDDisconnected (NonEmpty peer) | The GDD disconnected from the given peers due to insufficient density. |
TraceGDDDebug (GDDDebugInfo peer blk) |
Instances
(GetHeader blk, Show (Header blk), Show peer) ⇒ Show (TraceGDDEvent peer blk) Source # | |
Defined in Ouroboros.Consensus.Genesis.Governor showsPrec ∷ Int → TraceGDDEvent peer blk → ShowS # show ∷ TraceGDDEvent peer blk → String # showList ∷ [TraceGDDEvent peer blk] → ShowS # |
densityDisconnect ∷ (Ord peer, LedgerSupportsProtocol blk) ⇒ GenesisWindow → SecurityParam → Map peer (ChainSyncState blk) → [(peer, AnchoredFragment (Header blk))] → AnchoredFragment (Header blk) → ([peer], [(peer, DensityBounds blk)]) Source #
densityDisconnect genWin k states candidateSuffixes loeFrag
yields the list of peers which are known to lose the density comparison with
any other peer, when looking at the genesis window after loeFrag
.
The peers are taken from the keys of candidateSuffixes
.
candidateSuffixes
tells for every peer what is the fragment that the peer
proposes to use after loeFrag
.
states
contains further information for every peer, such as the last
ChainSync instruction the peer sent, and whether the peer is idling (i.e. it
sent MsgAwaitReply
).
loeFrag
is the fragment anchored at the immutable tip and ending in the
LoE tip.
ChainSync jumping depends on this function to disconnect either of any two peers that offer different chains and provided a header in the last slot of the genesis window or later. Either of them should be disconnected, even if both of them are serving adversarial chains. See Ouroboros.Consensus.MiniProtocol.ChainSync.Client.Jumping for more details.
∷ ∀ m blk peer. (IOLike m, Ord peer, LedgerSupportsProtocol blk, HasHardForkHistory blk) | |
⇒ TopLevelConfig blk | |
→ Tracer m (TraceGDDEvent peer blk) | |
→ ChainDB m blk | |
→ STM m GsmState | |
→ STM m (Map peer (ChainSyncClientHandle m blk)) | The ChainSync handles. We trigger the GDD whenever our |
→ StrictTVar m (AnchoredFragment (Header blk)) | The LoE fragment. It starts at a (recent) immutable tip and ends at the common intersection of the candidate fragments. |
→ Watcher m (GsmState, GDDStateView m blk peer) (Map peer (StrictMaybe (WithOrigin SlotNo), Bool)) |
A Watcher
that evaluates the GDD rule whenever necessary, writing the LoE
fragment to varLoEFrag
, and then triggering ChainSel to reprocess all
blocks that had previously been postponed by the LoE.
Evaluating the GDD rule might cause peers to be disconnected if they have sparser chains than the best chain.
sharedCandidatePrefix ∷ GetHeader blk ⇒ AnchoredFragment (Header blk) → [(peer, AnchoredFragment (Header blk))] → (AnchoredFragment (Header blk), [(peer, AnchoredFragment (Header blk))]) Source #
Compute the fragment loeFrag
between the immutable tip and the
earliest intersection between curChain
and any of the candidates
.
The immutable tip is the anchor of curChain
.
The function also yields the suffixes of the intersection of loeFrag
with
every candidate fragment.