{-# LANGUAGE DeriveFunctor       #-}
{-# LANGUAGE NamedFieldPuns      #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies        #-}

{-| Let's start with the big picture...

@
Key:  ┏━━━━━━━━━━━━┓  ╔═════════════╗  ┏━━━━━━━━━━━━━━┓   ╔════════════╗
      ┃ STM-based  ┃  ║active thread║  ┃state instance┃┓  ║ one thread ║╗
      ┃shared state┃  ║             ║  ┃   per peer   ┃┃  ║  per peer  ║║
      ┗━━━━━━━━━━━━┛  ╚═════════════╝  ┗━━━━━━━━━━━━━━┛┃  ╚════════════╝║
                                        ┗━━━━━━━━━━━━━━┛   ╚════════════╝
@

@
  ╔═════════════╗     ┏━━━━━━━━━━━━━┓
  ║ Chain sync  ║╗    ┃   Ledger    ┃
  ║  protocol   ║║◀───┨   state     ┃◀───────────╮
  ║(client side)║║    ┃             ┃            │
  ╚══════╤══════╝║    ┗━━━━━━━━━━━━━┛            │
   ╚═════╪═══════╝                               │
         ▼                                       │
  ┏━━━━━━━━━━━━━┓     ┏━━━━━━━━━━━━━┓     ╔══════╧══════╗
  ┃  Candidate  ┃     ┃   Set of    ┃     ║  Chain and  ║
  ┃  chains     ┃     ┃  downloaded ┠────▶║   ledger    ║
  ┃  (headers)  ┃     ┃   blocks    ┃     ║  validation ║
  ┗━━━━━┯━━━━━━━┛     ┗━━━━━┯━━━━━━━┛     ╚══════╤══════╝
        │                   │ ▲                  │
        │ ╭─────────────────╯ │                  │
░░░░░░░░▼░▼░░░░░░░░           │                  ▼
░░╔═════════════╗░░           │           ┏━━━━━━━━━━━━━┓     ╔═════════════╗
░░║    Block    ║░░           │           ┃   Current   ┃     ║ Block fetch ║╗
░░╢    fetch    ║◀────────────┼───────────┨    chain    ┠────▶║ protocol    ║║
░░║    logic    ║░░           │           ┃  (blocks)   ┃     ║(server side)║║
░░╚═════════════╝░░           │           ┠─────────────┨     ╚═════════════╝║
░░░░░░░░░▲░░░░░░░░░           │           ┃  Tentative  ┃      ╚═════════════╝
░░░░░░░░░▼░░░░░░░░░░░░░░░░░░░░│░░░░░░░░   ┃    chain    ┠──╮
░░┏━━━━━━━━━━━━━┓░░░░░╔═══════╧═════╗░░   ┃  (headers)  ┃  │  ╔═════════════╗
░░┃ Block fetch ┃┓░░░░║ block fetch ║╗░   ┗━━━━━━━━━━━━━┛  │  ║ Chain sync  ║╗
░░┃  state and  ┃┃◀──▶║  protocol   ║║░                    ╰─▶║ protocol    ║║
░░┃  requests   ┃┃░░░░║(client side)║║░                       ║(server side)║║
░░┗━━━━━━━━━━━━━┛┃░░░░╚═════════════╝║░                       ╚═════════════╝║
░░░┗━━━━━━━━━━━━━┛░░░░░╚═════════════╝░                        ╚═════════════╝
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
@
Notes:

 * Thread communication is via STM based state.
 * Outbound: threads update STM state.
 * Inbound: threads wait on STM state changing (using retry).
 * These are no queues: there is only the current state, not all change events.

We consider the block fetch logic and the policy for the block fetch protocol
client together as one unit of functionality. This is the shaded area in the
diagram.

Looking at the diagram we see that these two threads interact with each other
and other threads via the following shared state

+-----------------------------+----------------+--------------------+
|  State                      |  Interactions  | Internal\/External |
+=============================+================+====================+
|  Candidate chains (headers) |  Read          |  External          |
+-----------------------------+----------------+--------------------+
|  Current chain (blocks)     |  Read          |  External          |
+-----------------------------+----------------+--------------------+
|  Set of downloaded blocks   |  Read & Write  |  External          |
+-----------------------------+----------------+--------------------+
|  Block fetch requests       |  Read & Write  |  Internal          |
+-----------------------------+----------------+--------------------+

The block fetch requests state is private between the block fetch logic
and the block fetch protocol client, so it is implemented here.

The other state is managed by the consensus layer and is considered external
here. So here we define interfaces for interacting with the external state.
These have to be provided when instantiating the block fetch logic.

-}
module Ouroboros.Network.BlockFetch
  ( blockFetchLogic
  , BlockFetchConfiguration (..)
  , BlockFetchConsensusInterface (..)
    -- ** Tracer types
  , FetchDecision
  , TraceFetchClientState (..)
  , TraceLabelPeer (..)
    -- * The 'FetchClientRegistry'
  , FetchClientRegistry
  , newFetchClientRegistry
  , bracketFetchClient
  , bracketSyncWithFetchClient
  , bracketKeepAliveClient
    -- * Re-export types used by 'BlockFetchConsensusInterface'
  , FetchMode (..)
  , FromConsensus (..)
  , SizeInBytes
  , WhetherReceivingTentativeBlocks (..)
  ) where

import           Data.Hashable (Hashable)
import           Data.Map.Strict (Map)
import           Data.Void
import           GHC.Stack (HasCallStack)

import           Control.Monad.Class.MonadSTM
import           Control.Monad.Class.MonadTime
import           Control.Monad.Class.MonadTimer
import           Control.Tracer (Tracer)

import           Ouroboros.Network.AnchoredFragment (AnchoredFragment)
import           Ouroboros.Network.Block
import           Ouroboros.Network.DeltaQ (SizeInBytes)

import           Ouroboros.Network.BlockFetch.ClientRegistry
                     (FetchClientPolicy (..), FetchClientRegistry,
                     bracketFetchClient, bracketKeepAliveClient,
                     bracketSyncWithFetchClient, newFetchClientRegistry,
                     readFetchClientsStateVars, readFetchClientsStatus,
                     readPeerGSVs, setFetchClientContext)
import           Ouroboros.Network.BlockFetch.ClientState (FromConsensus (..),
                     WhetherReceivingTentativeBlocks (..))
import           Ouroboros.Network.BlockFetch.State


-- | The consensus layer functionality that the block fetch logic requires.
--
-- These are provided as input to the block fetch by the consensus layer.
--
data BlockFetchConsensusInterface peer header block m =
     BlockFetchConsensusInterface {

       -- | Read the K-suffixes of the candidate chains.
       --
       -- Assumptions:
       -- * They must be already validated.
       -- * They may contain /fewer/ than @K@ blocks.
       -- * Their anchor does not have to intersect with the current chain.
       BlockFetchConsensusInterface peer header block m
-> STM m (Map peer (AnchoredFragment header))
readCandidateChains    :: STM m (Map peer (AnchoredFragment header)),

       -- | Read the K-suffix of the current chain.
       --
       -- This must contain info on the last @K@ blocks (unless we're near
       -- the chain genesis of course).
       --
       BlockFetchConsensusInterface peer header block m
-> STM m (AnchoredFragment header)
readCurrentChain       :: STM m (AnchoredFragment header),

       -- | Read the current fetch mode that the block fetch logic should use.
       --
       -- The fetch mode is a dynamic part of the block fetch policy. In
       -- 'FetchModeBulkSync' it follows a policy that optimises for expected
       -- bandwidth over latency to fetch any particular block, whereas in
       -- 'FetchModeDeadline' it follows a policy optimises for the latency
       -- to fetch blocks, at the expense of wasting bandwidth.
       --
       -- This mode should be set so that when the node's current chain is near
       -- to \"now\" it uses the deadline mode, and when it is far away it uses
       -- the bulk sync mode.
       --
       BlockFetchConsensusInterface peer header block m -> STM m FetchMode
readFetchMode          :: STM m FetchMode,

       -- | Recent, only within last K
       BlockFetchConsensusInterface peer header block m
-> STM m (Point block -> Bool)
readFetchedBlocks      :: STM m (Point block -> Bool),

       -- | This method allocates an @addFetchedBlock@ function per client.
       -- That function and 'readFetchedBlocks' are required to be linked. Upon
       -- successful completion of @addFetchedBlock@ it must be the case that
       -- 'readFetchedBlocks' reports the block.
       BlockFetchConsensusInterface peer header block m
-> WhetherReceivingTentativeBlocks
-> STM m (Point block -> block -> m ())
mkAddFetchedBlock      :: WhetherReceivingTentativeBlocks
                              -> STM m (Point block -> block -> m ()),

       -- | The highest stored/downloaded slot number.
       --
       -- This is used to optimise the filtering of fragments in the block
       -- fetch logic: when removing already downloaded blocks from a
       -- fragment, the filtering (with a linear cost) is stopped as soon as a
       -- block has a slot number higher than this slot number, as it cannot
       -- have been downloaded anyway.
       BlockFetchConsensusInterface peer header block m -> STM m MaxSlotNo
readFetchedMaxSlotNo    :: STM m MaxSlotNo,

       -- | Given the current chain, is the given chain plausible as a
       -- candidate chain. Classically for Ouroboros this would simply
       -- check if the candidate is strictly longer, but for Ouroboros
       -- with operational key certificates there are also cases where
       -- we would consider a chain of equal length to the current chain.
       --
       BlockFetchConsensusInterface peer header block m
-> HasCallStack =>
   AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain :: HasCallStack
                               => AnchoredFragment header
                               -> AnchoredFragment header -> Bool,

       -- | Compare two candidate chains and return a preference ordering.
       -- This is used as part of selecting which chains to prioritise for
       -- downloading block bodies.
       --
       BlockFetchConsensusInterface peer header block m
-> HasCallStack =>
   AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains  :: HasCallStack
                               => AnchoredFragment header
                               -> AnchoredFragment header
                               -> Ordering,

       -- | Much of the logic for deciding which blocks to download from which
       -- peer depends on making estimates based on recent performance metrics.
       -- These estimates of course depend on the amount of data we will be
       -- downloading.
       --
       BlockFetchConsensusInterface peer header block m
-> header -> SizeInBytes
blockFetchSize          :: header -> SizeInBytes,

       -- | Given a block header, validate the supposed corresponding block
       -- body.
       --
       BlockFetchConsensusInterface peer header block m
-> header -> block -> Bool
blockMatchesHeader      :: header -> block -> Bool,

       -- | Calculate when a header's block was forged.
       --
       -- PRECONDITION: This function will succeed and give a _correct_ result
       -- when applied to headers obtained via this interface (ie via
       -- Consensus, ie via 'readCurrentChain' or 'readCandidateChains').
       --
       -- WARNING: This function may fail or, worse, __give an incorrect result
       -- (!!)__ if applied to headers obtained from sources outside of this
       -- interface. The 'FromConsensus' newtype wrapper is intended to make it
       -- difficult to make that mistake, so please pay that syntactic price
       -- and consider its meaning at each call to this function. Relatedly,
       -- preserve that argument wrapper as much as possible when deriving
       -- ancillary functions\/interfaces from this function.
       BlockFetchConsensusInterface peer header block m
-> FromConsensus header -> STM m UTCTime
headerForgeUTCTime :: FromConsensus header -> STM m UTCTime,

       -- | Calculate when a block was forged.
       --
       -- PRECONDITION: Same as 'headerForgeUTCTime'.
       --
       -- WARNING: Same as 'headerForgeUTCTime'.
       BlockFetchConsensusInterface peer header block m
-> FromConsensus block -> STM m UTCTime
blockForgeUTCTime  :: FromConsensus block -> STM m UTCTime
     }

-- | Configuration for FetchDecisionPolicy.
-- Should be determined by external local node config.
data BlockFetchConfiguration =
     BlockFetchConfiguration {
         -- | Maximum concurrent downloads during bulk syncing.
         BlockFetchConfiguration -> Word
bfcMaxConcurrencyBulkSync :: !Word,

         -- | Maximum concurrent downloads during deadline syncing.
         BlockFetchConfiguration -> Word
bfcMaxConcurrencyDeadline :: !Word,

         -- | Maximum requests in flight per each peer.
         BlockFetchConfiguration -> Word
bfcMaxRequestsInflight    :: !Word,

         -- | Desired intervall between calls to fetchLogicIteration
         BlockFetchConfiguration -> DiffTime
bfcDecisionLoopInterval   :: !DiffTime,

         -- | Salt used when comparing peers
         BlockFetchConfiguration -> Int
bfcSalt                   :: !Int
     }

-- | Execute the block fetch logic. It monitors the current chain and candidate
-- chains. It decided which block bodies to fetch and manages the process of
-- fetching them, including making alternative decisions based on timeouts and
-- failures.
--
-- This runs forever and should be shut down using mechanisms such as async.
--
blockFetchLogic :: forall peer header block m.
                   ( HasHeader header
                   , HasHeader block
                   , HeaderHash header ~ HeaderHash block
                   , MonadDelay m
                   , MonadMonotonicTime m
                   , MonadSTM m
                   , Ord peer
                   , Hashable peer
                   )
                => Tracer m [TraceLabelPeer peer (FetchDecision [Point header])]
                -> Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
                -> BlockFetchConsensusInterface peer header block m
                -> FetchClientRegistry peer header block m
                -> BlockFetchConfiguration
                -> m Void
blockFetchLogic :: Tracer m [TraceLabelPeer peer (FetchDecision [Point header])]
-> Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
-> BlockFetchConsensusInterface peer header block m
-> FetchClientRegistry peer header block m
-> BlockFetchConfiguration
-> m Void
blockFetchLogic Tracer m [TraceLabelPeer peer (FetchDecision [Point header])]
decisionTracer Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
clientStateTracer
                BlockFetchConsensusInterface{STM m (Map peer (AnchoredFragment header))
STM m (AnchoredFragment header)
STM m MaxSlotNo
STM m FetchMode
STM m (Point block -> Bool)
header -> SizeInBytes
header -> block -> Bool
HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
FromConsensus header -> STM m UTCTime
FromConsensus block -> STM m UTCTime
WhetherReceivingTentativeBlocks
-> STM m (Point block -> block -> m ())
blockForgeUTCTime :: FromConsensus block -> STM m UTCTime
headerForgeUTCTime :: FromConsensus header -> STM m UTCTime
blockMatchesHeader :: header -> block -> Bool
blockFetchSize :: header -> SizeInBytes
compareCandidateChains :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
plausibleCandidateChain :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
readFetchedMaxSlotNo :: STM m MaxSlotNo
mkAddFetchedBlock :: WhetherReceivingTentativeBlocks
-> STM m (Point block -> block -> m ())
readFetchedBlocks :: STM m (Point block -> Bool)
readFetchMode :: STM m FetchMode
readCurrentChain :: STM m (AnchoredFragment header)
readCandidateChains :: STM m (Map peer (AnchoredFragment header))
blockForgeUTCTime :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> FromConsensus block -> STM m UTCTime
headerForgeUTCTime :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> FromConsensus header -> STM m UTCTime
blockMatchesHeader :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> header -> block -> Bool
blockFetchSize :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> header -> SizeInBytes
compareCandidateChains :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> HasCallStack =>
   AnchoredFragment header -> AnchoredFragment header -> Ordering
plausibleCandidateChain :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> HasCallStack =>
   AnchoredFragment header -> AnchoredFragment header -> Bool
readFetchedMaxSlotNo :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m -> STM m MaxSlotNo
mkAddFetchedBlock :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> WhetherReceivingTentativeBlocks
-> STM m (Point block -> block -> m ())
readFetchedBlocks :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> STM m (Point block -> Bool)
readFetchMode :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m -> STM m FetchMode
readCurrentChain :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> STM m (AnchoredFragment header)
readCandidateChains :: forall peer header block (m :: * -> *).
BlockFetchConsensusInterface peer header block m
-> STM m (Map peer (AnchoredFragment header))
..}
                FetchClientRegistry peer header block m
registry
                BlockFetchConfiguration{Int
Word
DiffTime
bfcSalt :: Int
bfcDecisionLoopInterval :: DiffTime
bfcMaxRequestsInflight :: Word
bfcMaxConcurrencyDeadline :: Word
bfcMaxConcurrencyBulkSync :: Word
bfcSalt :: BlockFetchConfiguration -> Int
bfcDecisionLoopInterval :: BlockFetchConfiguration -> DiffTime
bfcMaxRequestsInflight :: BlockFetchConfiguration -> Word
bfcMaxConcurrencyDeadline :: BlockFetchConfiguration -> Word
bfcMaxConcurrencyBulkSync :: BlockFetchConfiguration -> Word
..} = do

    FetchClientRegistry peer header block m
-> Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
-> (WhetherReceivingTentativeBlocks
    -> STM m (FetchClientPolicy header block m))
-> m ()
forall (m :: * -> *) peer header block.
MonadSTM m =>
FetchClientRegistry peer header block m
-> Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
-> (WhetherReceivingTentativeBlocks
    -> STM m (FetchClientPolicy header block m))
-> m ()
setFetchClientContext FetchClientRegistry peer header block m
registry Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
clientStateTracer WhetherReceivingTentativeBlocks
-> STM m (FetchClientPolicy header block m)
mkFetchClientPolicy

    Tracer m [TraceLabelPeer peer (FetchDecision [Point header])]
-> Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
-> FetchDecisionPolicy header
-> FetchTriggerVariables peer header m
-> FetchNonTriggerVariables peer header block m
-> m Void
forall header block (m :: * -> *) peer.
(HasHeader header, HasHeader block,
 HeaderHash header ~ HeaderHash block, MonadDelay m,
 MonadMonotonicTime m, MonadSTM m, Ord peer, Hashable peer) =>
Tracer m [TraceLabelPeer peer (FetchDecision [Point header])]
-> Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
-> FetchDecisionPolicy header
-> FetchTriggerVariables peer header m
-> FetchNonTriggerVariables peer header block m
-> m Void
fetchLogicIterations
      Tracer m [TraceLabelPeer peer (FetchDecision [Point header])]
decisionTracer Tracer m (TraceLabelPeer peer (TraceFetchClientState header))
clientStateTracer
      FetchDecisionPolicy header
fetchDecisionPolicy
      FetchTriggerVariables peer header m
fetchTriggerVariables
      FetchNonTriggerVariables peer header block m
fetchNonTriggerVariables
  where
    mkFetchClientPolicy :: WhetherReceivingTentativeBlocks -> STM m (FetchClientPolicy header block m)
    mkFetchClientPolicy :: WhetherReceivingTentativeBlocks
-> STM m (FetchClientPolicy header block m)
mkFetchClientPolicy WhetherReceivingTentativeBlocks
receivingTentativeBlocks = do
      Point block -> block -> m ()
addFetchedBlock <- WhetherReceivingTentativeBlocks
-> STM m (Point block -> block -> m ())
mkAddFetchedBlock WhetherReceivingTentativeBlocks
receivingTentativeBlocks
      FetchClientPolicy header block m
-> STM m (FetchClientPolicy header block m)
forall (f :: * -> *) a. Applicative f => a -> f a
pure FetchClientPolicy :: forall header block (m :: * -> *).
(header -> SizeInBytes)
-> (header -> block -> Bool)
-> (Point block -> block -> m ())
-> (FromConsensus block -> STM m UTCTime)
-> FetchClientPolicy header block m
FetchClientPolicy {
          header -> SizeInBytes
blockFetchSize :: header -> SizeInBytes
blockFetchSize :: header -> SizeInBytes
blockFetchSize,
          header -> block -> Bool
blockMatchesHeader :: header -> block -> Bool
blockMatchesHeader :: header -> block -> Bool
blockMatchesHeader,
          Point block -> block -> m ()
addFetchedBlock :: Point block -> block -> m ()
addFetchedBlock :: Point block -> block -> m ()
addFetchedBlock,
          FromConsensus block -> STM m UTCTime
blockForgeUTCTime :: FromConsensus block -> STM m UTCTime
blockForgeUTCTime :: FromConsensus block -> STM m UTCTime
blockForgeUTCTime
        }

    fetchDecisionPolicy :: FetchDecisionPolicy header
    fetchDecisionPolicy :: FetchDecisionPolicy header
fetchDecisionPolicy =
      FetchDecisionPolicy :: forall header.
Word
-> Word
-> Word
-> DiffTime
-> Int
-> (HasCallStack =>
    AnchoredFragment header -> AnchoredFragment header -> Bool)
-> (HasCallStack =>
    AnchoredFragment header -> AnchoredFragment header -> Ordering)
-> (header -> SizeInBytes)
-> FetchDecisionPolicy header
FetchDecisionPolicy {
        maxInFlightReqsPerPeer :: Word
maxInFlightReqsPerPeer   = Word
bfcMaxRequestsInflight,
        maxConcurrencyBulkSync :: Word
maxConcurrencyBulkSync   = Word
bfcMaxConcurrencyBulkSync,
        maxConcurrencyDeadline :: Word
maxConcurrencyDeadline   = Word
bfcMaxConcurrencyDeadline,
        decisionLoopInterval :: DiffTime
decisionLoopInterval     = DiffTime
bfcDecisionLoopInterval,
        peerSalt :: Int
peerSalt                 = Int
bfcSalt,

        HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain,
        HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains,
        header -> SizeInBytes
blockFetchSize :: header -> SizeInBytes
blockFetchSize :: header -> SizeInBytes
blockFetchSize
      }

    fetchTriggerVariables :: FetchTriggerVariables peer header m
    fetchTriggerVariables :: FetchTriggerVariables peer header m
fetchTriggerVariables =
      FetchTriggerVariables :: forall peer header (m :: * -> *).
STM m (AnchoredFragment header)
-> STM m (Map peer (AnchoredFragment header))
-> STM m (Map peer (PeerFetchStatus header))
-> FetchTriggerVariables peer header m
FetchTriggerVariables {
        readStateCurrentChain :: STM m (AnchoredFragment header)
readStateCurrentChain    = STM m (AnchoredFragment header)
readCurrentChain,
        readStateCandidateChains :: STM m (Map peer (AnchoredFragment header))
readStateCandidateChains = STM m (Map peer (AnchoredFragment header))
readCandidateChains,
        readStatePeerStatus :: STM m (Map peer (PeerFetchStatus header))
readStatePeerStatus      = FetchClientRegistry peer header block m
-> STM m (Map peer (PeerFetchStatus header))
forall (m :: * -> *) peer header block.
MonadSTM m =>
FetchClientRegistry peer header block m
-> STM m (Map peer (PeerFetchStatus header))
readFetchClientsStatus FetchClientRegistry peer header block m
registry
      }

    fetchNonTriggerVariables :: FetchNonTriggerVariables peer header block m
    fetchNonTriggerVariables :: FetchNonTriggerVariables peer header block m
fetchNonTriggerVariables =
      FetchNonTriggerVariables :: forall peer header block (m :: * -> *).
STM m (Point block -> Bool)
-> STM m (Map peer (FetchClientStateVars m header))
-> STM m (Map peer PeerGSV)
-> STM m FetchMode
-> STM m MaxSlotNo
-> FetchNonTriggerVariables peer header block m
FetchNonTriggerVariables {
        readStateFetchedBlocks :: STM m (Point block -> Bool)
readStateFetchedBlocks    = STM m (Point block -> Bool)
readFetchedBlocks,
        readStatePeerStateVars :: STM m (Map peer (FetchClientStateVars m header))
readStatePeerStateVars    = FetchClientRegistry peer header block m
-> STM m (Map peer (FetchClientStateVars m header))
forall (m :: * -> *) peer header block.
MonadSTM m =>
FetchClientRegistry peer header block m
-> STM m (Map peer (FetchClientStateVars m header))
readFetchClientsStateVars FetchClientRegistry peer header block m
registry,
        readStatePeerGSVs :: STM m (Map peer PeerGSV)
readStatePeerGSVs         = FetchClientRegistry peer header block m -> STM m (Map peer PeerGSV)
forall (m :: * -> *) peer header block.
MonadSTM m =>
FetchClientRegistry peer header block m -> STM m (Map peer PeerGSV)
readPeerGSVs FetchClientRegistry peer header block m
registry,
        readStateFetchMode :: STM m FetchMode
readStateFetchMode        = STM m FetchMode
readFetchMode,
        readStateFetchedMaxSlotNo :: STM m MaxSlotNo
readStateFetchedMaxSlotNo = STM m MaxSlotNo
readFetchedMaxSlotNo
      }