{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Ouroboros.Consensus.NodeKernel.Forge
( forge
) where
import Control.Monad
import Control.Monad.Except
import Control.Tracer
import qualified Data.List.NonEmpty as NE
import Data.Maybe (isJust)
import Data.Proxy
import Ouroboros.Consensus.Block hiding (blockMatchesHeader)
import qualified Ouroboros.Consensus.Block as Block
import Ouroboros.Consensus.Config
import Ouroboros.Consensus.Forecast
import Ouroboros.Consensus.HeaderValidation
( BasicEnvelopeValidation (..)
, HeaderState (..)
, headerStateChainDep
)
import Ouroboros.Consensus.Ledger.Abstract
import Ouroboros.Consensus.Ledger.Extended
import Ouroboros.Consensus.Ledger.SupportsMempool
import Ouroboros.Consensus.Ledger.SupportsProtocol
import Ouroboros.Consensus.Ledger.Tables.Utils (forgetLedgerTables)
import Ouroboros.Consensus.Mempool
import Ouroboros.Consensus.Mempool.API (TxMeasureWithDiffTime)
import Ouroboros.Consensus.Node.Run
import Ouroboros.Consensus.Node.Tracers
import Ouroboros.Consensus.Protocol.Abstract
import Ouroboros.Consensus.Storage.ChainDB.API
( AddBlockResult (..)
, ChainDB
)
import qualified Ouroboros.Consensus.Storage.ChainDB.API as ChainDB
import qualified Ouroboros.Consensus.Storage.ChainDB.API.Types.InvalidBlockPunishment as InvalidBlockPunishment
import Ouroboros.Consensus.Storage.LedgerDB
import qualified Ouroboros.Consensus.Storage.LedgerDB as LedgerDB
import Ouroboros.Consensus.Util (whenJust)
import Ouroboros.Consensus.Util.EarlyExit
import Ouroboros.Consensus.Util.IOLike
import Ouroboros.Consensus.Util.Orphans ()
import Ouroboros.Consensus.Util.STM
import Ouroboros.Network.AnchoredFragment
( AnchoredFragment
, AnchoredSeq (..)
)
import qualified Ouroboros.Network.AnchoredFragment as AF
import Ouroboros.Network.Protocol.LocalStateQuery.Type (Target (..))
forge ::
forall m blk.
(IOLike m, RunNode blk) =>
Tracer m (TraceLabelCreds (TraceForgeEvent blk)) ->
Tracer m (TraceLabelCreds (ForgeStateInfo blk)) ->
TopLevelConfig blk ->
ChainDB m blk ->
Mempool m blk ->
BlockForging m blk ->
SlotNo ->
WithEarlyExit m ()
forge :: forall (m :: * -> *) blk.
(IOLike m, RunNode blk) =>
Tracer m (TraceLabelCreds (TraceForgeEvent blk))
-> Tracer m (TraceLabelCreds (ForgeStateInfo blk))
-> TopLevelConfig blk
-> ChainDB m blk
-> Mempool m blk
-> BlockForging m blk
-> SlotNo
-> WithEarlyExit m ()
forge Tracer m (TraceLabelCreds (TraceForgeEvent blk))
forgeEventTracer Tracer m (TraceLabelCreds (ForgeStateInfo blk))
forgeStateInfoTracer TopLevelConfig blk
cfg ChainDB m blk
chainDB Mempool m blk
mempool BlockForging m blk
blockForging SlotNo
currentSlot = do
let trace :: TraceForgeEvent blk -> WithEarlyExit m ()
trace :: TraceForgeEvent blk -> WithEarlyExit m ()
trace =
m () -> WithEarlyExit m ()
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift
(m () -> WithEarlyExit m ())
-> (TraceForgeEvent blk -> m ())
-> TraceForgeEvent blk
-> WithEarlyExit m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tracer m (TraceLabelCreds (TraceForgeEvent blk))
-> TraceLabelCreds (TraceForgeEvent blk) -> m ()
forall (m :: * -> *) a. Monad m => Tracer m a -> a -> m ()
traceWith Tracer m (TraceLabelCreds (TraceForgeEvent blk))
forgeEventTracer
(TraceLabelCreds (TraceForgeEvent blk) -> m ())
-> (TraceForgeEvent blk -> TraceLabelCreds (TraceForgeEvent blk))
-> TraceForgeEvent blk
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text
-> TraceForgeEvent blk -> TraceLabelCreds (TraceForgeEvent blk)
forall a. Text -> a -> TraceLabelCreds a
TraceLabelCreds (BlockForging m blk -> Text
forall (m :: * -> *) blk. BlockForging m blk -> Text
forgeLabel BlockForging m blk
blockForging)
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> TraceForgeEvent blk
forall blk. SlotNo -> TraceForgeEvent blk
TraceStartLeadershipCheck SlotNo
currentSlot
BlockContext{bcBlockNo, bcPrevPoint} <- (TraceForgeEvent blk -> WithEarlyExit m ())
-> ChainDB m blk -> SlotNo -> WithEarlyExit m (BlockContext blk)
forall (m :: * -> *) blk.
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ())
-> ChainDB m blk -> SlotNo -> WithEarlyExit m (BlockContext blk)
getBlockContext TraceForgeEvent blk -> WithEarlyExit m ()
trace ChainDB m blk
chainDB SlotNo
currentSlot
trace $ TraceBlockContext currentSlot bcBlockNo bcPrevPoint
(fbArgs, txssz, snapSize, forgingOnTopOf) <-
ChainDB.withReadOnlyForkerAtPoint chainDB (SpecificPoint bcPrevPoint) $ \case
Left GetForkerError
_ -> do
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> Point blk -> TraceForgeEvent blk
forall blk. SlotNo -> Point blk -> TraceForgeEvent blk
TraceNoLedgerState SlotNo
currentSlot Point blk
bcPrevPoint
WithEarlyExit
m
(ForgeBlockArgs blk, TxMeasureWithDiffTime blk, MempoolSize,
Point blk)
forall (m :: * -> *) a. Applicative m => WithEarlyExit m a
exitEarly
Right ReadOnlyForker' m blk
forker -> do
unticked <- m (ExtLedgerState blk EmptyMK)
-> WithEarlyExit m (ExtLedgerState blk EmptyMK)
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (ExtLedgerState blk EmptyMK)
-> WithEarlyExit m (ExtLedgerState blk EmptyMK))
-> m (ExtLedgerState blk EmptyMK)
-> WithEarlyExit m (ExtLedgerState blk EmptyMK)
forall a b. (a -> b) -> a -> b
$ STM m (ExtLedgerState blk EmptyMK)
-> m (ExtLedgerState blk EmptyMK)
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (ExtLedgerState blk EmptyMK)
-> m (ExtLedgerState blk EmptyMK))
-> STM m (ExtLedgerState blk EmptyMK)
-> m (ExtLedgerState blk EmptyMK)
forall a b. (a -> b) -> a -> b
$ ReadOnlyForker' m blk -> STM m (ExtLedgerState blk EmptyMK)
forall (m :: * -> *) (l :: StateKind) blk.
ReadOnlyForker m l blk -> STM m (l blk EmptyMK)
LedgerDB.roforkerGetLedgerState ReadOnlyForker' m blk
forker
trace $ TraceLedgerState currentSlot bcPrevPoint
ledgerView <- getLedgerView trace cfg currentSlot unticked
let tickedChainDepState = TopLevelConfig blk
-> SlotNo
-> ExtLedgerState blk EmptyMK
-> LedgerView (BlockProtocol blk)
-> Ticked (ChainDepState (BlockProtocol blk))
forall blk.
RunNode blk =>
TopLevelConfig blk
-> SlotNo
-> ExtLedgerState blk EmptyMK
-> LedgerView (BlockProtocol blk)
-> Ticked (ChainDepState (BlockProtocol blk))
getTickedChainDepState TopLevelConfig blk
cfg SlotNo
currentSlot ExtLedgerState blk EmptyMK
unticked LedgerView (BlockProtocol blk)
ledgerView
proof <-
getIsLeaderProof
trace
forgeStateInfoTracer
blockForging
cfg
currentSlot
tickedChainDepState
tickedLedgerState <- getTickedLedgerState trace cfg currentSlot bcPrevPoint unticked
traceForgingMempoolSnapshot trace mempool currentSlot bcPrevPoint
(txs, txssz, snapSize) <- getTransactionsToForge cfg mempool currentSlot tickedLedgerState forker
let fbArgs =
Block.ForgeBlockArgs
{ fbConfig :: TopLevelConfig blk
Block.fbConfig = TopLevelConfig blk
cfg
, fbCurrentBlockNo :: BlockNo
Block.fbCurrentBlockNo = BlockNo
bcBlockNo
, fbCurrentSlotNo :: SlotNo
Block.fbCurrentSlotNo = SlotNo
currentSlot
, fbPerasCert :: Maybe (PerasCert blk)
Block.fbPerasCert = Maybe (PerasCert blk)
forall a. Maybe a
Nothing
, fbCurrentTickedLedgerState :: TickedLedgerState blk EmptyMK
Block.fbCurrentTickedLedgerState = Ticked LedgerState blk DiffMK -> TickedLedgerState blk EmptyMK
forall (l :: StateKind) blk (mk :: MapKind).
HasLedgerTables l blk =>
l blk mk -> l blk EmptyMK
forgetLedgerTables Ticked LedgerState blk DiffMK
tickedLedgerState
, fbTxs :: [Validated (GenTx blk)]
Block.fbTxs = [Validated (GenTx blk)]
txs
, fbIsLeader :: IsLeader (BlockProtocol blk)
Block.fbIsLeader = IsLeader (BlockProtocol blk)
proof
}
pure
( fbArgs
, txssz
, snapSize
, ledgerTipPoint (ledgerState unticked)
)
newBlock <- lift $ Block.forgeBlock blockForging fbArgs
trace $
TraceForgedBlock
currentSlot
forgingOnTopOf
newBlock
snapSize
txssz
addBlockToChainDB trace chainDB mempool currentSlot (fbTxs fbArgs) newBlock
data BlockContext blk = BlockContext
{ forall blk. BlockContext blk -> BlockNo
bcBlockNo :: !BlockNo
, forall blk. BlockContext blk -> Point blk
bcPrevPoint :: !(Point blk)
}
getBlockContext ::
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ()) ->
ChainDB m blk ->
SlotNo ->
WithEarlyExit m (BlockContext blk)
getBlockContext :: forall (m :: * -> *) blk.
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ())
-> ChainDB m blk -> SlotNo -> WithEarlyExit m (BlockContext blk)
getBlockContext TraceForgeEvent blk -> WithEarlyExit m ()
trace ChainDB m blk
chainDB SlotNo
currentSlot = do
eBlkCtx <-
m (Either (TraceForgeEvent blk) (BlockContext blk))
-> WithEarlyExit
m (Either (TraceForgeEvent blk) (BlockContext blk))
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Either (TraceForgeEvent blk) (BlockContext blk))
-> WithEarlyExit
m (Either (TraceForgeEvent blk) (BlockContext blk)))
-> m (Either (TraceForgeEvent blk) (BlockContext blk))
-> WithEarlyExit
m (Either (TraceForgeEvent blk) (BlockContext blk))
forall a b. (a -> b) -> a -> b
$
STM m (Either (TraceForgeEvent blk) (BlockContext blk))
-> m (Either (TraceForgeEvent blk) (BlockContext blk))
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (Either (TraceForgeEvent blk) (BlockContext blk))
-> m (Either (TraceForgeEvent blk) (BlockContext blk)))
-> STM m (Either (TraceForgeEvent blk) (BlockContext blk))
-> m (Either (TraceForgeEvent blk) (BlockContext blk))
forall a b. (a -> b) -> a -> b
$
SlotNo
-> AnchoredFragment (Header blk)
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall blk.
RunNode blk =>
SlotNo
-> AnchoredFragment (Header blk)
-> Either (TraceForgeEvent blk) (BlockContext blk)
mkCurrentBlockContext SlotNo
currentSlot
(AnchoredFragment (Header blk)
-> Either (TraceForgeEvent blk) (BlockContext blk))
-> STM m (AnchoredFragment (Header blk))
-> STM m (Either (TraceForgeEvent blk) (BlockContext blk))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ChainDB m blk -> STM m (AnchoredFragment (Header blk))
forall (m :: * -> *) blk.
ChainDB m blk -> STM m (AnchoredFragment (Header blk))
ChainDB.getCurrentChain ChainDB m blk
chainDB
case eBlkCtx of
Right BlockContext blk
blkCtx -> BlockContext blk -> WithEarlyExit m (BlockContext blk)
forall a. a -> WithEarlyExit m a
forall (m :: * -> *) a. Monad m => a -> m a
return BlockContext blk
blkCtx
Left TraceForgeEvent blk
failure -> do
TraceForgeEvent blk -> WithEarlyExit m ()
trace TraceForgeEvent blk
failure
WithEarlyExit m (BlockContext blk)
forall (m :: * -> *) a. Applicative m => WithEarlyExit m a
exitEarly
blockContextFromPrevHeader ::
HasHeader (Header blk) =>
Header blk -> BlockContext blk
Header blk
hdr =
BlockNo -> Point blk -> BlockContext blk
forall blk. BlockNo -> Point blk -> BlockContext blk
BlockContext (BlockNo -> BlockNo
forall a. Enum a => a -> a
succ (Header blk -> BlockNo
forall b. HasHeader b => b -> BlockNo
blockNo Header blk
hdr)) (Header blk -> Point blk
forall blk. HasHeader (Header blk) => Header blk -> Point blk
headerPoint Header blk
hdr)
mkCurrentBlockContext ::
forall blk.
RunNode blk =>
SlotNo ->
AnchoredFragment (Header blk) ->
Either (TraceForgeEvent blk) (BlockContext blk)
mkCurrentBlockContext :: forall blk.
RunNode blk =>
SlotNo
-> AnchoredFragment (Header blk)
-> Either (TraceForgeEvent blk) (BlockContext blk)
mkCurrentBlockContext SlotNo
currentSlot AnchoredFragment (Header blk)
c = case AnchoredFragment (Header blk)
c of
Empty Anchor (Header blk)
AF.AnchorGenesis ->
BlockContext blk -> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. b -> Either a b
Right (BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk))
-> BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. (a -> b) -> a -> b
$ BlockNo -> Point blk -> BlockContext blk
forall blk. BlockNo -> Point blk -> BlockContext blk
BlockContext (Proxy blk -> BlockNo
forall blk (proxy :: * -> *).
BasicEnvelopeValidation blk =>
proxy blk -> BlockNo
forall (proxy :: * -> *). proxy blk -> BlockNo
expectedFirstBlockNo (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @blk)) Point blk
forall {k} (block :: k). Point block
GenesisPoint
Empty (AF.Anchor SlotNo
anchorSlot HeaderHash (Header blk)
anchorHash BlockNo
anchorBlockNo) ->
let Point blk
p :: Point blk = SlotNo -> HeaderHash blk -> Point blk
forall {k} (block :: k). SlotNo -> HeaderHash block -> Point block
BlockPoint SlotNo
anchorSlot HeaderHash blk
HeaderHash (Header blk)
anchorHash
in if SlotNo
anchorSlot SlotNo -> SlotNo -> Bool
forall a. Ord a => a -> a -> Bool
< SlotNo
currentSlot
then BlockContext blk -> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. b -> Either a b
Right (BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk))
-> BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. (a -> b) -> a -> b
$ BlockNo -> Point blk -> BlockContext blk
forall blk. BlockNo -> Point blk -> BlockContext blk
BlockContext (BlockNo -> BlockNo
forall a. Enum a => a -> a
succ BlockNo
anchorBlockNo) Point blk
p
else TraceForgeEvent blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. a -> Either a b
Left (TraceForgeEvent blk
-> Either (TraceForgeEvent blk) (BlockContext blk))
-> TraceForgeEvent blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. (a -> b) -> a -> b
$ SlotNo -> Point blk -> BlockNo -> TraceForgeEvent blk
forall blk. SlotNo -> Point blk -> BlockNo -> TraceForgeEvent blk
TraceSlotIsImmutable SlotNo
currentSlot Point blk
p BlockNo
anchorBlockNo
AnchoredFragment (Header blk)
c' :> Header blk
hdr -> case Header blk -> SlotNo
forall b. HasHeader b => b -> SlotNo
blockSlot Header blk
hdr SlotNo -> SlotNo -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` SlotNo
currentSlot of
Ordering
LT -> BlockContext blk -> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. b -> Either a b
Right (BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk))
-> BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. (a -> b) -> a -> b
$ Header blk -> BlockContext blk
forall blk.
HasHeader (Header blk) =>
Header blk -> BlockContext blk
blockContextFromPrevHeader Header blk
hdr
Ordering
GT -> TraceForgeEvent blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. a -> Either a b
Left (TraceForgeEvent blk
-> Either (TraceForgeEvent blk) (BlockContext blk))
-> TraceForgeEvent blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. (a -> b) -> a -> b
$ SlotNo -> SlotNo -> TraceForgeEvent blk
forall blk. SlotNo -> SlotNo -> TraceForgeEvent blk
TraceBlockFromFuture SlotNo
currentSlot (Header blk -> SlotNo
forall b. HasHeader b => b -> SlotNo
blockSlot Header blk
hdr)
Ordering
EQ ->
BlockContext blk -> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. b -> Either a b
Right (BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk))
-> BlockContext blk
-> Either (TraceForgeEvent blk) (BlockContext blk)
forall a b. (a -> b) -> a -> b
$
if Maybe EpochNo -> Bool
forall a. Maybe a -> Bool
isJust (Header blk -> Maybe EpochNo
forall blk. GetHeader blk => Header blk -> Maybe EpochNo
headerIsEBB Header blk
hdr)
then Header blk -> BlockContext blk
forall blk.
HasHeader (Header blk) =>
Header blk -> BlockContext blk
blockContextFromPrevHeader Header blk
hdr
else BlockNo -> Point blk -> BlockContext blk
forall blk. BlockNo -> Point blk -> BlockContext blk
BlockContext (Header blk -> BlockNo
forall b. HasHeader b => b -> BlockNo
blockNo Header blk
hdr) (Point blk -> BlockContext blk) -> Point blk -> BlockContext blk
forall a b. (a -> b) -> a -> b
$ Point (Header blk) -> Point blk
forall {k1} {k2} (b :: k1) (b' :: k2).
Coercible (HeaderHash b) (HeaderHash b') =>
Point b -> Point b'
castPoint (Point (Header blk) -> Point blk)
-> Point (Header blk) -> Point blk
forall a b. (a -> b) -> a -> b
$ AnchoredFragment (Header blk) -> Point (Header blk)
forall block.
HasHeader block =>
AnchoredFragment block -> Point block
AF.headPoint AnchoredFragment (Header blk)
c'
addBlockToChainDB ::
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ()) ->
ChainDB m blk ->
Mempool m blk ->
SlotNo ->
[Validated (GenTx blk)] ->
blk ->
WithEarlyExit m ()
addBlockToChainDB :: forall (m :: * -> *) blk.
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ())
-> ChainDB m blk
-> Mempool m blk
-> SlotNo
-> [Validated (GenTx blk)]
-> blk
-> WithEarlyExit m ()
addBlockToChainDB TraceForgeEvent blk -> WithEarlyExit m ()
trace ChainDB m blk
chainDB Mempool m blk
mempool SlotNo
currentSlot [Validated (GenTx blk)]
txs blk
newBlock = do
let noPunish :: InvalidBlockPunishment m
noPunish = InvalidBlockPunishment m
forall (m :: * -> *). Applicative m => InvalidBlockPunishment m
InvalidBlockPunishment.noPunishment
WithEarlyExit m () -> WithEarlyExit m ()
forall a. WithEarlyExit m a -> WithEarlyExit m a
forall (m :: * -> *) a. MonadMask m => m a -> m a
uninterruptibleMask_ (WithEarlyExit m () -> WithEarlyExit m ())
-> WithEarlyExit m () -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ do
result <- m (AddBlockPromise m blk)
-> WithEarlyExit m (AddBlockPromise m blk)
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (AddBlockPromise m blk)
-> WithEarlyExit m (AddBlockPromise m blk))
-> m (AddBlockPromise m blk)
-> WithEarlyExit m (AddBlockPromise m blk)
forall a b. (a -> b) -> a -> b
$ ChainDB m blk
-> InvalidBlockPunishment m -> blk -> m (AddBlockPromise m blk)
forall (m :: * -> *) blk.
ChainDB m blk
-> InvalidBlockPunishment m -> blk -> m (AddBlockPromise m blk)
ChainDB.addBlockAsync ChainDB m blk
chainDB InvalidBlockPunishment m
noPunish blk
newBlock
mbCurTip <- lift $ atomically $ ChainDB.blockProcessed result
when (mbCurTip /= SuccesfullyAddedBlock (blockPoint newBlock)) $ do
isInvalid <-
lift $
atomically $
($ blockHash newBlock) . forgetFingerprint
<$> ChainDB.getIsInvalidBlock chainDB
case isInvalid of
Maybe (ExtValidationError blk)
Nothing ->
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> blk -> TraceForgeEvent blk
forall blk. SlotNo -> blk -> TraceForgeEvent blk
TraceDidntAdoptBlock SlotNo
currentSlot blk
newBlock
Just ExtValidationError blk
reason -> do
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> blk -> ExtValidationError blk -> TraceForgeEvent blk
forall blk.
SlotNo -> blk -> ExtValidationError blk -> TraceForgeEvent blk
TraceForgedInvalidBlock SlotNo
currentSlot blk
newBlock ExtValidationError blk
reason
Maybe (NonEmpty (TxId (GenTx blk)))
-> (NonEmpty (TxId (GenTx blk)) -> WithEarlyExit m ())
-> WithEarlyExit m ()
forall (f :: * -> *) a.
Applicative f =>
Maybe a -> (a -> f ()) -> f ()
whenJust
([TxId (GenTx blk)] -> Maybe (NonEmpty (TxId (GenTx blk)))
forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty ((Validated (GenTx blk) -> TxId (GenTx blk))
-> [Validated (GenTx blk)] -> [TxId (GenTx blk)]
forall a b. (a -> b) -> [a] -> [b]
map (GenTx blk -> TxId (GenTx blk)
forall tx. HasTxId tx => tx -> TxId tx
txId (GenTx blk -> TxId (GenTx blk))
-> (Validated (GenTx blk) -> GenTx blk)
-> Validated (GenTx blk)
-> TxId (GenTx blk)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validated (GenTx blk) -> GenTx blk
forall blk.
LedgerSupportsMempool blk =>
Validated (GenTx blk) -> GenTx blk
txForgetValidated) [Validated (GenTx blk)]
txs))
(m () -> WithEarlyExit m ()
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WithEarlyExit m ())
-> (NonEmpty (TxId (GenTx blk)) -> m ())
-> NonEmpty (TxId (GenTx blk))
-> WithEarlyExit m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mempool m blk -> NonEmpty (TxId (GenTx blk)) -> m ()
forall (m :: * -> *) blk.
Mempool m blk -> NonEmpty (GenTxId blk) -> m ()
removeTxsEvenIfValid Mempool m blk
mempool)
exitEarly
trace $ TraceAdoptedBlock currentSlot newBlock txs
getLedgerView ::
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ()) ->
TopLevelConfig blk ->
SlotNo ->
ExtLedgerState blk EmptyMK ->
WithEarlyExit m (LedgerView (BlockProtocol blk))
getLedgerView :: forall (m :: * -> *) blk.
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ())
-> TopLevelConfig blk
-> SlotNo
-> ExtLedgerState blk EmptyMK
-> WithEarlyExit m (LedgerView (BlockProtocol blk))
getLedgerView TraceForgeEvent blk -> WithEarlyExit m ()
trace TopLevelConfig blk
cfg SlotNo
currentSlot ExtLedgerState blk EmptyMK
unticked = do
ledgerView <-
case Except OutsideForecastRange (LedgerView (BlockProtocol blk))
-> Either OutsideForecastRange (LedgerView (BlockProtocol blk))
forall e a. Except e a -> Either e a
runExcept (Except OutsideForecastRange (LedgerView (BlockProtocol blk))
-> Either OutsideForecastRange (LedgerView (BlockProtocol blk)))
-> Except OutsideForecastRange (LedgerView (BlockProtocol blk))
-> Either OutsideForecastRange (LedgerView (BlockProtocol blk))
forall a b. (a -> b) -> a -> b
$
Forecast (LedgerView (BlockProtocol blk))
-> SlotNo
-> Except OutsideForecastRange (LedgerView (BlockProtocol blk))
forall a. Forecast a -> SlotNo -> Except OutsideForecastRange a
forecastFor
( LedgerConfig blk
-> LedgerState blk EmptyMK
-> Forecast (LedgerView (BlockProtocol blk))
forall blk (mk :: MapKind).
(LedgerSupportsProtocol blk, HasCallStack) =>
LedgerConfig blk
-> LedgerState blk mk -> Forecast (LedgerView (BlockProtocol blk))
forall (mk :: MapKind).
HasCallStack =>
LedgerConfig blk
-> LedgerState blk mk -> Forecast (LedgerView (BlockProtocol blk))
ledgerViewForecastAt
(TopLevelConfig blk -> LedgerConfig blk
forall blk. TopLevelConfig blk -> LedgerConfig blk
configLedger TopLevelConfig blk
cfg)
(ExtLedgerState blk EmptyMK -> LedgerState blk EmptyMK
forall blk (mk :: MapKind).
ExtLedgerState blk mk -> LedgerState blk mk
ledgerState ExtLedgerState blk EmptyMK
unticked)
)
SlotNo
currentSlot of
Left OutsideForecastRange
err -> do
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> OutsideForecastRange -> TraceForgeEvent blk
forall blk. SlotNo -> OutsideForecastRange -> TraceForgeEvent blk
TraceNoLedgerView SlotNo
currentSlot OutsideForecastRange
err
WithEarlyExit m (LedgerView (BlockProtocol blk))
forall (m :: * -> *) a. Applicative m => WithEarlyExit m a
exitEarly
Right LedgerView (BlockProtocol blk)
lv ->
LedgerView (BlockProtocol blk)
-> WithEarlyExit m (LedgerView (BlockProtocol blk))
forall a. a -> WithEarlyExit m a
forall (m :: * -> *) a. Monad m => a -> m a
return LedgerView (BlockProtocol blk)
lv
trace $ TraceLedgerView currentSlot
pure ledgerView
getTickedChainDepState ::
RunNode blk =>
TopLevelConfig blk ->
SlotNo ->
ExtLedgerState blk EmptyMK ->
LedgerView (BlockProtocol blk) ->
Ticked (ChainDepState (BlockProtocol blk))
getTickedChainDepState :: forall blk.
RunNode blk =>
TopLevelConfig blk
-> SlotNo
-> ExtLedgerState blk EmptyMK
-> LedgerView (BlockProtocol blk)
-> Ticked (ChainDepState (BlockProtocol blk))
getTickedChainDepState TopLevelConfig blk
cfg SlotNo
currentSlot ExtLedgerState blk EmptyMK
unticked LedgerView (BlockProtocol blk)
ledgerView =
ConsensusConfig (BlockProtocol blk)
-> LedgerView (BlockProtocol blk)
-> SlotNo
-> ChainDepState (BlockProtocol blk)
-> Ticked (ChainDepState (BlockProtocol blk))
forall p.
ConsensusProtocol p =>
ConsensusConfig p
-> LedgerView p
-> SlotNo
-> ChainDepState p
-> Ticked (ChainDepState p)
tickChainDepState
(TopLevelConfig blk -> ConsensusConfig (BlockProtocol blk)
forall blk.
TopLevelConfig blk -> ConsensusConfig (BlockProtocol blk)
configConsensus TopLevelConfig blk
cfg)
LedgerView (BlockProtocol blk)
ledgerView
SlotNo
currentSlot
(HeaderState blk -> ChainDepState (BlockProtocol blk)
forall blk. HeaderState blk -> ChainDepState (BlockProtocol blk)
headerStateChainDep (ExtLedgerState blk EmptyMK -> HeaderState blk
forall blk (mk :: MapKind).
ExtLedgerState blk mk -> HeaderState blk
headerState ExtLedgerState blk EmptyMK
unticked))
getIsLeaderProof ::
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ()) ->
Tracer m (TraceLabelCreds (ForgeStateInfo blk)) ->
BlockForging m blk ->
TopLevelConfig blk ->
SlotNo ->
Ticked (ChainDepState (BlockProtocol blk)) ->
WithEarlyExit m (IsLeader (BlockProtocol blk))
getIsLeaderProof :: forall (m :: * -> *) blk.
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ())
-> Tracer m (TraceLabelCreds (ForgeStateInfo blk))
-> BlockForging m blk
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> WithEarlyExit m (IsLeader (BlockProtocol blk))
getIsLeaderProof TraceForgeEvent blk -> WithEarlyExit m ()
trace Tracer m (TraceLabelCreds (ForgeStateInfo blk))
forgeStateInfoTracer BlockForging m blk
blockForging TopLevelConfig blk
cfg SlotNo
currentSlot Ticked (ChainDepState (BlockProtocol blk))
tickedChainDepState = do
proof <- do
shouldForge <-
m (ShouldForge blk) -> WithEarlyExit m (ShouldForge blk)
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (ShouldForge blk) -> WithEarlyExit m (ShouldForge blk))
-> m (ShouldForge blk) -> WithEarlyExit m (ShouldForge blk)
forall a b. (a -> b) -> a -> b
$
BlockForging m blk
-> Tracer m (ForgeStateInfo blk)
-> TopLevelConfig blk
-> SlotNo
-> Ticked (ChainDepState (BlockProtocol blk))
-> m (ShouldForge blk)
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
blockForging
( (ForgeStateInfo blk -> TraceLabelCreds (ForgeStateInfo blk))
-> Tracer m (TraceLabelCreds (ForgeStateInfo blk))
-> Tracer m (ForgeStateInfo blk)
forall a' a. (a' -> a) -> Tracer m a -> Tracer m a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap
(Text -> ForgeStateInfo blk -> TraceLabelCreds (ForgeStateInfo blk)
forall a. Text -> a -> TraceLabelCreds a
TraceLabelCreds (BlockForging m blk -> Text
forall (m :: * -> *) blk. BlockForging m blk -> Text
forgeLabel BlockForging m blk
blockForging))
Tracer m (TraceLabelCreds (ForgeStateInfo blk))
forgeStateInfoTracer
)
TopLevelConfig blk
cfg
SlotNo
currentSlot
Ticked (ChainDepState (BlockProtocol blk))
tickedChainDepState
case shouldForge of
ForgeStateUpdateError ForgeStateUpdateError blk
err -> do
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> ForgeStateUpdateError blk -> TraceForgeEvent blk
forall blk.
SlotNo -> ForgeStateUpdateError blk -> TraceForgeEvent blk
TraceForgeStateUpdateError SlotNo
currentSlot ForgeStateUpdateError blk
err
WithEarlyExit m (IsLeader (BlockProtocol blk))
forall (m :: * -> *) a. Applicative m => WithEarlyExit m a
exitEarly
CannotForge CannotForge blk
cannotForge -> do
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> CannotForge blk -> TraceForgeEvent blk
forall blk. SlotNo -> CannotForge blk -> TraceForgeEvent blk
TraceNodeCannotForge SlotNo
currentSlot CannotForge blk
cannotForge
WithEarlyExit m (IsLeader (BlockProtocol blk))
forall (m :: * -> *) a. Applicative m => WithEarlyExit m a
exitEarly
ShouldForge blk
NotLeader -> do
TraceForgeEvent blk -> WithEarlyExit m ()
trace (TraceForgeEvent blk -> WithEarlyExit m ())
-> TraceForgeEvent blk -> WithEarlyExit m ()
forall a b. (a -> b) -> a -> b
$ SlotNo -> TraceForgeEvent blk
forall blk. SlotNo -> TraceForgeEvent blk
TraceNodeNotLeader SlotNo
currentSlot
WithEarlyExit m (IsLeader (BlockProtocol blk))
forall (m :: * -> *) a. Applicative m => WithEarlyExit m a
exitEarly
ShouldForge IsLeader (BlockProtocol blk)
p -> IsLeader (BlockProtocol blk)
-> WithEarlyExit m (IsLeader (BlockProtocol blk))
forall a. a -> WithEarlyExit m a
forall (m :: * -> *) a. Monad m => a -> m a
return IsLeader (BlockProtocol blk)
p
trace $ TraceNodeIsLeader currentSlot
pure proof
getTickedLedgerState ::
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ()) ->
TopLevelConfig blk ->
SlotNo ->
Point blk ->
ExtLedgerState blk EmptyMK ->
WithEarlyExit m (Ticked LedgerState blk DiffMK)
getTickedLedgerState :: forall (m :: * -> *) blk.
(IOLike m, RunNode blk) =>
(TraceForgeEvent blk -> WithEarlyExit m ())
-> TopLevelConfig blk
-> SlotNo
-> Point blk
-> ExtLedgerState blk EmptyMK
-> WithEarlyExit m (Ticked LedgerState blk DiffMK)
getTickedLedgerState TraceForgeEvent blk -> WithEarlyExit m ()
trace TopLevelConfig blk
cfg SlotNo
currentSlot Point blk
bcPrevPoint ExtLedgerState blk EmptyMK
unticked = do
let tickedLedgerState :: Ticked LedgerState blk DiffMK
tickedLedgerState =
ComputeLedgerEvents
-> LedgerCfg LedgerState blk
-> SlotNo
-> LedgerState blk EmptyMK
-> Ticked LedgerState blk DiffMK
forall (l :: StateKind) blk.
IsLedger l blk =>
ComputeLedgerEvents
-> LedgerCfg l blk
-> SlotNo
-> l blk EmptyMK
-> Ticked l blk DiffMK
applyChainTick
ComputeLedgerEvents
OmitLedgerEvents
(TopLevelConfig blk -> LedgerCfg LedgerState blk
forall blk. TopLevelConfig blk -> LedgerConfig blk
configLedger TopLevelConfig blk
cfg)
SlotNo
currentSlot
(ExtLedgerState blk EmptyMK -> LedgerState blk EmptyMK
forall blk (mk :: MapKind).
ExtLedgerState blk mk -> LedgerState blk mk
ledgerState ExtLedgerState blk EmptyMK
unticked)
_ <- Ticked LedgerState blk DiffMK
-> WithEarlyExit m (Ticked LedgerState blk DiffMK)
forall a. a -> WithEarlyExit m a
forall (m :: * -> *) a. MonadEvaluate m => a -> m a
evaluate Ticked LedgerState blk DiffMK
tickedLedgerState
trace $ TraceForgeTickedLedgerState currentSlot bcPrevPoint
pure tickedLedgerState
traceForgingMempoolSnapshot ::
IOLike m =>
(TraceForgeEvent blk -> WithEarlyExit m ()) ->
Mempool m blk ->
SlotNo ->
Point blk ->
WithEarlyExit m ()
traceForgingMempoolSnapshot :: forall (m :: * -> *) blk.
IOLike m =>
(TraceForgeEvent blk -> WithEarlyExit m ())
-> Mempool m blk -> SlotNo -> Point blk -> WithEarlyExit m ()
traceForgingMempoolSnapshot TraceForgeEvent blk -> WithEarlyExit m ()
trace Mempool m blk
mempool SlotNo
currentSlot Point blk
bcPrevPoint = do
(mempoolHash, mempoolSlotNo) <- m (ChainHash blk, SlotNo)
-> WithEarlyExit m (ChainHash blk, SlotNo)
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (ChainHash blk, SlotNo)
-> WithEarlyExit m (ChainHash blk, SlotNo))
-> m (ChainHash blk, SlotNo)
-> WithEarlyExit m (ChainHash blk, SlotNo)
forall a b. (a -> b) -> a -> b
$ STM m (ChainHash blk, SlotNo) -> m (ChainHash blk, SlotNo)
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (ChainHash blk, SlotNo) -> m (ChainHash blk, SlotNo))
-> STM m (ChainHash blk, SlotNo) -> m (ChainHash blk, SlotNo)
forall a b. (a -> b) -> a -> b
$ do
snap <- Mempool m blk -> STM m (MempoolSnapshot blk)
forall (m :: * -> *) blk.
Mempool m blk -> STM m (MempoolSnapshot blk)
getSnapshot Mempool m blk
mempool
pure (castHash $ snapshotStateHash snap, snapshotSlotNo snap)
_ <- evaluate mempoolHash
trace $ TraceForgingMempoolSnapshot currentSlot bcPrevPoint mempoolHash mempoolSlotNo
getTransactionsToForge ::
(IOLike m, RunNode blk) =>
TopLevelConfig blk ->
Mempool m blk ->
SlotNo ->
Ticked LedgerState blk DiffMK ->
ReadOnlyForker m l blk ->
WithEarlyExit m ([Validated (GenTx blk)], TxMeasureWithDiffTime blk, MempoolSize)
getTransactionsToForge :: forall (m :: * -> *) blk (l :: StateKind).
(IOLike m, RunNode blk) =>
TopLevelConfig blk
-> Mempool m blk
-> SlotNo
-> Ticked LedgerState blk DiffMK
-> ReadOnlyForker m l blk
-> WithEarlyExit
m ([Validated (GenTx blk)], TxMeasureWithDiffTime blk, MempoolSize)
getTransactionsToForge TopLevelConfig blk
cfg Mempool m blk
mempool SlotNo
currentSlot Ticked LedgerState blk DiffMK
tickedLedgerState ReadOnlyForker m l blk
forker = m ([Validated (GenTx blk)], TxMeasureWithDiffTime blk, MempoolSize)
-> WithEarlyExit
m ([Validated (GenTx blk)], TxMeasureWithDiffTime blk, MempoolSize)
forall (m :: * -> *) a. Monad m => m a -> WithEarlyExit m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m ([Validated (GenTx blk)], TxMeasureWithDiffTime blk,
MempoolSize)
-> WithEarlyExit
m
([Validated (GenTx blk)], TxMeasureWithDiffTime blk, MempoolSize))
-> m ([Validated (GenTx blk)], TxMeasureWithDiffTime blk,
MempoolSize)
-> WithEarlyExit
m ([Validated (GenTx blk)], TxMeasureWithDiffTime blk, MempoolSize)
forall a b. (a -> b) -> a -> b
$ do
mempoolSnapshot <-
Mempool m blk
-> SlotNo
-> Ticked LedgerState blk DiffMK
-> (LedgerTables blk KeysMK -> m (LedgerTables blk ValuesMK))
-> m (MempoolSnapshot blk)
forall (m :: * -> *) blk.
Mempool m blk
-> SlotNo
-> TickedLedgerState blk DiffMK
-> (LedgerTables blk KeysMK -> m (LedgerTables blk ValuesMK))
-> m (MempoolSnapshot blk)
getSnapshotFor
Mempool m blk
mempool
SlotNo
currentSlot
Ticked LedgerState blk DiffMK
tickedLedgerState
(ReadOnlyForker m l blk
-> LedgerTables blk KeysMK -> m (LedgerTables blk ValuesMK)
forall (m :: * -> *) (l :: StateKind) blk.
ReadOnlyForker m l blk
-> LedgerTables blk KeysMK -> m (LedgerTables blk ValuesMK)
roforkerReadTables ReadOnlyForker m l blk
forker)
let (txs, txssz) =
snapshotTake mempoolSnapshot $
blockCapacityTxMeasure (configLedger cfg) tickedLedgerState
_ <- evaluate (length txs)
pure (txs, txssz, snapshotMempoolSize mempoolSnapshot)