Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
The ChainSync client logic
Its core specification is found in "The Shelley Networking Protocol", currently found at https://ouroboros-network.cardano.intersectmbo.org/pdfs/network-spec/network-spec.pdf.
It would be difficult to maintain or extrend this module without
understanding the typed-protocols
architecture; eg see
https://github.com/input-output-hk/typed-protocols.
This module is intended for qualified import, aliased as either CSC, CSClient, or CsClient.
Synopsis
- bracketChainSyncClient ∷ ∀ m peer blk a. (IOLike m, Ord peer, LedgerSupportsProtocol blk, MonadTimer m) ⇒ Tracer m (TraceChainSyncClientEvent blk) → ChainDbView m blk → StrictTVar m (Map peer (ChainSyncClientHandle m blk)) → STM m GsmState → peer → NodeToNodeVersion → ChainSyncLoPBucketConfig → CSJConfig → DiffusionPipeliningSupport → (ChainSyncStateView m blk → m a) → m a
- chainSyncClient ∷ ∀ m blk. (IOLike m, LedgerSupportsProtocol blk) ⇒ ConfigEnv m blk → DynamicEnv m blk → Consensus ChainSyncClientPipelined blk m
- data ChainDbView m blk = ChainDbView {
- getCurrentChain ∷ STM m (AnchoredFragment (Header blk))
- getHeaderStateHistory ∷ STM m (HeaderStateHistory blk)
- getPastLedger ∷ Point blk → STM m (Maybe (ExtLedgerState blk))
- getIsInvalidBlock ∷ STM m (WithFingerprint (HeaderHash blk → Maybe (ExtValidationError blk)))
- data ConfigEnv m blk = ConfigEnv {}
- data DynamicEnv m blk = DynamicEnv {
- version ∷ NodeToNodeVersion
- controlMessageSTM ∷ ControlMessageSTM m
- headerMetricsTracer ∷ HeaderMetricsTracer m
- setCandidate ∷ AnchoredFragment (Header blk) → STM m ()
- setLatestSlot ∷ WithOrigin SlotNo → STM m ()
- idling ∷ Idling m
- loPBucket ∷ LoPBucket m
- jumping ∷ Jumping m blk
- data InternalEnv m blk arrival judgment = InternalEnv {
- drainThePipe ∷ ∀ s n. NoThunks s ⇒ Nat n → Stateful m blk s (ClientPipelinedStIdle 'Z) → Stateful m blk s (ClientPipelinedStIdle n)
- disconnect ∷ ∀ m' a. MonadThrow m' ⇒ ChainSyncClientException → m' a
- headerInFutureCheck ∷ HeaderInFutureCheck m blk arrival judgment
- intersectsWithCurrentChain ∷ KnownIntersectionState blk → STM m (UpdatedIntersectionState blk ())
- terminate ∷ ChainSyncClientResult → m (Consensus (ClientPipelinedStIdle 'Z) blk m)
- terminateAfterDrain ∷ ∀ n. Nat n → ChainSyncClientResult → m (Consensus (ClientPipelinedStIdle n) blk m)
- traceException ∷ ∀ a. m a → m a
- defaultChainDbView ∷ (IOLike m, LedgerSupportsProtocol blk) ⇒ ChainDB m blk → ChainDbView m blk
- data ChainSyncClientException
- = ∀ blk.(BlockSupportsProtocol blk, ValidateEnvelope blk) ⇒ HeaderError (Point blk) (HeaderError blk) (Our (Tip blk)) (Their (Tip blk))
- | ∀ blk.BlockSupportsProtocol blk ⇒ InvalidIntersection (Point blk) (Our (Tip blk)) (Their (Tip blk))
- | ∀ blk.LedgerSupportsProtocol blk ⇒ InvalidBlock (Point blk) (HeaderHash blk) (ExtValidationError blk)
- | InFutureHeaderExceedsClockSkew !HeaderArrivalException
- | HistoricityError !HistoricityException
- | EmptyBucket
- | InvalidJumpResponse
- | DensityTooLow
- data ChainSyncClientResult
- = ∀ blk.BlockSupportsProtocol blk ⇒ ForkTooDeep (Point blk) (Our (Tip blk)) (Their (Tip blk))
- | ∀ blk.BlockSupportsProtocol blk ⇒ NoMoreIntersection (Our (Tip blk)) (Their (Tip blk))
- | ∀ blk.BlockSupportsProtocol blk ⇒ RolledBackPastIntersection (Point blk) (Our (Tip blk)) (Their (Tip blk))
- | AskedToTerminate
- type Consensus (client ∷ Type → Type → Type → (Type → Type) → Type → Type) blk m = client (Header blk) (Point blk) (Tip blk) m ChainSyncClientResult
- newtype Our a = Our {
- unOur ∷ a
- newtype Their a = Their {
- unTheir ∷ a
- data CSJConfig
- newtype CSJEnabledConfig = CSJEnabledConfig {}
- data ChainSyncLoPBucketConfig
- data ChainSyncLoPBucketEnabledConfig = ChainSyncLoPBucketEnabledConfig {}
- data TraceChainSyncClientEvent blk
- = TraceDownloadedHeader (Header blk)
- | TraceRolledBack (Point blk)
- | TraceFoundIntersection (Point blk) (Our (Tip blk)) (Their (Tip blk))
- | TraceException ChainSyncClientException
- | TraceTermination ChainSyncClientResult
- | TraceValidatedHeader (Header blk)
- | TraceWaitingBeyondForecastHorizon SlotNo
- | TraceAccessingForecastHorizon SlotNo
- | TraceGaveLoPToken Bool (Header blk) BlockNo
- | TraceOfferJump (Point blk)
- | TraceJumpResult (JumpResult blk)
- | TraceJumpingWaitingForNextInstruction
- | TraceJumpingInstructionIs (Instruction blk)
- data ChainSyncClientHandle m blk = ChainSyncClientHandle {
- cschGDDKill ∷ !(m ())
- cschOnGsmStateChanged ∷ !(GsmState → Time → STM m ())
- cschState ∷ !(StrictTVar m (ChainSyncState blk))
- cschJumping ∷ !(StrictTVar m (ChainSyncJumpingState m blk))
- cschJumpInfo ∷ !(StrictTVar m (Maybe (JumpInfo blk)))
- data ChainSyncState blk = ChainSyncState {
- csCandidate ∷ !(AnchoredFragment (Header blk))
- csIdling ∷ !Bool
- csLatestSlot ∷ !(StrictMaybe (WithOrigin SlotNo))
- data ChainSyncStateView m blk = ChainSyncStateView {
- csvSetCandidate ∷ !(AnchoredFragment (Header blk) → STM m ())
- csvSetLatestSlot ∷ !(WithOrigin SlotNo → STM m ())
- csvIdling ∷ !(Idling m)
- csvLoPBucket ∷ !(LoPBucket m)
- csvJumping ∷ !(Jumping m blk)
- noJumping ∷ MonadSTM m ⇒ Jumping m blk
- chainSyncStateFor ∷ Ord peer ⇒ IOLike m ⇒ StrictTVar m (Map peer (ChainSyncClientHandle m blk)) → peer → STM m (ChainSyncState blk)
- noIdling ∷ Applicative m ⇒ Idling m
- noLoPBucket ∷ Applicative m ⇒ LoPBucket m
- viewChainSyncState ∷ IOLike m ⇒ StrictTVar m (Map peer (ChainSyncClientHandle m blk)) → (ChainSyncState blk → a) → STM m (Map peer a)
ChainSync client
bracketChainSyncClient Source #
∷ ∀ m peer blk a. (IOLike m, Ord peer, LedgerSupportsProtocol blk, MonadTimer m) | |
⇒ Tracer m (TraceChainSyncClientEvent blk) | |
→ ChainDbView m blk | |
→ StrictTVar m (Map peer (ChainSyncClientHandle m blk)) | The kill handle and states for each peer, we need the whole map because we
(de)register nodes ( |
→ STM m GsmState | A function giving the current GSM state; only used at startup. |
→ peer | |
→ NodeToNodeVersion | |
→ ChainSyncLoPBucketConfig | |
→ CSJConfig | |
→ DiffusionPipeliningSupport | |
→ (ChainSyncStateView m blk → m a) | |
→ m a |
chainSyncClient ∷ ∀ m blk. (IOLike m, LedgerSupportsProtocol blk) ⇒ ConfigEnv m blk → DynamicEnv m blk → Consensus ChainSyncClientPipelined blk m Source #
Chain sync client
This never terminates. In case of a failure, a ChainSyncClientException
is thrown. The network layer classifies exception such that the
corresponding peer will never be chosen again.
Arguments
data ChainDbView m blk Source #
Abstract over the ChainDB
ChainDbView | |
|
Arguments determined by configuration
These are available before the diffusion layer is online.
ConfigEnv | |
|
data DynamicEnv m blk Source #
Arguments determined dynamically
These are available only after the diffusion layer is online and/or on per client basis.
DynamicEnv | |
|
data InternalEnv m blk arrival judgment Source #
General values collectively needed by the top-level entry points
InternalEnv | |
|
defaultChainDbView ∷ (IOLike m, LedgerSupportsProtocol blk) ⇒ ChainDB m blk → ChainDbView m blk Source #
Results
data ChainSyncClientException Source #
When the upstream node violates the protocol or exhibits malicious behaviour, e.g., serving an invalid header or a header corresponding to a known invalid block, we throw an exception to disconnect. This will bring down all miniprotocols in both directions with that node.
∀ blk.(BlockSupportsProtocol blk, ValidateEnvelope blk) ⇒ HeaderError | |
∀ blk.BlockSupportsProtocol blk ⇒ InvalidIntersection | |
| |
∀ blk.LedgerSupportsProtocol blk ⇒ InvalidBlock | |
| |
InFutureHeaderExceedsClockSkew !HeaderArrivalException | A header arrived from the far future. |
HistoricityError !HistoricityException | |
EmptyBucket | The peer lost its race against the bucket. |
InvalidJumpResponse | When the peer responded incorrectly to a jump request. |
DensityTooLow | The peer has been deemed unworthy by the GDD |
data ChainSyncClientResult Source #
The Chain sync client only _gracefully_ terminates when the upstream node's chain is not interesting (e.g., forked off too far in the past). By gracefully terminating, the network layer can keep the other mini-protocols connect to the same upstream node running.
For example, a relay node will often receive connections from nodes syncing from scratch or an old chain. Since these nodes have a chain that is shorter than the relay node's chain, it's useless for the relay node to run the client-side of the chain sync protocol. However, the other direction of the protocol, and, e.g., the transaction submission protocol, should keep running.
∀ blk.BlockSupportsProtocol blk ⇒ ForkTooDeep | |
∀ blk.BlockSupportsProtocol blk ⇒ NoMoreIntersection (Our (Tip blk)) (Their (Tip blk)) | Our chain changed such that it no longer intersects with the candidate's fragment, and asking for a new intersection did not yield one. |
∀ blk.BlockSupportsProtocol blk ⇒ RolledBackPastIntersection | |
AskedToTerminate | We were asked to terminate via the |
Instances
Misc
type Consensus (client ∷ Type → Type → Type → (Type → Type) → Type → Type) blk m = client (Header blk) (Point blk) (Tip blk) m ChainSyncClientResult Source #
Merely a helpful abbreviation
A newtype wrapper to avoid confusing our tip with their tip.
A newtype wrapper to avoid confusing our tip with their tip.
Genesis configuration
Configuration of ChainSync Jumping
CSJDisabled | Disable ChainSync Jumping. All clients will fully synchronize with the chain of its peer. |
CSJEnabled CSJEnabledConfig | Enable ChainSync Jumping |
newtype CSJEnabledConfig Source #
CSJEnabledConfig | |
|
data ChainSyncLoPBucketConfig Source #
Configuration of the leaky bucket.
ChainSyncLoPBucketDisabled | Fully disable the leaky bucket. The background thread that is used to run it will not even be started. |
ChainSyncLoPBucketEnabled ChainSyncLoPBucketEnabledConfig | Enable the leaky bucket. |
data ChainSyncLoPBucketEnabledConfig Source #
Configuration of the leaky bucket when it is enabled.
ChainSyncLoPBucketEnabledConfig | |
|
Trace events
data TraceChainSyncClientEvent blk Source #
Events traced by the Chain Sync Client.
TraceDownloadedHeader (Header blk) | While following a candidate chain, we rolled forward by downloading a header. |
TraceRolledBack (Point blk) | While following a candidate chain, we rolled back to the given point. |
TraceFoundIntersection (Point blk) (Our (Tip blk)) (Their (Tip blk)) | We found an intersection between our chain fragment and the candidate's chain. |
TraceException ChainSyncClientException | An exception was thrown by the Chain Sync Client. |
TraceTermination ChainSyncClientResult | The client has terminated. |
TraceValidatedHeader (Header blk) | We have validated the given header. |
TraceWaitingBeyondForecastHorizon SlotNo | The |
TraceAccessingForecastHorizon SlotNo | The |
TraceGaveLoPToken Bool (Header blk) BlockNo | Whether we added a token to the LoP bucket of the peer. Also carries the considered header and the best block number known prior to this header. |
TraceOfferJump (Point blk) | ChainSync Jumping offering a point to jump to. |
TraceJumpResult (JumpResult blk) | ChainSync Jumping -- reply. |
TraceJumpingWaitingForNextInstruction | ChainSync Jumping -- the ChainSync client is requesting the next instruction. |
TraceJumpingInstructionIs (Instruction blk) | ChainSync Jumping -- the ChainSync client got its next instruction. |
Instances
(BlockSupportsProtocol blk, Show (Header blk)) ⇒ Show (TraceChainSyncClientEvent blk) Source # | |
Defined in Ouroboros.Consensus.MiniProtocol.ChainSync.Client showsPrec ∷ Int → TraceChainSyncClientEvent blk → ShowS # show ∷ TraceChainSyncClientEvent blk → String # showList ∷ [TraceChainSyncClientEvent blk] → ShowS # | |
(BlockSupportsProtocol blk, Eq (Header blk)) ⇒ Eq (TraceChainSyncClientEvent blk) Source # | |
Defined in Ouroboros.Consensus.MiniProtocol.ChainSync.Client (==) ∷ TraceChainSyncClientEvent blk → TraceChainSyncClientEvent blk → Bool # (/=) ∷ TraceChainSyncClientEvent blk → TraceChainSyncClientEvent blk → Bool # |
State shared with other components
data ChainSyncClientHandle m blk Source #
An interface to a ChainSync client that's used by other components, like the GDD governor.
ChainSyncClientHandle | |
|
Instances
data ChainSyncState blk Source #
A ChainSync client's state that's used by other components, like the GDD or the jumping governor.
ChainSyncState | |
|
Instances
data ChainSyncStateView m blk Source #
Interface for the ChainSync client to its state allocated by
bracketChainSyncClient
.
ChainSyncStateView | |
|
Instances
Generic (ChainSyncStateView m blk) Source # | |
Defined in Ouroboros.Consensus.MiniProtocol.ChainSync.Client type Rep (ChainSyncStateView m blk) ∷ Type → Type # from ∷ ChainSyncStateView m blk → Rep (ChainSyncStateView m blk) x # to ∷ Rep (ChainSyncStateView m blk) x → ChainSyncStateView m blk # | |
(IOLike m, HasHeader blk, NoThunks (Header blk)) ⇒ NoThunks (ChainSyncStateView m blk) Source # | |
type Rep (ChainSyncStateView m blk) Source # | |
chainSyncStateFor ∷ Ord peer ⇒ IOLike m ⇒ StrictTVar m (Map peer (ChainSyncClientHandle m blk)) → peer → STM m (ChainSyncState blk) Source #
Convenience function for reading the ChainSyncState
for a single peer
from a nested set of TVars.
noIdling ∷ Applicative m ⇒ Idling m Source #
No-op implementation, for tests.
noLoPBucket ∷ Applicative m ⇒ LoPBucket m Source #
No-op implementation, for tests.
viewChainSyncState ∷ IOLike m ⇒ StrictTVar m (Map peer (ChainSyncClientHandle m blk)) → (ChainSyncState blk → a) → STM m (Map peer a) Source #
Convenience function for reading a nested set of TVars and extracting some
data from ChainSyncState
.