{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE KindSignatures      #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | A view of the transaction submission protocol from the point of view of
-- the server.
--
-- This provides a view that uses less complex types and should be easier to
-- use than the underlying typed protocol itself.
--
-- For execution, a conversion into the typed protocol is provided.
--
module Ouroboros.Network.Protocol.TxSubmission2.Server
  ( -- * Protocol type for the server
    -- | The protocol states from the point of view of the server.
    TxSubmissionServerPipelined (..)
  , ServerStIdle (..)
  , Collect (..)
  , TxSizeInBytes
    -- * Execution as a typed protocol
  , txSubmissionServerPeerPipelined
  ) where

import           Data.List.NonEmpty (NonEmpty)
import           Data.Word (Word16)

import           Network.TypedProtocol.Core
import           Network.TypedProtocol.Pipelined

import           Ouroboros.Network.Protocol.TxSubmission2.Type


data TxSubmissionServerPipelined txid tx m a where
  TxSubmissionServerPipelined
    :: m (ServerStIdle              Z txid tx m a)
    ->    TxSubmissionServerPipelined txid tx m a


-- | This is the type of the pipelined results, collected by 'CollectPipelined'.
-- This protocol can pipeline requests for transaction ids and transactions,
-- so we use a sum of either for collecting the responses.
--
data Collect txid tx =
       -- | The result of 'SendMsgRequestTxIdsPipelined'. It also carries
       -- the number of txids originally requested.
       CollectTxIds Word16 [(txid, TxSizeInBytes)]

       -- | The result of 'SendMsgRequestTxsPipelined'. The actual reply only
       -- contains the transactions sent, but this pairs them up with the
       -- transactions requested. This is because the peer can determine that
       -- some transactions are no longer needed.
     | CollectTxs [txid] [tx]


data ServerStIdle (n :: N) txid tx m a where

  -- |
  --
  SendMsgRequestTxIdsBlocking
    :: Word16                               -- ^ number of txids to acknowledge
    -> Word16                               -- ^ number of txids to request
    -> m a                                  -- ^ Result if done
    -> (NonEmpty (txid, TxSizeInBytes)
        -> m (ServerStIdle Z txid tx m a))
    -> ServerStIdle        Z txid tx m a

  -- |
  --
  SendMsgRequestTxIdsPipelined
    :: Word16
    -> Word16
    -> m (ServerStIdle (S n) txid tx m a)
    -> ServerStIdle       n  txid tx m a

  -- |
  --
  SendMsgRequestTxsPipelined
    :: [txid]
    -> m (ServerStIdle (S n) txid tx m a)
    -> ServerStIdle       n  txid tx m a

  -- | Collect a pipelined result.
  --
  CollectPipelined
    :: Maybe                 (ServerStIdle (S n) txid tx m a)
    -> (Collect txid tx -> m (ServerStIdle    n  txid tx m a))
    ->                        ServerStIdle (S n) txid tx m a


-- | Transform a 'TxSubmissionServerPipelined' into a 'PeerPipelined'.
--
txSubmissionServerPeerPipelined
    :: forall txid tx m a.
       Functor m
    => TxSubmissionServerPipelined txid tx m a
    -> PeerPipelined (TxSubmission2 txid tx) AsServer StInit m a
txSubmissionServerPeerPipelined :: TxSubmissionServerPipelined txid tx m a
-> PeerPipelined (TxSubmission2 txid tx) 'AsServer 'StInit m a
txSubmissionServerPeerPipelined (TxSubmissionServerPipelined m (ServerStIdle 'Z txid tx m a)
server) =
    PeerSender
  (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a
-> PeerPipelined (TxSubmission2 txid tx) 'AsServer 'StInit m a
forall ps (pr :: PeerRole) (st :: ps) c (m :: * -> *) a.
PeerSender ps pr st 'Z c m a -> PeerPipelined ps pr st m a
PeerPipelined ( PeerSender
  (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a
goInit
                  (PeerSender
   (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a
forall a b. (a -> b) -> a -> b
$ m (PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps)
       (n :: Outstanding) c a.
m (PeerSender ps pr st n c m a) -> PeerSender ps pr st n c m a
SenderEffect (ServerStIdle 'Z txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
forall (n :: Outstanding).
ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
go (ServerStIdle 'Z txid tx m a
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a)
-> m (ServerStIdle 'Z txid tx m a)
-> m (PeerSender
        (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ServerStIdle 'Z txid tx m a)
server)
                  )
  where
    goInit :: PeerSender (TxSubmission2 txid tx) AsServer StIdle
                         Z (Collect txid tx) m a
           -> PeerSender (TxSubmission2 txid tx) AsServer StInit
                         Z (Collect txid tx) m a
    goInit :: PeerSender
  (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a
goInit PeerSender
  (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
k = TheyHaveAgency 'AsServer 'StInit
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) 'StInit st'
    -> PeerSender
         (TxSubmission2 txid tx) 'AsServer st' 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a
forall (pr :: PeerRole) ps (st :: ps) c (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps).
    Message ps st st' -> PeerSender ps pr st' 'Z c m a)
-> PeerSender ps pr st 'Z c m a
SenderAwait (ClientHasAgency 'StInit -> PeerHasAgency 'AsClient 'StInit
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StInit
forall k k (txid :: k) (tx :: k). ClientHasAgency 'StInit
TokInit) ((forall (st' :: TxSubmission2 txid tx).
  Message (TxSubmission2 txid tx) 'StInit st'
  -> PeerSender
       (TxSubmission2 txid tx) 'AsServer st' 'Z (Collect txid tx) m a)
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a)
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) 'StInit st'
    -> PeerSender
         (TxSubmission2 txid tx) 'AsServer st' 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StInit 'Z (Collect txid tx) m a
forall a b. (a -> b) -> a -> b
$ \Message (TxSubmission2 txid tx) 'StInit st'
MsgInit -> PeerSender
  (TxSubmission2 txid tx) 'AsServer st' 'Z (Collect txid tx) m a
PeerSender
  (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
k

    go :: forall (n :: N).
          ServerStIdle n txid tx m a
       -> PeerSender (TxSubmission2 txid tx) AsServer StIdle
                     n (Collect txid tx) m a

    go :: ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
go (SendMsgRequestTxIdsBlocking Word16
ackNo Word16
reqNo m a
kDone NonEmpty (txid, TxSizeInBytes) -> m (ServerStIdle 'Z txid tx m a)
k) =
      WeHaveAgency 'AsServer 'StIdle
-> Message (TxSubmission2 txid tx) 'StIdle ('StTxIds 'StBlocking)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     ('StTxIds 'StBlocking)
     'Z
     (Collect txid tx)
     m
     a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) c (m :: * -> *)
       a.
WeHaveAgency pr st
-> Message ps st st'
-> PeerSender ps pr st' 'Z c m a
-> PeerSender ps pr st 'Z c m a
SenderYield
        (ServerHasAgency 'StIdle -> WeHaveAgency 'AsServer 'StIdle
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency ServerHasAgency 'StIdle
forall k k (txid :: k) (tx :: k). ServerHasAgency 'StIdle
TokIdle)
        (TokBlockingStyle 'StBlocking
-> Word16
-> Word16
-> Message (TxSubmission2 txid tx) 'StIdle ('StTxIds 'StBlocking)
forall k k (blocking :: StBlockingStyle) (txid :: k) (tx :: k).
TokBlockingStyle blocking
-> Word16
-> Word16
-> Message (TxSubmission2 txid tx) 'StIdle ('StTxIds blocking)
MsgRequestTxIds TokBlockingStyle 'StBlocking
TokBlocking Word16
ackNo Word16
reqNo) (PeerSender
   (TxSubmission2 txid tx)
   'AsServer
   ('StTxIds 'StBlocking)
   'Z
   (Collect txid tx)
   m
   a
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     ('StTxIds 'StBlocking)
     'Z
     (Collect txid tx)
     m
     a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
forall a b. (a -> b) -> a -> b
$
      TheyHaveAgency 'AsServer ('StTxIds 'StBlocking)
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) ('StTxIds 'StBlocking) st'
    -> PeerSender
         (TxSubmission2 txid tx) 'AsServer st' 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     ('StTxIds 'StBlocking)
     'Z
     (Collect txid tx)
     m
     a
forall (pr :: PeerRole) ps (st :: ps) c (m :: * -> *) a.
TheyHaveAgency pr st
-> (forall (st' :: ps).
    Message ps st st' -> PeerSender ps pr st' 'Z c m a)
-> PeerSender ps pr st 'Z c m a
SenderAwait
        (ClientHasAgency ('StTxIds 'StBlocking)
-> PeerHasAgency 'AsClient ('StTxIds 'StBlocking)
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency (TokBlockingStyle 'StBlocking
-> ClientHasAgency ('StTxIds 'StBlocking)
forall k k (txid :: k) (tx :: k) (b :: StBlockingStyle).
TokBlockingStyle b -> ClientHasAgency ('StTxIds b)
TokTxIds TokBlockingStyle 'StBlocking
TokBlocking)) ((forall (st' :: TxSubmission2 txid tx).
  Message (TxSubmission2 txid tx) ('StTxIds 'StBlocking) st'
  -> PeerSender
       (TxSubmission2 txid tx) 'AsServer st' 'Z (Collect txid tx) m a)
 -> PeerSender
      (TxSubmission2 txid tx)
      'AsServer
      ('StTxIds 'StBlocking)
      'Z
      (Collect txid tx)
      m
      a)
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) ('StTxIds 'StBlocking) st'
    -> PeerSender
         (TxSubmission2 txid tx) 'AsServer st' 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     ('StTxIds 'StBlocking)
     'Z
     (Collect txid tx)
     m
     a
forall a b. (a -> b) -> a -> b
$ \Message (TxSubmission2 txid tx) ('StTxIds 'StBlocking) st'
msg ->
        case Message (TxSubmission2 txid tx) ('StTxIds 'StBlocking) st'
msg of
          Message (TxSubmission2 txid tx) ('StTxIds 'StBlocking) st'
MsgDone ->
            m (PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StDone 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StDone 'Z (Collect txid tx) m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps)
       (n :: Outstanding) c a.
m (PeerSender ps pr st n c m a) -> PeerSender ps pr st n c m a
SenderEffect (NobodyHasAgency 'StDone
-> a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StDone 'Z (Collect txid tx) m a
forall ps (st :: ps) a (pr :: PeerRole) c (m :: * -> *).
NobodyHasAgency st -> a -> PeerSender ps pr st 'Z c m a
SenderDone NobodyHasAgency 'StDone
forall k k (txid :: k) (tx :: k). NobodyHasAgency 'StDone
TokDone (a
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StDone 'Z (Collect txid tx) m a)
-> m a
-> m (PeerSender
        (TxSubmission2 txid tx) 'AsServer 'StDone 'Z (Collect txid tx) m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
kDone)

          MsgReplyTxIds (BlockingReply txids) ->
            m (PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps)
       (n :: Outstanding) c a.
m (PeerSender ps pr st n c m a) -> PeerSender ps pr st n c m a
SenderEffect (ServerStIdle 'Z txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a
forall (n :: Outstanding).
ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
go (ServerStIdle 'Z txid tx m a
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a)
-> m (ServerStIdle 'Z txid tx m a)
-> m (PeerSender
        (TxSubmission2 txid tx) 'AsServer 'StIdle 'Z (Collect txid tx) m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty (txid, TxSizeInBytes) -> m (ServerStIdle 'Z txid tx m a)
k NonEmpty (txid, TxSizeInBytes)
NonEmpty (txid, TxSizeInBytes)
txids)

    go (SendMsgRequestTxIdsPipelined Word16
ackNo Word16
reqNo m (ServerStIdle ('S n) txid tx m a)
k) =
      WeHaveAgency 'AsServer 'StIdle
-> Message
     (TxSubmission2 txid tx) 'StIdle ('StTxIds 'StNonBlocking)
-> PeerReceiver
     (TxSubmission2 txid tx)
     'AsServer
     ('StTxIds 'StNonBlocking)
     'StIdle
     m
     (Collect txid tx)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (st'' :: ps)
       (m :: * -> *) c (n :: Outstanding) a.
WeHaveAgency pr st
-> Message ps st st'
-> PeerReceiver ps pr st' st'' m c
-> PeerSender ps pr st'' ('S n) c m a
-> PeerSender ps pr st n c m a
SenderPipeline
        (ServerHasAgency 'StIdle -> WeHaveAgency 'AsServer 'StIdle
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency ServerHasAgency 'StIdle
forall k k (txid :: k) (tx :: k). ServerHasAgency 'StIdle
TokIdle)
        (TokBlockingStyle 'StNonBlocking
-> Word16
-> Word16
-> Message
     (TxSubmission2 txid tx) 'StIdle ('StTxIds 'StNonBlocking)
forall k k (blocking :: StBlockingStyle) (txid :: k) (tx :: k).
TokBlockingStyle blocking
-> Word16
-> Word16
-> Message (TxSubmission2 txid tx) 'StIdle ('StTxIds blocking)
MsgRequestTxIds TokBlockingStyle 'StNonBlocking
TokNonBlocking Word16
ackNo Word16
reqNo)
        (TheyHaveAgency 'AsServer ('StTxIds 'StNonBlocking)
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) ('StTxIds 'StNonBlocking) st'
    -> PeerReceiver
         (TxSubmission2 txid tx) 'AsServer st' 'StIdle m (Collect txid tx))
-> PeerReceiver
     (TxSubmission2 txid tx)
     'AsServer
     ('StTxIds 'StNonBlocking)
     'StIdle
     m
     (Collect txid tx)
forall (pr :: PeerRole) ps (st :: ps) (stdone :: ps) (m :: * -> *)
       c.
TheyHaveAgency pr st
-> (forall (st' :: ps).
    Message ps st st' -> PeerReceiver ps pr st' stdone m c)
-> PeerReceiver ps pr st stdone m c
ReceiverAwait (ClientHasAgency ('StTxIds 'StNonBlocking)
-> PeerHasAgency 'AsClient ('StTxIds 'StNonBlocking)
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency (TokBlockingStyle 'StNonBlocking
-> ClientHasAgency ('StTxIds 'StNonBlocking)
forall k k (txid :: k) (tx :: k) (b :: StBlockingStyle).
TokBlockingStyle b -> ClientHasAgency ('StTxIds b)
TokTxIds TokBlockingStyle 'StNonBlocking
TokNonBlocking)) ((forall (st' :: TxSubmission2 txid tx).
  Message (TxSubmission2 txid tx) ('StTxIds 'StNonBlocking) st'
  -> PeerReceiver
       (TxSubmission2 txid tx) 'AsServer st' 'StIdle m (Collect txid tx))
 -> PeerReceiver
      (TxSubmission2 txid tx)
      'AsServer
      ('StTxIds 'StNonBlocking)
      'StIdle
      m
      (Collect txid tx))
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) ('StTxIds 'StNonBlocking) st'
    -> PeerReceiver
         (TxSubmission2 txid tx) 'AsServer st' 'StIdle m (Collect txid tx))
-> PeerReceiver
     (TxSubmission2 txid tx)
     'AsServer
     ('StTxIds 'StNonBlocking)
     'StIdle
     m
     (Collect txid tx)
forall a b. (a -> b) -> a -> b
$ \Message (TxSubmission2 txid tx) ('StTxIds 'StNonBlocking) st'
msg ->
           case Message (TxSubmission2 txid tx) ('StTxIds 'StNonBlocking) st'
msg of
             MsgReplyTxIds (NonBlockingReply txids) ->
               Collect txid tx
-> PeerReceiver
     (TxSubmission2 txid tx) 'AsServer st' st' m (Collect txid tx)
forall c ps (pr :: PeerRole) (st :: ps) (m :: * -> *).
c -> PeerReceiver ps pr st st m c
ReceiverDone (Word16 -> [(txid, TxSizeInBytes)] -> Collect txid tx
forall txid tx.
Word16 -> [(txid, TxSizeInBytes)] -> Collect txid tx
CollectTxIds Word16
reqNo [(txid, TxSizeInBytes)]
txids))
        (m (PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps)
       (n :: Outstanding) c a.
m (PeerSender ps pr st n c m a) -> PeerSender ps pr st n c m a
SenderEffect (ServerStIdle ('S n) txid tx m a
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
forall (n :: Outstanding).
ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
go (ServerStIdle ('S n) txid tx m a
 -> PeerSender
      (TxSubmission2 txid tx)
      'AsServer
      'StIdle
      ('S n)
      (Collect txid tx)
      m
      a)
-> m (ServerStIdle ('S n) txid tx m a)
-> m (PeerSender
        (TxSubmission2 txid tx)
        'AsServer
        'StIdle
        ('S n)
        (Collect txid tx)
        m
        a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ServerStIdle ('S n) txid tx m a)
k))

    go (SendMsgRequestTxsPipelined [txid]
txids m (ServerStIdle ('S n) txid tx m a)
k) =
      WeHaveAgency 'AsServer 'StIdle
-> Message (TxSubmission2 txid tx) 'StIdle 'StTxs
-> PeerReceiver
     (TxSubmission2 txid tx)
     'AsServer
     'StTxs
     'StIdle
     m
     (Collect txid tx)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
forall (pr :: PeerRole) ps (st :: ps) (st' :: ps) (st'' :: ps)
       (m :: * -> *) c (n :: Outstanding) a.
WeHaveAgency pr st
-> Message ps st st'
-> PeerReceiver ps pr st' st'' m c
-> PeerSender ps pr st'' ('S n) c m a
-> PeerSender ps pr st n c m a
SenderPipeline
        (ServerHasAgency 'StIdle -> WeHaveAgency 'AsServer 'StIdle
forall ps (st :: ps).
ServerHasAgency st -> PeerHasAgency 'AsServer st
ServerAgency ServerHasAgency 'StIdle
forall k k (txid :: k) (tx :: k). ServerHasAgency 'StIdle
TokIdle)
        ([txid] -> Message (TxSubmission2 txid tx) 'StIdle 'StTxs
forall k txid (tx :: k).
[txid] -> Message (TxSubmission2 txid tx) 'StIdle 'StTxs
MsgRequestTxs [txid]
txids)
        (TheyHaveAgency 'AsServer 'StTxs
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) 'StTxs st'
    -> PeerReceiver
         (TxSubmission2 txid tx) 'AsServer st' 'StIdle m (Collect txid tx))
-> PeerReceiver
     (TxSubmission2 txid tx)
     'AsServer
     'StTxs
     'StIdle
     m
     (Collect txid tx)
forall (pr :: PeerRole) ps (st :: ps) (stdone :: ps) (m :: * -> *)
       c.
TheyHaveAgency pr st
-> (forall (st' :: ps).
    Message ps st st' -> PeerReceiver ps pr st' stdone m c)
-> PeerReceiver ps pr st stdone m c
ReceiverAwait (ClientHasAgency 'StTxs -> PeerHasAgency 'AsClient 'StTxs
forall ps (st :: ps).
ClientHasAgency st -> PeerHasAgency 'AsClient st
ClientAgency ClientHasAgency 'StTxs
forall k k (txid :: k) (tx :: k). ClientHasAgency 'StTxs
TokTxs) ((forall (st' :: TxSubmission2 txid tx).
  Message (TxSubmission2 txid tx) 'StTxs st'
  -> PeerReceiver
       (TxSubmission2 txid tx) 'AsServer st' 'StIdle m (Collect txid tx))
 -> PeerReceiver
      (TxSubmission2 txid tx)
      'AsServer
      'StTxs
      'StIdle
      m
      (Collect txid tx))
-> (forall (st' :: TxSubmission2 txid tx).
    Message (TxSubmission2 txid tx) 'StTxs st'
    -> PeerReceiver
         (TxSubmission2 txid tx) 'AsServer st' 'StIdle m (Collect txid tx))
-> PeerReceiver
     (TxSubmission2 txid tx)
     'AsServer
     'StTxs
     'StIdle
     m
     (Collect txid tx)
forall a b. (a -> b) -> a -> b
$ \Message (TxSubmission2 txid tx) 'StTxs st'
msg ->
           case Message (TxSubmission2 txid tx) 'StTxs st'
msg of
             MsgReplyTxs txs -> Collect txid tx
-> PeerReceiver
     (TxSubmission2 txid tx) 'AsServer st' st' m (Collect txid tx)
forall c ps (pr :: PeerRole) (st :: ps) (m :: * -> *).
c -> PeerReceiver ps pr st st m c
ReceiverDone ([txid] -> [tx] -> Collect txid tx
forall txid tx. [txid] -> [tx] -> Collect txid tx
CollectTxs [txid]
txids [tx]
txs))
        (m (PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps)
       (n :: Outstanding) c a.
m (PeerSender ps pr st n c m a) -> PeerSender ps pr st n c m a
SenderEffect (ServerStIdle ('S n) txid tx m a
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
forall (n :: Outstanding).
ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
go (ServerStIdle ('S n) txid tx m a
 -> PeerSender
      (TxSubmission2 txid tx)
      'AsServer
      'StIdle
      ('S n)
      (Collect txid tx)
      m
      a)
-> m (ServerStIdle ('S n) txid tx m a)
-> m (PeerSender
        (TxSubmission2 txid tx)
        'AsServer
        'StIdle
        ('S n)
        (Collect txid tx)
        m
        a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (ServerStIdle ('S n) txid tx m a)
k))

    go (CollectPipelined Maybe (ServerStIdle ('S n) txid tx m a)
mNone Collect txid tx -> m (ServerStIdle n txid tx m a)
collect) =
      Maybe
  (PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a)
-> (Collect txid tx
    -> PeerSender
         (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
forall ps (pr :: PeerRole) (st :: ps) (n1 :: Outstanding) c
       (m :: * -> *) a.
Maybe (PeerSender ps pr st ('S n1) c m a)
-> (c -> PeerSender ps pr st n1 c m a)
-> PeerSender ps pr st ('S n1) c m a
SenderCollect
        ((ServerStIdle ('S n) txid tx m a
 -> PeerSender
      (TxSubmission2 txid tx)
      'AsServer
      'StIdle
      ('S n)
      (Collect txid tx)
      m
      a)
-> Maybe (ServerStIdle ('S n) txid tx m a)
-> Maybe
     (PeerSender
        (TxSubmission2 txid tx)
        'AsServer
        'StIdle
        ('S n)
        (Collect txid tx)
        m
        a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ServerStIdle ('S n) txid tx m a
-> PeerSender
     (TxSubmission2 txid tx)
     'AsServer
     'StIdle
     ('S n)
     (Collect txid tx)
     m
     a
forall (n :: Outstanding).
ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
go Maybe (ServerStIdle ('S n) txid tx m a)
mNone)
        (m (PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a)
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
forall (m :: * -> *) ps (pr :: PeerRole) (st :: ps)
       (n :: Outstanding) c a.
m (PeerSender ps pr st n c m a) -> PeerSender ps pr st n c m a
SenderEffect (m (PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a)
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a)
-> (Collect txid tx
    -> m (PeerSender
            (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a))
-> Collect txid tx
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ServerStIdle n txid tx m a
 -> PeerSender
      (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a)
-> m (ServerStIdle n txid tx m a)
-> m (PeerSender
        (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
forall (n :: Outstanding).
ServerStIdle n txid tx m a
-> PeerSender
     (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a
go (m (ServerStIdle n txid tx m a)
 -> m (PeerSender
         (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a))
-> (Collect txid tx -> m (ServerStIdle n txid tx m a))
-> Collect txid tx
-> m (PeerSender
        (TxSubmission2 txid tx) 'AsServer 'StIdle n (Collect txid tx) m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Collect txid tx -> m (ServerStIdle n txid tx m a)
collect)