{-# LANGUAGE BlockArguments      #-}
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE NamedFieldPuns      #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections       #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeOperators       #-}

{-# OPTIONS_GHC -Wno-orphans #-}

module Test.Ouroboros.Network.TxSubmission.AppV1 (tests) where

import Prelude hiding (seq)

import NoThunks.Class

import Control.Concurrent.Class.MonadMVar (MonadMVar)
import Control.Concurrent.Class.MonadSTM
import Control.Monad (unless, void)
import Control.Monad.Class.MonadAsync
import Control.Monad.Class.MonadFork
import Control.Monad.Class.MonadSay
import Control.Monad.Class.MonadST
import Control.Monad.Class.MonadThrow
import Control.Monad.Class.MonadTime.SI
import Control.Monad.Class.MonadTimer.SI
import Control.Monad.IOSim hiding (SimResult)
import Control.Tracer (Tracer (..), contramap, nullTracer)

import Data.ByteString.Lazy qualified as BSL
import Data.Function (on)
import Data.List (intercalate, nubBy)
import Data.Maybe (fromMaybe)

import Network.TypedProtocol.Codec (CodecF (..))

import Ouroboros.Network.Channel
import Ouroboros.Network.ControlMessage (ControlMessage (..), ControlMessageSTM)
import Ouroboros.Network.Driver
import Ouroboros.Network.Protocol.Limits (sizeLimitForState)
import Ouroboros.Network.Protocol.TxSubmission2.Client
import Ouroboros.Network.Protocol.TxSubmission2.Codec
import Ouroboros.Network.Protocol.TxSubmission2.Server
import Ouroboros.Network.Protocol.TxSubmission2.Type
import Ouroboros.Network.TxSubmission.Inbound.V1
import Ouroboros.Network.TxSubmission.Inbound.V2.Policy (max_TX_SIZE)
import Ouroboros.Network.TxSubmission.Inbound.V2.Types
           (const_MAX_TX_SIZE_DISCREPANCY)
import Ouroboros.Network.TxSubmission.Outbound
import Ouroboros.Network.Util.ShowProxy

import Test.QuickCheck
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.QuickCheck (testProperty)

import Test.Ouroboros.Network.TxSubmission.SizedBytes (SizedBytes (..),
           codec_sized)
import Test.Ouroboros.Network.TxSubmission.Types
import Test.Ouroboros.Network.Utils


tests :: TestTree
tests :: TestTree
tests = TestName -> [TestTree] -> TestTree
testGroup TestName
"AppV1"
  [ TestName -> Property -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"txSubmission" ((ArbTxSubmissionConfigs
 -> ArbNumTxsToRequest
 -> NonEmptyList (Tx Int)
 -> Maybe (Positive SmallDelay)
 -> Property)
-> Property
forall prop. Testable prop => prop -> Property
checkCoverage ArbTxSubmissionConfigs
-> ArbNumTxsToRequest
-> NonEmptyList (Tx Int)
-> Maybe (Positive SmallDelay)
-> Property
prop_txSubmission)
  , TestName -> (ArbNumTxsToRequest -> Property) -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"maxNumTxsToRequest is clamped to the sane range"
                 ArbNumTxsToRequest -> Property
prop_clampMaxNumTxsToRequest
  , TestName -> Property -> TestTree
forall a. Testable a => TestName -> a -> TestTree
testProperty TestName
"maxSaneNumTxsToRequest txs fit within the size limit"
                 Property
prop_maxSaneNumTxsToRequest_fitsSizeLimit
  ]

data TestVersion = TestVersion
  deriving (TestVersion -> TestVersion -> Bool
(TestVersion -> TestVersion -> Bool)
-> (TestVersion -> TestVersion -> Bool) -> Eq TestVersion
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TestVersion -> TestVersion -> Bool
== :: TestVersion -> TestVersion -> Bool
$c/= :: TestVersion -> TestVersion -> Bool
/= :: TestVersion -> TestVersion -> Bool
Eq, Eq TestVersion
Eq TestVersion =>
(TestVersion -> TestVersion -> Ordering)
-> (TestVersion -> TestVersion -> Bool)
-> (TestVersion -> TestVersion -> Bool)
-> (TestVersion -> TestVersion -> Bool)
-> (TestVersion -> TestVersion -> Bool)
-> (TestVersion -> TestVersion -> TestVersion)
-> (TestVersion -> TestVersion -> TestVersion)
-> Ord TestVersion
TestVersion -> TestVersion -> Bool
TestVersion -> TestVersion -> Ordering
TestVersion -> TestVersion -> TestVersion
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: TestVersion -> TestVersion -> Ordering
compare :: TestVersion -> TestVersion -> Ordering
$c< :: TestVersion -> TestVersion -> Bool
< :: TestVersion -> TestVersion -> Bool
$c<= :: TestVersion -> TestVersion -> Bool
<= :: TestVersion -> TestVersion -> Bool
$c> :: TestVersion -> TestVersion -> Bool
> :: TestVersion -> TestVersion -> Bool
$c>= :: TestVersion -> TestVersion -> Bool
>= :: TestVersion -> TestVersion -> Bool
$cmax :: TestVersion -> TestVersion -> TestVersion
max :: TestVersion -> TestVersion -> TestVersion
$cmin :: TestVersion -> TestVersion -> TestVersion
min :: TestVersion -> TestVersion -> TestVersion
Ord, TestVersion
TestVersion -> TestVersion -> Bounded TestVersion
forall a. a -> a -> Bounded a
$cminBound :: TestVersion
minBound :: TestVersion
$cmaxBound :: TestVersion
maxBound :: TestVersion
Bounded, Int -> TestVersion
TestVersion -> Int
TestVersion -> [TestVersion]
TestVersion -> TestVersion
TestVersion -> TestVersion -> [TestVersion]
TestVersion -> TestVersion -> TestVersion -> [TestVersion]
(TestVersion -> TestVersion)
-> (TestVersion -> TestVersion)
-> (Int -> TestVersion)
-> (TestVersion -> Int)
-> (TestVersion -> [TestVersion])
-> (TestVersion -> TestVersion -> [TestVersion])
-> (TestVersion -> TestVersion -> [TestVersion])
-> (TestVersion -> TestVersion -> TestVersion -> [TestVersion])
-> Enum TestVersion
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 :: TestVersion -> TestVersion
succ :: TestVersion -> TestVersion
$cpred :: TestVersion -> TestVersion
pred :: TestVersion -> TestVersion
$ctoEnum :: Int -> TestVersion
toEnum :: Int -> TestVersion
$cfromEnum :: TestVersion -> Int
fromEnum :: TestVersion -> Int
$cenumFrom :: TestVersion -> [TestVersion]
enumFrom :: TestVersion -> [TestVersion]
$cenumFromThen :: TestVersion -> TestVersion -> [TestVersion]
enumFromThen :: TestVersion -> TestVersion -> [TestVersion]
$cenumFromTo :: TestVersion -> TestVersion -> [TestVersion]
enumFromTo :: TestVersion -> TestVersion -> [TestVersion]
$cenumFromThenTo :: TestVersion -> TestVersion -> TestVersion -> [TestVersion]
enumFromThenTo :: TestVersion -> TestVersion -> TestVersion -> [TestVersion]
Enum, Int -> TestVersion -> ShowS
[TestVersion] -> ShowS
TestVersion -> TestName
(Int -> TestVersion -> ShowS)
-> (TestVersion -> TestName)
-> ([TestVersion] -> ShowS)
-> Show TestVersion
forall a.
(Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TestVersion -> ShowS
showsPrec :: Int -> TestVersion -> ShowS
$cshow :: TestVersion -> TestName
show :: TestVersion -> TestName
$cshowList :: [TestVersion] -> ShowS
showList :: [TestVersion] -> ShowS
Show)

txSubmissionSimulation
  :: forall m txid.
     ( MonadAsync m
     , MonadDelay m
     , MonadEvaluate m
     , MonadFork  m
     , MonadMask  m
     , MonadMVar  m
     , MonadSay   m
     , MonadST    m
     , MonadSTM   m
     , MonadTime  m
     , MonadTimer m
     , MonadThrow m
     , MonadThrow (STM m)
     , MonadMonotonicTime m
     , Ord txid
     , Eq  txid
     , ShowProxy txid
     , NoThunks (Tx txid)

     , txid ~ Int
     )
  => Tracer m (String, TraceSendRecv (TxSubmission2 txid (Tx txid)))
  -> Tracer m OutboundRequest
  -- ^ requests received by the outbound, see `traceOutboundRequests`
  -> TxSubmissionConfig
  -- ^ inbound config
  -> TxSubmissionConfig
  -- ^ outbound config
  -> NumTxsToReq
  -> TxOutboundVersion
  -> [Tx txid]
  -> Maybe Int
  -- ^ number of txs expected in the inbound mempool; the simulation stops
  -- once they arrived, or at the deadline
  -> DiffTime
  -- ^ deadline
  -> Maybe DiffTime
  -> Maybe DiffTime
  -> m ([Tx txid], [Tx txid])
txSubmissionSimulation :: forall (m :: * -> *) txid.
(MonadAsync m, MonadDelay m, MonadEvaluate m, MonadFork m,
 MonadMask m, MonadMVar m, MonadSay m, MonadST m, MonadSTM m,
 MonadTime m, MonadTimer m, MonadThrow m, MonadThrow (STM m),
 MonadMonotonicTime m, Ord txid, Eq txid, ShowProxy txid,
 NoThunks (Tx txid), txid ~ Int) =>
Tracer m (TestName, TraceSendRecv (TxSubmission2 txid (Tx txid)))
-> Tracer m OutboundRequest
-> TxSubmissionConfig
-> TxSubmissionConfig
-> NumTxsToReq
-> TxOutboundVersion
-> [Tx txid]
-> Maybe Int
-> DiffTime
-> Maybe DiffTime
-> Maybe DiffTime
-> m ([Tx txid], [Tx txid])
txSubmissionSimulation Tracer m (TestName, TraceSendRecv (TxSubmission2 txid (Tx txid)))
tracer
                       Tracer m OutboundRequest
requestTracer
                       TxSubmissionConfig
inboundConfig
                       TxSubmissionConfig
outboundConfig
                       NumTxsToReq
maxNumTxsToRequest
                       TxOutboundVersion
version
                       [Tx txid]
outboundTxs
                       Maybe Int
expectedTxs
                       DiffTime
deadline
                       Maybe DiffTime
inboundDelay
                       Maybe DiffTime
outboundDelay = do

    controlMessageVar <- ControlMessage -> m (TVar m ControlMessage)
forall a. a -> m (TVar m a)
forall (m :: * -> *) a. MonadSTM m => a -> m (TVar m a)
newTVarIO ControlMessage
Continue
    let controlMessageSTM = TVar m ControlMessage -> STM m ControlMessage
forall a. TVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
readTVar TVar m ControlMessage
controlMessageVar
    inboundMempool  <- emptyMempool
    duplicateTxIdsVar <- newTVarIO []
    outboundMempool <- newMempool outboundTxs
    (outboundChannel, inboundChannel) <- createConnectedChannels
    outboundAsync <-
      async $ runPeerWithLimits
                (("OUTBOUND",) `contramap` tracer)
                txSubmissionCodec2
                (byteLimitsTxSubmission2 (fromIntegral . BSL.length))
                timeLimitsTxSubmission2
                (maybe id delayChannel outboundDelay outboundChannel)
                (txSubmissionClientPeer
                  (traceOutboundRequests
                    requestTracer
                    (maxNumUnacknowledgedTxIds outboundConfig)
                    (outboundPeer controlMessageSTM outboundMempool)))

    inboundAsync <-
      async $ runPipelinedPeerWithLimits
                (("INBOUND",) `contramap` verboseTracer)
                txSubmissionCodec2
                (byteLimitsTxSubmission2 (fromIntegral . BSL.length))
                timeLimitsTxSubmission2
                (maybe id delayChannel inboundDelay inboundChannel)
                (txSubmissionServerPeerPipelined (inboundPeer duplicateTxIdsVar inboundMempool))

    -- terminate the outbound once the expected txs arrived, or at the
    -- deadline
    terminateAsync <-
      async $ do
        let delivered Int
expected = do
              inmp <- Mempool m txid (Tx txid) -> m [Tx txid]
forall (m :: * -> *) txid.
MonadSTM m =>
Mempool m txid (Tx txid) -> m [Tx txid]
readMempool Mempool m txid (Tx txid)
inboundMempool
              unless (length inmp >= expected) $
                threadDelay 1 >> delivered expected
        case expectedTxs of
          Maybe Int
Nothing       -> DiffTime -> m ()
forall (m :: * -> *). MonadDelay m => DiffTime -> m ()
threadDelay DiffTime
deadline
          Just Int
expected -> m (Maybe ()) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Maybe ()) -> m ()) -> m (Maybe ()) -> m ()
forall a b. (a -> b) -> a -> b
$ DiffTime -> m () -> m (Maybe ())
forall a. DiffTime -> m a -> m (Maybe a)
forall (m :: * -> *) a.
MonadTimer m =>
DiffTime -> m a -> m (Maybe a)
timeout DiffTime
deadline (Int -> m ()
delivered Int
expected)
        atomically (writeTVar controlMessageVar Terminate)

    _ <- waitAnyCancel [ outboundAsync, inboundAsync ]
    cancel terminateAsync

    inmp <- readMempool inboundMempool
    outmp <- readMempool outboundMempool
    return (inmp, outmp)
  where
    outboundPeer :: ControlMessageSTM m
                 -> Mempool m txid (Tx txid)
                 -> TxSubmissionClient txid (Tx txid) m ()
    outboundPeer :: STM m ControlMessage
-> Mempool m txid (Tx txid)
-> TxSubmissionClient txid (Tx txid) m ()
outboundPeer STM m ControlMessage
controlMessageSTM Mempool m txid (Tx txid)
outboundMempool =
      Tracer m (TraceTxSubmissionOutbound txid (Tx txid))
-> TxSubmissionConfig
-> TxSubmissionMempoolReader txid (Tx txid) Integer m
-> TxOutboundVersion
-> STM m ControlMessage
-> TxSubmissionClient txid (Tx txid) m ()
forall txid tx idx (m :: * -> *).
(Ord txid, Show txid, Ord idx, MonadSTM m, MonadThrow m) =>
Tracer m (TraceTxSubmissionOutbound txid tx)
-> TxSubmissionConfig
-> TxSubmissionMempoolReader txid tx idx m
-> TxOutboundVersion
-> ControlMessageSTM m
-> TxSubmissionClient txid tx m ()
txSubmissionOutbound
        Tracer m (TraceTxSubmissionOutbound txid (Tx txid))
forall (m :: * -> *) a. Monad m => Tracer m a
nullTracer
        TxSubmissionConfig
outboundConfig
        (Mempool m txid (Tx txid)
-> TxSubmissionMempoolReader txid (Tx txid) Integer m
forall txid (m :: * -> *).
(MonadSTM m, Ord txid, Show txid) =>
Mempool m txid (Tx txid)
-> TxSubmissionMempoolReader txid (Tx txid) Integer m
getMempoolReader Mempool m txid (Tx txid)
outboundMempool)
        TxOutboundVersion
version
        STM m ControlMessage
controlMessageSTM

    inboundPeer :: TVar m [txid]
                -> Mempool m txid (Tx txid)
                -> TxSubmissionServerPipelined txid (Tx txid) m ()
    inboundPeer :: TVar m [txid]
-> Mempool m txid (Tx txid)
-> TxSubmissionServerPipelined txid (Tx txid) m ()
inboundPeer TVar m [txid]
duplicateTxIdsVar Mempool m txid (Tx txid)
inboundMempool =
      Tracer m (TraceTxSubmissionInbound txid (Tx txid))
-> TxSubmissionInitDelay
-> TxSubmissionConfig
-> NumTxsToReq
-> TxSubmissionMempoolReader txid (Tx txid) Integer m
-> TxSubmissionMempoolWriter txid (Tx txid) Integer m InvalidTx
-> TxSubmissionServerPipelined txid (Tx txid) m ()
forall txid tx idx (m :: * -> *) err.
(Ord txid, NoThunks txid, NoThunks tx, MonadSTM m, MonadThrow m,
 MonadDelay m) =>
Tracer m (TraceTxSubmissionInbound txid tx)
-> TxSubmissionInitDelay
-> TxSubmissionConfig
-> NumTxsToReq
-> TxSubmissionMempoolReader txid tx idx m
-> TxSubmissionMempoolWriter txid tx idx m err
-> TxSubmissionServerPipelined txid tx m ()
txSubmissionInbound
        ((TestName
"INBOUND",) (TraceTxSubmissionInbound txid (Tx txid)
 -> (TestName, TraceTxSubmissionInbound txid (Tx txid)))
-> Tracer m (TestName, TraceTxSubmissionInbound txid (Tx txid))
-> Tracer m (TraceTxSubmissionInbound txid (Tx txid))
forall a' a. (a' -> a) -> Tracer m a -> Tracer m a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
`contramap` Tracer m (TestName, TraceTxSubmissionInbound txid (Tx txid))
forall a (m :: * -> *).
(MonadFork m, MonadDelay m, MonadSay m, MonadMonotonicTime m,
 Show a) =>
Tracer m a
verboseTracer)
        TxSubmissionInitDelay
