{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE ExistentialQuantification  #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE NamedFieldPuns             #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE StandaloneDeriving         #-}
{-# LANGUAGE TypeApplications           #-}

module Ouroboros.Network.TxSubmission.Inbound.V2.Types
  ( -- * PeerTxState
    PeerTxState (..)
    -- * SharedTxState
  , SharedTxState (..)
    -- * Decisions
  , TxsToMempool (..)
  , TxDecision (..)
  , emptyTxDecision
  , TraceTxLogic (..)
  , TxSubmissionInitDelay (..)
  , defaultTxSubmissionInitDelay
    -- * Types shared with V1
    -- ** Various
  , ProcessedTxCount (..)
  , TxSubmissionLogicVersion (..)
    -- ** Mempool API
  , TxSubmissionMempoolWriter (..)
    -- ** Traces
  , TraceTxSubmissionInbound (..)
  , TxSubmissionCounters (..)
  , mkTxSubmissionCounters
    -- ** Protocol Error
  , TxSubmissionProtocolError (..)
  ) where

import Control.Exception (Exception (..))
import Control.Monad.Class.MonadTime.SI
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Monoid (Sum (..))
import Data.Sequence.Strict (StrictSeq)
import Data.Set (Set)
import Data.Set qualified as Set
import Data.Typeable (Typeable, eqT, (:~:) (Refl))
import GHC.Generics (Generic)
import System.Random (StdGen)

import NoThunks.Class (NoThunks (..))

import Ouroboros.Network.Protocol.TxSubmission2.Type

-- | Flag to enable/disable the usage of the new tx-submission logic.
--
data TxSubmissionLogicVersion =
      -- | the legacy `Ouroboros.Network.TxSubmission.Inbound.V1`
      TxSubmissionLogicV1
      -- | the new `Ouroboros.Network.TxSubmission.Inbound.V2`
    | TxSubmissionLogicV2
    deriving (TxSubmissionLogicVersion -> TxSubmissionLogicVersion -> Bool
(TxSubmissionLogicVersion -> TxSubmissionLogicVersion -> Bool)
-> (TxSubmissionLogicVersion -> TxSubmissionLogicVersion -> Bool)
-> Eq TxSubmissionLogicVersion
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion -> Bool
== :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion -> Bool
$c/= :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion -> Bool
/= :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion -> Bool
Eq, Int -> TxSubmissionLogicVersion -> ShowS
[TxSubmissionLogicVersion] -> ShowS
TxSubmissionLogicVersion -> String
(Int -> TxSubmissionLogicVersion -> ShowS)
-> (TxSubmissionLogicVersion -> String)
-> ([TxSubmissionLogicVersion] -> ShowS)
-> Show TxSubmissionLogicVersion
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TxSubmissionLogicVersion -> ShowS
showsPrec :: Int -> TxSubmissionLogicVersion -> ShowS
$cshow :: TxSubmissionLogicVersion -> String
show :: TxSubmissionLogicVersion -> String
$cshowList :: [TxSubmissionLogicVersion] -> ShowS
showList :: [TxSubmissionLogicVersion] -> ShowS
Show, Int -> TxSubmissionLogicVersion
TxSubmissionLogicVersion -> Int
TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
TxSubmissionLogicVersion -> TxSubmissionLogicVersion
TxSubmissionLogicVersion
-> TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
TxSubmissionLogicVersion
-> TxSubmissionLogicVersion
-> TxSubmissionLogicVersion
-> [TxSubmissionLogicVersion]
(TxSubmissionLogicVersion -> TxSubmissionLogicVersion)
-> (TxSubmissionLogicVersion -> TxSubmissionLogicVersion)
-> (Int -> TxSubmissionLogicVersion)
-> (TxSubmissionLogicVersion -> Int)
-> (TxSubmissionLogicVersion -> [TxSubmissionLogicVersion])
-> (TxSubmissionLogicVersion
    -> TxSubmissionLogicVersion -> [TxSubmissionLogicVersion])
-> (TxSubmissionLogicVersion
    -> TxSubmissionLogicVersion -> [TxSubmissionLogicVersion])
-> (TxSubmissionLogicVersion
    -> TxSubmissionLogicVersion
    -> TxSubmissionLogicVersion
    -> [TxSubmissionLogicVersion])
-> Enum TxSubmissionLogicVersion
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion
succ :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion
$cpred :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion
pred :: TxSubmissionLogicVersion -> TxSubmissionLogicVersion
$ctoEnum :: Int -> TxSubmissionLogicVersion
toEnum :: Int -> TxSubmissionLogicVersion
$cfromEnum :: TxSubmissionLogicVersion -> Int
fromEnum :: TxSubmissionLogicVersion -> Int
$cenumFrom :: TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
enumFrom :: TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
$cenumFromThen :: TxSubmissionLogicVersion
-> TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
enumFromThen :: TxSubmissionLogicVersion
-> TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
$cenumFromTo :: TxSubmissionLogicVersion
-> TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
enumFromTo :: TxSubmissionLogicVersion
-> TxSubmissionLogicVersion -> [TxSubmissionLogicVersion]
$cenumFromThenTo :: TxSubmissionLogicVersion
-> TxSubmissionLogicVersion
-> TxSubmissionLogicVersion
-> [TxSubmissionLogicVersion]
enumFromThenTo :: TxSubmissionLogicVersion
-> TxSubmissionLogicVersion
-> TxSubmissionLogicVersion
-> [TxSubmissionLogicVersion]
Enum, TxSubmissionLogicVersion
TxSubmissionLogicVersion
-> TxSubmissionLogicVersion -> Bounded TxSubmissionLogicVersion
forall a. a -> a -> Bounded a
$cminBound :: TxSubmissionLogicVersion
minBound :: TxSubmissionLogicVersion
$cmaxBound :: TxSubmissionLogicVersion
maxBound :: TxSubmissionLogicVersion
Bounded)

--
-- PeerTxState, SharedTxState
--

data PeerTxState txid tx = PeerTxState {
       -- | Those transactions (by their identifier) that the client has told
       -- us about, and which we have not yet acknowledged. This is kept in
       -- the order in which the client gave them to us. This is the same order
       -- in which we submit them to the mempool (or for this example, the final
       -- result order). It is also the order we acknowledge in.
       --
       forall txid tx. PeerTxState txid tx -> StrictSeq txid
unacknowledgedTxIds      :: !(StrictSeq txid),

       -- | Set of known transaction ids which can be requested from this peer.
       --
       forall txid tx. PeerTxState txid tx -> Map txid SizeInBytes
availableTxIds           :: !(Map txid SizeInBytes),

       -- | The number of transaction identifiers that we have requested but
       -- which have not yet been replied to. We need to track this it keep
       -- our requests within the limit on the number of unacknowledged txids.
       --
       forall txid tx. PeerTxState txid tx -> NumTxIdsToReq
requestedTxIdsInflight   :: !NumTxIdsToReq,

       -- | The size in bytes of transactions that we have requested but which
       -- have not yet been replied to. We need to track this to keep our
       -- requests within the `maxTxsSizeInflight` limit.
       --
       forall txid tx. PeerTxState txid tx -> SizeInBytes
requestedTxsInflightSize :: !SizeInBytes,

       -- | The set of requested `txid`s.
       --
       forall txid tx. PeerTxState txid tx -> Set txid
requestedTxsInflight     :: !(Set txid),

       -- | A subset of `unacknowledgedTxIds` which were unknown to the peer
       -- (i.e. requested but not received). We need to track these `txid`s
       -- since they need to be acknowledged.
       --
       -- We track these `txid` per peer, rather than in `bufferedTxs` map,
       -- since that could potentially lead to corrupting the node, not being
       -- able to download a `tx` which is needed & available from other nodes.
       --
       forall txid tx. PeerTxState txid tx -> Set txid
unknownTxs               :: !(Set txid),

       -- | Score is a metric that tracks how usefull a peer has been.
       -- The larger the value the less usefull peer. It slowly decays towards
       -- zero.
       forall txid tx. PeerTxState txid tx -> Double
score                    :: !Double,

       -- | Timestamp for the last time `score` was drained.
       forall txid tx. PeerTxState txid tx -> Time
scoreTs                  :: !Time,

       -- | A set of TXs downloaded from the peer. They are not yet
       -- acknowledged and haven't been sent to the mempool yet.
       --
       -- Life cycle of entries:
       -- * added when a tx is downloaded (see `collectTxsImpl`)
       -- * follows `unacknowledgedTxIds` (see `acknowledgeTxIds`)
       --
       forall txid tx. PeerTxState txid tx -> Map txid tx
downloadedTxs            :: !(Map txid tx),

       -- | A set of TXs on their way to the mempool.
       -- Tracked here so that we can cleanup `inSubmissionToMempoolTxs` if the
       -- peer dies.
       --
       -- Life cycle of entries:
       -- * added by `acknowledgeTxIds` (where decide which txs can be
       --   submitted to the mempool)
       -- * removed by `withMempoolSem`
       --
       forall txid tx. PeerTxState txid tx -> Map txid tx
toMempoolTxs             :: !(Map txid tx)

    }
    deriving (PeerTxState txid tx -> PeerTxState txid tx -> Bool
(PeerTxState txid tx -> PeerTxState txid tx -> Bool)
-> (PeerTxState txid tx -> PeerTxState txid tx -> Bool)
-> Eq (PeerTxState txid tx)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall txid tx.
(Eq txid, Eq tx) =>
PeerTxState txid tx -> PeerTxState txid tx -> Bool
$c== :: forall txid tx.
(Eq txid, Eq tx) =>
PeerTxState txid tx -> PeerTxState txid tx -> Bool
== :: PeerTxState txid tx -> PeerTxState txid tx -> Bool
$c/= :: forall txid tx.
(Eq txid, Eq tx) =>
PeerTxState txid tx -> PeerTxState txid tx -> Bool
/= :: PeerTxState txid tx -> PeerTxState txid tx -> Bool
Eq, Int -> PeerTxState txid tx -> ShowS
[PeerTxState txid tx] -> ShowS
PeerTxState txid tx -> String
(Int -> PeerTxState txid tx -> ShowS)
-> (PeerTxState txid tx -> String)
-> ([PeerTxState txid tx] -> ShowS)
-> Show (PeerTxState txid tx)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall txid tx.
(Show txid, Show tx) =>
Int -> PeerTxState txid tx -> ShowS
forall txid tx.
(Show txid, Show tx) =>
[PeerTxState txid tx] -> ShowS
forall txid tx.
(Show txid, Show tx) =>
PeerTxState txid tx -> String
$cshowsPrec :: forall txid tx.
(Show txid, Show tx) =>
Int -> PeerTxState txid tx -> ShowS
showsPrec :: Int -> PeerTxState txid tx -> ShowS
$cshow :: forall txid tx.
(Show txid, Show tx) =>
PeerTxState txid tx -> String
show :: PeerTxState txid tx -> String
$cshowList :: forall txid tx.
(Show txid, Show tx) =>
[PeerTxState txid tx] -> ShowS
showList :: [PeerTxState txid tx] -> ShowS
Show, (forall x. PeerTxState txid tx -> Rep (PeerTxState txid tx) x)
-> (forall x. Rep (PeerTxState txid tx) x -> PeerTxState txid tx)
-> Generic (PeerTxState txid tx)
forall x. Rep (PeerTxState txid tx) x -> PeerTxState txid tx
forall x. PeerTxState txid tx -> Rep (PeerTxState txid tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall txid tx x.
Rep (PeerTxState txid tx) x -> PeerTxState txid tx
forall txid tx x.
PeerTxState txid tx -> Rep (PeerTxState txid tx) x
$cfrom :: forall txid tx x.
PeerTxState txid tx -> Rep (PeerTxState txid tx) x
from :: forall x. PeerTxState txid tx -> Rep (PeerTxState txid tx) x
$cto :: forall txid tx x.
Rep (PeerTxState txid tx) x -> PeerTxState txid tx
to :: forall x. Rep (PeerTxState txid tx) x -> PeerTxState txid tx
Generic)

instance ( NoThunks txid
         , NoThunks tx
         ) => NoThunks (PeerTxState txid tx)


-- | Shared state of all `TxSubmission` clients.
--
-- New `txid` enters `unacknowledgedTxIds` it is also added to `availableTxIds`
-- and `referenceCounts` (see `acknowledgeTxIdsImpl`).
--
-- When a `txid` id is selected to be downloaded, it's added to
-- `requestedTxsInflightSize` (see
-- `Ouroboros.Network.TxSubmission.Inbound.Decision.pickTxsToDownload`).
--
-- When the request arrives, the `txid` is removed from `inflightTxs`.  It
-- might be added to `unknownTxs` if the server didn't have that `txid`, or
-- it's added to `bufferedTxs` (see `collectTxsImpl`).
--
-- Whenever we choose `txid` to acknowledge (either in `acknowledtxsIdsImpl`,
-- `collectTxsImpl` or
-- `Ouroboros.Network.TxSubmission.Inbound.Decision.pickTxsToDownload`, we also
-- recalculate `referenceCounts` and only keep live `txid`s in other maps (e.g.
-- `availableTxIds`, `bufferedTxs`, `unknownTxs`).
--
data SharedTxState peeraddr txid tx = SharedTxState {

      -- | Map of peer states.
      --
      -- /Invariant:/ for peeraddr's which are registered using `withPeer`,
      -- there's always an entry in this map even if the set of `txid`s is
      -- empty.
      --
      forall peeraddr txid tx.
SharedTxState peeraddr txid tx
-> Map peeraddr (PeerTxState txid tx)
peerTxStates             :: !(Map peeraddr (PeerTxState txid tx)),

      -- | Set of transactions which are in-flight (have already been
      -- requested) together with multiplicities (from how many peers it is
      -- currently in-flight)
      --
      -- This set can intersect with `availableTxIds`.
      --
      forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid Int
inflightTxs              :: !(Map txid Int),

      -- | Overall size of all `tx`s in-flight.
      --
      forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> SizeInBytes
inflightTxsSize          :: !SizeInBytes,

      -- | Map of `tx` which:
      --
      --    * were downloaded and added to the mempool,
      --    * are already in the mempool (`Nothing` is inserted in that case),
      --
      -- We only keep live `txid`, e.g. ones which `txid` is unacknowledged by
      -- at least one peer or has a `timedTxs` entry.
      --
      -- /Note:/ `txid`s which `tx` were unknown by a peer are tracked
      -- separately in `unknownTxs`.
      --
      -- /Note:/ previous implementation also needed to explicitly track
      -- `txid`s which were already acknowledged, but are still unacknowledged.
      -- In this implementation, this is done using reference counting.
      --
      -- This map is useful to acknowledge `txid`s, it's basically taking the
      -- longest prefix which contains entries in `bufferedTxs` or `unknownTxs`.
      --
      forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid (Maybe tx)
bufferedTxs              :: !(Map txid (Maybe tx)),

      -- | We track reference counts of all unacknowledged and timedTxs txids.
      -- Once the count reaches 0, a tx is removed from `bufferedTxs`.
      --
      -- The `bufferedTx` map contains a subset of `txid` which
      -- `referenceCounts` contains.
      --
      -- /Invariants:/
      --
      --    * the txid count is equal to multiplicity of txid in all
      --      `unacknowledgedTxIds` sequences;
      --    * @Map.keysSet bufferedTxs `Set.isSubsetOf` Map.keysSet referenceCounts@;
      --    * all counts are positive integers.
      --
      forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid Int
referenceCounts          :: !(Map txid Int),

      -- | A set of timeouts for txids that have been added to bufferedTxs after being
      -- inserted into the mempool.
      --
      -- We need these short timeouts to avoid re-downloading a `tx`.  We could
      -- acknowledge this `txid` to all peers, when a peer from another
      -- continent presents us it again.
      --
      -- Every txid entry has a reference count in `referenceCounts`.
      --
      forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map Time [txid]
timedTxs                 :: !(Map Time [txid]),

      -- | A set of txids that have been downloaded by a peer and are on their
      -- way to the mempool. We won't issue further fetch-requests for TXs in
      -- this state.  We track these txs to not re-download them from another
      -- peer.
      --
      -- * We subtract from the counter when a given tx is added or rejected by
      --   the mempool or do that for all txs in `toMempoolTxs` when a peer is
      --   unregistered.
      -- * We add to the counter when a given tx is selected to be added to the
      --   mempool in `pickTxsToDownload`.
      --
      forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid Int
inSubmissionToMempoolTxs :: !(Map txid Int),

      -- | Rng used to randomly order peers
      forall peeraddr txid tx. SharedTxState peeraddr txid tx -> StdGen
peerRng                  :: !StdGen
    }
    deriving (SharedTxState peeraddr txid tx
-> SharedTxState peeraddr txid tx -> Bool
(SharedTxState peeraddr txid tx
 -> SharedTxState peeraddr txid tx -> Bool)
-> (SharedTxState peeraddr txid tx
    -> SharedTxState peeraddr txid tx -> Bool)
-> Eq (SharedTxState peeraddr txid tx)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall peeraddr txid tx.
(Eq peeraddr, Eq txid, Eq tx) =>
SharedTxState peeraddr txid tx
-> SharedTxState peeraddr txid tx -> Bool
$c== :: forall peeraddr txid tx.
(Eq peeraddr, Eq txid, Eq tx) =>
SharedTxState peeraddr txid tx
-> SharedTxState peeraddr txid tx -> Bool
== :: SharedTxState peeraddr txid tx
-> SharedTxState peeraddr txid tx -> Bool
$c/= :: forall peeraddr txid tx.
(Eq peeraddr, Eq txid, Eq tx) =>
SharedTxState peeraddr txid tx
-> SharedTxState peeraddr txid tx -> Bool
/= :: SharedTxState peeraddr txid tx
-> SharedTxState peeraddr txid tx -> Bool
Eq, Int -> SharedTxState peeraddr txid tx -> ShowS
[SharedTxState peeraddr txid tx] -> ShowS
SharedTxState peeraddr txid tx -> String
(Int -> SharedTxState peeraddr txid tx -> ShowS)
-> (SharedTxState peeraddr txid tx -> String)
-> ([SharedTxState peeraddr txid tx] -> ShowS)
-> Show (SharedTxState peeraddr txid tx)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
Int -> SharedTxState peeraddr txid tx -> ShowS
forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
[SharedTxState peeraddr txid tx] -> ShowS
forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
SharedTxState peeraddr txid tx -> String
$cshowsPrec :: forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
Int -> SharedTxState peeraddr txid tx -> ShowS
showsPrec :: Int -> SharedTxState peeraddr txid tx -> ShowS
$cshow :: forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
SharedTxState peeraddr txid tx -> String
show :: SharedTxState peeraddr txid tx -> String
$cshowList :: forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
[SharedTxState peeraddr txid tx] -> ShowS
showList :: [SharedTxState peeraddr txid tx] -> ShowS
Show, (forall x.
 SharedTxState peeraddr txid tx
 -> Rep (SharedTxState peeraddr txid tx) x)
-> (forall x.
    Rep (SharedTxState peeraddr txid tx) x
    -> SharedTxState peeraddr txid tx)
-> Generic (SharedTxState peeraddr txid tx)
forall x.
Rep (SharedTxState peeraddr txid tx) x
-> SharedTxState peeraddr txid tx
forall x.
SharedTxState peeraddr txid tx
-> Rep (SharedTxState peeraddr txid tx) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall peeraddr txid tx x.
Rep (SharedTxState peeraddr txid tx) x
-> SharedTxState peeraddr txid tx
forall peeraddr txid tx x.
SharedTxState peeraddr txid tx
-> Rep (SharedTxState peeraddr txid tx) x
$cfrom :: forall peeraddr txid tx x.
SharedTxState peeraddr txid tx
-> Rep (SharedTxState peeraddr txid tx) x
from :: forall x.
SharedTxState peeraddr txid tx
-> Rep (SharedTxState peeraddr txid tx) x
$cto :: forall peeraddr txid tx x.
Rep (SharedTxState peeraddr txid tx) x
-> SharedTxState peeraddr txid tx
to :: forall x.
Rep (SharedTxState peeraddr txid tx) x
-> SharedTxState peeraddr txid tx
Generic)

instance ( NoThunks peeraddr
         , NoThunks tx
         , NoThunks txid
         , NoThunks StdGen
         ) => NoThunks (SharedTxState peeraddr txid tx)


--
-- Decisions
--

newtype TxsToMempool txid tx = TxsToMempool { forall txid tx. TxsToMempool txid tx -> [(txid, tx)]
listOfTxsToMempool :: [(txid, tx)] }
  deriving newtype (TxsToMempool txid tx -> TxsToMempool txid tx -> Bool
(TxsToMempool txid tx -> TxsToMempool txid tx -> Bool)
-> (TxsToMempool txid tx -> TxsToMempool txid tx -> Bool)
-> Eq (TxsToMempool txid tx)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall txid tx.
(Eq txid, Eq tx) =>
TxsToMempool txid tx -> TxsToMempool txid tx -> Bool
$c== :: forall txid tx.
(Eq txid, Eq tx) =>
TxsToMempool txid tx -> TxsToMempool txid tx -> Bool
== :: TxsToMempool txid tx -> TxsToMempool txid tx -> Bool
$c/= :: forall txid tx.
(Eq txid, Eq tx) =>
TxsToMempool txid tx -> TxsToMempool txid tx -> Bool
/= :: TxsToMempool txid tx -> TxsToMempool txid tx -> Bool
Eq, Int -> TxsToMempool txid tx -> ShowS
[TxsToMempool txid tx] -> ShowS
TxsToMempool txid tx -> String
(Int -> TxsToMempool txid tx -> ShowS)
-> (TxsToMempool txid tx -> String)
-> ([TxsToMempool txid tx] -> ShowS)
-> Show (TxsToMempool txid tx)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall txid tx.
(Show txid, Show tx) =>
Int -> TxsToMempool txid tx -> ShowS
forall txid tx.
(Show txid, Show tx) =>
[TxsToMempool txid tx] -> ShowS
forall txid tx.
(Show txid, Show tx) =>
TxsToMempool txid tx -> String
$cshowsPrec :: forall txid tx.
(Show txid, Show tx) =>
Int -> TxsToMempool txid tx -> ShowS
showsPrec :: Int -> TxsToMempool txid tx -> ShowS
$cshow :: forall txid tx.
(Show txid, Show tx) =>
TxsToMempool txid tx -> String
show :: TxsToMempool txid tx -> String
$cshowList :: forall txid tx.
(Show txid, Show tx) =>
[TxsToMempool txid tx] -> ShowS
showList :: [TxsToMempool txid tx] -> ShowS
Show, NonEmpty (TxsToMempool txid tx) -> TxsToMempool txid tx
TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
(TxsToMempool txid tx
 -> TxsToMempool txid tx -> TxsToMempool txid tx)
-> (NonEmpty (TxsToMempool txid tx) -> TxsToMempool txid tx)
-> (forall b.
    Integral b =>
    b -> TxsToMempool txid tx -> TxsToMempool txid tx)
-> Semigroup (TxsToMempool txid tx)
forall b.
Integral b =>
b -> TxsToMempool txid tx -> TxsToMempool txid tx
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall txid tx.
NonEmpty (TxsToMempool txid tx) -> TxsToMempool txid tx
forall txid tx.
TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
forall txid tx b.
Integral b =>
b -> TxsToMempool txid tx -> TxsToMempool txid tx
$c<> :: forall txid tx.
TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
<> :: TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
$csconcat :: forall txid tx.
NonEmpty (TxsToMempool txid tx) -> TxsToMempool txid tx
sconcat :: NonEmpty (TxsToMempool txid tx) -> TxsToMempool txid tx
$cstimes :: forall txid tx b.
Integral b =>
b -> TxsToMempool txid tx -> TxsToMempool txid tx
stimes :: forall b.
Integral b =>
b -> TxsToMempool txid tx -> TxsToMempool txid tx
Semigroup, Semigroup (TxsToMempool txid tx)
TxsToMempool txid tx
Semigroup (TxsToMempool txid tx) =>
TxsToMempool txid tx
-> (TxsToMempool txid tx
    -> TxsToMempool txid tx -> TxsToMempool txid tx)
-> ([TxsToMempool txid tx] -> TxsToMempool txid tx)
-> Monoid (TxsToMempool txid tx)
[TxsToMempool txid tx] -> TxsToMempool txid tx
TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall txid tx. Semigroup (TxsToMempool txid tx)
forall txid tx. TxsToMempool txid tx
forall txid tx. [TxsToMempool txid tx] -> TxsToMempool txid tx
forall txid tx.
TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
$cmempty :: forall txid tx. TxsToMempool txid tx
mempty :: TxsToMempool txid tx
$cmappend :: forall txid tx.
TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
mappend :: TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
$cmconcat :: forall txid tx. [TxsToMempool txid tx] -> TxsToMempool txid tx
mconcat :: [TxsToMempool txid tx] -> TxsToMempool txid tx
Monoid)


-- | Decision made by the decision logic.  Each peer will receive a 'Decision'.
--
-- /note:/ it is rather non-standard to represent a choice between requesting
-- `txid`s and `tx`'s as a product rather than a sum type.  The client will
-- need to download `tx`s first and then send a request for more txids (and
-- acknowledge some `txid`s).   Due to pipelining each client will request
-- decision from the decision logic quite often (every two pipelined requests),
-- but with this design a decision once taken will make the peer non-active
-- (e.g. it won't be returned by `filterActivePeers`) for longer, and thus the
-- expensive `makeDecision` computation will not need to take that peer into
-- account.
--
data TxDecision txid tx = TxDecision {
    forall txid tx. TxDecision txid tx -> NumTxIdsToAck
txdTxIdsToAcknowledge :: !NumTxIdsToAck,
    -- ^ txid's to acknowledge

    forall txid tx. TxDecision txid tx -> NumTxIdsToReq
txdTxIdsToRequest     :: !NumTxIdsToReq,
    -- ^ number of txid's to request

    forall txid tx. TxDecision txid tx -> Bool
txdPipelineTxIds      :: !Bool,
    -- ^ the tx-submission protocol only allows to pipeline `txid`'s requests
    -- if we have non-acknowledged `txid`s.

    forall txid tx. TxDecision txid tx -> Map txid SizeInBytes
txdTxsToRequest       :: !(Map txid SizeInBytes),
    -- ^ txid's to download.

    forall txid tx. TxDecision txid tx -> TxsToMempool txid tx
txdTxsToMempool       :: !(TxsToMempool txid tx)
    -- ^ list of `tx`s to submit to the mempool.
  }
  deriving (Int -> TxDecision txid tx -> ShowS
[TxDecision txid tx] -> ShowS
TxDecision txid tx -> String
(Int -> TxDecision txid tx -> ShowS)
-> (TxDecision txid tx -> String)
-> ([TxDecision txid tx] -> ShowS)
-> Show (TxDecision txid tx)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall txid tx.
(Show txid, Show tx) =>
Int -> TxDecision txid tx -> ShowS
forall txid tx.
(Show txid, Show tx) =>
[TxDecision txid tx] -> ShowS
forall txid tx.
(Show txid, Show tx) =>
TxDecision txid tx -> String
$cshowsPrec :: forall txid tx.
(Show txid, Show tx) =>
Int -> TxDecision txid tx -> ShowS
showsPrec :: Int -> TxDecision txid tx -> ShowS
$cshow :: forall txid tx.
(Show txid, Show tx) =>
TxDecision txid tx -> String
show :: TxDecision txid tx -> String
$cshowList :: forall txid tx.
(Show txid, Show tx) =>
[TxDecision txid tx] -> ShowS
showList :: [TxDecision txid tx] -> ShowS
Show, TxDecision txid tx -> TxDecision txid tx -> Bool
(TxDecision txid tx -> TxDecision txid tx -> Bool)
-> (TxDecision txid tx -> TxDecision txid tx -> Bool)
-> Eq (TxDecision txid tx)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall txid tx.
(Eq txid, Eq tx) =>
TxDecision txid tx -> TxDecision txid tx -> Bool
$c== :: forall txid tx.
(Eq txid, Eq tx) =>
TxDecision txid tx -> TxDecision txid tx -> Bool
== :: TxDecision txid tx -> TxDecision txid tx -> Bool
$c/= :: forall txid tx.
(Eq txid, Eq tx) =>
TxDecision txid tx -> TxDecision txid tx -> Bool
/= :: TxDecision txid tx -> TxDecision txid tx -> Bool
Eq)

-- | A non-commutative semigroup instance.
--
-- /note:/ this instance must be consistent with `pickTxsToDownload` and how
-- `PeerTxState` is updated.  It is designed to work with `TMergeVar`s.
--
instance Ord txid => Semigroup (TxDecision txid tx) where
    TxDecision { NumTxIdsToAck
txdTxIdsToAcknowledge :: forall txid tx. TxDecision txid tx -> NumTxIdsToAck
txdTxIdsToAcknowledge :: NumTxIdsToAck
txdTxIdsToAcknowledge,
                 NumTxIdsToReq
txdTxIdsToRequest :: forall txid tx. TxDecision txid tx -> NumTxIdsToReq
txdTxIdsToRequest :: NumTxIdsToReq
txdTxIdsToRequest,
                 txdPipelineTxIds :: forall txid tx. TxDecision txid tx -> Bool
txdPipelineTxIds = Bool
_ignored,
                 Map txid SizeInBytes
txdTxsToRequest :: forall txid tx. TxDecision txid tx -> Map txid SizeInBytes
txdTxsToRequest :: Map txid SizeInBytes
txdTxsToRequest,
                 TxsToMempool txid tx
txdTxsToMempool :: forall txid tx. TxDecision txid tx -> TxsToMempool txid tx
txdTxsToMempool :: TxsToMempool txid tx
txdTxsToMempool }
      <> :: TxDecision txid tx -> TxDecision txid tx -> TxDecision txid tx
<>
      TxDecision { txdTxIdsToAcknowledge :: forall txid tx. TxDecision txid tx -> NumTxIdsToAck
txdTxIdsToAcknowledge = NumTxIdsToAck
txdTxIdsToAcknowledge',
                   txdTxIdsToRequest :: forall txid tx. TxDecision txid tx -> NumTxIdsToReq
txdTxIdsToRequest     = NumTxIdsToReq
txdTxIdsToRequest',
                   txdPipelineTxIds :: forall txid tx. TxDecision txid tx -> Bool
txdPipelineTxIds      = Bool
txdPipelineTxIds',
                   txdTxsToRequest :: forall txid tx. TxDecision txid tx -> Map txid SizeInBytes
txdTxsToRequest       = Map txid SizeInBytes
txdTxsToRequest',
                   txdTxsToMempool :: forall txid tx. TxDecision txid tx -> TxsToMempool txid tx
txdTxsToMempool       = TxsToMempool txid tx
txdTxsToMempool' }
      =
      TxDecision { txdTxIdsToAcknowledge :: NumTxIdsToAck
txdTxIdsToAcknowledge = NumTxIdsToAck
txdTxIdsToAcknowledge NumTxIdsToAck -> NumTxIdsToAck -> NumTxIdsToAck
forall a. Num a => a -> a -> a
+ NumTxIdsToAck
txdTxIdsToAcknowledge',
                   txdTxIdsToRequest :: NumTxIdsToReq
txdTxIdsToRequest     = NumTxIdsToReq
txdTxIdsToRequest NumTxIdsToReq -> NumTxIdsToReq -> NumTxIdsToReq
forall a. Num a => a -> a -> a
+ NumTxIdsToReq
txdTxIdsToRequest',
                   txdPipelineTxIds :: Bool
txdPipelineTxIds      = Bool
txdPipelineTxIds',
                   txdTxsToRequest :: Map txid SizeInBytes
txdTxsToRequest       = Map txid SizeInBytes
txdTxsToRequest Map txid SizeInBytes
-> Map txid SizeInBytes -> Map txid SizeInBytes
forall a. Semigroup a => a -> a -> a
<> Map txid SizeInBytes
txdTxsToRequest',
                   txdTxsToMempool :: TxsToMempool txid tx
txdTxsToMempool       = TxsToMempool txid tx
txdTxsToMempool TxsToMempool txid tx
-> TxsToMempool txid tx -> TxsToMempool txid tx
forall a. Semigroup a => a -> a -> a
<> TxsToMempool txid tx
txdTxsToMempool'
                 }

-- | A no-op decision.
emptyTxDecision :: TxDecision txid tx
emptyTxDecision :: forall txid tx. TxDecision txid tx
emptyTxDecision = TxDecision {
    txdTxIdsToAcknowledge :: NumTxIdsToAck
txdTxIdsToAcknowledge = NumTxIdsToAck
0,
    txdTxIdsToRequest :: NumTxIdsToReq
txdTxIdsToRequest     = NumTxIdsToReq
0,
    txdPipelineTxIds :: Bool
txdPipelineTxIds      = Bool
False,
    txdTxsToRequest :: Map txid SizeInBytes
txdTxsToRequest       = Map txid SizeInBytes
forall k a. Map k a
Map.empty,
    txdTxsToMempool :: TxsToMempool txid tx
txdTxsToMempool       = TxsToMempool txid tx
forall a. Monoid a => a
mempty
  }


-- | TxLogic tracer.
--
data TraceTxLogic peeraddr txid tx =
    TraceSharedTxState String (SharedTxState peeraddr txid tx)
  | TraceTxDecisions (Map peeraddr (TxDecision txid tx))
  deriving Int -> TraceTxLogic peeraddr txid tx -> ShowS
[TraceTxLogic peeraddr txid tx] -> ShowS
TraceTxLogic peeraddr txid tx -> String
(Int -> TraceTxLogic peeraddr txid tx -> ShowS)
-> (TraceTxLogic peeraddr txid tx -> String)
-> ([TraceTxLogic peeraddr txid tx] -> ShowS)
-> Show (TraceTxLogic peeraddr txid tx)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
Int -> TraceTxLogic peeraddr txid tx -> ShowS
forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
[TraceTxLogic peeraddr txid tx] -> ShowS
forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
TraceTxLogic peeraddr txid tx -> String
$cshowsPrec :: forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
Int -> TraceTxLogic peeraddr txid tx -> ShowS
showsPrec :: Int -> TraceTxLogic peeraddr txid tx -> ShowS
$cshow :: forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
TraceTxLogic peeraddr txid tx -> String
show :: TraceTxLogic peeraddr txid tx -> String
$cshowList :: forall peeraddr txid tx.
(Show peeraddr, Show txid, Show tx) =>
[TraceTxLogic peeraddr txid tx] -> ShowS
showList :: [TraceTxLogic peeraddr txid tx] -> ShowS
Show


data ProcessedTxCount = ProcessedTxCount {
      -- | Just accepted this many transactions.
      ProcessedTxCount -> Int
ptxcAccepted :: Int
      -- | Just rejected this many transactions.
    , ProcessedTxCount -> Int
ptxcRejected :: Int
    , ProcessedTxCount -> Double
ptxcScore    :: Double
    }
  deriving (ProcessedTxCount -> ProcessedTxCount -> Bool
(ProcessedTxCount -> ProcessedTxCount -> Bool)
-> (ProcessedTxCount -> ProcessedTxCount -> Bool)
-> Eq ProcessedTxCount
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ProcessedTxCount -> ProcessedTxCount -> Bool
== :: ProcessedTxCount -> ProcessedTxCount -> Bool
$c/= :: ProcessedTxCount -> ProcessedTxCount -> Bool
/= :: ProcessedTxCount -> ProcessedTxCount -> Bool
Eq, Int -> ProcessedTxCount -> ShowS
[ProcessedTxCount] -> ShowS
ProcessedTxCount -> String
(Int -> ProcessedTxCount -> ShowS)
-> (ProcessedTxCount -> String)
-> ([ProcessedTxCount] -> ShowS)
-> Show ProcessedTxCount
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ProcessedTxCount -> ShowS
showsPrec :: Int -> ProcessedTxCount -> ShowS
$cshow :: ProcessedTxCount -> String
show :: ProcessedTxCount -> String
$cshowList :: [ProcessedTxCount] -> ShowS
showList :: [ProcessedTxCount] -> ShowS
Show)


-- | The consensus layer functionality that the inbound side of the tx
-- submission logic requires.
--
-- This is provided to the tx submission logic by the consensus layer.
--
data TxSubmissionMempoolWriter txid tx idx m =
     TxSubmissionMempoolWriter {

       -- | Compute the transaction id from a transaction.
       --
       -- This is used in the protocol handler to verify a full transaction
       -- matches a previously given transaction id.
       --
       forall txid tx idx (m :: * -> *).
TxSubmissionMempoolWriter txid tx idx m -> tx -> txid
txId          :: tx -> txid,

       -- | Supply a batch of transactions to the mempool. They are either
       -- accepted or rejected individually, but in the order supplied.
       --
       -- The 'txid's of all transactions that were added successfully are
       -- returned.
       forall txid tx idx (m :: * -> *).
TxSubmissionMempoolWriter txid tx idx m -> [tx] -> m [txid]
mempoolAddTxs :: [tx] -> m [txid]
    }


data TraceTxSubmissionInbound txid tx =
    -- | Number of transactions just about to be inserted.
    TraceTxSubmissionCollected [txid]
    -- | Just processed transaction pass/fail breakdown.
  | TraceTxSubmissionProcessed ProcessedTxCount
  | TraceTxInboundCanRequestMoreTxs Int
  | TraceTxInboundCannotRequestMoreTxs Int
  | TraceTxInboundAddedToMempool [txid] DiffTime
  | TraceTxInboundRejectedFromMempool [txid] DiffTime
  | TraceTxInboundError TxSubmissionProtocolError

  --
  -- messages emitted by the new implementation of the server in
  -- "Ouroboros.Network.TxSubmission.Inbound.Server"; some of them are also
  -- used in this module.
  --

  -- | Server received 'MsgDone'
  | TraceTxInboundTerminated
  | TraceTxInboundDecision (TxDecision txid tx)
  deriving (TraceTxSubmissionInbound txid tx
-> TraceTxSubmissionInbound txid tx -> Bool
(TraceTxSubmissionInbound txid tx
 -> TraceTxSubmissionInbound txid tx -> Bool)
-> (TraceTxSubmissionInbound txid tx
    -> TraceTxSubmissionInbound txid tx -> Bool)
-> Eq (TraceTxSubmissionInbound txid tx)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall txid tx.
(Eq txid, Eq tx) =>
TraceTxSubmissionInbound txid tx
-> TraceTxSubmissionInbound txid tx -> Bool
$c== :: forall txid tx.
(Eq txid, Eq tx) =>
TraceTxSubmissionInbound txid tx
-> TraceTxSubmissionInbound txid tx -> Bool
== :: TraceTxSubmissionInbound txid tx
-> TraceTxSubmissionInbound txid tx -> Bool
$c/= :: forall txid tx.
(Eq txid, Eq tx) =>
TraceTxSubmissionInbound txid tx
-> TraceTxSubmissionInbound txid tx -> Bool
/= :: TraceTxSubmissionInbound txid tx
-> TraceTxSubmissionInbound txid tx -> Bool
Eq, Int -> TraceTxSubmissionInbound txid tx -> ShowS
[TraceTxSubmissionInbound txid tx] -> ShowS
TraceTxSubmissionInbound txid tx -> String
(Int -> TraceTxSubmissionInbound txid tx -> ShowS)
-> (TraceTxSubmissionInbound txid tx -> String)
-> ([TraceTxSubmissionInbound txid tx] -> ShowS)
-> Show (TraceTxSubmissionInbound txid tx)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall txid tx.
(Show txid, Show tx) =>
Int -> TraceTxSubmissionInbound txid tx -> ShowS
forall txid tx.
(Show txid, Show tx) =>
[TraceTxSubmissionInbound txid tx] -> ShowS
forall txid tx.
(Show txid, Show tx) =>
TraceTxSubmissionInbound txid tx -> String
$cshowsPrec :: forall txid tx.
(Show txid, Show tx) =>
Int -> TraceTxSubmissionInbound txid tx -> ShowS
showsPrec :: Int -> TraceTxSubmissionInbound txid tx -> ShowS
$cshow :: forall txid tx.
(Show txid, Show tx) =>
TraceTxSubmissionInbound txid tx -> String
show :: TraceTxSubmissionInbound txid tx -> String
$cshowList :: forall txid tx.
(Show txid, Show tx) =>
[TraceTxSubmissionInbound txid tx] -> ShowS
showList :: [TraceTxSubmissionInbound txid tx] -> ShowS
Show)


data TxSubmissionCounters =
    TxSubmissionCounters {
      TxSubmissionCounters -> Int
numOfOutstandingTxIds         :: Int,
      -- ^ txids which are not yet downloaded.  This is a diff of keys sets of
      -- `referenceCounts` and a sum of `bufferedTxs` and
      -- `inbubmissionToMempoolTxs` maps.
      TxSubmissionCounters -> Int
numOfBufferedTxs              :: Int,
      -- ^ number of all buffered txs (downloaded or not available)
      TxSubmissionCounters -> Int
numOfInSubmissionToMempoolTxs :: Int,
      -- ^ number of all tx's which were submitted to the mempool
      TxSubmissionCounters -> Int
numOfTxIdsInflight            :: Int
      -- ^ number of all in-flight txid's.
    }
    deriving (TxSubmissionCounters -> TxSubmissionCounters -> Bool
(TxSubmissionCounters -> TxSubmissionCounters -> Bool)
-> (TxSubmissionCounters -> TxSubmissionCounters -> Bool)
-> Eq TxSubmissionCounters
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TxSubmissionCounters -> TxSubmissionCounters -> Bool
== :: TxSubmissionCounters -> TxSubmissionCounters -> Bool
$c/= :: TxSubmissionCounters -> TxSubmissionCounters -> Bool
/= :: TxSubmissionCounters -> TxSubmissionCounters -> Bool
Eq, Int -> TxSubmissionCounters -> ShowS
[TxSubmissionCounters] -> ShowS
TxSubmissionCounters -> String
(Int -> TxSubmissionCounters -> ShowS)
-> (TxSubmissionCounters -> String)
-> ([TxSubmissionCounters] -> ShowS)
-> Show TxSubmissionCounters
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TxSubmissionCounters -> ShowS
showsPrec :: Int -> TxSubmissionCounters -> ShowS
$cshow :: TxSubmissionCounters -> String
show :: TxSubmissionCounters -> String
$cshowList :: [TxSubmissionCounters] -> ShowS
showList :: [TxSubmissionCounters] -> ShowS
Show)

mkTxSubmissionCounters
  :: Ord txid
  => SharedTxState peeraddr txid tx
  -> TxSubmissionCounters
mkTxSubmissionCounters :: forall txid peeraddr tx.
Ord txid =>
SharedTxState peeraddr txid tx -> TxSubmissionCounters
mkTxSubmissionCounters
  SharedTxState {
    Map txid Int
inflightTxs :: forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid Int
inflightTxs :: Map txid Int
inflightTxs,
    Map txid (Maybe tx)
bufferedTxs :: forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid (Maybe tx)
bufferedTxs :: Map txid (Maybe tx)
bufferedTxs,
    Map txid Int
referenceCounts :: forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid Int
referenceCounts :: Map txid Int
referenceCounts,
    Map txid Int
inSubmissionToMempoolTxs :: forall peeraddr txid tx.
SharedTxState peeraddr txid tx -> Map txid Int
inSubmissionToMempoolTxs :: Map txid Int
inSubmissionToMempoolTxs
  }
  =
  TxSubmissionCounters {
    numOfOutstandingTxIds :: Int
numOfOutstandingTxIds         = Set txid -> Int
forall a. Set a -> Int
Set.size (Set txid -> Int) -> Set txid -> Int
forall a b. (a -> b) -> a -> b
$ Map txid Int -> Set txid
forall k a. Map k a -> Set k
Map.keysSet Map txid Int
referenceCounts
                                        Set txid -> Set txid -> Set txid
forall a. Ord a => Set a -> Set a -> Set a
Set.\\ Map txid (Maybe tx) -> Set txid
forall k a. Map k a -> Set k
Map.keysSet Map txid (Maybe tx)
bufferedTxs
                                        Set txid -> Set txid -> Set txid
forall a. Ord a => Set a -> Set a -> Set a
Set.\\ Map txid Int -> Set txid
forall k a. Map k a -> Set k
Map.keysSet Map txid Int
inSubmissionToMempoolTxs,
    numOfBufferedTxs :: Int
numOfBufferedTxs              = Map txid (Maybe tx) -> Int
forall k a. Map k a -> Int
Map.size Map txid (Maybe tx)
bufferedTxs,
    numOfInSubmissionToMempoolTxs :: Int
numOfInSubmissionToMempoolTxs = Map txid Int -> Int
forall k a. Map k a -> Int
Map.size Map txid Int
inSubmissionToMempoolTxs,
    numOfTxIdsInflight :: Int
numOfTxIdsInflight            = Sum Int -> Int
forall a. Sum a -> a
getSum (Sum Int -> Int) -> Sum Int -> Int
forall a b. (a -> b) -> a -> b
$ (Int -> Sum Int) -> Map txid Int -> Sum Int
forall m a. Monoid m => (a -> m) -> Map txid a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Int -> Sum Int
forall a. a -> Sum a
Sum Map txid Int
inflightTxs
  }


data TxSubmissionProtocolError =
       ProtocolErrorTxNotRequested
     | ProtocolErrorTxIdsNotRequested
     | forall txid. (Typeable txid, Show txid, Eq txid)
       => ProtocolErrorTxSizeError [(txid, SizeInBytes, SizeInBytes)]
     -- ^ a list of txid for which the received size and advertised size didn't
     -- match.

instance Eq   TxSubmissionProtocolError where
    TxSubmissionProtocolError
ProtocolErrorTxNotRequested    == :: TxSubmissionProtocolError -> TxSubmissionProtocolError -> Bool
== TxSubmissionProtocolError
ProtocolErrorTxNotRequested      = Bool
True
    TxSubmissionProtocolError
ProtocolErrorTxNotRequested    == TxSubmissionProtocolError
_                                = Bool
False
    TxSubmissionProtocolError
ProtocolErrorTxIdsNotRequested == TxSubmissionProtocolError
ProtocolErrorTxIdsNotRequested   = Bool
True
    TxSubmissionProtocolError
ProtocolErrorTxIdsNotRequested == TxSubmissionProtocolError
_                                = Bool
True
    ProtocolErrorTxSizeError ([(txid, SizeInBytes, SizeInBytes)]
as :: [(a, SizeInBytes, SizeInBytes)])
      == ProtocolErrorTxSizeError ([(txid, SizeInBytes, SizeInBytes)]
as' :: [(a', SizeInBytes, SizeInBytes)]) =
        case forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall a b. (Typeable a, Typeable b) => Maybe (a :~: b)
eqT @a @a' of
          Maybe (txid :~: txid)
Nothing   -> Bool
False
          Just txid :~: txid
Refl -> [(txid, SizeInBytes, SizeInBytes)]
as [(txid, SizeInBytes, SizeInBytes)]
-> [(txid, SizeInBytes, SizeInBytes)] -> Bool
forall a. Eq a => a -> a -> Bool
== [(txid, SizeInBytes, SizeInBytes)]
[(txid, SizeInBytes, SizeInBytes)]
as'
    ProtocolErrorTxSizeError {} == TxSubmissionProtocolError
_ = Bool
False

deriving instance Show TxSubmissionProtocolError

instance Exception TxSubmissionProtocolError where
  displayException :: TxSubmissionProtocolError -> String
displayException TxSubmissionProtocolError
ProtocolErrorTxNotRequested =
      String
"The peer replied with a transaction we did not ask for."
  displayException TxSubmissionProtocolError
ProtocolErrorTxIdsNotRequested =
      String
"The peer replied with more txids than we asked for."
  displayException (ProtocolErrorTxSizeError [(txid, SizeInBytes, SizeInBytes)]
txids) =
      String
"The peer received txs with wrong sizes " String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(txid, SizeInBytes, SizeInBytes)] -> String
forall a. Show a => a -> String
show [(txid, SizeInBytes, SizeInBytes)]
txids

data TxSubmissionInitDelay =
     TxSubmissionInitDelay DiffTime
 | NoTxSubmissionInitDelay
 deriving (TxSubmissionInitDelay -> TxSubmissionInitDelay -> Bool
(TxSubmissionInitDelay -> TxSubmissionInitDelay -> Bool)
-> (TxSubmissionInitDelay -> TxSubmissionInitDelay -> Bool)
-> Eq TxSubmissionInitDelay
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TxSubmissionInitDelay -> TxSubmissionInitDelay -> Bool
== :: TxSubmissionInitDelay -> TxSubmissionInitDelay -> Bool
$c/= :: TxSubmissionInitDelay -> TxSubmissionInitDelay -> Bool
/= :: TxSubmissionInitDelay -> TxSubmissionInitDelay -> Bool
Eq, Int -> TxSubmissionInitDelay -> ShowS
[TxSubmissionInitDelay] -> ShowS
TxSubmissionInitDelay -> String
(Int -> TxSubmissionInitDelay -> ShowS)
-> (TxSubmissionInitDelay -> String)
-> ([TxSubmissionInitDelay] -> ShowS)
-> Show TxSubmissionInitDelay
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TxSubmissionInitDelay -> ShowS
showsPrec :: Int -> TxSubmissionInitDelay -> ShowS
$cshow :: TxSubmissionInitDelay -> String
show :: TxSubmissionInitDelay -> String
$cshowList :: [TxSubmissionInitDelay] -> ShowS
showList :: [TxSubmissionInitDelay] -> ShowS
Show)

defaultTxSubmissionInitDelay :: TxSubmissionInitDelay
defaultTxSubmissionInitDelay :: TxSubmissionInitDelay
defaultTxSubmissionInitDelay = DiffTime -> TxSubmissionInitDelay
TxSubmissionInitDelay DiffTime
60