{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Ouroboros.Consensus.Block.Forging (
BlockForging (..)
, CannotForge
, ForgeStateInfo
, ForgeStateUpdateError
, ForgeStateUpdateInfo (..)
, ShouldForge (..)
, castForgeStateUpdateInfo
, checkShouldForge
, forgeStateUpdateInfoFromUpdateInfo
, UpdateInfo (..)
, takeLargestPrefixThatFits
) where
import Control.Tracer (Tracer, traceWith)
import Data.Kind (Type)
import Data.Text (Text)
import GHC.Stack
import qualified Data.Measure as Measure
import Ouroboros.Consensus.Block.Abstract
import Ouroboros.Consensus.Config
import Ouroboros.Consensus.Ledger.Abstract
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Mempool.TxLimits (TxLimits)
import qualified Ouroboros.Consensus.Mempool.TxLimits as TxLimits
import Ouroboros.Consensus.Protocol.Abstract
import Ouroboros.Consensus.Ticked
type family CannotForge blk :: Type
type family ForgeStateInfo blk :: Type
type family ForgeStateUpdateError blk :: Type
data ForgeStateUpdateInfo blk =
ForgeStateUpdated (ForgeStateInfo blk)
| ForgeStateUpdateFailed (ForgeStateUpdateError blk)
| ForgeStateUpdateSuppressed
deriving instance (Show (ForgeStateInfo blk), Show (ForgeStateUpdateError blk))
=> Show (ForgeStateUpdateInfo blk)
castForgeStateUpdateInfo ::
( ForgeStateInfo blk ~ ForgeStateInfo blk'
, ForgeStateUpdateError blk ~ ForgeStateUpdateError blk'
)
=> ForgeStateUpdateInfo blk -> ForgeStateUpdateInfo blk'
castForgeStateUpdateInfo :: ForgeStateUpdateInfo blk -> ForgeStateUpdateInfo blk'
castForgeStateUpdateInfo = \case
ForgeStateUpdated ForgeStateInfo blk
x -> ForgeStateInfo blk' -> ForgeStateUpdateInfo blk'
forall blk. ForgeStateInfo blk -> ForgeStateUpdateInfo blk
ForgeStateUpdated ForgeStateInfo blk
ForgeStateInfo blk'
x
ForgeStateUpdateFailed ForgeStateUpdateError blk
x -> ForgeStateUpdateError blk' -> ForgeStateUpdateInfo blk'
forall blk. ForgeStateUpdateError blk -> ForgeStateUpdateInfo blk
ForgeStateUpdateFailed ForgeStateUpdateError blk
ForgeStateUpdateError blk'
x
ForgeStateUpdateInfo blk
ForgeStateUpdateSuppressed -> ForgeStateUpdateInfo blk'
forall blk. ForgeStateUpdateInfo blk
ForgeStateUpdateSuppressed
data BlockForging m blk = BlockForging {
BlockForging m blk -> Text
forgeLabel :: Text
, BlockForging m blk -> CanBeLeader (BlockProtocol blk)
canBeLeader :: CanBeLeader (BlockProtocol blk)
, BlockForging m blk
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
updateForgeState ::
TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
, BlockForging m blk
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
checkCanForge ::
TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
, BlockForging m blk
-> TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m blk
forgeBlock ::
TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m blk
}
takeLargestPrefixThatFits ::
TxLimits blk
=> TxLimits.Overrides blk
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> [Validated (GenTx blk)]
takeLargestPrefixThatFits :: Overrides blk
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> [Validated (GenTx blk)]
takeLargestPrefixThatFits Overrides blk
overrides TickedLedgerState blk
ledger [Validated (GenTx blk)]
txs =
(Validated (GenTx blk) -> TxMeasure blk)
-> TxMeasure blk
-> [Validated (GenTx blk)]
-> [Validated (GenTx blk)]
forall a e. Measure a => (e -> a) -> a -> [e] -> [e]
Measure.take Validated (GenTx blk) -> TxMeasure blk
forall blk. TxLimits blk => Validated (GenTx blk) -> TxMeasure blk
TxLimits.txMeasure TxMeasure blk
capacity [Validated (GenTx blk)]
txs
where
capacity :: TxMeasure blk
capacity =
Overrides blk -> TxMeasure blk -> TxMeasure blk
forall blk.
TxLimits blk =>
Overrides blk -> TxMeasure blk -> TxMeasure blk
TxLimits.applyOverrides
Overrides blk
overrides
(TickedLedgerState blk -> TxMeasure blk
forall blk.
TxLimits blk =>
Ticked (LedgerState blk) -> TxMeasure blk
TxLimits.txsBlockCapacity TickedLedgerState blk
ledger)
data ShouldForge blk =
ForgeStateUpdateError (ForgeStateUpdateError blk)
| CannotForge (CannotForge blk)
| NotLeader
| ShouldForge (IsLeader (BlockProtocol blk))
checkShouldForge ::
forall m blk.
( Monad m
, ConsensusProtocol (BlockProtocol blk)
, HasCallStack
)
=> BlockForging m blk
-> Tracer m (ForgeStateInfo blk)
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ShouldForge blk)
checkShouldForge :: BlockForging m blk
-> Tracer m (ForgeStateInfo blk)
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ShouldForge blk)
checkShouldForge BlockForging{Text
CanBeLeader (BlockProtocol blk)
TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m blk
forgeBlock :: TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m blk
checkCanForge :: TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
updateForgeState :: TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
canBeLeader :: CanBeLeader (BlockProtocol blk)
forgeLabel :: Text
forgeBlock :: forall (m :: * -> *) blk.
BlockForging m blk
-> TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m blk
checkCanForge :: forall (m :: * -> *) blk.
BlockForging m blk
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
updateForgeState :: forall (m :: * -> *) blk.
BlockForging m blk
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
canBeLeader :: forall (m :: * -> *) blk.
BlockForging m blk -> CanBeLeader (BlockProtocol blk)
forgeLabel :: forall (m :: * -> *) blk. BlockForging m blk -> Text
..}
Tracer m (ForgeStateInfo blk)
forgeStateInfoTracer
TopLevelConfig blk
cfg
SlotNo
slot
Ticked (ChainDepState (BlockProtocol blk))
tickedChainDepState =
TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
updateForgeState TopLevelConfig blk
cfg SlotNo
slot Ticked (ChainDepState (BlockProtocol blk))
tickedChainDepState m (ForgeStateUpdateInfo blk)
-> (ForgeStateUpdateInfo blk -> m (ShouldForge blk))
-> m (ShouldForge blk)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ForgeStateUpdateInfo blk
updateInfo ->
case ForgeStateUpdateInfo blk
updateInfo of
ForgeStateUpdated ForgeStateInfo blk
info -> ForgeStateInfo blk -> m (ShouldForge blk)
handleUpdated ForgeStateInfo blk
info
ForgeStateUpdateFailed ForgeStateUpdateError blk
err -> ShouldForge blk -> m (ShouldForge blk)
forall (m :: * -> *) a. Monad m => a -> m a
return (ShouldForge blk -> m (ShouldForge blk))
-> ShouldForge blk -> m (ShouldForge blk)
forall a b. (a -> b) -> a -> b
$ ForgeStateUpdateError blk -> ShouldForge blk
forall blk. ForgeStateUpdateError blk -> ShouldForge blk
ForgeStateUpdateError ForgeStateUpdateError blk
err
ForgeStateUpdateInfo blk
ForgeStateUpdateSuppressed -> ShouldForge blk -> m (ShouldForge blk)
forall (m :: * -> *) a. Monad m => a -> m a
return ShouldForge blk
forall blk. ShouldForge blk
NotLeader
where
mbIsLeader :: Maybe (IsLeader (BlockProtocol blk))
mbIsLeader :: Maybe (IsLeader (BlockProtocol blk))
mbIsLeader =
ConsensusConfig (BlockProtocol blk)
-> CanBeLeader (BlockProtocol blk)
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> Maybe (IsLeader (BlockProtocol blk))
forall p.
(ConsensusProtocol p, HasCallStack) =>
ConsensusConfig p
-> CanBeLeader p
-> SlotNo
-> Ticked (ChainDepState p)
-> Maybe (IsLeader p)
checkIsLeader
(TopLevelConfig blk -> ConsensusConfig (BlockProtocol blk)
forall blk.
TopLevelConfig blk -> ConsensusConfig (BlockProtocol blk)
configConsensus TopLevelConfig blk
cfg)
CanBeLeader (BlockProtocol blk)
canBeLeader
SlotNo
slot
Ticked (ChainDepState (BlockProtocol blk))
tickedChainDepState
handleUpdated :: ForgeStateInfo blk -> m (ShouldForge blk)
handleUpdated :: ForgeStateInfo blk -> m (ShouldForge blk)
handleUpdated ForgeStateInfo blk
info = do
Tracer m (ForgeStateInfo blk) -> ForgeStateInfo blk -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (ForgeStateInfo blk)
forgeStateInfoTracer ForgeStateInfo blk
info
ShouldForge blk -> m (ShouldForge blk)
forall (m :: * -> *) a. Monad m => a -> m a
return (ShouldForge blk -> m (ShouldForge blk))
-> ShouldForge blk -> m (ShouldForge blk)
forall a b. (a -> b) -> a -> b
$ case Maybe (IsLeader (BlockProtocol blk))
mbIsLeader of
Maybe (IsLeader (BlockProtocol blk))
Nothing -> ShouldForge blk
forall blk. ShouldForge blk
NotLeader
Just IsLeader (BlockProtocol blk)
isLeader ->
case TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
checkCanForge TopLevelConfig blk
cfg SlotNo
slot Ticked (ChainDepState (BlockProtocol blk))
tickedChainDepState IsLeader (BlockProtocol blk)
isLeader ForgeStateInfo blk
info of
Left CannotForge blk
cannotForge -> CannotForge blk -> ShouldForge blk
forall blk. CannotForge blk -> ShouldForge blk
CannotForge CannotForge blk
cannotForge
Right () -> IsLeader (BlockProtocol blk) -> ShouldForge blk
forall blk. IsLeader (BlockProtocol blk) -> ShouldForge blk
ShouldForge IsLeader (BlockProtocol blk)
isLeader
data UpdateInfo updated failed =
Updated updated
| UpdateFailed failed
deriving (Int -> UpdateInfo updated failed -> ShowS
[UpdateInfo updated failed] -> ShowS
UpdateInfo updated failed -> String
(Int -> UpdateInfo updated failed -> ShowS)
-> (UpdateInfo updated failed -> String)
-> ([UpdateInfo updated failed] -> ShowS)
-> Show (UpdateInfo updated failed)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall updated failed.
(Show updated, Show failed) =>
Int -> UpdateInfo updated failed -> ShowS
forall updated failed.
(Show updated, Show failed) =>
[UpdateInfo updated failed] -> ShowS
forall updated failed.
(Show updated, Show failed) =>
UpdateInfo updated failed -> String
showList :: [UpdateInfo updated failed] -> ShowS
$cshowList :: forall updated failed.
(Show updated, Show failed) =>
[UpdateInfo updated failed] -> ShowS
show :: UpdateInfo updated failed -> String
$cshow :: forall updated failed.
(Show updated, Show failed) =>
UpdateInfo updated failed -> String
showsPrec :: Int -> UpdateInfo updated failed -> ShowS
$cshowsPrec :: forall updated failed.
(Show updated, Show failed) =>
Int -> UpdateInfo updated failed -> ShowS
Show)
forgeStateUpdateInfoFromUpdateInfo ::
UpdateInfo (ForgeStateInfo blk) (ForgeStateUpdateError blk)
-> ForgeStateUpdateInfo blk
forgeStateUpdateInfoFromUpdateInfo :: UpdateInfo (ForgeStateInfo blk) (ForgeStateUpdateError blk)
-> ForgeStateUpdateInfo blk
forgeStateUpdateInfoFromUpdateInfo = \case
Updated ForgeStateInfo blk
info -> ForgeStateInfo blk -> ForgeStateUpdateInfo blk
forall blk. ForgeStateInfo blk -> ForgeStateUpdateInfo blk
ForgeStateUpdated ForgeStateInfo blk
info
UpdateFailed ForgeStateUpdateError blk
err -> ForgeStateUpdateError blk -> ForgeStateUpdateInfo blk
forall blk. ForgeStateUpdateError blk -> ForgeStateUpdateInfo blk
ForgeStateUpdateFailed ForgeStateUpdateError blk
err