NoTxSubmissionInitDelay
        TxSubmissionConfig
inboundConfig
        NumTxsToReq
maxNumTxsToRequest
        (Mempool m txid (Tx txid)
-> TxSubmissionMempoolReader txid (Tx txid) Integer m
forall txid (m :: * -> *).
(MonadSTM m, Ord txid, Show txid) =>
Mempool m txid (Tx txid)
-> TxSubmissionMempoolReader txid (Tx txid) Integer m
getMempoolReader Mempool m txid (Tx txid)
inboundMempool)
        (TVar m [txid]
-> Mempool m txid (Tx txid)
-> TxSubmissionMempoolWriter txid (Tx txid) Integer m InvalidTx
forall txid (m :: * -> *).
(MonadSTM m, MonadTime m, MonadThrow m, Ord txid, Eq txid,
 Typeable txid, Show txid) =>
TVar m [txid]
-> Mempool m txid (Tx txid)
-> TxSubmissionMempoolWriter txid (Tx txid) Integer m InvalidTx
getMempoolWriter TVar m [txid]
duplicateTxIdsVar Mempool m txid (Tx txid)
inboundMempool)



prop_txSubmission :: ArbTxSubmissionConfigs
                  -> ArbNumTxsToRequest
                  -> NonEmptyList (Tx Int)
                  -> Maybe (Positive SmallDelay)
                  -- ^ The delay must be smaller (<) than 5s, so that overall
                  -- delay is less than 10s, otherwise 'smallDelay' in
                  -- 'timeLimitsTxSubmission2' will kick in.
                  -> Property
