{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
module Ouroboros.Consensus.Mempool.API (
Mempool(..)
, addTxs
, ForgeLedgerState(..)
, MempoolCapacityBytes (..)
, MempoolSnapshot(..)
, MempoolAddTxResult (..)
, isMempoolTxAdded
, isMempoolTxRejected
, MempoolSize (..)
, TraceEventMempool(..)
, TxSizeInBytes
) where
import Data.Word (Word32)
import Ouroboros.Network.Protocol.TxSubmission.Type (TxSizeInBytes)
import Ouroboros.Consensus.Block
import Ouroboros.Consensus.Ledger.Abstract
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Util.IOLike
data Mempool m blk idx = Mempool {
Mempool m blk idx
-> [GenTx blk]
-> m ([(GenTx blk, MempoolAddTxResult blk)], [GenTx blk])
tryAddTxs :: [GenTx blk]
-> m ( [(GenTx blk, MempoolAddTxResult blk)]
, [GenTx blk]
)
, Mempool m blk idx -> [GenTxId blk] -> m ()
removeTxs :: [GenTxId blk] -> m ()
, Mempool m blk idx -> m (MempoolSnapshot blk idx)
syncWithLedger :: m (MempoolSnapshot blk idx)
, Mempool m blk idx -> STM m (MempoolSnapshot blk idx)
getSnapshot :: STM m (MempoolSnapshot blk idx)
, Mempool m blk idx
-> ForgeLedgerState blk -> STM m (MempoolSnapshot blk idx)
getSnapshotFor :: ForgeLedgerState blk -> STM m (MempoolSnapshot blk idx)
, Mempool m blk idx -> STM m MempoolCapacityBytes
getCapacity :: STM m MempoolCapacityBytes
, Mempool m blk idx -> GenTx blk -> TxSizeInBytes
getTxSize :: GenTx blk -> TxSizeInBytes
, Mempool m blk idx -> idx
zeroIdx :: idx
}
data MempoolAddTxResult blk
= MempoolTxAdded
| MempoolTxRejected !(ApplyTxErr blk)
deriving instance Eq (ApplyTxErr blk) => Eq (MempoolAddTxResult blk)
deriving instance Show (ApplyTxErr blk) => Show (MempoolAddTxResult blk)
isMempoolTxAdded :: MempoolAddTxResult blk -> Bool
isMempoolTxAdded :: MempoolAddTxResult blk -> Bool
isMempoolTxAdded MempoolAddTxResult blk
MempoolTxAdded = Bool
True
isMempoolTxAdded MempoolAddTxResult blk
_ = Bool
False
isMempoolTxRejected :: MempoolAddTxResult blk -> Bool
isMempoolTxRejected :: MempoolAddTxResult blk -> Bool
isMempoolTxRejected (MempoolTxRejected ApplyTxErr blk
_) = Bool
True
isMempoolTxRejected MempoolAddTxResult blk
_ = Bool
False
addTxs
:: forall m blk idx. MonadSTM m
=> Mempool m blk idx
-> [GenTx blk]
-> m [(GenTx blk, MempoolAddTxResult blk)]
addTxs :: Mempool m blk idx
-> [GenTx blk] -> m [(GenTx blk, MempoolAddTxResult blk)]
addTxs Mempool m blk idx
mempool = \[GenTx blk]
txs -> do
([(GenTx blk, MempoolAddTxResult blk)]
processed, [GenTx blk]
toAdd) <- Mempool m blk idx
-> [GenTx blk]
-> m ([(GenTx blk, MempoolAddTxResult blk)], [GenTx blk])
forall (m :: * -> *) blk idx.
Mempool m blk idx
-> [GenTx blk]
-> m ([(GenTx blk, MempoolAddTxResult blk)], [GenTx blk])
tryAddTxs Mempool m blk idx
mempool [GenTx blk]
txs
case [GenTx blk]
toAdd of
[] -> [(GenTx blk, MempoolAddTxResult blk)]
-> m [(GenTx blk, MempoolAddTxResult blk)]
forall (m :: * -> *) a. Monad m => a -> m a
return [(GenTx blk, MempoolAddTxResult blk)]
processed
[GenTx blk]
_ -> [[(GenTx blk, MempoolAddTxResult blk)]]
-> [GenTx blk] -> m [(GenTx blk, MempoolAddTxResult blk)]
go [[(GenTx blk, MempoolAddTxResult blk)]
processed] [GenTx blk]
toAdd
where
go
:: [[(GenTx blk, MempoolAddTxResult blk)]]
-> [GenTx blk]
-> m [(GenTx blk, MempoolAddTxResult blk)]
go :: [[(GenTx blk, MempoolAddTxResult blk)]]
-> [GenTx blk] -> m [(GenTx blk, MempoolAddTxResult blk)]
go [[(GenTx blk, MempoolAddTxResult blk)]]
acc [] = [(GenTx blk, MempoolAddTxResult blk)]
-> m [(GenTx blk, MempoolAddTxResult blk)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[(GenTx blk, MempoolAddTxResult blk)]]
-> [(GenTx blk, MempoolAddTxResult blk)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[(GenTx blk, MempoolAddTxResult blk)]]
-> [[(GenTx blk, MempoolAddTxResult blk)]]
forall a. [a] -> [a]
reverse [[(GenTx blk, MempoolAddTxResult blk)]]
acc))
go [[(GenTx blk, MempoolAddTxResult blk)]]
acc txs :: [GenTx blk]
txs@(GenTx blk
tx:[GenTx blk]
_) = do
let firstTxSize :: TxSizeInBytes
firstTxSize = Mempool m blk idx -> GenTx blk -> TxSizeInBytes
forall (m :: * -> *) blk idx.
Mempool m blk idx -> GenTx blk -> TxSizeInBytes
getTxSize Mempool m blk idx
mempool GenTx blk
tx
STM m () -> m ()
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m () -> m ()) -> STM m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
TxSizeInBytes
curSize <- MempoolSize -> TxSizeInBytes
msNumBytes (MempoolSize -> TxSizeInBytes)
-> (MempoolSnapshot blk idx -> MempoolSize)
-> MempoolSnapshot blk idx
-> TxSizeInBytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MempoolSnapshot blk idx -> MempoolSize
forall blk idx. MempoolSnapshot blk idx -> MempoolSize
snapshotMempoolSize (MempoolSnapshot blk idx -> TxSizeInBytes)
-> STM m (MempoolSnapshot blk idx) -> STM m TxSizeInBytes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Mempool m blk idx -> STM m (MempoolSnapshot blk idx)
forall (m :: * -> *) blk idx.
Mempool m blk idx -> STM m (MempoolSnapshot blk idx)
getSnapshot Mempool m blk idx
mempool
MempoolCapacityBytes TxSizeInBytes
capacity <- Mempool m blk idx -> STM m MempoolCapacityBytes
forall (m :: * -> *) blk idx.
Mempool m blk idx -> STM m MempoolCapacityBytes
getCapacity Mempool m blk idx
mempool
Bool -> STM m ()
forall (stm :: * -> *). MonadSTMTx stm => Bool -> stm ()
check (TxSizeInBytes
curSize TxSizeInBytes -> TxSizeInBytes -> TxSizeInBytes
forall a. Num a => a -> a -> a
+ TxSizeInBytes
firstTxSize TxSizeInBytes -> TxSizeInBytes -> Bool
forall a. Ord a => a -> a -> Bool
<= TxSizeInBytes
capacity)
([(GenTx blk, MempoolAddTxResult blk)]
added, [GenTx blk]
toAdd) <- Mempool m blk idx
-> [GenTx blk]
-> m ([(GenTx blk, MempoolAddTxResult blk)], [GenTx blk])
forall (m :: * -> *) blk idx.
Mempool m blk idx
-> [GenTx blk]
-> m ([(GenTx blk, MempoolAddTxResult blk)], [GenTx blk])
tryAddTxs Mempool m blk idx
mempool [GenTx blk]
txs
[[(GenTx blk, MempoolAddTxResult blk)]]
-> [GenTx blk] -> m [(GenTx blk, MempoolAddTxResult blk)]
go ([(GenTx blk, MempoolAddTxResult blk)]
added[(GenTx blk, MempoolAddTxResult blk)]
-> [[(GenTx blk, MempoolAddTxResult blk)]]
-> [[(GenTx blk, MempoolAddTxResult blk)]]
forall a. a -> [a] -> [a]
:[[(GenTx blk, MempoolAddTxResult blk)]]
acc) [GenTx blk]
toAdd
data ForgeLedgerState blk =
ForgeInKnownSlot SlotNo (TickedLedgerState blk)
| ForgeInUnknownSlot (LedgerState blk)
newtype MempoolCapacityBytes = MempoolCapacityBytes {
MempoolCapacityBytes -> TxSizeInBytes
getMempoolCapacityBytes :: Word32
}
deriving (MempoolCapacityBytes -> MempoolCapacityBytes -> Bool
(MempoolCapacityBytes -> MempoolCapacityBytes -> Bool)
-> (MempoolCapacityBytes -> MempoolCapacityBytes -> Bool)
-> Eq MempoolCapacityBytes
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MempoolCapacityBytes -> MempoolCapacityBytes -> Bool
$c/= :: MempoolCapacityBytes -> MempoolCapacityBytes -> Bool
== :: MempoolCapacityBytes -> MempoolCapacityBytes -> Bool
$c== :: MempoolCapacityBytes -> MempoolCapacityBytes -> Bool
Eq, Int -> MempoolCapacityBytes -> ShowS
[MempoolCapacityBytes] -> ShowS
MempoolCapacityBytes -> String
(Int -> MempoolCapacityBytes -> ShowS)
-> (MempoolCapacityBytes -> String)
-> ([MempoolCapacityBytes] -> ShowS)
-> Show MempoolCapacityBytes
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MempoolCapacityBytes] -> ShowS
$cshowList :: [MempoolCapacityBytes] -> ShowS
show :: MempoolCapacityBytes -> String
$cshow :: MempoolCapacityBytes -> String
showsPrec :: Int -> MempoolCapacityBytes -> ShowS
$cshowsPrec :: Int -> MempoolCapacityBytes -> ShowS
Show, Context -> MempoolCapacityBytes -> IO (Maybe ThunkInfo)
Proxy MempoolCapacityBytes -> String
(Context -> MempoolCapacityBytes -> IO (Maybe ThunkInfo))
-> (Context -> MempoolCapacityBytes -> IO (Maybe ThunkInfo))
-> (Proxy MempoolCapacityBytes -> String)
-> NoThunks MempoolCapacityBytes
forall a.
(Context -> a -> IO (Maybe ThunkInfo))
-> (Context -> a -> IO (Maybe ThunkInfo))
-> (Proxy a -> String)
-> NoThunks a
showTypeOf :: Proxy MempoolCapacityBytes -> String
$cshowTypeOf :: Proxy MempoolCapacityBytes -> String
wNoThunks :: Context -> MempoolCapacityBytes -> IO (Maybe ThunkInfo)
$cwNoThunks :: Context -> MempoolCapacityBytes -> IO (Maybe ThunkInfo)
noThunks :: Context -> MempoolCapacityBytes -> IO (Maybe ThunkInfo)
$cnoThunks :: Context -> MempoolCapacityBytes -> IO (Maybe ThunkInfo)
NoThunks)
data MempoolSnapshot blk idx = MempoolSnapshot {
MempoolSnapshot blk idx -> [(GenTx blk, idx)]
snapshotTxs :: [(GenTx blk, idx)]
, MempoolSnapshot blk idx -> idx -> [(GenTx blk, idx)]
snapshotTxsAfter :: idx -> [(GenTx blk, idx)]
, MempoolSnapshot blk idx -> TxSizeInBytes -> [(GenTx blk, idx)]
snapshotTxsForSize :: Word32 -> [(GenTx blk, idx)]
, MempoolSnapshot blk idx -> idx -> Maybe (GenTx blk)
snapshotLookupTx :: idx -> Maybe (GenTx blk)
, MempoolSnapshot blk idx -> GenTxId blk -> Bool
snapshotHasTx :: GenTxId blk -> Bool
, MempoolSnapshot blk idx -> MempoolSize
snapshotMempoolSize :: MempoolSize
, MempoolSnapshot blk idx -> SlotNo
snapshotSlotNo :: SlotNo
, MempoolSnapshot blk idx -> TickedLedgerState blk
snapshotLedgerState :: TickedLedgerState blk
}
data MempoolSize = MempoolSize
{ MempoolSize -> TxSizeInBytes
msNumTxs :: !Word32
, MempoolSize -> TxSizeInBytes
msNumBytes :: !Word32
} deriving (MempoolSize -> MempoolSize -> Bool
(MempoolSize -> MempoolSize -> Bool)
-> (MempoolSize -> MempoolSize -> Bool) -> Eq MempoolSize
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MempoolSize -> MempoolSize -> Bool
$c/= :: MempoolSize -> MempoolSize -> Bool
== :: MempoolSize -> MempoolSize -> Bool
$c== :: MempoolSize -> MempoolSize -> Bool
Eq, Int -> MempoolSize -> ShowS
[MempoolSize] -> ShowS
MempoolSize -> String
(Int -> MempoolSize -> ShowS)
-> (MempoolSize -> String)
-> ([MempoolSize] -> ShowS)
-> Show MempoolSize
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MempoolSize] -> ShowS
$cshowList :: [MempoolSize] -> ShowS
show :: MempoolSize -> String
$cshow :: MempoolSize -> String
showsPrec :: Int -> MempoolSize -> ShowS
$cshowsPrec :: Int -> MempoolSize -> ShowS
Show)
instance Semigroup MempoolSize where
MempoolSize TxSizeInBytes
xt TxSizeInBytes
xb <> :: MempoolSize -> MempoolSize -> MempoolSize
<> MempoolSize TxSizeInBytes
yt TxSizeInBytes
yb = TxSizeInBytes -> TxSizeInBytes -> MempoolSize
MempoolSize (TxSizeInBytes
xt TxSizeInBytes -> TxSizeInBytes -> TxSizeInBytes
forall a. Num a => a -> a -> a
+ TxSizeInBytes
yt) (TxSizeInBytes
xb TxSizeInBytes -> TxSizeInBytes -> TxSizeInBytes
forall a. Num a => a -> a -> a
+ TxSizeInBytes
yb)
instance Monoid MempoolSize where
mempty :: MempoolSize
mempty = MempoolSize :: TxSizeInBytes -> TxSizeInBytes -> MempoolSize
MempoolSize { msNumTxs :: TxSizeInBytes
msNumTxs = TxSizeInBytes
0, msNumBytes :: TxSizeInBytes
msNumBytes = TxSizeInBytes
0 }
mappend :: MempoolSize -> MempoolSize -> MempoolSize
mappend = MempoolSize -> MempoolSize -> MempoolSize
forall a. Semigroup a => a -> a -> a
(<>)
data TraceEventMempool blk
= TraceMempoolAddedTx
!(GenTx blk)
!MempoolSize
!MempoolSize
| TraceMempoolRejectedTx
!(GenTx blk)
!(ApplyTxErr blk)
!MempoolSize
| TraceMempoolRemoveTxs
![GenTx blk]
!MempoolSize
| TraceMempoolManuallyRemovedTxs
![GenTxId blk]
![GenTx blk]
!MempoolSize
deriving instance ( Eq (GenTx blk)
, Eq (GenTxId blk)
, Eq (ApplyTxErr blk)
) => Eq (TraceEventMempool blk)
deriving instance ( Show (GenTx blk)
, Show (GenTxId blk)
, Show (ApplyTxErr blk)
) => Show (TraceEventMempool blk)