{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Ouroboros.Consensus.Network.NodeToNode.LeiosFetch
( leiosFetchClient
, leiosFetchMiniProtocol
, leiosFetchServer
, catchAndRethrow
) where
import Cardano.Network.NodeToNode (addSafetyMargin)
import Cardano.Network.PeerSelection (PeerTrustable)
import Control.Tracer (Tracer, traceWith)
import qualified Data.ByteString as BS
import qualified Data.IntSet as IntSet
import qualified Data.Vector.Strict as V
import Ouroboros.Consensus.Leios.Types
( EndorserBlock
, LeiosPoint (..)
, LeiosTx (..)
, mkEndorserBlock
)
import Ouroboros.Consensus.MiniProtocol.LeiosFetch.Client
( LeiosFetchClientPeer
, leiosFetchClientPeerIdle
)
import Ouroboros.Consensus.MiniProtocol.LeiosFetch.Server
( ExnLeiosInvalidRequest (..)
, LeiosFetchRequestHandler (..)
, LeiosFetchServerPeer
, leiosFetchServerPeer
)
import Ouroboros.Consensus.MiniProtocol.LeiosFetch.Trace (TraceLeiosFetchServerEvent (..))
import Ouroboros.Consensus.MiniProtocol.LeiosFetch.Type
( Message (..)
, TxBitmaps
, bitmapOffsets
)
import Ouroboros.Consensus.Network.LeiosFetch (leiosFetchMiniProtocolNum, maxLeiosFetchIngressBytes)
import Ouroboros.Consensus.Storage.LeiosDB.API (LeiosDbReader (..))
import Ouroboros.Consensus.Util.IOLike
( Exception
, MonadCatch (..)
, MonadSTM (..)
, MonadThrow (..)
)
import Ouroboros.Network.ControlMessage (ControlMessage (..), ControlMessageSTM)
import Ouroboros.Network.Mux
( MiniProtocol (..)
, MiniProtocolLimits (..)
, MiniProtocolWithExpandedCtx
, RunMiniProtocolWithExpandedCtx
, StartOnDemandOrEagerly (..)
)
leiosFetchClient ::
MonadSTM m =>
ControlMessageSTM m ->
LeiosFetchClientPeer LeiosPoint EndorserBlock LeiosTx m ()
leiosFetchClient :: forall (m :: * -> *).
MonadSTM m =>
ControlMessageSTM m
-> LeiosFetchClientPeer LeiosPoint EndorserBlock LeiosTx m ()
leiosFetchClient ControlMessageSTM m
controlMessageSTM =
STM m ()
-> LeiosFetchClientPeer LeiosPoint EndorserBlock LeiosTx m ()
forall (m :: * -> *) a point eb tx.
MonadSTM m =>
STM m a -> LeiosFetchClientPeer point eb tx m a
leiosFetchClientPeerIdle (STM m ()
-> LeiosFetchClientPeer LeiosPoint EndorserBlock LeiosTx m ())
-> STM m ()
-> LeiosFetchClientPeer LeiosPoint EndorserBlock LeiosTx m ()
forall a b. (a -> b) -> a -> b
$
ControlMessageSTM m
controlMessageSTM ControlMessageSTM m -> (ControlMessage -> STM m ()) -> STM m ()
forall a b. STM m a -> (a -> STM m b) -> STM m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ControlMessage
Continue -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
ControlMessage
Quiesce -> STM m ()
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
ControlMessage
Terminate -> () -> STM m ()
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
leiosFetchServer ::
MonadCatch m =>
Tracer m TraceLeiosFetchServerEvent ->
LeiosDbReader m ->
LeiosFetchServerPeer LeiosPoint EndorserBlock LeiosTx m ()
leiosFetchServer :: forall (m :: * -> *).
MonadCatch m =>
Tracer m TraceLeiosFetchServerEvent
-> LeiosDbReader m
-> LeiosFetchServerPeer LeiosPoint EndorserBlock LeiosTx m ()
leiosFetchServer Tracer m TraceLeiosFetchServerEvent
tracer LeiosDbReader m
reader =
LeiosFetchRequestHandler LeiosPoint EndorserBlock LeiosTx m
-> LeiosFetchServerPeer LeiosPoint EndorserBlock LeiosTx m ()
forall point eb tx (m :: * -> *).
Functor m =>
LeiosFetchRequestHandler point eb tx m
-> LeiosFetchServerPeer point eb tx m ()
leiosFetchServerPeer (LeiosFetchRequestHandler LeiosPoint EndorserBlock LeiosTx m
-> LeiosFetchServerPeer LeiosPoint EndorserBlock LeiosTx m ())
-> LeiosFetchRequestHandler LeiosPoint EndorserBlock LeiosTx m
-> LeiosFetchServerPeer LeiosPoint EndorserBlock LeiosTx m ()
forall a b. (a -> b) -> a -> b
$ (forall (st :: LeiosFetchBusy LeiosPoint EndorserBlock LeiosTx).
Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) 'StIdle ('StBusy st)
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx)
('StBusy st)
'StIdle))
-> LeiosFetchRequestHandler LeiosPoint EndorserBlock LeiosTx m
forall point eb tx (m :: * -> *).
(forall (st :: LeiosFetchBusy point eb tx).
Message (LeiosFetch point eb tx) 'StIdle ('StBusy st)
-> m (Message (LeiosFetch point eb tx) ('StBusy st) 'StIdle))
-> LeiosFetchRequestHandler point eb tx m
MkLeiosFetchRequestHandler ((forall (st :: LeiosFetchBusy LeiosPoint EndorserBlock LeiosTx).
Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) 'StIdle ('StBusy st)
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx)
('StBusy st)
'StIdle))
-> LeiosFetchRequestHandler LeiosPoint EndorserBlock LeiosTx m)
-> (forall (st :: LeiosFetchBusy LeiosPoint EndorserBlock LeiosTx).
Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) 'StIdle ('StBusy st)
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx)
('StBusy st)
'StIdle))
-> LeiosFetchRequestHandler LeiosPoint EndorserBlock LeiosTx m
forall a b. (a -> b) -> a -> b
$ \case
MsgLeiosBlockRequest LeiosPoint
point ->
(EndorserBlock
-> Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle)
-> m EndorserBlock
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap EndorserBlock
-> Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle
EndorserBlock
-> Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx)
('StBusy 'StBlock)
'StIdle
forall eb point tx.
eb -> Message (LeiosFetch point eb tx) ('StBusy 'StBlock) 'StIdle
MsgLeiosBlock (m EndorserBlock
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx)
('StBusy st)
'StIdle))
-> m EndorserBlock
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle)
forall a b. (a -> b) -> a -> b
$
Tracer m TraceLeiosFetchServerEvent
-> (ExnLeiosInvalidRequest -> TraceLeiosFetchServerEvent)
-> m EndorserBlock
-> m EndorserBlock
forall (m :: * -> *) e ev a.
(MonadCatch m, Exception e) =>
Tracer m ev -> (e -> ev) -> m a -> m a
catchAndRethrow Tracer m TraceLeiosFetchServerEvent
tracer ExnLeiosInvalidRequest -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerInvalidRequest (m EndorserBlock -> m EndorserBlock)
-> m EndorserBlock -> m EndorserBlock
forall a b. (a -> b) -> a -> b
$
Tracer m TraceLeiosFetchServerEvent
-> (LeiosDbException -> TraceLeiosFetchServerEvent)
-> m EndorserBlock
-> m EndorserBlock
forall (m :: * -> *) e ev a.
(MonadCatch m, Exception e) =>
Tracer m ev -> (e -> ev) -> m a -> m a
catchAndRethrow Tracer m TraceLeiosFetchServerEvent
tracer (LeiosPoint -> LeiosDbException -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerBlockDbFailure LeiosPoint
point) (m EndorserBlock -> m EndorserBlock)
-> m EndorserBlock -> m EndorserBlock
forall a b. (a -> b) -> a -> b
$
Tracer m TraceLeiosFetchServerEvent
-> LeiosDbReader m -> LeiosPoint -> m EndorserBlock
forall (m :: * -> *).
MonadThrow m =>
Tracer m TraceLeiosFetchServerEvent
-> LeiosDbReader m -> LeiosPoint -> m EndorserBlock
serveEb Tracer m TraceLeiosFetchServerEvent
tracer LeiosDbReader m
reader LeiosPoint
point
MsgLeiosBlockTxsRequest LeiosPoint
point TxBitmaps
bitmaps ->
(Vector LeiosTx
-> Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle)
-> m (Vector LeiosTx)
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Vector LeiosTx
-> Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle
Vector LeiosTx
-> Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx)
('StBusy 'StBlockTxs)
'StIdle
forall tx point eb.
Vector tx
-> Message (LeiosFetch point eb tx) ('StBusy 'StBlockTxs) 'StIdle
MsgLeiosBlockTxs (m (Vector LeiosTx)
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx)
('StBusy st)
'StIdle))
-> m (Vector LeiosTx)
-> m (Message
(LeiosFetch LeiosPoint EndorserBlock LeiosTx) ('StBusy st) 'StIdle)
forall a b. (a -> b) -> a -> b
$
Tracer m TraceLeiosFetchServerEvent
-> (ExnLeiosInvalidRequest -> TraceLeiosFetchServerEvent)
-> m (Vector LeiosTx)
-> m (Vector LeiosTx)
forall (m :: * -> *) e ev a.
(MonadCatch m, Exception e) =>
Tracer m ev -> (e -> ev) -> m a -> m a
catchAndRethrow Tracer m TraceLeiosFetchServerEvent
tracer ExnLeiosInvalidRequest -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerInvalidRequest (m (Vector LeiosTx) -> m (Vector LeiosTx))
-> m (Vector LeiosTx) -> m (Vector LeiosTx)
forall a b. (a -> b) -> a -> b
$
Tracer m TraceLeiosFetchServerEvent
-> (LeiosDbException -> TraceLeiosFetchServerEvent)
-> m (Vector LeiosTx)
-> m (Vector LeiosTx)
forall (m :: * -> *) e ev a.
(MonadCatch m, Exception e) =>
Tracer m ev -> (e -> ev) -> m a -> m a
catchAndRethrow Tracer m TraceLeiosFetchServerEvent
tracer (LeiosPoint
-> TxBitmaps -> LeiosDbException -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerTxsDbFailure LeiosPoint
point TxBitmaps
bitmaps) (m (Vector LeiosTx) -> m (Vector LeiosTx))
-> m (Vector LeiosTx) -> m (Vector LeiosTx)
forall a b. (a -> b) -> a -> b
$
Tracer m TraceLeiosFetchServerEvent
-> LeiosDbReader m -> LeiosPoint -> TxBitmaps -> m (Vector LeiosTx)
forall (m :: * -> *).
MonadThrow m =>
Tracer m TraceLeiosFetchServerEvent
-> LeiosDbReader m -> LeiosPoint -> TxBitmaps -> m (Vector LeiosTx)
serveTxs Tracer m TraceLeiosFetchServerEvent
tracer LeiosDbReader m
reader LeiosPoint
point TxBitmaps
bitmaps
serveEb ::
MonadThrow m =>
Tracer m TraceLeiosFetchServerEvent ->
LeiosDbReader m ->
LeiosPoint ->
m EndorserBlock
serveEb :: forall (m :: * -> *).
MonadThrow m =>
Tracer m TraceLeiosFetchServerEvent
-> LeiosDbReader m -> LeiosPoint -> m EndorserBlock
serveEb Tracer m TraceLeiosFetchServerEvent
tracer LeiosDbReader m
reader LeiosPoint
point = do
Tracer m TraceLeiosFetchServerEvent
-> TraceLeiosFetchServerEvent -> m ()
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer m TraceLeiosFetchServerEvent
tracer (TraceLeiosFetchServerEvent -> m ())
-> TraceLeiosFetchServerEvent -> m ()
forall a b. (a -> b) -> a -> b
$ LeiosPoint -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerBlockRequested LeiosPoint
point
LeiosDbReader m
-> HasCallStack => EndorserBlockHash -> m [(TxHash, BytesSize)]
forall (m :: * -> *).
LeiosDbReader m
-> HasCallStack => EndorserBlockHash -> m [(TxHash, BytesSize)]
lookupEbBody LeiosDbReader m
reader (LeiosPoint -> EndorserBlockHash
pointEbHash LeiosPoint
point) m [(TxHash, BytesSize)]
-> ([(TxHash, BytesSize)] -> m EndorserBlock) -> m EndorserBlock
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
[] -> ExnLeiosInvalidRequest -> m EndorserBlock
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO (ExnLeiosInvalidRequest -> m EndorserBlock)
-> ExnLeiosInvalidRequest -> m EndorserBlock
forall a b. (a -> b) -> a -> b
$ LeiosPoint -> ExnLeiosInvalidRequest
ExnLeiosUnknownBlockRequested LeiosPoint
point
[(TxHash, BytesSize)]
refs -> do
let n :: Int
n = [(TxHash, BytesSize)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(TxHash, BytesSize)]
refs
Tracer m TraceLeiosFetchServerEvent
-> TraceLeiosFetchServerEvent -> m ()
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer m TraceLeiosFetchServerEvent
tracer (TraceLeiosFetchServerEvent -> m ())
-> TraceLeiosFetchServerEvent -> m ()
forall a b. (a -> b) -> a -> b
$ LeiosPoint -> Int -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerBlockServed LeiosPoint
point Int
n
EndorserBlock -> m EndorserBlock
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EndorserBlock -> m EndorserBlock)
-> EndorserBlock -> m EndorserBlock
forall a b. (a -> b) -> a -> b
$ [(TxHash, BytesSize)] -> EndorserBlock
mkEndorserBlock [(TxHash, BytesSize)]
refs
serveTxs ::
MonadThrow m =>
Tracer m TraceLeiosFetchServerEvent ->
LeiosDbReader m ->
LeiosPoint ->
TxBitmaps ->
m (V.Vector LeiosTx)
serveTxs :: forall (m :: * -> *).
MonadThrow m =>
Tracer m TraceLeiosFetchServerEvent
-> LeiosDbReader m -> LeiosPoint -> TxBitmaps -> m (Vector LeiosTx)
serveTxs Tracer m TraceLeiosFetchServerEvent
tracer LeiosDbReader m
reader LeiosPoint
point TxBitmaps
bitmaps = do
Tracer m TraceLeiosFetchServerEvent
-> TraceLeiosFetchServerEvent -> m ()
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer m TraceLeiosFetchServerEvent
tracer (TraceLeiosFetchServerEvent -> m ())
-> TraceLeiosFetchServerEvent -> m ()
forall a b. (a -> b) -> a -> b
$ LeiosPoint -> Int -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerTxsRequested LeiosPoint
point ([Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
offsets)
rows <- LeiosDbReader m
-> HasCallStack =>
EndorserBlockHash -> [Int] -> m [(Int, TxHash, Maybe ByteString)]
forall (m :: * -> *).
LeiosDbReader m
-> HasCallStack =>
EndorserBlockHash -> [Int] -> m [(Int, TxHash, Maybe ByteString)]
batchRetrieveTxs LeiosDbReader m
reader (LeiosPoint -> EndorserBlockHash
pointEbHash LeiosPoint
point) [Int]
offsets
case traverse (\(Int
_offset, TxHash
_txHash, Maybe ByteString
mbBytes) -> ByteString -> LeiosTx
MkLeiosTx (ByteString -> LeiosTx) -> Maybe ByteString -> Maybe LeiosTx
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ByteString
mbBytes) rows of
Just [LeiosTx]
txs | [LeiosTx] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [LeiosTx]
txs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
offsets -> do
let n :: Int
n = [LeiosTx] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [LeiosTx]
txs
Tracer m TraceLeiosFetchServerEvent
-> TraceLeiosFetchServerEvent -> m ()
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer m TraceLeiosFetchServerEvent
tracer (TraceLeiosFetchServerEvent -> m ())
-> TraceLeiosFetchServerEvent -> m ()
forall a b. (a -> b) -> a -> b
$
LeiosPoint -> Int -> Int -> TraceLeiosFetchServerEvent
TraceLeiosFetchServerTxsServed LeiosPoint
point Int
n ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ByteString -> Int
BS.length (LeiosTx -> ByteString
leiosTxBytes LeiosTx
tx) | LeiosTx
tx <- [LeiosTx]
txs])
Vector LeiosTx -> m (Vector LeiosTx)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Vector LeiosTx -> m (Vector LeiosTx))
-> Vector LeiosTx -> m (Vector LeiosTx)
forall a b. (a -> b) -> a -> b
$ Int -> [LeiosTx] -> Vector LeiosTx
forall a. Int -> [a] -> Vector a
V.fromListN Int
n [LeiosTx]
txs
Maybe [LeiosTx]
_ -> do
let held :: IntSet
held = [Int] -> IntSet
IntSet.fromList [Int
offset | (Int
offset, TxHash
_txHash, Just ByteString
_bytes) <- [(Int, TxHash, Maybe ByteString)]
rows]
ExnLeiosInvalidRequest -> m (Vector LeiosTx)
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO (ExnLeiosInvalidRequest -> m (Vector LeiosTx))
-> ExnLeiosInvalidRequest -> m (Vector LeiosTx)
forall a b. (a -> b) -> a -> b
$ LeiosPoint -> [Int] -> ExnLeiosInvalidRequest
ExnLeiosUnknownTxsRequested LeiosPoint
point ((Int -> Bool) -> [Int] -> [Int]
forall a. (a -> Bool) -> [a] -> [a]
filter (Int -> IntSet -> Bool
`IntSet.notMember` IntSet
held) [Int]
offsets)
where
offsets :: [Int]
offsets = TxBitmaps -> [Int]
bitmapOffsets TxBitmaps
bitmaps
catchAndRethrow :: (MonadCatch m, Exception e) => Tracer m ev -> (e -> ev) -> m a -> m a
catchAndRethrow :: forall (m :: * -> *) e ev a.
(MonadCatch m, Exception e) =>
Tracer m ev -> (e -> ev) -> m a -> m a
catchAndRethrow Tracer m ev
tracer e -> ev
mkEvent m a
action =
m a
action m a -> (e -> m a) -> m a
forall e a. Exception e => m a -> (e -> m a) -> m a
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` \e
e -> do
Tracer m ev -> ev -> m ()
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer m ev
tracer (e -> ev
mkEvent e
e)
e -> m a
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwIO e
e
leiosFetchMiniProtocol ::
RunMiniProtocolWithExpandedCtx mode addr PeerTrustable b m a c ->
MiniProtocolWithExpandedCtx mode addr PeerTrustable b m a c
leiosFetchMiniProtocol :: forall (mode :: Mode) addr b (m :: * -> *) a c.
RunMiniProtocolWithExpandedCtx mode addr PeerTrustable b m a c
-> MiniProtocolWithExpandedCtx mode addr PeerTrustable b m a c
leiosFetchMiniProtocol RunMiniProtocolWithExpandedCtx mode addr PeerTrustable b m a c
run =
MiniProtocol
{ miniProtocolNum :: MiniProtocolNum
miniProtocolNum = MiniProtocolNum
leiosFetchMiniProtocolNum
, miniProtocolStart :: StartOnDemandOrEagerly
miniProtocolStart = StartOnDemandOrEagerly
StartOnDemand
, miniProtocolLimits :: MiniProtocolLimits
miniProtocolLimits = MiniProtocolLimits
leiosFetchProtocolLimits
, miniProtocolRun :: RunMiniProtocolWithExpandedCtx mode addr PeerTrustable b m a c
miniProtocolRun = RunMiniProtocolWithExpandedCtx mode addr PeerTrustable b m a c
run
}
leiosFetchProtocolLimits :: MiniProtocolLimits
leiosFetchProtocolLimits :: MiniProtocolLimits
leiosFetchProtocolLimits =
MiniProtocolLimits
{ maximumIngressQueue :: Int
maximumIngressQueue = Int -> Int
addSafetyMargin Int
maxLeiosFetchIngressBytes
}