prop_txSubmission :: ArbTxSubmissionConfigs
-> ArbNumTxsToRequest
-> NonEmptyList (Tx Int)
-> Maybe (Positive SmallDelay)
-> Property
prop_txSubmission
    (ArbTxSubmissionConfigs TxOutboundVersion
version TxSubmissionConfig
inboundConfig TxSubmissionConfig
outboundConfig)
    (ArbNumTxsToRequest NumTxsToReq
maxNumTxsToRequest)
    (NonEmpty [Tx Int]
outboundTxs)
    Maybe (Positive SmallDelay)
delay
    =
    let mbDelayTime :: Maybe DiffTime
mbDelayTime = SmallDelay -> DiffTime
getSmallDelay (SmallDelay -> DiffTime)
-> (Positive SmallDelay -> SmallDelay)
-> Positive SmallDelay
-> DiffTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Positive SmallDelay -> SmallDelay
forall a. Positive a -> a
getPositive (Positive SmallDelay -> DiffTime)
-> Maybe (Positive SmallDelay) -> Maybe DiffTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (Positive SmallDelay)
delay
        outUniqueTxIds :: [Tx Int]
outUniqueTxIds = (Tx Int -> Tx Int -> Bool) -> [Tx Int] -> [Tx Int]
forall a. (a -> a -> Bool) -> [a] -> [a]
nubBy ((Int -> Int -> Bool) -> (Tx Int -> Int) -> Tx Int -> Tx Int -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
(==) Tx Int -> Int
forall txid. Tx txid -> txid
getTxId) [Tx Int]
outboundTxs
        outValidTxs :: [Tx Int]
