{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Test.Consensus.PeerSimulator.Handlers
( handlerBlockFetch
, handlerFindIntersection
, handlerRequestNext
, handlerSendBlocks
) where
import Cardano.Slotting.Slot (WithOrigin (..))
import Control.Monad.Trans (lift)
import Control.Monad.Writer.Strict
( MonadWriter (tell)
, WriterT (runWriterT)
)
import Data.Maybe (fromJust, fromMaybe)
import Ouroboros.Consensus.Block
( GetHeader
, HasHeader
, Point (GenesisPoint)
, getHeader
, withOrigin
)
import Ouroboros.Consensus.Util.IOLike
( IOLike
, STM
, StrictTVar
, readTVar
, writeTVar
)
import Ouroboros.Network.AnchoredFragment (AnchoredFragment)
import qualified Ouroboros.Network.AnchoredFragment as AF
import Ouroboros.Network.Block
( Tip (TipGenesis)
, blockPoint
, getTipPoint
, tipFromHeader
)
import Ouroboros.Network.BlockFetch.ClientState
( ChainRange (ChainRange)
)
import Test.Consensus.BlockTree (BlockTree, isAncestorOf)
import qualified Test.Consensus.BlockTree as BT
import Test.Consensus.Network.AnchoredFragment.Extras (intersectWith)
import Test.Consensus.PeerSimulator.ScheduledBlockFetchServer
( BlockFetch (..)
, SendBlocks (..)
)
import Test.Consensus.PeerSimulator.ScheduledChainSyncServer
( FindIntersect (..)
, RequestNext (AwaitReply, RollBackward, RollForward)
)
import Test.Consensus.PeerSimulator.Trace
( TraceScheduledBlockFetchServerEvent (..)
, TraceScheduledChainSyncServerEvent (..)
)
import Test.Consensus.PointSchedule.NodeState
import Test.Util.Orphans.IOLike ()
handlerFindIntersection ::
(IOLike m, HasHeader blk) =>
StrictTVar m (Point blk) ->
BlockTree blk ->
[Point blk] ->
NodeState blk ->
STM m (Maybe (FindIntersect blk), [TraceScheduledChainSyncServerEvent (NodeState blk) blk])
handlerFindIntersection :: forall (m :: * -> *) blk.
(IOLike m, HasHeader blk) =>
StrictTVar m (Point blk)
-> BlockTree blk
-> [Point blk]
-> NodeState blk
-> STM
m
(Maybe (FindIntersect blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
handlerFindIntersection StrictTVar m (Point blk)
currentIntersection BlockTree blk
blockTree [Point blk]
clientPoints NodeState blk
points = do
let tip' :: Tip blk
tip' = NodeState blk -> Tip blk
forall blk. HasHeader blk => NodeState blk -> Tip blk
nsTipTip NodeState blk
points
tipPoint :: Point blk
tipPoint = Tip blk -> Point blk
forall {k} (b :: k). Tip b -> Point b
getTipPoint Tip blk
tip'
fragment :: AnchoredFragment blk
fragment = Maybe (AnchoredFragment blk) -> AnchoredFragment blk
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (AnchoredFragment blk) -> AnchoredFragment blk)
-> Maybe (AnchoredFragment blk) -> AnchoredFragment blk
forall a b. (a -> b) -> a -> b
$ Point blk -> BlockTree blk -> Maybe (AnchoredFragment blk)
forall blk.
HasHeader blk =>
Point blk -> BlockTree blk -> Maybe (AnchoredFragment blk)
BT.findFragment Point blk
tipPoint BlockTree blk
blockTree
case AnchoredFragment blk -> [Point blk] -> Maybe (Point blk)
forall b.
HasHeader b =>
AnchoredFragment b -> [Point b] -> Maybe (Point b)
intersectWith AnchoredFragment blk
fragment [Point blk]
clientPoints of
Maybe (Point blk)
Nothing ->
(Maybe (FindIntersect blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
-> STM
m
(Maybe (FindIntersect blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FindIntersect blk -> Maybe (FindIntersect blk)
forall a. a -> Maybe a
Just (Tip blk -> FindIntersect blk
forall blk. Tip blk -> FindIntersect blk
IntersectNotFound Tip blk
tip'), [])
Just Point blk
intersection -> do
StrictTVar m (Point blk) -> Point blk -> STM m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar m (Point blk)
currentIntersection Point blk
intersection
(Maybe (FindIntersect blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
-> STM
m
(Maybe (FindIntersect blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FindIntersect blk -> Maybe (FindIntersect blk)
forall a. a -> Maybe a
Just (Point blk -> Tip blk -> FindIntersect blk
forall blk. Point blk -> Tip blk -> FindIntersect blk
IntersectFound Point blk
intersection Tip blk
tip'), [])
handlerRequestNext ::
forall m blk.
(IOLike m, HasHeader blk, GetHeader blk, Eq blk) =>
StrictTVar m (Point blk) ->
BlockTree blk ->
NodeState blk ->
STM m (Maybe (RequestNext blk), [TraceScheduledChainSyncServerEvent (NodeState blk) blk])
handlerRequestNext :: forall (m :: * -> *) blk.
(IOLike m, HasHeader blk, GetHeader blk, Eq blk) =>
StrictTVar m (Point blk)
-> BlockTree blk
-> NodeState blk
-> STM
m
(Maybe (RequestNext blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
handlerRequestNext StrictTVar m (Point blk)
currentIntersection BlockTree blk
blockTree NodeState blk
points =
WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
-> STM
m
(Maybe (RequestNext blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
-> STM
m
(Maybe (RequestNext blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]))
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
-> STM
m
(Maybe (RequestNext blk),
[TraceScheduledChainSyncServerEvent (NodeState blk) blk])
forall a b. (a -> b) -> a -> b
$ do
intersection <- STM m (Point blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Point blk)
forall (m :: * -> *) a.
Monad m =>
m a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (STM m (Point blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Point blk))
-> STM m (Point blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Point blk)
forall a b. (a -> b) -> a -> b
$ StrictTVar m (Point blk) -> STM m (Point blk)
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar m (Point blk)
currentIntersection
trace $ TraceLastIntersection intersection
withHeader intersection (nsHeader points)
where
withHeader ::
Point blk ->
WithOrigin blk ->
WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
withHeader :: Point blk
-> WithOrigin blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
withHeader Point blk
intersection WithOrigin blk
h =
WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
-> ((PathAnchoredAtSource,
AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk)))
-> Maybe
(PathAnchoredAtSource,
AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall {a}. a
noPathError (PathAnchoredAtSource,
AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
analysePath (Point blk
-> Point blk
-> BlockTree blk
-> Maybe
(PathAnchoredAtSource,
AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk)
forall blk.
HasHeader blk =>
Point blk
-> Point blk
-> BlockTree blk
-> Maybe (PathAnchoredAtSource, AnchoredFragment blk)
BT.findPath Point blk
intersection Point blk
hp BlockTree blk
blockTree)
where
hp :: Point blk
hp = Point blk -> (blk -> Point blk) -> WithOrigin blk -> Point blk
forall b t. b -> (t -> b) -> WithOrigin t -> b
withOrigin Point blk
forall {k} (block :: k). Point block
GenesisPoint blk -> Point blk
forall block. HasHeader block => block -> Point block
blockPoint WithOrigin blk
h
noPathError :: a
noPathError = [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"serveHeader: intersection and headerPoint should always be in the block tree"
analysePath :: (PathAnchoredAtSource,
AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
analysePath = \case
(BT.PathAnchoredAtSource Bool
True, AF.Empty Anchor blk
_) | BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
forall blk.
(HasHeader blk, Eq blk) =>
BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
isAncestorOf BlockTree blk
blockTree (NodeState blk -> WithOrigin blk
forall blk. NodeState blk -> WithOrigin blk
nsTip NodeState blk
points) (NodeState blk -> WithOrigin blk
forall blk. NodeState blk -> WithOrigin blk
nsHeader NodeState blk
points) -> do
TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
trace TraceScheduledChainSyncServerEvent (NodeState blk) blk
forall state blk. TraceScheduledChainSyncServerEvent state blk
TraceChainIsFullyServed
Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall a.
a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RequestNext blk -> Maybe (RequestNext blk)
forall a. a -> Maybe a
Just RequestNext blk
forall blk. RequestNext blk
AwaitReply)
(BT.PathAnchoredAtSource Bool
True, AF.Empty Anchor blk
_) -> do
TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
trace TraceScheduledChainSyncServerEvent (NodeState blk) blk
forall state blk. TraceScheduledChainSyncServerEvent state blk
TraceIntersectionIsHeaderPoint
Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall a.
a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (RequestNext blk)
forall a. Maybe a
Nothing
(BT.PathAnchoredAtSource Bool
True, fragmentAhead :: AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk
fragmentAhead@(blk
next AF.:< AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk
_)) -> do
TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
trace (TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
())
-> TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
forall a b. (a -> b) -> a -> b
$ AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk
-> TraceScheduledChainSyncServerEvent (NodeState blk) blk
forall state blk.
AnchoredFragment blk
-> TraceScheduledChainSyncServerEvent state blk
TraceIntersectionIsStrictAncestorOfHeaderPoint AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk
fragmentAhead
STM m ()
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
forall (m :: * -> *) a.
Monad m =>
m a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (STM m ()
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
())
-> STM m ()
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
forall a b. (a -> b) -> a -> b
$ StrictTVar m (Point blk) -> Point blk -> STM m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar m (Point blk)
currentIntersection (Point blk -> STM m ()) -> Point blk -> STM m ()
forall a b. (a -> b) -> a -> b
$ blk -> Point blk
forall block. HasHeader block => block -> Point block
blockPoint blk
next
Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall a.
a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk)))
-> Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall a b. (a -> b) -> a -> b
$ RequestNext blk -> Maybe (RequestNext blk)
forall a. a -> Maybe a
Just (Header blk -> Tip blk -> RequestNext blk
forall blk. Header blk -> Tip blk -> RequestNext blk
RollForward (blk -> Header blk
forall blk. GetHeader blk => blk -> Header blk
getHeader blk
next) (NodeState blk -> Tip blk
forall blk. HasHeader blk => NodeState blk -> Tip blk
nsTipTip NodeState blk
points))
(BT.PathAnchoredAtSource Bool
False, AF.Empty Anchor blk
_) -> do
TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
trace TraceScheduledChainSyncServerEvent (NodeState blk) blk
forall state blk. TraceScheduledChainSyncServerEvent state blk
TraceIntersectionIsStrictDescendentOfHeaderPoint
Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall a.
a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (RequestNext blk)
forall a. Maybe a
Nothing
(BT.PathAnchoredAtSource Bool
False, AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk
fragment) -> do
let point :: Point blk
point = AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk -> Point blk
forall block. AnchoredFragment block -> Point block
AF.anchorPoint AnchoredSeq (WithOrigin SlotNo) (Anchor blk) blk
fragment
STM m ()
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
forall (m :: * -> *) a.
Monad m =>
m a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (STM m ()
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
())
-> STM m ()
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
forall a b. (a -> b) -> a -> b
$ StrictTVar m (Point blk) -> Point blk -> STM m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
StrictTVar m a -> a -> STM m ()
writeTVar StrictTVar m (Point blk)
currentIntersection Point blk
point
Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall a.
a
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk)))
-> Maybe (RequestNext blk)
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
(Maybe (RequestNext blk))
forall a b. (a -> b) -> a -> b
$ RequestNext blk -> Maybe (RequestNext blk)
forall a. a -> Maybe a
Just (Point blk -> Tip blk -> RequestNext blk
forall blk. Point blk -> Tip blk -> RequestNext blk
RollBackward Point blk
point Tip blk
tip')
tip' :: Tip blk
tip' = Tip blk -> (blk -> Tip blk) -> WithOrigin blk -> Tip blk
forall b t. b -> (t -> b) -> WithOrigin t -> b
withOrigin Tip blk
forall {k} (b :: k). Tip b
TipGenesis blk -> Tip blk
forall a. HasHeader a => a -> Tip a
tipFromHeader (WithOrigin blk -> Tip blk) -> WithOrigin blk -> Tip blk
forall a b. (a -> b) -> a -> b
$ NodeState blk -> WithOrigin blk
forall blk. NodeState blk -> WithOrigin blk
nsTip NodeState blk
points
trace :: TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
trace = [TraceScheduledChainSyncServerEvent (NodeState blk) blk]
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell ([TraceScheduledChainSyncServerEvent (NodeState blk) blk]
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk]
(STM m)
())
-> (TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> [TraceScheduledChainSyncServerEvent (NodeState blk) blk])
-> TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledChainSyncServerEvent (NodeState blk) blk] (STM m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TraceScheduledChainSyncServerEvent (NodeState blk) blk
-> [TraceScheduledChainSyncServerEvent (NodeState blk) blk]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure
fragmentUpTo :: HasHeader blk => BlockTree blk -> String -> Point blk -> AnchoredFragment blk
fragmentUpTo :: forall blk.
HasHeader blk =>
BlockTree blk -> [Char] -> Point blk -> AnchoredFragment blk
fragmentUpTo BlockTree blk
blockTree [Char]
desc Point blk
b =
AnchoredFragment blk
-> Maybe (AnchoredFragment blk) -> AnchoredFragment blk
forall a. a -> Maybe a -> a
fromMaybe AnchoredFragment blk
fatal (Point blk -> BlockTree blk -> Maybe (AnchoredFragment blk)
forall blk.
HasHeader blk =>
Point blk -> BlockTree blk -> Maybe (AnchoredFragment blk)
BT.findFragment Point blk
b BlockTree blk
blockTree)
where
fatal :: AnchoredFragment blk
fatal = [Char] -> AnchoredFragment blk
forall a. HasCallStack => [Char] -> a
error ([Char]
"BlockFetch: Could not find " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
desc [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" in the block tree")
handlerBlockFetch ::
forall m blk.
(IOLike m, HasHeader blk) =>
BlockTree blk ->
ChainRange (Point blk) ->
NodeState blk ->
STM m (Maybe (BlockFetch blk), [TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
handlerBlockFetch :: forall (m :: * -> *) blk.
(IOLike m, HasHeader blk) =>
BlockTree blk
-> ChainRange (Point blk)
-> NodeState blk
-> STM
m
(Maybe (BlockFetch blk),
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
handlerBlockFetch BlockTree blk
blockTree (ChainRange Point blk
from Point blk
to) NodeState blk
_ =
WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (BlockFetch blk))
-> STM
m
(Maybe (BlockFetch blk),
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (Maybe (AnchoredFragment blk)
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (BlockFetch blk))
serveFromBpFragment (AnchoredFragment blk
-> Point blk -> Point blk -> Maybe (AnchoredFragment blk)
forall block.
HasHeader block =>
AnchoredFragment block
-> Point block -> Point block -> Maybe (AnchoredFragment block)
AF.sliceRange AnchoredFragment blk
chain Point blk
from Point blk
to))
where
serveFromBpFragment :: Maybe (AnchoredFragment blk)
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (BlockFetch blk))
serveFromBpFragment = \case
Just AnchoredFragment blk
slice -> do
TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
trace (TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
())
-> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
forall a b. (a -> b) -> a -> b
$ AnchoredFragment blk
-> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
forall state blk.
AnchoredFragment blk
-> TraceScheduledBlockFetchServerEvent state blk
TraceStartingBatch AnchoredFragment blk
slice
Maybe (BlockFetch blk)
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (BlockFetch blk))
forall a.
a
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BlockFetch blk -> Maybe (BlockFetch blk)
forall a. a -> Maybe a
Just ([blk] -> BlockFetch blk
forall blk. [blk] -> BlockFetch blk
StartBatch (AnchoredFragment blk -> [blk]
forall v a b. AnchoredSeq v a b -> [b]
AF.toOldestFirst AnchoredFragment blk
slice)))
Maybe (AnchoredFragment blk)
Nothing -> do
TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
trace (TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
())
-> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
forall a b. (a -> b) -> a -> b
$ Point blk
-> Point blk
-> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
forall state blk.
Point blk
-> Point blk -> TraceScheduledBlockFetchServerEvent state blk
TraceWaitingForRange Point blk
from Point blk
to
Maybe (BlockFetch blk)
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (BlockFetch blk))
forall a.
a
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (BlockFetch blk)
forall a. Maybe a
Nothing
chain :: AnchoredFragment blk
chain = BlockTree blk -> [Char] -> Point blk -> AnchoredFragment blk
forall blk.
HasHeader blk =>
BlockTree blk -> [Char] -> Point blk -> AnchoredFragment blk
fragmentUpTo BlockTree blk
blockTree [Char]
"upper range bound" Point blk
to
trace :: TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
trace = [TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell ([TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
())
-> (TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> [TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
-> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> [TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure
handlerSendBlocks ::
forall m blk.
(IOLike m, HasHeader blk, Eq blk) =>
BlockTree blk ->
[blk] ->
NodeState blk ->
STM m (Maybe (SendBlocks blk), [TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
handlerSendBlocks :: forall (m :: * -> *) blk.
(IOLike m, HasHeader blk, Eq blk) =>
BlockTree blk
-> [blk]
-> NodeState blk
-> STM
m
(Maybe (SendBlocks blk),
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
handlerSendBlocks BlockTree blk
bt [blk]
blocks NodeState{WithOrigin blk
nsHeader :: forall blk. NodeState blk -> WithOrigin blk
nsHeader :: WithOrigin blk
nsHeader, WithOrigin blk
nsBlock :: WithOrigin blk
nsBlock :: forall blk. NodeState blk -> WithOrigin blk
nsBlock} =
WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
-> STM
m
(Maybe (SendBlocks blk),
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT ([blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
checkDone [blk]
blocks)
where
checkDone :: [blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
checkDone = \case
[] -> do
TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
trace TraceScheduledBlockFetchServerEvent (NodeState blk) blk
forall state blk. TraceScheduledBlockFetchServerEvent state blk
TraceBatchIsDone
Maybe (SendBlocks blk)
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
forall a.
a
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SendBlocks blk -> Maybe (SendBlocks blk)
forall a. a -> Maybe a
Just SendBlocks blk
forall blk. SendBlocks blk
BatchDone)
(blk
next : [blk]
future) ->
blk
-> [blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
blocksLeft blk
next [blk]
future
blocksLeft :: blk
-> [blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
blocksLeft blk
next [blk]
future
| BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
forall blk.
(HasHeader blk, Eq blk) =>
BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
isAncestorOf BlockTree blk
bt (blk -> WithOrigin blk
forall t. t -> WithOrigin t
At blk
next) WithOrigin blk
nsBlock
Bool -> Bool -> Bool
|| blk -> Bool
compensateForScheduleRollback blk
next =
do
TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
trace (TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
())
-> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
forall a b. (a -> b) -> a -> b
$ blk -> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
forall state blk.
blk -> TraceScheduledBlockFetchServerEvent state blk
TraceSendingBlock blk
next
Maybe (SendBlocks blk)
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
forall a.
a
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SendBlocks blk -> Maybe (SendBlocks blk)
forall a. a -> Maybe a
Just (blk -> [blk] -> SendBlocks blk
forall blk. blk -> [blk] -> SendBlocks blk
SendBlock blk
next [blk]
future))
| Bool
otherwise =
do
TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
trace TraceScheduledBlockFetchServerEvent (NodeState blk) blk
forall state blk. TraceScheduledBlockFetchServerEvent state blk
TraceBlockPointIsBehind
Maybe (SendBlocks blk)
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
(Maybe (SendBlocks blk))
forall a.
a
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk] (STM m) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (SendBlocks blk)
forall a. Maybe a
Nothing
compensateForScheduleRollback :: blk -> Bool
compensateForScheduleRollback blk
next =
Bool -> Bool
not (BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
forall blk.
(HasHeader blk, Eq blk) =>
BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
isAncestorOf BlockTree blk
bt (blk -> WithOrigin blk
forall t. t -> WithOrigin t
At blk
next) WithOrigin blk
nsHeader)
Bool -> Bool -> Bool
&& BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
forall blk.
(HasHeader blk, Eq blk) =>
BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
isAncestorOf BlockTree blk
bt WithOrigin blk
nsBlock WithOrigin blk
nsHeader
Bool -> Bool -> Bool
&& Bool -> Bool
not (BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
forall blk.
(HasHeader blk, Eq blk) =>
BlockTree blk -> WithOrigin blk -> WithOrigin blk -> Bool
isAncestorOf BlockTree blk
bt WithOrigin blk
nsBlock (blk -> WithOrigin blk
forall t. t -> WithOrigin t
At blk
next))
trace :: TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
trace = [TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell ([TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
())
-> (TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> [TraceScheduledBlockFetchServerEvent (NodeState blk) blk])
-> TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> WriterT
[TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
(STM m)
()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TraceScheduledBlockFetchServerEvent (NodeState blk) blk
-> [TraceScheduledBlockFetchServerEvent (NodeState blk) blk]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure