{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Ouroboros.Network.BlockFetch.Decision.Genesis
(
fetchDecisionsGenesisM
) where
import Control.Exception (assert)
import Control.Monad (guard)
import Control.Monad.Class.MonadTime.SI (MonadMonotonicTime (getMonotonicTime),
addTime)
import Control.Monad.Trans.Maybe (MaybeT (MaybeT, runMaybeT))
import Control.Monad.Trans.Writer.CPS (Writer, runWriter, tell)
import Control.Tracer (Tracer, traceWith)
import Data.Bifunctor (Bifunctor (..), first)
import Data.DList (DList)
import Data.DList qualified as DList
import Data.Foldable (find, toList)
import Data.List qualified as List
import Data.Maybe (maybeToList)
import Data.Sequence (Seq (..), (<|), (><), (|>))
import Data.Sequence qualified as Sequence
import Data.Set qualified as Set
import Cardano.Prelude (partitionEithers)
import Ouroboros.Network.AnchoredFragment (AnchoredFragment)
import Ouroboros.Network.AnchoredFragment qualified as AF
import Ouroboros.Network.Block
import Ouroboros.Network.BlockFetch.ClientState (FetchRequest (..),
PeerFetchInFlight (..), PeersOrder (..))
import Ouroboros.Network.BlockFetch.ConsensusInterface (ChainSelStarvation (..),
FetchMode (..))
import Ouroboros.Network.BlockFetch.DeltaQ (calculatePeerFetchInFlightLimits)
import Cardano.Slotting.Slot (WithOrigin)
import Ouroboros.Network.BlockFetch.Decision
import Ouroboros.Network.BlockFetch.Decision.Trace (TraceDecisionEvent (..))
type WithDeclined peer = Writer (DList (FetchDecline, peer))
runWithDeclined :: WithDeclined peer a -> (a, DList (FetchDecline, peer))
runWithDeclined :: forall peer a.
WithDeclined peer a -> (a, DList (FetchDecline, peer))
runWithDeclined = Writer (DList (FetchDecline, peer)) a
-> (a, DList (FetchDecline, peer))
forall w a. Monoid w => Writer w a -> (a, w)
runWriter
fetchDecisionsGenesisM
:: forall peer header block m extra.
(Ord peer,
HasHeader header,
HeaderHash header ~ HeaderHash block, MonadMonotonicTime m)
=> Tracer m (TraceDecisionEvent peer header)
-> FetchDecisionPolicy header
-> AnchoredFragment header
-> (Point block -> Bool)
-> MaxSlotNo
-> ChainSelStarvation
-> ( PeersOrder peer
, PeersOrder peer -> m ()
, peer -> m ()
)
-> [(AnchoredFragment header, PeerInfo header peer extra)]
-> m [(FetchDecision (FetchRequest header), PeerInfo header peer extra)]
fetchDecisionsGenesisM :: forall peer header block (m :: * -> *) extra.
(Ord peer, HasHeader header, HeaderHash header ~ HeaderHash block,
MonadMonotonicTime m) =>
Tracer m (TraceDecisionEvent peer header)
-> FetchDecisionPolicy header
-> AnchoredFragment header
-> (Point block -> Bool)
-> MaxSlotNo
-> ChainSelStarvation
-> (PeersOrder peer, PeersOrder peer -> m (), peer -> m ())
-> [(AnchoredFragment header, PeerInfo header peer extra)]
-> m [(FetchDecision (FetchRequest header),
PeerInfo header peer extra)]
fetchDecisionsGenesisM
Tracer m (TraceDecisionEvent peer header)
tracer
fetchDecisionPolicy :: FetchDecisionPolicy header
fetchDecisionPolicy@FetchDecisionPolicy {DiffTime
bulkSyncGracePeriod :: DiffTime
bulkSyncGracePeriod :: forall header. FetchDecisionPolicy header -> DiffTime
bulkSyncGracePeriod}
AnchoredFragment header
currentChain
Point block -> Bool
fetchedBlocks
MaxSlotNo
fetchedMaxSlotNo
ChainSelStarvation
chainSelStarvation
( PeersOrder peer
peersOrder0,
PeersOrder peer -> m ()
writePeersOrder,
peer -> m ()
demoteCSJDynamo
)
[(AnchoredFragment header, PeerInfo header peer extra)]
candidatesAndPeers = do
peersOrder1 <- PeersOrder peer -> m (PeersOrder peer)
checkLastChainSelStarvation PeersOrder peer
peersOrder0
let (peersOrder, orderedCandidatesAndPeers) =
alignPeersOrderWithActualPeers
(peerInfoPeer . snd)
(Sequence.fromList candidatesAndPeers)
peersOrder1
let (theDecision, declines) =
fetchDecisionsGenesis
fetchDecisionPolicy
currentChain
fetchedBlocks
fetchedMaxSlotNo
(toList orderedCandidatesAndPeers)
newCurrentPeer = PeerInfo header peer extra -> peer
forall header peer extra. PeerInfo header peer extra -> peer
peerInfoPeer (PeerInfo header peer extra -> peer)
-> ((FetchRequest header, PeerInfo header peer extra)
-> PeerInfo header peer extra)
-> (FetchRequest header, PeerInfo header peer extra)
-> peer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FetchRequest header, PeerInfo header peer extra)
-> PeerInfo header peer extra
forall a b. (a, b) -> b
snd ((FetchRequest header, PeerInfo header peer extra) -> peer)
-> Maybe (FetchRequest header, PeerInfo header peer extra)
-> Maybe peer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (FetchRequest header, PeerInfo header peer extra)
theDecision
case theDecision of
Just (FetchRequest header
_, (PeerFetchStatus header
_, PeerFetchInFlight header
inflight, PeerGSV
_, peer
_, extra
_))
| Set (Point header) -> Bool
forall a. Set a -> Bool
Set.null (PeerFetchInFlight header -> Set (Point header)
forall header. PeerFetchInFlight header -> Set (Point header)
peerFetchBlocksInFlight PeerFetchInFlight header
inflight)
-> do
peersOrderStart <- m Time
forall (m :: * -> *). MonadMonotonicTime m => m Time
getMonotonicTime
writePeersOrder $ setCurrentPeer newCurrentPeer peersOrder
{ peersOrderStart }
| Maybe peer
newCurrentPeer Maybe peer -> Maybe peer -> Bool
forall a. Eq a => a -> a -> Bool
/= PeersOrder peer -> Maybe peer
forall peer. PeersOrder peer -> Maybe peer
peersOrderCurrent PeersOrder peer
peersOrder0
->
PeersOrder peer -> m ()
writePeersOrder (PeersOrder peer -> m ()) -> PeersOrder peer -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe peer -> PeersOrder peer -> PeersOrder peer
setCurrentPeer Maybe peer
newCurrentPeer PeersOrder peer
peersOrder
Maybe (FetchRequest header, PeerInfo header peer extra)
_ -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
pure $
map (first Right) (maybeToList theDecision)
++ map (first Left) declines
where
alignPeersOrderWithActualPeers
:: forall d.
(d -> peer)
-> Seq d
-> PeersOrder peer
-> (PeersOrder peer, Seq d)
alignPeersOrderWithActualPeers :: forall d.
(d -> peer) -> Seq d -> PeersOrder peer -> (PeersOrder peer, Seq d)
alignPeersOrderWithActualPeers
d -> peer
peerOf
Seq d
actualPeers
PeersOrder {Time
peersOrderStart :: forall peer. PeersOrder peer -> Time
peersOrderStart :: Time
peersOrderStart, Maybe peer
peersOrderCurrent :: forall peer. PeersOrder peer -> Maybe peer
peersOrderCurrent :: Maybe peer
peersOrderCurrent, Seq peer
peersOrderAll :: Seq peer
peersOrderAll :: forall peer. PeersOrder peer -> Seq peer
peersOrderAll} =
let peersOrderAll' :: Seq d
peersOrderAll' :: Seq d
peersOrderAll' =
(peer -> Seq d -> Seq d) -> Seq d -> Seq peer -> Seq d
forall a b. (a -> b -> b) -> b -> Seq a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\peer
p Seq d
ds ->
case (d -> Bool) -> Seq d -> Maybe d
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((peer
p peer -> peer -> Bool
forall a. Eq a => a -> a -> Bool
==) (peer -> Bool) -> (d -> peer) -> d -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> peer
peerOf) Seq d
actualPeers of
Just d
d -> d
d d -> Seq d -> Seq d
forall a. a -> Seq a -> Seq a
<| Seq d
ds
Maybe d
Nothing -> Seq d
ds
)
Seq d
forall a. Seq a
Sequence.empty
Seq peer
peersOrderAll
Seq d -> Seq d -> Seq d
forall a. Seq a -> Seq a -> Seq a
>< (d -> Bool) -> Seq d -> Seq d
forall a. (a -> Bool) -> Seq a -> Seq a
Sequence.filter ((peer -> Seq peer -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` Seq peer
peersOrderAll) (peer -> Bool) -> (d -> peer) -> d -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. d -> peer
peerOf) Seq d
actualPeers
peersOrderCurrent' :: Maybe peer
peersOrderCurrent' :: Maybe peer
peersOrderCurrent' = do
peer <- Maybe peer
peersOrderCurrent
guard $ case peersOrderAll' of
d
d Sequence.:<| Seq d
_ -> d -> peer
peerOf d
d peer -> peer -> Bool
forall a. Eq a => a -> a -> Bool
== peer
peer
Seq d
Sequence.Empty -> Bool
False
pure peer
in (PeersOrder
{ peersOrderCurrent :: Maybe peer
peersOrderCurrent = Maybe peer
peersOrderCurrent',
peersOrderAll :: Seq peer
peersOrderAll = (d -> peer) -> Seq d -> Seq peer
forall a b. (a -> b) -> Seq a -> Seq b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap d -> peer
peerOf Seq d
peersOrderAll',
Time
peersOrderStart :: Time
peersOrderStart :: Time
peersOrderStart
}
, Seq d
peersOrderAll'
)
checkLastChainSelStarvation :: PeersOrder peer -> m (PeersOrder peer)
checkLastChainSelStarvation :: PeersOrder peer -> m (PeersOrder peer)
checkLastChainSelStarvation
peersOrder :: PeersOrder peer
peersOrder@PeersOrder {Time
peersOrderStart :: forall peer. PeersOrder peer -> Time
peersOrderStart :: Time
peersOrderStart, Maybe peer
peersOrderCurrent :: forall peer. PeersOrder peer -> Maybe peer
peersOrderCurrent :: Maybe peer
peersOrderCurrent, Seq peer
peersOrderAll :: forall peer. PeersOrder peer -> Seq peer
peersOrderAll :: Seq peer
peersOrderAll} = do
lastStarvationTime <- case ChainSelStarvation
chainSelStarvation of
ChainSelStarvationEndedAt Time
time -> Time -> m Time
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Time
time
ChainSelStarvation
ChainSelStarvationOngoing -> m Time
forall (m :: * -> *). MonadMonotonicTime m => m Time
getMonotonicTime
case peersOrderCurrent of
Just peer
peer
| Time
lastStarvationTime Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
>= DiffTime -> Time -> Time
addTime DiffTime
bulkSyncGracePeriod Time
peersOrderStart -> do
Tracer m (TraceDecisionEvent peer header)
-> TraceDecisionEvent peer header -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceDecisionEvent peer header)
tracer (peer -> TraceDecisionEvent peer header
forall peer header. peer -> TraceDecisionEvent peer header
PeerStarvedUs peer
peer)
peer -> m ()
demoteCSJDynamo peer
peer
PeersOrder peer -> m (PeersOrder peer)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure PeersOrder
{
peersOrderCurrent :: Maybe peer
peersOrderCurrent = Maybe peer
forall a. Maybe a
Nothing,
peersOrderAll :: Seq peer
peersOrderAll = Int -> Seq peer -> Seq peer
forall a. Int -> Seq a -> Seq a
Sequence.drop Int
1 Seq peer
peersOrderAll Seq peer -> peer -> Seq peer
forall a. Seq a -> a -> Seq a
|> peer
peer,
Time
peersOrderStart :: Time
peersOrderStart :: Time
peersOrderStart
}
Maybe peer
_ -> PeersOrder peer -> m (PeersOrder peer)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure PeersOrder peer
peersOrder
setCurrentPeer :: Maybe peer -> PeersOrder peer -> PeersOrder peer
setCurrentPeer :: Maybe peer -> PeersOrder peer -> PeersOrder peer
setCurrentPeer Maybe peer
Nothing PeersOrder peer
peersOrder = PeersOrder peer
peersOrder {peersOrderCurrent = Nothing}
setCurrentPeer (Just peer
peer) PeersOrder peer
peersOrder =
case (peer -> Bool) -> Seq peer -> (Seq peer, Seq peer)
forall a. (a -> Bool) -> Seq a -> (Seq a, Seq a)
Sequence.breakl (peer
peer peer -> peer -> Bool
forall a. Eq a => a -> a -> Bool
==) (PeersOrder peer -> Seq peer
forall peer. PeersOrder peer -> Seq peer
peersOrderAll PeersOrder peer
peersOrder) of
(Seq peer
xs, peer
p :<| Seq peer
ys) ->
PeersOrder peer
peersOrder
{ peersOrderCurrent = Just p,
peersOrderAll = p <| xs >< ys
}
(Seq peer
_, Seq peer
Empty) -> PeersOrder peer
peersOrder {peersOrderCurrent = Nothing}
fetchDecisionsGenesis
:: forall header block peer extra.
( HasHeader header
, HeaderHash header ~ HeaderHash block
)
=> FetchDecisionPolicy header
-> AnchoredFragment header
-> (Point block -> Bool)
-> MaxSlotNo
-> [(AnchoredFragment header, PeerInfo header peer extra)]
-> ( Maybe (FetchRequest header, PeerInfo header peer extra),
[(FetchDecline, PeerInfo header peer extra)]
)
fetchDecisionsGenesis :: forall header block peer extra.
(HasHeader header, HeaderHash header ~ HeaderHash block) =>
FetchDecisionPolicy header
-> AnchoredFragment header
-> (Point block -> Bool)
-> MaxSlotNo
-> [(AnchoredFragment header, PeerInfo header peer extra)]
-> (Maybe (FetchRequest header, PeerInfo header peer extra),
[(FetchDecline, PeerInfo header peer extra)])
fetchDecisionsGenesis
FetchDecisionPolicy header
fetchDecisionPolicy
AnchoredFragment header
currentChain
Point block -> Bool
fetchedBlocks
MaxSlotNo
fetchedMaxSlotNo
[(AnchoredFragment header, PeerInfo header peer extra)]
candidatesAndPeers = MaybeT
(WithDeclined (PeerInfo header peer extra))
(FetchRequest header, PeerInfo header peer extra)
-> (Maybe (FetchRequest header, PeerInfo header peer extra),
[(FetchDecline, PeerInfo header peer extra)])
forall peerInfo a.
MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> (Maybe (a, peerInfo), [(FetchDecline, peerInfo)])
combineWithDeclined (MaybeT
(WithDeclined (PeerInfo header peer extra))
(FetchRequest header, PeerInfo header peer extra)
-> (Maybe (FetchRequest header, PeerInfo header peer extra),
[(FetchDecline, PeerInfo header peer extra)]))
-> MaybeT
(WithDeclined (PeerInfo header peer extra))
(FetchRequest header, PeerInfo header peer extra)
-> (Maybe (FetchRequest header, PeerInfo header peer extra),
[(FetchDecline, PeerInfo header peer extra)])
forall a b. (a -> b) -> a -> b
$ do
( theCandidate :: ChainSuffix header,
candidatesAndPeers' :: [(ChainSuffix header, PeerInfo header peer extra)]
) <-
WithDeclined
(PeerInfo header peer extra)
(Maybe
(ChainSuffix header,
[(ChainSuffix header, PeerInfo header peer extra)]))
-> MaybeT
(WithDeclined (PeerInfo header peer extra))
(ChainSuffix header,
[(ChainSuffix header, PeerInfo header peer extra)])
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (WithDeclined
(PeerInfo header peer extra)
(Maybe
(ChainSuffix header,
[(ChainSuffix header, PeerInfo header peer extra)]))
-> MaybeT
(WithDeclined (PeerInfo header peer extra))
(ChainSuffix header,
[(ChainSuffix header, PeerInfo header peer extra)]))
-> WithDeclined
(PeerInfo header peer extra)
(Maybe
(ChainSuffix header,
[(ChainSuffix header, PeerInfo header peer extra)]))
-> MaybeT
(WithDeclined (PeerInfo header peer extra))
(ChainSuffix header,
[(ChainSuffix header, PeerInfo header peer extra)])
forall a b. (a -> b) -> a -> b
$
FetchDecisionPolicy header
-> AnchoredFragment header
-> [(AnchoredFragment header, PeerInfo header peer extra)]
-> WithDeclined
(PeerInfo header peer extra)
(Maybe
(ChainSuffix header,
[(ChainSuffix header, PeerInfo header peer extra)]))
forall header peerInfo.
HasHeader header =>
FetchDecisionPolicy header
-> AnchoredFragment header
-> [(AnchoredFragment header, peerInfo)]
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
selectTheCandidate
FetchDecisionPolicy header
fetchDecisionPolicy
AnchoredFragment header
currentChain
[(AnchoredFragment header, PeerInfo header peer extra)]
candidatesAndPeers
theFragments :: CandidateFragments header
<- MaybeT $ dropAlreadyFetchedBlocks candidatesAndPeers' theCandidate
( thePeerCandidate :: ChainSuffix header,
thePeer :: PeerInfo header peer extra
) <-
MaybeT $ selectThePeer theFragments candidatesAndPeers'
MaybeT $
makeFetchRequest
fetchDecisionPolicy
theFragments
thePeer
thePeerCandidate
where
combineWithDeclined
:: forall peerInfo a.
MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> ( Maybe (a, peerInfo),
[(FetchDecline, peerInfo)]
)
combineWithDeclined :: forall peerInfo a.
MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> (Maybe (a, peerInfo), [(FetchDecline, peerInfo)])
combineWithDeclined = (DList (FetchDecline, peerInfo) -> [(FetchDecline, peerInfo)])
-> (Maybe (a, peerInfo), DList (FetchDecline, peerInfo))
-> (Maybe (a, peerInfo), [(FetchDecline, peerInfo)])
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second DList (FetchDecline, peerInfo) -> [(FetchDecline, peerInfo)]
forall a. DList a -> [a]
DList.toList ((Maybe (a, peerInfo), DList (FetchDecline, peerInfo))
-> (Maybe (a, peerInfo), [(FetchDecline, peerInfo)]))
-> (MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> (Maybe (a, peerInfo), DList (FetchDecline, peerInfo)))
-> MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> (Maybe (a, peerInfo), [(FetchDecline, peerInfo)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WithDeclined peerInfo (Maybe (a, peerInfo))
-> (Maybe (a, peerInfo), DList (FetchDecline, peerInfo))
forall peer a.
WithDeclined peer a -> (a, DList (FetchDecline, peer))
runWithDeclined (WithDeclined peerInfo (Maybe (a, peerInfo))
-> (Maybe (a, peerInfo), DList (FetchDecline, peerInfo)))
-> (MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> WithDeclined peerInfo (Maybe (a, peerInfo)))
-> MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> (Maybe (a, peerInfo), DList (FetchDecline, peerInfo))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MaybeT (WithDeclined peerInfo) (a, peerInfo)
-> WithDeclined peerInfo (Maybe (a, peerInfo))
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT
dropAlreadyFetchedBlocks
:: forall peerInfo.
[(ChainSuffix header, peerInfo)]
-> ChainSuffix header
-> WithDeclined peerInfo (Maybe (CandidateFragments header))
dropAlreadyFetchedBlocks :: forall peerInfo.
[(ChainSuffix header, peerInfo)]
-> ChainSuffix header
-> WithDeclined peerInfo (Maybe (CandidateFragments header))
dropAlreadyFetchedBlocks [(ChainSuffix header, peerInfo)]
candidatesAndPeers' ChainSuffix header
theCandidate =
case (Point block -> Bool)
-> MaxSlotNo
-> ChainSuffix header
-> FetchDecision (CandidateFragments header)
forall header block.
(HasHeader header, HeaderHash header ~ HeaderHash block) =>
(Point block -> Bool)
-> MaxSlotNo
-> ChainSuffix header
-> FetchDecision (CandidateFragments header)
dropAlreadyFetched Point block -> Bool
fetchedBlocks MaxSlotNo
fetchedMaxSlotNo ChainSuffix header
theCandidate of
Left FetchDecline
reason -> do
DList (FetchDecline, peerInfo)
-> WriterT (DList (FetchDecline, peerInfo)) Identity ()
forall w (m :: * -> *). (Monoid w, Monad m) => w -> WriterT w m ()
tell ([(FetchDecline, peerInfo)] -> DList (FetchDecline, peerInfo)
forall a. [a] -> DList a
DList.fromList [(FetchDecline
reason, peerInfo
peerInfo) | (ChainSuffix header
_, peerInfo
peerInfo) <- [(ChainSuffix header, peerInfo)]
candidatesAndPeers'])
Maybe (CandidateFragments header)
-> WithDeclined peerInfo (Maybe (CandidateFragments header))
forall a. a -> WriterT (DList (FetchDecline, peerInfo)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (CandidateFragments header)
forall a. Maybe a
Nothing
Right CandidateFragments header
theFragments -> Maybe (CandidateFragments header)
-> WithDeclined peerInfo (Maybe (CandidateFragments header))
forall a. a -> WriterT (DList (FetchDecline, peerInfo)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CandidateFragments header -> Maybe (CandidateFragments header)
forall a. a -> Maybe a
Just CandidateFragments header
theFragments)
dropAlreadyFetched
:: (HasHeader header, HeaderHash header ~ HeaderHash block)
=> (Point block -> Bool)
-> MaxSlotNo
-> ChainSuffix header
-> FetchDecision (CandidateFragments header)
dropAlreadyFetched :: forall header block.
(HasHeader header, HeaderHash header ~ HeaderHash block) =>
(Point block -> Bool)
-> MaxSlotNo
-> ChainSuffix header
-> FetchDecision (CandidateFragments header)
dropAlreadyFetched Point block -> Bool
alreadyDownloaded MaxSlotNo
fetchedMaxSlotNo ChainSuffix header
candidate =
if [AnchoredFragment header] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [AnchoredFragment header]
fragments
then FetchDecline -> Either FetchDecline (CandidateFragments header)
forall a b. a -> Either a b
Left FetchDecline
FetchDeclineAlreadyFetched
else CandidateFragments header
-> Either FetchDecline (CandidateFragments header)
forall a b. b -> Either a b
Right (ChainSuffix header
candidate, [AnchoredFragment header]
fragments)
where
fragments :: [AnchoredFragment header]
fragments = (header -> Bool)
-> MaxSlotNo
-> AnchoredFragment header
-> [AnchoredFragment header]
forall header.
HasHeader header =>
(header -> Bool)
-> MaxSlotNo
-> AnchoredFragment header
-> [AnchoredFragment header]
filterWithMaxSlotNo header -> Bool
notAlreadyFetched MaxSlotNo
fetchedMaxSlotNo (ChainSuffix header -> AnchoredFragment header
forall header. ChainSuffix header -> AnchoredFragment header
getChainSuffix ChainSuffix header
candidate)
notAlreadyFetched :: header -> Bool
notAlreadyFetched = Bool -> Bool
not (Bool -> Bool) -> (header -> Bool) -> header -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point block -> Bool
alreadyDownloaded (Point block -> Bool) -> (header -> Point block) -> header -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point header -> Point block
forall {k1} {k2} (b :: k1) (b' :: k2).
Coercible (HeaderHash b) (HeaderHash b') =>
Point b -> Point b'
castPoint (Point header -> Point block)
-> (header -> Point header) -> header -> Point block
forall b c a. (b -> c) -> (a -> b) -> a -> c
. header -> Point header
forall block. HasHeader block => block -> Point block
blockPoint
selectTheCandidate
:: forall header peerInfo.
HasHeader header
=> FetchDecisionPolicy header
-> AnchoredFragment header
-> [(AnchoredFragment header, peerInfo)]
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
selectTheCandidate :: forall header peerInfo.
HasHeader header =>
FetchDecisionPolicy header
-> AnchoredFragment header
-> [(AnchoredFragment header, peerInfo)]
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
selectTheCandidate
FetchDecisionPolicy {HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains :: forall header.
FetchDecisionPolicy header
-> HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains, HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain :: HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain :: forall header.
FetchDecisionPolicy header
-> HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain}
AnchoredFragment header
currentChain =
[(FetchDecision (ChainSuffix header), peerInfo)]
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
separateDeclinedAndStillInRace
([(FetchDecision (ChainSuffix header), peerInfo)]
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])))
-> ([(AnchoredFragment header, peerInfo)]
-> [(FetchDecision (ChainSuffix header), peerInfo)])
-> [(AnchoredFragment header, peerInfo)]
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AnchoredFragment header
-> [(FetchDecision (AnchoredFragment header), peerInfo)]
-> [(FetchDecision (ChainSuffix header), peerInfo)]
forall header block peerinfo.
(HasHeader header, HasHeader block,
HeaderHash header ~ HeaderHash block) =>
AnchoredFragment block
-> [(FetchDecision (AnchoredFragment header), peerinfo)]
-> [(FetchDecision (ChainSuffix header), peerinfo)]
selectForkSuffixes AnchoredFragment header
currentChain
([(FetchDecision (AnchoredFragment header), peerInfo)]
-> [(FetchDecision (ChainSuffix header), peerInfo)])
-> ([(AnchoredFragment header, peerInfo)]
-> [(FetchDecision (AnchoredFragment header), peerInfo)])
-> [(AnchoredFragment header, peerInfo)]
-> [(FetchDecision (ChainSuffix header), peerInfo)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AnchoredFragment header -> AnchoredFragment header -> Bool)
-> AnchoredFragment header
-> [(AnchoredFragment header, peerInfo)]
-> [(FetchDecision (AnchoredFragment header), peerInfo)]
forall block header peerinfo.
(AnchoredFragment block -> AnchoredFragment header -> Bool)
-> AnchoredFragment block
-> [(AnchoredFragment header, peerinfo)]
-> [(FetchDecision (AnchoredFragment header), peerinfo)]
filterPlausibleCandidates HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Bool
AnchoredFragment header -> AnchoredFragment header -> Bool
plausibleCandidateChain AnchoredFragment header
currentChain
where
separateDeclinedAndStillInRace
:: [(FetchDecision (ChainSuffix header), peerInfo)]
-> WithDeclined peerInfo (Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
separateDeclinedAndStillInRace :: [(FetchDecision (ChainSuffix header), peerInfo)]
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
separateDeclinedAndStillInRace [(FetchDecision (ChainSuffix header), peerInfo)]
decisions = do
let ([(FetchDecline, peerInfo)]
declined, [(ChainSuffix header, peerInfo)]
inRace) = [Either (FetchDecline, peerInfo) (ChainSuffix header, peerInfo)]
-> ([(FetchDecline, peerInfo)], [(ChainSuffix header, peerInfo)])
forall a b. [Either a b] -> ([a], [b])
partitionEithers
[ (FetchDecline -> (FetchDecline, peerInfo))
-> (ChainSuffix header -> (ChainSuffix header, peerInfo))
-> FetchDecision (ChainSuffix header)
-> Either (FetchDecline, peerInfo) (ChainSuffix header, peerInfo)
forall a b c d. (a -> b) -> (c -> d) -> Either a c -> Either b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (,peerInfo
p) (,peerInfo
p) FetchDecision (ChainSuffix header)
d | (FetchDecision (ChainSuffix header)
d, peerInfo
p) <- [(FetchDecision (ChainSuffix header), peerInfo)]
decisions ]
DList (FetchDecline, peerInfo)
-> WriterT (DList (FetchDecline, peerInfo)) Identity ()
forall w (m :: * -> *). (Monoid w, Monad m) => w -> WriterT w m ()
tell ([(FetchDecline, peerInfo)] -> DList (FetchDecline, peerInfo)
forall a. [a] -> DList a
DList.fromList [(FetchDecline, peerInfo)]
declined)
case [(ChainSuffix header, peerInfo)]
inRace of
[] -> Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
forall a. a -> WriterT (DList (FetchDecline, peerInfo)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])
forall a. Maybe a
Nothing
(ChainSuffix header, peerInfo)
_ : [(ChainSuffix header, peerInfo)]
_ -> do
let maxChainOn :: ((ChainSuffix header, peerInfo) -> AnchoredFragment header)
-> (ChainSuffix header, peerInfo)
-> (ChainSuffix header, peerInfo)
-> (ChainSuffix header, peerInfo)
maxChainOn (ChainSuffix header, peerInfo) -> AnchoredFragment header
f (ChainSuffix header, peerInfo)
c0 (ChainSuffix header, peerInfo)
c1 = case HasCallStack =>
AnchoredFragment header -> AnchoredFragment header -> Ordering
AnchoredFragment header -> AnchoredFragment header -> Ordering
compareCandidateChains ((ChainSuffix header, peerInfo) -> AnchoredFragment header
f (ChainSuffix header, peerInfo)
c0) ((ChainSuffix header, peerInfo) -> AnchoredFragment header
f (ChainSuffix header, peerInfo)
c1) of
Ordering
LT -> (ChainSuffix header, peerInfo)
c1
Ordering
_ -> (ChainSuffix header, peerInfo)
c0
chainSfx :: ChainSuffix header
chainSfx = (ChainSuffix header, peerInfo) -> ChainSuffix header
forall a b. (a, b) -> a
fst ((ChainSuffix header, peerInfo) -> ChainSuffix header)
-> (ChainSuffix header, peerInfo) -> ChainSuffix header
forall a b. (a -> b) -> a -> b
$
((ChainSuffix header, peerInfo)
-> (ChainSuffix header, peerInfo)
-> (ChainSuffix header, peerInfo))
-> [(ChainSuffix header, peerInfo)]
-> (ChainSuffix header, peerInfo)
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
List.foldl1' (((ChainSuffix header, peerInfo) -> AnchoredFragment header)
-> (ChainSuffix header, peerInfo)
-> (ChainSuffix header, peerInfo)
-> (ChainSuffix header, peerInfo)
maxChainOn (ChainSuffix header -> AnchoredFragment header
forall header. ChainSuffix header -> AnchoredFragment header
getChainSuffix (ChainSuffix header -> AnchoredFragment header)
-> ((ChainSuffix header, peerInfo) -> ChainSuffix header)
-> (ChainSuffix header, peerInfo)
-> AnchoredFragment header
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ChainSuffix header, peerInfo) -> ChainSuffix header
forall a b. (a, b) -> a
fst)) [(ChainSuffix header, peerInfo)]
inRace
Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
forall a. a -> WriterT (DList (FetchDecline, peerInfo)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])))
-> Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])
-> WithDeclined
peerInfo
(Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)]))
forall a b. (a -> b) -> a -> b
$ (ChainSuffix header, [(ChainSuffix header, peerInfo)])
-> Maybe (ChainSuffix header, [(ChainSuffix header, peerInfo)])
forall a. a -> Maybe a
Just (ChainSuffix header
chainSfx, [(ChainSuffix header, peerInfo)]
inRace)
selectThePeer
:: forall header peer extra.
HasHeader header
=> CandidateFragments header
-> [(ChainSuffix header, PeerInfo header peer extra)]
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (ChainSuffix header, PeerInfo header peer extra))
selectThePeer :: forall header peer extra.
HasHeader header =>
CandidateFragments header
-> [(ChainSuffix header, PeerInfo header peer extra)]
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (ChainSuffix header, PeerInfo header peer extra))
selectThePeer
CandidateFragments header
theFragments
[(ChainSuffix header, PeerInfo header peer extra)]
candidates = do
let firstBlock :: [AF.AnchoredSeq (WithOrigin SlotNo) (AF.Anchor header) header]
-> [AF.AnchoredSeq (WithOrigin SlotNo) (AF.Anchor header) header]
firstBlock :: [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
firstBlock = (AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header)
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall a b. (a -> b) -> [a] -> [b]
map (Int
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
forall v a b.
Anchorable v a b =>
Int -> AnchoredSeq v a b -> AnchoredSeq v a b
AF.takeOldest Int
1) ([AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header])
-> ([AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header])
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall a. Int -> [a] -> [a]
take Int
1 ([AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header])
-> ([AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header])
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AnchoredSeq (WithOrigin SlotNo) (Anchor header) header -> Bool)
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (AnchoredSeq (WithOrigin SlotNo) (Anchor header) header -> Bool)
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AnchoredSeq (WithOrigin SlotNo) (Anchor header) header -> Bool
forall v a b. AnchoredSeq v a b -> Bool
AF.null)
fetchRequestFragments :: [AF.AnchoredSeq (WithOrigin SlotNo) (AF.Anchor header) header]
fetchRequestFragments :: [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
fetchRequestFragments = [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
firstBlock ([AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header])
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall a b. (a -> b) -> a -> b
$ CandidateFragments header
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall a b. (a, b) -> b
snd CandidateFragments header
theFragments
grossRequest :: FetchRequest header
grossRequest :: FetchRequest header
grossRequest = Bool -> FetchRequest header -> FetchRequest header
forall a. HasCallStack => Bool -> a -> a
assert ((AnchoredSeq (WithOrigin SlotNo) (Anchor header) header -> Bool)
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool -> Bool
not (Bool -> Bool)
-> (AnchoredSeq (WithOrigin SlotNo) (Anchor header) header -> Bool)
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AnchoredSeq (WithOrigin SlotNo) (Anchor header) header -> Bool
forall v a b. AnchoredSeq v a b -> Bool
AF.null) [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
fetchRequestFragments)
(FetchRequest header -> FetchRequest header)
-> FetchRequest header -> FetchRequest header
forall a b. (a -> b) -> a -> b
$ FetchRequest { [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
fetchRequestFragments :: [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
fetchRequestFragments :: [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
fetchRequestFragments }
FetchRequest header
-> [(ChainSuffix header, PeerInfo header peer extra)]
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra))
Identity
(Maybe (ChainSuffix header, PeerInfo header peer extra))
go FetchRequest header
grossRequest [(ChainSuffix header, PeerInfo header peer extra)]
candidates
where
go :: FetchRequest header
-> [(ChainSuffix header, PeerInfo header peer extra)]
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra))
Identity
(Maybe (ChainSuffix header, PeerInfo header peer extra))
go FetchRequest header
grossRequest (c :: (ChainSuffix header, PeerInfo header peer extra)
c@(ChainSuffix header
candidate, PeerInfo header peer extra
peerInfo) : [(ChainSuffix header, PeerInfo header peer extra)]
xs) = do
if FetchRequest header
grossRequest FetchRequest header -> ChainSuffix header -> Bool
`requestHeadInCandidate` ChainSuffix header
candidate then do
DList (FetchDecline, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ()
forall w (m :: * -> *). (Monoid w, Monad m) => w -> WriterT w m ()
tell (DList (FetchDecline, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ())
-> DList (FetchDecline, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ()
forall a b. (a -> b) -> a -> b
$ [(FetchDecline, PeerInfo header peer extra)]
-> DList (FetchDecline, PeerInfo header peer extra)
forall a. [a] -> DList a
DList.fromList
[(FetchMode -> Word -> FetchDecline
FetchDeclineConcurrencyLimit FetchMode
FetchModeGenesis Word
1, PeerInfo header peer extra
pInfo)
| (ChainSuffix header
_, PeerInfo header peer extra
pInfo) <- [(ChainSuffix header, PeerInfo header peer extra)]
xs
]
Maybe (ChainSuffix header, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra))
Identity
(Maybe (ChainSuffix header, PeerInfo header peer extra))
forall a.
a
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((ChainSuffix header, PeerInfo header peer extra)
-> Maybe (ChainSuffix header, PeerInfo header peer extra)
forall a. a -> Maybe a
Just (ChainSuffix header, PeerInfo header peer extra)
c)
else do
DList (FetchDecline, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ()
forall w (m :: * -> *). (Monoid w, Monad m) => w -> WriterT w m ()
tell (DList (FetchDecline, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ())
-> DList (FetchDecline, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ()
forall a b. (a -> b) -> a -> b
$ [(FetchDecline, PeerInfo header peer extra)]
-> DList (FetchDecline, PeerInfo header peer extra)
forall a. [a] -> DList a
DList.fromList [(FetchDecline
FetchDeclineAlreadyFetched, PeerInfo header peer extra
peerInfo)]
FetchRequest header
-> [(ChainSuffix header, PeerInfo header peer extra)]
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra))
Identity
(Maybe (ChainSuffix header, PeerInfo header peer extra))
go FetchRequest header
grossRequest [(ChainSuffix header, PeerInfo header peer extra)]
xs
go FetchRequest header
_grossRequest [] = Maybe (ChainSuffix header, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra))
Identity
(Maybe (ChainSuffix header, PeerInfo header peer extra))
forall a.
a
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (ChainSuffix header, PeerInfo header peer extra)
forall a. Maybe a
Nothing
requestHeadInCandidate :: FetchRequest header -> ChainSuffix header -> Bool
requestHeadInCandidate :: FetchRequest header -> ChainSuffix header -> Bool
requestHeadInCandidate FetchRequest header
request ChainSuffix header
candidate =
case FetchRequest header
-> [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
forall header. FetchRequest header -> [AnchoredFragment header]
fetchRequestFragments FetchRequest header
request of
fragments :: [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
fragments@(AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
_:[AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
_)
| Point header
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header -> Bool
forall block.
HasHeader block =>
Point block -> AnchoredFragment block -> Bool
AF.withinFragmentBounds
(AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
-> Point header
forall block.
HasHeader block =>
AnchoredFragment block -> Point block
AF.headPoint (AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
-> Point header)
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
-> Point header
forall a b. (a -> b) -> a -> b
$ [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
forall a. HasCallStack => [a] -> a
last [AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
fragments)
(ChainSuffix header
-> AnchoredSeq (WithOrigin SlotNo) (Anchor header) header
forall header. ChainSuffix header -> AnchoredFragment header
getChainSuffix ChainSuffix header
candidate)
->
Bool
True
[AnchoredSeq (WithOrigin SlotNo) (Anchor header) header]
_ ->
Bool
False
makeFetchRequest
:: HasHeader header
=> FetchDecisionPolicy header
-> CandidateFragments header
-> PeerInfo header peer extra
-> ChainSuffix header
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra))
makeFetchRequest :: forall header peer extra.
HasHeader header =>
FetchDecisionPolicy header
-> CandidateFragments header
-> PeerInfo header peer extra
-> ChainSuffix header
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra))
makeFetchRequest
FetchDecisionPolicy header
fetchDecisionPolicy
CandidateFragments header
theFragments
thePeer :: PeerInfo header peer extra
thePeer@(PeerFetchStatus header
status, PeerFetchInFlight header
inflight, PeerGSV
gsvs, peer
_, extra
_)
ChainSuffix header
thePeerCandidate =
let theDecision :: Either FetchDecline (FetchRequest header)
theDecision = do
fragments <- PeerFetchInFlight header
-> CandidateFragments header
-> FetchDecision (CandidateFragments header)
forall header.
HasHeader header =>
PeerFetchInFlight header
-> CandidateFragments header
-> FetchDecision (CandidateFragments header)
dropAlreadyInFlightWithPeer PeerFetchInFlight header
inflight CandidateFragments header
theFragments
trimmedFragments <- snd fragments `trimFragmentsToCandidate` thePeerCandidate
fetchRequestDecision
fetchDecisionPolicy
FetchModeBulkSync
0
(calculatePeerFetchInFlightLimits gsvs)
inflight
status
(Right trimmedFragments)
in case Either FetchDecline (FetchRequest header)
theDecision of
Left FetchDecline
reason -> DList (FetchDecline, PeerInfo header peer extra)
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ()
forall w (m :: * -> *). (Monoid w, Monad m) => w -> WriterT w m ()
tell ([(FetchDecline, PeerInfo header peer extra)]
-> DList (FetchDecline, PeerInfo header peer extra)
forall a. [a] -> DList a
DList.fromList [(FetchDecline
reason, PeerInfo header peer extra
thePeer)]) WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity ()
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra))
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra))
forall a b.
WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity a
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity b
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe (FetchRequest header, PeerInfo header peer extra)
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra))
forall a.
a
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (FetchRequest header, PeerInfo header peer extra)
forall a. Maybe a
Nothing
Right FetchRequest header
theRequest -> Maybe (FetchRequest header, PeerInfo header peer extra)
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra))
forall a.
a
-> WriterT
(DList (FetchDecline, PeerInfo header peer extra)) Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (FetchRequest header, PeerInfo header peer extra)
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra)))
-> Maybe (FetchRequest header, PeerInfo header peer extra)
-> WithDeclined
(PeerInfo header peer extra)
(Maybe (FetchRequest header, PeerInfo header peer extra))
forall a b. (a -> b) -> a -> b
$ (FetchRequest header, PeerInfo header peer extra)
-> Maybe (FetchRequest header, PeerInfo header peer extra)
forall a. a -> Maybe a
Just (FetchRequest header
theRequest, PeerInfo header peer extra
thePeer)
where
trimFragmentsToCandidate :: [AnchoredFragment b]
-> ChainSuffix block1 -> Either FetchDecline [AnchoredFragment b]
trimFragmentsToCandidate [AnchoredFragment b]
fragments ChainSuffix block1
candidate =
let trimmedFragments :: [AnchoredFragment b]
trimmedFragments =
[ AnchoredFragment b
prefix
| AnchoredFragment b
fragment <- [AnchoredFragment b]
fragments
, Just (AnchoredFragment block1
_, AnchoredFragment b
prefix, AnchoredFragment block1
_, AnchoredFragment b
_) <- [AnchoredFragment block1
-> AnchoredFragment b
-> Maybe
(AnchoredFragment block1, AnchoredFragment b,
AnchoredFragment block1, AnchoredFragment b)
forall block1 block2.
(HasHeader block1, HasHeader block2,
HeaderHash block1 ~ HeaderHash block2) =>
AnchoredFragment block1
-> AnchoredFragment block2
-> Maybe
(AnchoredFragment block1, AnchoredFragment block2,
AnchoredFragment block1, AnchoredFragment block2)
AF.intersect (ChainSuffix block1 -> AnchoredFragment block1
forall header. ChainSuffix header -> AnchoredFragment header
getChainSuffix ChainSuffix block1
candidate) AnchoredFragment b
fragment]
, Bool -> Bool
not (AnchoredFragment b -> Bool
forall v a b. AnchoredSeq v a b -> Bool
AF.null AnchoredFragment b
prefix)
]
in if [AnchoredFragment b] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [AnchoredFragment b]
trimmedFragments
then FetchDecline -> Either FetchDecline [AnchoredFragment b]
forall a b. a -> Either a b
Left FetchDecline
FetchDeclineAlreadyFetched
else [AnchoredFragment b] -> Either FetchDecline [AnchoredFragment b]
forall a b. b -> Either a b
Right [AnchoredFragment b]
trimmedFragments
dropAlreadyInFlightWithPeer ::
(HasHeader header) =>
PeerFetchInFlight header ->
CandidateFragments header ->
FetchDecision (CandidateFragments header)
dropAlreadyInFlightWithPeer :: forall header.
HasHeader header =>
PeerFetchInFlight header
-> CandidateFragments header
-> FetchDecision (CandidateFragments header)
dropAlreadyInFlightWithPeer PeerFetchInFlight header
inflight (ChainSuffix header
candidate, [AnchoredFragment header]
chainfragments) =
if [AnchoredFragment header] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [AnchoredFragment header]
fragments
then FetchDecline
-> Either
FetchDecline (ChainSuffix header, [AnchoredFragment header])
forall a b. a -> Either a b
Left FetchDecline
FetchDeclineInFlightThisPeer
else (ChainSuffix header, [AnchoredFragment header])
-> Either
FetchDecline (ChainSuffix header, [AnchoredFragment header])
forall a b. b -> Either a b
Right (ChainSuffix header
candidate, [AnchoredFragment header]
fragments)
where
fragments :: [AnchoredFragment header]
fragments = (AnchoredFragment header -> [AnchoredFragment header])
-> [AnchoredFragment header] -> [AnchoredFragment header]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((header -> Bool)
-> MaxSlotNo
-> AnchoredFragment header
-> [AnchoredFragment header]
forall header.
HasHeader header =>
(header -> Bool)
-> MaxSlotNo
-> AnchoredFragment header
-> [AnchoredFragment header]
filterWithMaxSlotNo header -> Bool
notAlreadyInFlight (PeerFetchInFlight header -> MaxSlotNo
forall header. PeerFetchInFlight header -> MaxSlotNo
peerFetchMaxSlotNo PeerFetchInFlight header
inflight)) [AnchoredFragment header]
chainfragments
notAlreadyInFlight :: header -> Bool
notAlreadyInFlight header
b = header -> Point header
forall block. HasHeader block => block -> Point block
blockPoint header
b Point header -> Set (Point header) -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.notMember` PeerFetchInFlight header -> Set (Point header)
forall header. PeerFetchInFlight header -> Set (Point header)
peerFetchBlocksInFlight PeerFetchInFlight header
inflight