outValidTxs    = (Tx Int -> Bool) -> [Tx Int] -> [Tx Int]
forall a. (a -> Bool) -> [a] -> [a]
filter Tx Int -> Bool
forall txid. Tx txid -> Bool
getTxValid [Tx Int]
outboundTxs
        uniqueTxIds :: Bool
uniqueTxIds    = [Tx Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Tx Int]
outUniqueTxIds Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [Tx Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Tx Int]
outboundTxs
        -- with unique txids every valid tx must arrive; otherwise run until
        -- the deadline
        expectedTxs :: Maybe Int
expectedTxs | Bool
uniqueTxIds = Int -> Maybe Int
forall a. a -> Maybe a
Just ([Tx Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Tx Int]
outValidTxs)
                    | Bool
otherwise   = Maybe Int
forall a. Maybe a
Nothing
        -- generous: each tx takes a few round trips
        deadline :: DiffTime
deadline = DiffTime
60 DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
+ DiffTime
20 DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
* DiffTime -> Maybe DiffTime -> DiffTime
forall a. a -> Maybe a -> a
fromMaybe DiffTime
1 Maybe DiffTime
mbDelayTime
                            DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
* Int -> DiffTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac ([Tx Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Tx Int]
outboundTxs)
        tr :: SimTrace ([Tx Int], [Tx Int])
