{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Ouroboros.Consensus.Mempool.API (
Mempool (..)
, MempoolAddTxResult (..)
, isMempoolTxAdded
, isMempoolTxRejected
, mempoolTxAddedToMaybe
, ForgeLedgerState (..)
, MempoolSnapshot (..)
, MempoolCapacityBytes (..)
, MempoolCapacityBytesOverride (..)
, MempoolSize (..)
, computeMempoolCapacity
, TraceEventMempool (..)
, addLocalTxs
, addTxs
, TxSizeInBytes
) where
import Data.Word (Word32)
import Ouroboros.Network.Protocol.TxSubmission2.Type (TxSizeInBytes)
import Ouroboros.Consensus.Block (SlotNo)
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
-> WhetherToIntervene
-> [GenTx blk]
-> m ([MempoolAddTxResult blk], [GenTx blk])
tryAddTxs :: WhetherToIntervene
-> [GenTx blk]
-> m ( [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 !(Validated (GenTx blk))
| MempoolTxRejected !(GenTx blk) !(ApplyTxErr blk)
deriving instance (Eq (GenTx blk), Eq (Validated (GenTx blk)), Eq (ApplyTxErr blk)) => Eq (MempoolAddTxResult blk)
deriving instance (Show (GenTx blk), Show (Validated (GenTx blk)), Show (ApplyTxErr blk)) => Show (MempoolAddTxResult blk)
mempoolTxAddedToMaybe :: MempoolAddTxResult blk -> Maybe (Validated (GenTx blk))
mempoolTxAddedToMaybe :: MempoolAddTxResult blk -> Maybe (Validated (GenTx blk))
mempoolTxAddedToMaybe (MempoolTxAdded Validated (GenTx blk)
vtx) = Validated (GenTx blk) -> Maybe (Validated (GenTx blk))
forall a. a -> Maybe a
Just Validated (GenTx blk)
vtx
mempoolTxAddedToMaybe MempoolAddTxResult blk
_ = Maybe (Validated (GenTx blk))
forall a. Maybe a
Nothing
isMempoolTxAdded :: MempoolAddTxResult blk -> Bool
isMempoolTxAdded :: MempoolAddTxResult blk -> Bool
isMempoolTxAdded MempoolTxAdded{} = Bool
True
isMempoolTxAdded MempoolAddTxResult blk
_ = Bool
False
isMempoolTxRejected :: MempoolAddTxResult blk -> Bool
isMempoolTxRejected :: MempoolAddTxResult blk -> Bool
isMempoolTxRejected MempoolTxRejected{} = Bool
True
isMempoolTxRejected MempoolAddTxResult blk
_ = Bool
False
addTxs
:: forall m blk idx. MonadSTM m
=> Mempool m blk idx
-> [GenTx blk]
-> m [MempoolAddTxResult blk]
addTxs :: Mempool m blk idx -> [GenTx blk] -> m [MempoolAddTxResult blk]
addTxs Mempool m blk idx
mempool = Mempool m blk idx
-> WhetherToIntervene -> [GenTx blk] -> m [MempoolAddTxResult blk]
forall (m :: * -> *) blk idx.
MonadSTM m =>
Mempool m blk idx
-> WhetherToIntervene -> [GenTx blk] -> m [MempoolAddTxResult blk]
addTxsHelper Mempool m blk idx
mempool WhetherToIntervene
DoNotIntervene
addLocalTxs
:: forall m blk idx. MonadSTM m
=> Mempool m blk idx
-> [GenTx blk]
-> m [MempoolAddTxResult blk]
addLocalTxs :: Mempool m blk idx -> [GenTx blk] -> m [MempoolAddTxResult blk]
addLocalTxs Mempool m blk idx
mempool = Mempool m blk idx
-> WhetherToIntervene -> [GenTx blk] -> m [MempoolAddTxResult blk]
forall (m :: * -> *) blk idx.
MonadSTM m =>
Mempool m blk idx
-> WhetherToIntervene -> [GenTx blk] -> m [MempoolAddTxResult blk]
addTxsHelper Mempool m blk idx
mempool WhetherToIntervene
Intervene
addTxsHelper
:: forall m blk idx. MonadSTM m
=> Mempool m blk idx
-> WhetherToIntervene
-> [GenTx blk]
-> m [MempoolAddTxResult blk]
addTxsHelper :: Mempool m blk idx
-> WhetherToIntervene -> [GenTx blk] -> m [MempoolAddTxResult blk]
addTxsHelper Mempool m blk idx
mempool WhetherToIntervene
wti = \[GenTx blk]
txs -> do
([MempoolAddTxResult blk]
processed, [GenTx blk]
toAdd) <- Mempool m blk idx
-> WhetherToIntervene
-> [GenTx blk]
-> m ([MempoolAddTxResult blk], [GenTx blk])
forall (m :: * -> *) blk idx.
Mempool m blk idx
-> WhetherToIntervene
-> [GenTx blk]
-> m ([MempoolAddTxResult blk], [GenTx blk])
tryAddTxs Mempool m blk idx
mempool WhetherToIntervene
wti [GenTx blk]
txs
case [GenTx blk]
toAdd of
[] -> [MempoolAddTxResult blk] -> m [MempoolAddTxResult blk]
forall (m :: * -> *) a. Monad m => a -> m a
return [MempoolAddTxResult blk]
processed
[GenTx blk]
_ -> [[MempoolAddTxResult blk]]
-> [GenTx blk] -> m [MempoolAddTxResult blk]
go [[MempoolAddTxResult blk]
processed] [GenTx blk]
toAdd
where
go
:: [[MempoolAddTxResult blk]]
-> [GenTx blk]
-> m [MempoolAddTxResult blk]
go :: [[MempoolAddTxResult blk]]
-> [GenTx blk] -> m [MempoolAddTxResult blk]
go [[MempoolAddTxResult blk]]
acc [] = [MempoolAddTxResult blk] -> m [MempoolAddTxResult blk]
forall (m :: * -> *) a. Monad m => a -> m a
return ([[MempoolAddTxResult blk]] -> [MempoolAddTxResult blk]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[MempoolAddTxResult blk]] -> [[MempoolAddTxResult blk]]
forall a. [a] -> [a]
reverse [[MempoolAddTxResult blk]]
acc))
go [[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 (m :: * -> *). MonadSTM m => Bool -> STM m ()
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)
([MempoolAddTxResult blk]
added, [GenTx blk]
toAdd) <- Mempool m blk idx
-> WhetherToIntervene
-> [GenTx blk]
-> m ([MempoolAddTxResult blk], [GenTx blk])
forall (m :: * -> *) blk idx.
Mempool m blk idx
-> WhetherToIntervene
-> [GenTx blk]
-> m ([MempoolAddTxResult blk], [GenTx blk])
tryAddTxs Mempool m blk idx
mempool WhetherToIntervene
wti [GenTx blk]
txs
[[MempoolAddTxResult blk]]
-> [GenTx blk] -> m [MempoolAddTxResult blk]
go ([MempoolAddTxResult blk]
added[MempoolAddTxResult blk]
-> [[MempoolAddTxResult blk]] -> [[MempoolAddTxResult blk]]
forall a. a -> [a] -> [a]
:[[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 MempoolCapacityBytesOverride
= NoMempoolCapacityBytesOverride
| MempoolCapacityBytesOverride !MempoolCapacityBytes
deriving (MempoolCapacityBytesOverride
-> MempoolCapacityBytesOverride -> Bool
(MempoolCapacityBytesOverride
-> MempoolCapacityBytesOverride -> Bool)
-> (MempoolCapacityBytesOverride
-> MempoolCapacityBytesOverride -> Bool)
-> Eq MempoolCapacityBytesOverride
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MempoolCapacityBytesOverride
-> MempoolCapacityBytesOverride -> Bool
$c/= :: MempoolCapacityBytesOverride
-> MempoolCapacityBytesOverride -> Bool
== :: MempoolCapacityBytesOverride
-> MempoolCapacityBytesOverride -> Bool
$c== :: MempoolCapacityBytesOverride
-> MempoolCapacityBytesOverride -> Bool
Eq, Int -> MempoolCapacityBytesOverride -> ShowS
[MempoolCapacityBytesOverride] -> ShowS
MempoolCapacityBytesOverride -> String
(Int -> MempoolCapacityBytesOverride -> ShowS)
-> (MempoolCapacityBytesOverride -> String)
-> ([MempoolCapacityBytesOverride] -> ShowS)
-> Show MempoolCapacityBytesOverride
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MempoolCapacityBytesOverride] -> ShowS
$cshowList :: [MempoolCapacityBytesOverride] -> ShowS
show :: MempoolCapacityBytesOverride -> String
$cshow :: MempoolCapacityBytesOverride -> String
showsPrec :: Int -> MempoolCapacityBytesOverride -> ShowS
$cshowsPrec :: Int -> MempoolCapacityBytesOverride -> ShowS
Show)
computeMempoolCapacity
:: LedgerSupportsMempool blk
=> TickedLedgerState blk
-> MempoolCapacityBytesOverride
-> MempoolCapacityBytes
computeMempoolCapacity :: TickedLedgerState blk
-> MempoolCapacityBytesOverride -> MempoolCapacityBytes
computeMempoolCapacity TickedLedgerState blk
st = \case
MempoolCapacityBytesOverride
NoMempoolCapacityBytesOverride -> MempoolCapacityBytes
noOverride
MempoolCapacityBytesOverride MempoolCapacityBytes
override -> MempoolCapacityBytes
override
where
noOverride :: MempoolCapacityBytes
noOverride = TxSizeInBytes -> MempoolCapacityBytes
MempoolCapacityBytes (TickedLedgerState blk -> TxSizeInBytes
forall blk.
LedgerSupportsMempool blk =>
TickedLedgerState blk -> TxSizeInBytes
txsMaxBytes TickedLedgerState blk
st TxSizeInBytes -> TxSizeInBytes -> TxSizeInBytes
forall a. Num a => a -> a -> a
* TxSizeInBytes
2)
data MempoolSnapshot blk idx = MempoolSnapshot {
MempoolSnapshot blk idx -> [(Validated (GenTx blk), idx)]
snapshotTxs :: [(Validated (GenTx blk), idx)]
, MempoolSnapshot blk idx -> idx -> [(Validated (GenTx blk), idx)]
snapshotTxsAfter :: idx -> [(Validated (GenTx blk), idx)]
, MempoolSnapshot blk idx -> idx -> Maybe (Validated (GenTx blk))
snapshotLookupTx :: idx -> Maybe (Validated (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
(Validated (GenTx blk))
MempoolSize
MempoolSize
| TraceMempoolRejectedTx
(GenTx blk)
(ApplyTxErr blk)
MempoolSize
| TraceMempoolRemoveTxs
[Validated (GenTx blk)]
MempoolSize
| TraceMempoolManuallyRemovedTxs
[GenTxId blk]
[Validated (GenTx blk)]
MempoolSize
deriving instance ( Eq (GenTx blk)
, Eq (Validated (GenTx blk))
, Eq (GenTxId blk)
, Eq (ApplyTxErr blk)
) => Eq (TraceEventMempool blk)
deriving instance ( Show (GenTx blk)
, Show (Validated (GenTx blk))
, Show (GenTxId blk)
, Show (ApplyTxErr blk)
) => Show (TraceEventMempool blk)