{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Ouroboros.Consensus.Block.Forging (
BlockForging (..)
, CannotForge
, ForgeStateInfo
, ForgeStateUpdateError
, ForgeStateUpdateInfo (..)
, ShouldForge (..)
, castForgeStateUpdateInfo
, checkShouldForge
, forgeStateUpdateInfoFromUpdateInfo
, UpdateInfo (..)
) where
import Control.Tracer (Tracer, traceWith)
import Data.Kind (Type)
import Data.Text (Text)
import GHC.Stack
import Ouroboros.Consensus.Block.Abstract
import Ouroboros.Consensus.Config
import Ouroboros.Consensus.Ledger.Abstract
import Ouroboros.Consensus.Ledger.SupportsMempool
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 :: forall blk blk'.
(ForgeStateInfo blk ~ ForgeStateInfo blk',
ForgeStateUpdateError blk ~ ForgeStateUpdateError blk') =>
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 {
forall (m :: * -> *) blk. BlockForging m blk -> Text
forgeLabel :: Text
, forall (m :: * -> *) blk.
BlockForging m blk -> CanBeLeader (BlockProtocol blk)
canBeLeader :: CanBeLeader (BlockProtocol blk)
, forall (m :: * -> *) 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)
, forall (m :: * -> *) 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) ()
, forall (m :: * -> *) 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
}
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 :: 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{Text
CanBeLeader (BlockProtocol blk)
TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m 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) ()
updateForgeState :: forall (m :: * -> *) blk.
BlockForging m blk
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
forgeLabel :: forall (m :: * -> *) blk. BlockForging m blk -> Text
canBeLeader :: forall (m :: * -> *) blk.
BlockForging m blk -> CanBeLeader (BlockProtocol blk)
checkCanForge :: forall (m :: * -> *) blk.
BlockForging m blk
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
forgeBlock :: forall (m :: * -> *) blk.
BlockForging m blk
-> TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m blk
forgeLabel :: Text
canBeLeader :: CanBeLeader (BlockProtocol blk)
updateForgeState :: TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ForgeStateUpdateInfo blk)
checkCanForge :: TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> IsLeader (BlockProtocol blk)
-> ForgeStateInfo blk
-> Either (CannotForge blk) ()
forgeBlock :: TopLevelConfig blk
-> BlockNo
-> SlotNo
-> TickedLedgerState blk
-> [Validated (GenTx blk)]
-> IsLeader (BlockProtocol blk)
-> m blk
..}
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 a b. m a -> (a -> m b) -> m b
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 a. a -> m a
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 a. a -> m a
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 a. a -> m a
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
$cshowsPrec :: forall updated failed.
(Show updated, Show failed) =>
Int -> UpdateInfo updated failed -> ShowS
showsPrec :: Int -> UpdateInfo updated failed -> ShowS
$cshow :: forall updated failed.
(Show updated, Show failed) =>
UpdateInfo updated failed -> String
show :: UpdateInfo updated failed -> String
$cshowList :: forall updated failed.
(Show updated, Show failed) =>
[UpdateInfo updated failed] -> ShowS
showList :: [UpdateInfo updated failed] -> ShowS
Show)
forgeStateUpdateInfoFromUpdateInfo ::
UpdateInfo (ForgeStateInfo blk) (ForgeStateUpdateError blk)
-> ForgeStateUpdateInfo blk
forgeStateUpdateInfoFromUpdateInfo :: forall blk.
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