tr = (forall s. IOSim s ([Tx Int], [Tx Int]))
-> SimTrace ([Tx Int], [Tx Int])
forall a. (forall s. IOSim s a) -> SimTrace a
runSimTrace ((forall s. IOSim s ([Tx Int], [Tx Int]))
 -> SimTrace ([Tx Int], [Tx Int]))
-> (forall s. IOSim s ([Tx Int], [Tx Int]))
-> SimTrace ([Tx Int], [Tx Int])
forall a b. (a -> b) -> a -> b
$
               Tracer
  (IOSim s) (TestName, TraceSendRecv (TxSubmission2 Int (Tx Int)))
-> Tracer (IOSim s) OutboundRequest
-> TxSubmissionConfig
-> TxSubmissionConfig
-> NumTxsToReq
-> TxOutboundVersion
-> [Tx Int]
-> Maybe Int
-> DiffTime
-> Maybe DiffTime
-> Maybe DiffTime
-> IOSim s ([Tx Int], [Tx Int])
forall (m :: * -> *) txid.
(MonadAsync m, MonadDelay m, MonadEvaluate m, MonadFork m,
 MonadMask m, MonadMVar m, MonadSay m, MonadST m, MonadSTM m,
 MonadTime m, MonadTimer m, MonadThrow m, MonadThrow (STM m),
 MonadMonotonicTime m, Ord txid, Eq txid, ShowProxy txid,
 NoThunks (Tx txid), txid ~ Int) =>
Tracer m (TestName, TraceSendRecv (TxSubmission2 txid (Tx txid)))
-> Tracer m OutboundRequest
-> TxSubmissionConfig
-> TxSubmissionConfig
-> NumTxsToReq
-> TxOutboundVersion
-> [Tx txid]
-> Maybe Int
-> DiffTime
-> Maybe DiffTime
-> Maybe DiffTime
-> m ([Tx txid], [Tx txid])
txSubmissionSimulation
                 Tracer
  (IOSim s) (TestName, TraceSendRecv (TxSubmission2 Int (Tx Int)))
forall a (m :: * -> *).
(MonadFork m, MonadDelay m, MonadSay m, MonadMonotonicTime m,
 Show a) =>
Tracer m a
verboseTracer
                 Tracer (IOSim s) OutboundRequest
forall a s. Typeable a => Tracer (IOSim s) a
dynamicTracer
                 TxSubmissionConfig
inboundConfig
                 TxSubmissionConfig
outboundConfig
                 NumTxsToReq
maxNumTxsToRequest
                 TxOutboundVersion
version
                 [Tx Int]
outboundTxs
                 Maybe Int
expectedTxs
                 DiffTime
deadline
                 Maybe DiffTime
mbDelayTime
                 Maybe DiffTime
mbDelayTime
        -- `selectTraceEventsDynamic'` doesn't throw if the simulation
        -- failed; failures are reported by `evaluateTrace`
        events :: [RequestTxIdsEvent]
events = [OutboundRequest] -> [RequestTxIdsEvent]
requestTxIdsEvents (SimTrace ([Tx Int], [Tx Int]) -> [OutboundRequest]
forall a b. Typeable b => Trace a SimEvent -> [b]
selectTraceEventsDynamic' SimTrace ([Tx Int], [Tx Int])
tr)
        inboundWindow :: NumTxIdsToAck
inboundWindow  = TxSubmissionConfig -> NumTxIdsToAck
maxNumUnacknowledgedTxIds TxSubmissionConfig
inboundConfig
        outboundWindow :: NumTxIdsToAck
outboundWindow = TxSubmissionConfig -> NumTxIdsToAck
maxNumUnacknowledgedTxIds TxSubmissionConfig
outboundConfig
    in
    TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
label (TxOutboundVersion -> TestName
forall a. Show a => a -> TestName
show TxOutboundVersion
version) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
    Bool -> TestName -> Property -> Property
forall prop. Testable prop => Bool -> TestName -> prop -> Property
classify (NumTxIdsToAck
outboundWindow NumTxIdsToAck -> NumTxIdsToAck -> Bool
forall a. Ord a => a -> a -> Bool
< NumTxIdsToAck
inboundWindow) TestName
"smaller outbound window" (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
    IO Property -> Property
forall prop. Testable prop => IO prop -> Property
ioProperty (IO Property -> Property) -> IO Property -> Property
forall a b. (a -> b) -> a -> b
$ do
        tr' <- SimTrace ([Tx Int], [Tx Int])
-> IO (SimResults ([Tx Int], [Tx Int]))
forall a. SimTrace a -> IO (SimResults a)
evaluateTrace SimTrace ([Tx Int], [Tx Int])
tr
        case tr' of
             SimException SomeException
e [TestName]
trace -> do
                Property -> IO Property
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName -> [TestName] -> TestName
forall a. [a] -> [[a]] -> [a]
intercalate TestName
"\n" ([TestName] -> TestName) -> [TestName] -> TestName
forall a b. (a -> b) -> a -> b
$ SomeException -> TestName
forall a. Show a => a -> TestName
show SomeException
e TestName -> [TestName] -> [TestName]
forall a. a -> [a] -> [a]
: [TestName]
trace) Bool
False
             SimDeadLock [TestName]
trace -> do
                 Property -> IO Property
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName -> [TestName] -> TestName
forall a. [a] -> [[a]] -> [a]
intercalate TestName
"\n" ([TestName] -> TestName) -> [TestName] -> TestName
forall a b. (a -> b) -> a -> b
$ TestName
"Deadlock" TestName -> [TestName] -> [TestName]
forall a. a -> [a] -> [a]
: [TestName]
trace) Bool
False
             SimReturn ([Tx Int]
inmp, [Tx Int]
outmp) [TestName]
trace -> do
                 (Property -> Property) -> IO Property -> IO Property
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ( TestName -> [TestName] -> Property -> Property
forall prop.
Testable prop =>
TestName -> [TestName] -> prop -> Property
tabulate TestName
"MsgRequestTxIds" (RequestTxIdsEvent -> TestName
forall a. Show a => a -> TestName
show (RequestTxIdsEvent -> TestName)
-> [RequestTxIdsEvent] -> [TestName]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [RequestTxIdsEvent]
events)
                      (Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Bool -> TestName -> Property -> Property
forall prop.
Testable prop =>
Double -> Bool -> TestName -> prop -> Property
cover Double
10 (RequestTxIdsEvent
Clamped RequestTxIdsEvent -> [RequestTxIdsEvent] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [RequestTxIdsEvent]
events) TestName
"clamped"
                      (Property -> Property)
-> (Property -> Property) -> Property -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Bool -> TestName -> Property -> Property
forall prop.
Testable prop =>
Double -> Bool -> TestName -> prop -> Property
cover Double
10 (RequestTxIdsEvent
ClampedToZero RequestTxIdsEvent -> [RequestTxIdsEvent] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [RequestTxIdsEvent]
events) TestName
"clamped to zero"
                      ) (IO Property -> IO Property) -> IO Property -> IO Property
forall a b. (a -> b) -> a -> b
$
                   -- the protocol only reads the outbound mempool
                   case (Bool
uniqueTxIds, [Tx Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Tx Int]
outValidTxs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [Tx Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Tx Int]
outmp) of
                      a :: (Bool, Bool)
a@(Bool
True, Bool
True) ->
                          -- If we are presented with a stream of unique txids for valid
                          -- transactions the inbound transactions should match the outbound
                          -- transactions exactly: all of them arrived, in order.
                          Property -> IO Property
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName -> [TestName] -> TestName
forall a. [a] -> [[a]] -> [a]
intercalate TestName
"\n" [TestName]
trace)
                                 (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample ((Bool, Bool) -> TestName
forall a. Show a => a -> TestName
show (Bool, Bool)
a)
                                 (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ [Tx Int]
inmp [Tx Int] -> [Tx Int] -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== [Tx Int]
outValidTxs
                      a :: (Bool, Bool)
a@(Bool
True, Bool
False) ->
                          -- If we are presented with a stream of unique txids then we should have
                          -- fetched all valid transactions.
                          Property -> IO Property
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName -> [TestName] -> TestName
forall a. [a] -> [[a]] -> [a]
intercalate TestName
"\n" [TestName]
trace)
                                 (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample ((Bool, Bool) -> TestName
forall a. Show a => a -> TestName
show (Bool, Bool)
a)
                                 (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ [Tx Int]
inmp [Tx Int] -> [Tx Int] -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== [Tx Int]
outValidTxs
                      a :: (Bool, Bool)
a@(Bool
False, Bool
True) ->
                          -- If we are presented with a stream of valid txids then we should have
                          -- fetched some version of those transactions.
                          Property -> IO Property
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName -> [TestName] -> TestName
forall a. [a] -> [[a]] -> [a]
intercalate TestName
"\n" [TestName]
trace)
                                 (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample ((Bool, Bool) -> TestName
forall a. Show a => a -> TestName
show (Bool, Bool)
a)
                                 (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (([Tx Int], [Tx Int]) -> TestName
forall a. Show a => a -> TestName
show ([Tx Int]
inmp, [Tx Int]
outmp))
                                 (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$ (Tx Int -> Int) -> [Tx Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Tx Int -> Int
forall txid. Tx txid -> txid
getTxId [Tx Int]
inmp [Int] -> [Int] -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
take ([Tx Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Tx Int]
inmp)
                                                             ((Tx Int -> Int) -> [Tx Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Tx Int -> Int
forall txid. Tx txid -> txid
getTxId ([Tx Int] -> [Int]) -> [Tx Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ (Tx Int -> Bool) -> [Tx Int] -> [Tx Int]
forall a. (a -> Bool) -> [a] -> [a]
filter Tx Int -> Bool
forall txid. Tx txid -> Bool
getTxValid [Tx Int]
outUniqueTxIds)
                      (Bool
False, Bool
False)
                           -- If we are presented with a stream of valid and invalid Txs with
                           -- duplicate txids we're content with completing the protocol
                           -- without error.
                           -> Property -> IO Property
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Property -> IO Property) -> Property -> IO Property
forall a b. (a -> b) -> a -> b
$ Bool -> Property
forall prop. Testable prop => prop -> Property
property Bool
True


-- | The number of txs the inbound requests at a time, including values
-- outside of the range checked by `saneMaxNumTxsToRequest`: `0` and values
-- above `maxSaneNumTxsToRequest`.
--
newtype ArbNumTxsToRequest = ArbNumTxsToRequest NumTxsToReq
  deriving Int -> ArbNumTxsToRequest -> ShowS
[ArbNumTxsToRequest] -> ShowS
ArbNumTxsToRequest -> TestName
(Int -> ArbNumTxsToRequest -> ShowS)
-> (ArbNumTxsToRequest -> TestName)
-> ([ArbNumTxsToRequest] -> ShowS)
-> Show ArbNumTxsToRequest
forall a.
(Int -> a -> ShowS) -> (a -> TestName) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ArbNumTxsToRequest -> ShowS
showsPrec :: Int -> ArbNumTxsToRequest -> ShowS
$cshow :: ArbNumTxsToRequest -> TestName
show :: ArbNumTxsToRequest -> TestName
$cshowList :: [ArbNumTxsToRequest] -> ShowS
showList :: [ArbNumTxsToRequest] -> ShowS
Show

instance Arbitrary ArbNumTxsToRequest where
  arbitrary :: Gen ArbNumTxsToRequest
arbitrary = NumTxsToReq -> ArbNumTxsToRequest
ArbNumTxsToRequest (NumTxsToReq -> ArbNumTxsToRequest)
-> (Word16 -> NumTxsToReq) -> Word16 -> ArbNumTxsToRequest
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> NumTxsToReq
NumTxsToReq (Word16 -> ArbNumTxsToRequest)
-> Gen Word16 -> Gen ArbNumTxsToRequest
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Int, Gen Word16)] -> Gen Word16
forall a. HasCallStack => [(Int, Gen a)] -> Gen a
frequency
    [ (Int
3, Word16 -> Gen Word16
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (NumTxsToReq -> Word16
getNumTxsToReq NumTxsToReq
defaultMaxNumTxsToRequest))
    , (Int
1, Word16 -> Gen Word16
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Word16
0)
    , (Int
2, (Word16, Word16) -> Gen Word16
forall a. Random a => (a, a) -> Gen a
choose (Word16
1, NumTxsToReq -> Word16
getNumTxsToReq NumTxsToReq
maxSaneNumTxsToRequest))
    , (Int
1, (Word16, Word16) -> Gen Word16
forall a. Random a => (a, a) -> Gen a
choose (NumTxsToReq -> Word16
getNumTxsToReq NumTxsToReq
maxSaneNumTxsToRequest Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
+ Word16
1, Word16
forall a. Bounded a => a
maxBound))
    ]
  shrink :: ArbNumTxsToRequest -> [ArbNumTxsToRequest]
shrink (ArbNumTxsToRequest (NumTxsToReq Word16
n)) =
    NumTxsToReq -> ArbNumTxsToRequest
ArbNumTxsToRequest (NumTxsToReq -> ArbNumTxsToRequest)
-> (Word16 -> NumTxsToReq) -> Word16 -> ArbNumTxsToRequest
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> NumTxsToReq
NumTxsToReq (Word16 -> ArbNumTxsToRequest) -> [Word16] -> [ArbNumTxsToRequest]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word16 -> [Word16]
forall a. Arbitrary a => a -> [a]
shrink Word16
n


-- | `clampMaxNumTxsToRequest` returns a value accepted by
-- `saneMaxNumTxsToRequest`, and keeps such values unchanged.
--
prop_clampMaxNumTxsToRequest :: ArbNumTxsToRequest -> Property
prop_clampMaxNumTxsToRequest :: ArbNumTxsToRequest -> Property
prop_clampMaxNumTxsToRequest (ArbNumTxsToRequest NumTxsToReq
n) =
    let sane :: Bool
sane = NumTxsToReq -> Bool
saneMaxNumTxsToRequest NumTxsToReq
n
    in Bool -> TestName -> Property -> Property
forall prop. Testable prop => Bool -> TestName -> prop -> Property
classify Bool
sane TestName
"sane" (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
       TestName -> Property -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (NumTxsToReq -> TestName
forall a. Show a => a -> TestName
show (NumTxsToReq -> NumTxsToReq
clampMaxNumTxsToRequest NumTxsToReq
n)) (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
            NumTxsToReq -> Bool
saneMaxNumTxsToRequest (NumTxsToReq -> NumTxsToReq
clampMaxNumTxsToRequest NumTxsToReq
n)
       Bool -> Bool -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. (Bool -> Bool
not Bool
sane Bool -> Bool -> Bool
|| NumTxsToReq -> NumTxsToReq
clampMaxNumTxsToRequest NumTxsToReq
n NumTxsToReq -> NumTxsToReq -> Bool
forall a. Eq a => a -> a -> Bool
== NumTxsToReq
n)


-- | `maxSaneNumTxsToRequest` is the largest number of txs of `max_TX_SIZE`,
-- each `const_MAX_TX_SIZE_DISCREPANCY` larger, for which a `MsgReplyTxs`
-- encoded with `codecTxSubmission2` fits within the `StTxs` size limit.
--
prop_maxSaneNumTxsToRequest_fitsSizeLimit :: Property
prop_maxSaneNumTxsToRequest_fitsSizeLimit :: Property
prop_maxSaneNumTxsToRequest_fitsSizeLimit =
    Property -> Property
forall prop. Testable prop => prop -> Property
once (Property -> Property) -> Property -> Property
forall a b. (a -> b) -> a -> b
$
         TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName
"reply with " TestName -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> TestName
forall a. Show a => a -> TestName
show Int
n TestName -> ShowS
forall a. [a] -> [a] -> [a]
++ TestName
" txs: " TestName -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> TestName
forall a. Show a => a -> TestName
show (Int -> Integer
replySize Int
n))
           (Int -> Integer
replySize Int
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
limit)
    Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. TestName -> Bool -> Property
forall prop. Testable prop => TestName -> prop -> Property
counterexample (TestName
"reply with " TestName -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> TestName
forall a. Show a => a -> TestName
show (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) TestName -> ShowS
forall a. [a] -> [a] -> [a]
++ TestName
" txs: " TestName -> ShowS
forall a. [a] -> [a] -> [a]
++ Integer -> TestName
forall a. Show a => a -> TestName
show (Int -> Integer
replySize (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)))
           (Int -> Integer
replySize (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
limit)
  where
    n :: Int
    n :: Int
n = NumTxsToReq -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral NumTxsToReq
maxSaneNumTxsToRequest

    tx :: SizedBytes
    tx :: SizedBytes
tx = Word -> SizedBytes
SizedBytes (SizeInBytes -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (SizeInBytes
max_TX_SIZE SizeInBytes -> SizeInBytes -> SizeInBytes
forall a. Num a => a -> a -> a
+ SizeInBytes
const_MAX_TX_SIZE_DISCREPANCY))

    replySize :: Int -> Integer
    replySize :: Int -> Integer
replySize Int
k =
      Int64 -> Integer
forall a. Integral a => a -> Integer
toInteger (Int64 -> Integer)
-> (Message (TxSubmission2 SizedBytes SizedBytes) 'StTxs 'StIdle
    -> Int64)
-> Message (TxSubmission2 SizedBytes SizedBytes) 'StTxs 'StIdle
-> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Int64
BSL.length (ByteString -> Int64)
-> (Message (TxSubmission2 SizedBytes SizedBytes) 'StTxs 'StIdle
    -> ByteString)
-> Message (TxSubmission2 SizedBytes SizedBytes) 'StTxs 'StIdle
-> Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CodecF
  (TxSubmission2 SizedBytes SizedBytes)
  DeserialiseFailure
  IO
  SomeMessage
  ByteString
-> forall (st :: TxSubmission2 SizedBytes SizedBytes)
          (st' :: TxSubmission2 SizedBytes SizedBytes).
   (StateTokenI st, ActiveState st) =>
   Message (TxSubmission2 SizedBytes SizedBytes) st st' -> ByteString
forall ps failure (m :: * -> *) (f :: ps -> *) bytes.
CodecF ps failure m f bytes
-> forall (st :: ps) (st' :: ps).
   (StateTokenI st, ActiveState st) =>
   Message ps st st' -> bytes
encode (forall (m :: * -> *).
MonadST m =>
Codec
  (TxSubmission2 SizedBytes SizedBytes)
  DeserialiseFailure
  m
  ByteString
codec_sized @IO)
        (Message (TxSubmission2 SizedBytes SizedBytes) 'StTxs 'StIdle
 -> Integer)
-> Message (TxSubmission2 SizedBytes SizedBytes) 'StTxs 'StIdle
-> Integer
forall a b. (a -> b) -> a -> b
$ ([SizedBytes]
-> Message (TxSubmission2 SizedBytes SizedBytes) 'StTxs 'StIdle
forall tx txid.
[tx] -> Message (TxSubmission2 txid tx) 'StTxs 'StIdle
MsgReplyTxs (Int -> SizedBytes -> [SizedBytes]
forall a. Int -> a -> [a]
replicate Int
k SizedBytes
tx)
            :: Message (TxSubmission2 SizedBytes SizedBytes) StTxs StIdle)

    limit :: Integer
    limit :: Integer
limit = Word -> Integer
forall a. Integral a => a -> Integer
toInteger
          (Word -> Integer) -> Word -> Integer
forall a b. (a -> b) -> a -> b
$ ProtocolSizeLimits
  (TxSubmission2 (ZonkAny 0) (ZonkAny 1)) (ZonkAny 2)
-> forall (st :: TxSubmission2 (ZonkAny 0) (ZonkAny 1)).
   ActiveState st =>
   StateToken st -> Word
forall ps bytes.
ProtocolSizeLimits ps bytes
-> forall (st :: ps). ActiveState st => StateToken st -> Word
sizeLimitForState ((ZonkAny 2 -> Word)
-> ProtocolSizeLimits
     (TxSubmission2 (ZonkAny 0) (ZonkAny 1)) (ZonkAny 2)
forall bytes txid tx.
(bytes -> Word) -> ProtocolSizeLimits (TxSubmission2 txid tx) bytes
byteLimitsTxSubmission2 (TestName -> ZonkAny 2 -> Word
forall a. HasCallStack => TestName -> a
error TestName
"unused")) StateToken 'StTxs
SingTxSubmission 'StTxs
forall {txid} {tx}. SingTxSubmission 'StTxs
SingTxs