{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ViewPatterns #-}
module Ouroboros.Consensus.Node.GSM (
CandidateVersusSelection (..)
, DurationFromNow (..)
, GsmEntryPoints (..)
, GsmNodeKernelArgs (..)
, GsmState (..)
, GsmView (..)
, MarkerFileView (..)
, WrapDurationUntilTooOld (..)
, TraceGsmEvent (..)
, gsmStateToLedgerJudgement
, initializationGsmState
, realDurationUntilTooOld
, realGsmEntryPoints
, realMarkerFileView
, module Ouroboros.Consensus.Node.GsmState
) where
import qualified Cardano.Slotting.Slot as Slot
import qualified Control.Concurrent.Class.MonadSTM.TVar as LazySTM
import Control.Monad (forever, join, unless)
import Control.Monad.Class.MonadSTM (MonadSTM, STM, atomically, check,
orElse)
import Control.Monad.Class.MonadThrow (MonadThrow)
import Control.Monad.Class.MonadTimer (threadDelay)
import qualified Control.Monad.Class.MonadTimer.SI as SI
import Control.Tracer (Tracer, traceWith)
import Data.Functor ((<&>))
import qualified Data.Map.Strict as Map
import Data.Time (NominalDiffTime)
import qualified Ouroboros.Consensus.BlockchainTime.WallClock.Types as Clock
import qualified Ouroboros.Consensus.HardFork.Abstract as HardFork
import qualified Ouroboros.Consensus.HardFork.History as HardFork
import qualified Ouroboros.Consensus.HardFork.History.Qry as Qry
import qualified Ouroboros.Consensus.Ledger.Basics as L
import Ouroboros.Consensus.Node.GsmState
import Ouroboros.Consensus.Storage.ChainDB.API (ChainDB)
import Ouroboros.Consensus.Util.NormalForm.StrictTVar (StrictTVar)
import qualified Ouroboros.Consensus.Util.NormalForm.StrictTVar as StrictSTM
import Ouroboros.Network.PeerSelection.LedgerPeers.Type
(LedgerStateJudgement (..))
import System.FS.API (HasFS, createDirectoryIfMissing, doesFileExist,
removeFile, withFile)
import System.FS.API.Types (AllowExisting (..), FsPath, OpenMode (..),
mkFsPath)
import System.Random (StdGen, uniformR)
data DurationFromNow =
After !NominalDiffTime
|
Already
deriving (DurationFromNow -> DurationFromNow -> Bool
(DurationFromNow -> DurationFromNow -> Bool)
-> (DurationFromNow -> DurationFromNow -> Bool)
-> Eq DurationFromNow
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DurationFromNow -> DurationFromNow -> Bool
== :: DurationFromNow -> DurationFromNow -> Bool
$c/= :: DurationFromNow -> DurationFromNow -> Bool
/= :: DurationFromNow -> DurationFromNow -> Bool
Eq, Int -> DurationFromNow -> ShowS
[DurationFromNow] -> ShowS
DurationFromNow -> String
(Int -> DurationFromNow -> ShowS)
-> (DurationFromNow -> String)
-> ([DurationFromNow] -> ShowS)
-> Show DurationFromNow
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DurationFromNow -> ShowS
showsPrec :: Int -> DurationFromNow -> ShowS
$cshow :: DurationFromNow -> String
show :: DurationFromNow -> String
$cshowList :: [DurationFromNow] -> ShowS
showList :: [DurationFromNow] -> ShowS
Show)
data CandidateVersusSelection =
CandidateDoesNotIntersect
|
WhetherCandidateIsBetter !Bool
deriving (CandidateVersusSelection -> CandidateVersusSelection -> Bool
(CandidateVersusSelection -> CandidateVersusSelection -> Bool)
-> (CandidateVersusSelection -> CandidateVersusSelection -> Bool)
-> Eq CandidateVersusSelection
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CandidateVersusSelection -> CandidateVersusSelection -> Bool
== :: CandidateVersusSelection -> CandidateVersusSelection -> Bool
$c/= :: CandidateVersusSelection -> CandidateVersusSelection -> Bool
/= :: CandidateVersusSelection -> CandidateVersusSelection -> Bool
Eq, Int -> CandidateVersusSelection -> ShowS
[CandidateVersusSelection] -> ShowS
CandidateVersusSelection -> String
(Int -> CandidateVersusSelection -> ShowS)
-> (CandidateVersusSelection -> String)
-> ([CandidateVersusSelection] -> ShowS)
-> Show CandidateVersusSelection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CandidateVersusSelection -> ShowS
showsPrec :: Int -> CandidateVersusSelection -> ShowS
$cshow :: CandidateVersusSelection -> String
show :: CandidateVersusSelection -> String
$cshowList :: [CandidateVersusSelection] -> ShowS
showList :: [CandidateVersusSelection] -> ShowS
Show)
data GsmView m upstreamPeer selection chainSyncState = GsmView {
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> Maybe StdGen
antiThunderingHerd :: Maybe StdGen
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> selection -> chainSyncState -> CandidateVersusSelection
candidateOverSelection ::
selection -> chainSyncState -> CandidateVersusSelection
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> chainSyncState -> Bool
peerIsIdle :: chainSyncState -> Bool
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> Maybe (selection -> m DurationFromNow)
durationUntilTooOld :: Maybe (selection -> m DurationFromNow)
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> selection -> selection -> Bool
equivalent :: selection -> selection -> Bool
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> STM m (Map upstreamPeer (StrictTVar m chainSyncState))
getChainSyncStates ::
STM m (Map.Map upstreamPeer (StrictTVar m chainSyncState))
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> STM m selection
getCurrentSelection :: STM m selection
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> NominalDiffTime
minCaughtUpDuration :: NominalDiffTime
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> Bool -> m ()
setCaughtUpPersistentMark :: Bool -> m ()
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> GsmState -> m ()
writeGsmState :: GsmState -> m ()
,
forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> STM m Bool
isHaaSatisfied :: STM m Bool
}
data GsmEntryPoints m = GsmEntryPoints {
forall (m :: * -> *).
GsmEntryPoints m -> forall neverTerminates. m neverTerminates
enterCaughtUp :: forall neverTerminates. m neverTerminates
,
forall (m :: * -> *).
GsmEntryPoints m -> forall neverTerminates. m neverTerminates
enterPreSyncing :: forall neverTerminates. m neverTerminates
}
initializationGsmState ::
( L.GetTip (L.LedgerState blk)
, Monad m
)
=> m (L.LedgerState blk)
-> Maybe (WrapDurationUntilTooOld m blk)
-> MarkerFileView m
-> m GsmState
initializationGsmState :: forall blk (m :: * -> *).
(GetTip (LedgerState blk), Monad m) =>
m (LedgerState blk)
-> Maybe (WrapDurationUntilTooOld m blk)
-> MarkerFileView m
-> m GsmState
initializationGsmState
m (LedgerState blk)
getCurrentLedger
Maybe (WrapDurationUntilTooOld m blk)
mbDurationUntilTooOld
MarkerFileView m
markerFileView
= do
Bool
wasCaughtUp <- MarkerFileView m -> m Bool
forall (m :: * -> *). MarkerFileView m -> m Bool
hasMarkerFile MarkerFileView m
markerFileView
if Bool -> Bool
not Bool
wasCaughtUp then GsmState -> m GsmState
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure GsmState
PreSyncing else do
case Maybe (WrapDurationUntilTooOld m blk)
mbDurationUntilTooOld of
Maybe (WrapDurationUntilTooOld m blk)
Nothing -> GsmState -> m GsmState
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return GsmState
CaughtUp
Just WrapDurationUntilTooOld m blk
wd -> do
WithOrigin SlotNo
sno <- LedgerState blk -> WithOrigin SlotNo
forall l. GetTip l => l -> WithOrigin SlotNo
L.getTipSlot (LedgerState blk -> WithOrigin SlotNo)
-> m (LedgerState blk) -> m (WithOrigin SlotNo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (LedgerState blk)
getCurrentLedger
WrapDurationUntilTooOld m blk
-> WithOrigin SlotNo -> m DurationFromNow
forall (m :: * -> *) blk.
WrapDurationUntilTooOld m blk
-> WithOrigin SlotNo -> m DurationFromNow
getDurationUntilTooOld WrapDurationUntilTooOld m blk
wd WithOrigin SlotNo
sno m DurationFromNow -> (DurationFromNow -> m GsmState) -> m GsmState
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
After{} -> GsmState -> m GsmState
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return GsmState
CaughtUp
DurationFromNow
Already -> do
MarkerFileView m -> m ()
forall (m :: * -> *). MarkerFileView m -> m ()
removeMarkerFile MarkerFileView m
markerFileView
GsmState -> m GsmState
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return GsmState
PreSyncing
gsmStateToLedgerJudgement :: GsmState -> LedgerStateJudgement
gsmStateToLedgerJudgement :: GsmState -> LedgerStateJudgement
gsmStateToLedgerJudgement = \case
GsmState
PreSyncing -> LedgerStateJudgement
TooOld
GsmState
Syncing -> LedgerStateJudgement
TooOld
GsmState
CaughtUp -> LedgerStateJudgement
YoungEnough
realGsmEntryPoints :: forall m upstreamPeer selection tracedSelection candidate.
( SI.MonadDelay m
, SI.MonadTimer m
)
=> (selection -> tracedSelection, Tracer m (TraceGsmEvent tracedSelection))
-> GsmView m upstreamPeer selection candidate
-> GsmEntryPoints m
realGsmEntryPoints :: forall (m :: * -> *) upstreamPeer selection tracedSelection
candidate.
(MonadDelay m, MonadTimer m) =>
(selection -> tracedSelection,
Tracer m (TraceGsmEvent tracedSelection))
-> GsmView m upstreamPeer selection candidate -> GsmEntryPoints m
realGsmEntryPoints (selection -> tracedSelection,
Tracer m (TraceGsmEvent tracedSelection))
tracerArgs GsmView m upstreamPeer selection candidate
gsmView = GsmEntryPoints {
m neverTerminates
forall neverTerminates. m neverTerminates
enterCaughtUp :: forall neverTerminates. m neverTerminates
enterCaughtUp :: forall neverTerminates. m neverTerminates
enterCaughtUp
,
m neverTerminates
forall neverTerminates. m neverTerminates
enterPreSyncing :: forall neverTerminates. m neverTerminates
enterPreSyncing :: forall neverTerminates. m neverTerminates
enterPreSyncing
}
where
(selection -> tracedSelection
cnvSelection, Tracer m (TraceGsmEvent tracedSelection)
tracer) = (selection -> tracedSelection,
Tracer m (TraceGsmEvent tracedSelection))
tracerArgs
GsmView {
Maybe StdGen
antiThunderingHerd :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> Maybe StdGen
antiThunderingHerd :: Maybe StdGen
antiThunderingHerd
,
selection -> candidate -> CandidateVersusSelection
candidateOverSelection :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> selection -> chainSyncState -> CandidateVersusSelection
candidateOverSelection :: selection -> candidate -> CandidateVersusSelection
candidateOverSelection
,
candidate -> Bool
peerIsIdle :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> chainSyncState -> Bool
peerIsIdle :: candidate -> Bool
peerIsIdle
,
Maybe (selection -> m DurationFromNow)
durationUntilTooOld :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> Maybe (selection -> m DurationFromNow)
durationUntilTooOld :: Maybe (selection -> m DurationFromNow)
durationUntilTooOld
,
selection -> selection -> Bool
equivalent :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> selection -> selection -> Bool
equivalent :: selection -> selection -> Bool
equivalent
,
STM m (Map upstreamPeer (StrictTVar m candidate))
getChainSyncStates :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState
-> STM m (Map upstreamPeer (StrictTVar m chainSyncState))
getChainSyncStates :: STM m (Map upstreamPeer (StrictTVar m candidate))
getChainSyncStates
,
STM m selection
getCurrentSelection :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> STM m selection
getCurrentSelection :: STM m selection
getCurrentSelection
,
NominalDiffTime
minCaughtUpDuration :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> NominalDiffTime
minCaughtUpDuration :: NominalDiffTime
minCaughtUpDuration
,
Bool -> m ()
setCaughtUpPersistentMark :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> Bool -> m ()
setCaughtUpPersistentMark :: Bool -> m ()
setCaughtUpPersistentMark
,
GsmState -> m ()
writeGsmState :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> GsmState -> m ()
writeGsmState :: GsmState -> m ()
writeGsmState
,
STM m Bool
isHaaSatisfied :: forall (m :: * -> *) upstreamPeer selection chainSyncState.
GsmView m upstreamPeer selection chainSyncState -> STM m Bool
isHaaSatisfied :: STM m Bool
isHaaSatisfied
} = GsmView m upstreamPeer selection candidate
gsmView
enterCaughtUp :: forall neverTerminates. m neverTerminates
enterCaughtUp :: forall neverTerminates. m neverTerminates
enterCaughtUp = Maybe StdGen -> m neverTerminates
forall neverTerminates. Maybe StdGen -> m neverTerminates
enterCaughtUp' Maybe StdGen
antiThunderingHerd
enterPreSyncing :: forall neverTerminates. m neverTerminates
enterPreSyncing :: forall neverTerminates. m neverTerminates
enterPreSyncing = Maybe StdGen -> forall neverTerminates. m neverTerminates
enterPreSyncing' Maybe StdGen
antiThunderingHerd
enterCaughtUp' :: forall neverTerminates. Maybe StdGen -> m neverTerminates
enterCaughtUp' :: forall neverTerminates. Maybe StdGen -> m neverTerminates
enterCaughtUp' Maybe StdGen
g = do
(Maybe StdGen
g', TraceGsmEvent tracedSelection
ev) <- Maybe StdGen -> m (Maybe StdGen, TraceGsmEvent tracedSelection)
blockWhileCaughtUp Maybe StdGen
g
Bool -> m ()
setCaughtUpPersistentMark Bool
False
GsmState -> m ()
writeGsmState GsmState
PreSyncing
Tracer m (TraceGsmEvent tracedSelection)
-> TraceGsmEvent tracedSelection -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceGsmEvent tracedSelection)
tracer TraceGsmEvent tracedSelection
ev
Maybe StdGen -> forall neverTerminates. m neverTerminates
enterPreSyncing' Maybe StdGen
g'
enterPreSyncing' :: Maybe StdGen -> forall neverTerminates. m neverTerminates
enterPreSyncing' :: Maybe StdGen -> forall neverTerminates. m neverTerminates
enterPreSyncing' Maybe StdGen
g = do
m ()
blockUntilHonestAvailabilityAssumption
GsmState -> m ()
writeGsmState GsmState
Syncing
Tracer m (TraceGsmEvent tracedSelection)
-> TraceGsmEvent tracedSelection -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceGsmEvent tracedSelection)
tracer TraceGsmEvent tracedSelection
forall selection. TraceGsmEvent selection
GsmEventPreSyncingToSyncing
Maybe StdGen -> forall neverTerminates. m neverTerminates
enterSyncing' Maybe StdGen
g
enterSyncing' :: Maybe StdGen -> forall neverTerminates. m neverTerminates
enterSyncing' :: Maybe StdGen -> forall neverTerminates. m neverTerminates
enterSyncing' Maybe StdGen
g = do
Maybe (TraceGsmEvent tracedSelection)
mev <- STM m (Maybe (TraceGsmEvent tracedSelection))
-> m (Maybe (TraceGsmEvent tracedSelection))
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (Maybe (TraceGsmEvent tracedSelection))
-> m (Maybe (TraceGsmEvent tracedSelection)))
-> STM m (Maybe (TraceGsmEvent tracedSelection))
-> m (Maybe (TraceGsmEvent tracedSelection))
forall a b. (a -> b) -> a -> b
$
(Maybe (TraceGsmEvent tracedSelection)
forall a. Maybe a
Nothing Maybe (TraceGsmEvent tracedSelection)
-> STM m () -> STM m (Maybe (TraceGsmEvent tracedSelection))
forall a b. a -> STM m b -> STM m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ STM m ()
blockWhileHonestAvailabilityAssumption)
STM m (Maybe (TraceGsmEvent tracedSelection))
-> STM m (Maybe (TraceGsmEvent tracedSelection))
-> STM m (Maybe (TraceGsmEvent tracedSelection))
forall a. STM m a -> STM m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a -> STM m a -> STM m a
`orElse`
(TraceGsmEvent tracedSelection
-> Maybe (TraceGsmEvent tracedSelection)
forall a. a -> Maybe a
Just (TraceGsmEvent tracedSelection
-> Maybe (TraceGsmEvent tracedSelection))
-> STM m (TraceGsmEvent tracedSelection)
-> STM m (Maybe (TraceGsmEvent tracedSelection))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> STM m (TraceGsmEvent tracedSelection)
blockUntilCaughtUp)
case Maybe (TraceGsmEvent tracedSelection)
mev of
Maybe (TraceGsmEvent tracedSelection)
Nothing -> do
GsmState -> m ()
writeGsmState GsmState
PreSyncing
Tracer m (TraceGsmEvent tracedSelection)
-> TraceGsmEvent tracedSelection -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceGsmEvent tracedSelection)
tracer TraceGsmEvent tracedSelection
forall selection. TraceGsmEvent selection
GsmEventSyncingToPreSyncing
Maybe StdGen -> forall neverTerminates. m neverTerminates
enterPreSyncing' Maybe StdGen
g
Just TraceGsmEvent tracedSelection
ev -> do
GsmState -> m ()
writeGsmState GsmState
CaughtUp
Bool -> m ()
setCaughtUpPersistentMark Bool
True
Tracer m (TraceGsmEvent tracedSelection)
-> TraceGsmEvent tracedSelection -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceGsmEvent tracedSelection)
tracer TraceGsmEvent tracedSelection
ev
DiffTime -> m ()
forall (m :: * -> *). MonadDelay m => DiffTime -> m ()
SI.threadDelay (DiffTime -> m ()) -> DiffTime -> m ()
forall a b. (a -> b) -> a -> b
$ NominalDiffTime -> DiffTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac NominalDiffTime
minCaughtUpDuration
Maybe StdGen -> m neverTerminates
forall neverTerminates. Maybe StdGen -> m neverTerminates
enterCaughtUp' Maybe StdGen
g
blockWhileCaughtUp ::
Maybe StdGen
-> m (Maybe StdGen, TraceGsmEvent tracedSelection)
blockWhileCaughtUp :: Maybe StdGen -> m (Maybe StdGen, TraceGsmEvent tracedSelection)
blockWhileCaughtUp Maybe StdGen
g = do
let (DiffTime
bonus, Maybe StdGen
g') = case Maybe StdGen
g of
Maybe StdGen
Nothing -> (DiffTime
0, Maybe StdGen
forall a. Maybe a
Nothing)
Just StdGen
x ->
let (Int
seconds, !StdGen
g'') =
(Int, Int) -> StdGen -> (Int, StdGen)
forall g a. (RandomGen g, UniformRange a) => (a, a) -> g -> (a, g)
uniformR (Int
0, Int
300 :: Int) StdGen
x
in
(Int -> DiffTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
seconds, StdGen -> Maybe StdGen
forall a. a -> Maybe a
Just StdGen
g'')
TraceGsmEvent tracedSelection
ev <- STM m selection -> m selection
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically STM m selection
getCurrentSelection m selection
-> (selection -> m (TraceGsmEvent tracedSelection))
-> m (TraceGsmEvent tracedSelection)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DiffTime -> selection -> m (TraceGsmEvent tracedSelection)
blockWhileCaughtUpHelper DiffTime
bonus
(Maybe StdGen, TraceGsmEvent tracedSelection)
-> m (Maybe StdGen, TraceGsmEvent tracedSelection)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe StdGen
g', TraceGsmEvent tracedSelection
ev)
blockWhileCaughtUpHelper ::
SI.DiffTime
-> selection
-> m (TraceGsmEvent tracedSelection)
blockWhileCaughtUpHelper :: DiffTime -> selection -> m (TraceGsmEvent tracedSelection)
blockWhileCaughtUpHelper DiffTime
bonus selection
selection = do
let tracedSelection :: tracedSelection
tracedSelection = selection -> tracedSelection
cnvSelection selection
selection
computeDuration :: m (Maybe DurationFromNow)
computeDuration :: m (Maybe DurationFromNow)
computeDuration = ((selection -> m DurationFromNow) -> m DurationFromNow)
-> Maybe (selection -> m DurationFromNow)
-> m (Maybe DurationFromNow)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Maybe a -> m (Maybe b)
mapM ((selection -> m DurationFromNow) -> selection -> m DurationFromNow
forall a b. (a -> b) -> a -> b
$ selection
selection) Maybe (selection -> m DurationFromNow)
durationUntilTooOld
m (Maybe DurationFromNow)
computeDuration m (Maybe DurationFromNow)
-> (Maybe DurationFromNow -> m (TraceGsmEvent tracedSelection))
-> m (TraceGsmEvent tracedSelection)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe DurationFromNow
Nothing -> m () -> m (TraceGsmEvent tracedSelection)
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (m () -> m (TraceGsmEvent tracedSelection))
-> m () -> m (TraceGsmEvent tracedSelection)
forall a b. (a -> b) -> a -> b
$ Int -> m ()
forall (m :: * -> *). MonadDelay m => Int -> m ()
threadDelay Int
forall a. Bounded a => a
maxBound
Just DurationFromNow
Already -> do
TraceGsmEvent tracedSelection -> m (TraceGsmEvent tracedSelection)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TraceGsmEvent tracedSelection
-> m (TraceGsmEvent tracedSelection))
-> TraceGsmEvent tracedSelection
-> m (TraceGsmEvent tracedSelection)
forall a b. (a -> b) -> a -> b
$ tracedSelection -> DurationFromNow -> TraceGsmEvent tracedSelection
forall selection.
selection -> DurationFromNow -> TraceGsmEvent selection
GsmEventLeaveCaughtUp tracedSelection
tracedSelection DurationFromNow
Already
Just (After NominalDiffTime
dur) -> do
TVar m Bool
varTimeoutExpired <- DiffTime -> m (TVar m Bool)
forall (m :: * -> *). MonadTimer m => DiffTime -> m (TVar m Bool)
SI.registerDelay (NominalDiffTime -> DiffTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac NominalDiffTime
dur DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
+ DiffTime
bonus)
m (m (TraceGsmEvent tracedSelection))
-> m (TraceGsmEvent tracedSelection)
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (m (m (TraceGsmEvent tracedSelection))
-> m (TraceGsmEvent tracedSelection))
-> m (m (TraceGsmEvent tracedSelection))
-> m (TraceGsmEvent tracedSelection)
forall a b. (a -> b) -> a -> b
$ STM m (m (TraceGsmEvent tracedSelection))
-> m (m (TraceGsmEvent tracedSelection))
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m (m (TraceGsmEvent tracedSelection))
-> m (m (TraceGsmEvent tracedSelection)))
-> STM m (m (TraceGsmEvent tracedSelection))
-> m (m (TraceGsmEvent tracedSelection))
forall a b. (a -> b) -> a -> b
$ do
Bool
expired <- TVar m Bool -> STM m Bool
forall a. TVar m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => TVar m a -> STM m a
LazySTM.readTVar TVar m Bool
varTimeoutExpired
let ev :: TraceGsmEvent tracedSelection
ev = tracedSelection -> DurationFromNow -> TraceGsmEvent tracedSelection
forall selection.
selection -> DurationFromNow -> TraceGsmEvent selection
GsmEventLeaveCaughtUp tracedSelection
tracedSelection (NominalDiffTime -> DurationFromNow
After NominalDiffTime
dur)
if Bool
expired then m (TraceGsmEvent tracedSelection)
-> STM m (m (TraceGsmEvent tracedSelection))
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TraceGsmEvent tracedSelection -> m (TraceGsmEvent tracedSelection)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure TraceGsmEvent tracedSelection
ev) else do
selection
selection' <- STM m selection
getCurrentSelection
Bool -> STM m ()
forall (m :: * -> *). MonadSTM m => Bool -> STM m ()
check (Bool -> STM m ()) -> Bool -> STM m ()
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ selection -> selection -> Bool
equivalent selection
selection selection
selection'
m (TraceGsmEvent tracedSelection)
-> STM m (m (TraceGsmEvent tracedSelection))
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (m (TraceGsmEvent tracedSelection)
-> STM m (m (TraceGsmEvent tracedSelection)))
-> m (TraceGsmEvent tracedSelection)
-> STM m (m (TraceGsmEvent tracedSelection))
forall a b. (a -> b) -> a -> b
$ DiffTime -> selection -> m (TraceGsmEvent tracedSelection)
blockWhileCaughtUpHelper DiffTime
bonus selection
selection'
blockUntilCaughtUp :: STM m (TraceGsmEvent tracedSelection)
blockUntilCaughtUp :: STM m (TraceGsmEvent tracedSelection)
blockUntilCaughtUp = do
Map upstreamPeer (StrictTVar m candidate)
varsState <- STM m (Map upstreamPeer (StrictTVar m candidate))
getChainSyncStates
Map upstreamPeer candidate
states <- (StrictTVar m candidate -> STM m candidate)
-> Map upstreamPeer (StrictTVar m candidate)
-> STM m (Map upstreamPeer candidate)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Map upstreamPeer a -> f (Map upstreamPeer b)
traverse StrictTVar m candidate -> STM m candidate
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
StrictSTM.readTVar Map upstreamPeer (StrictTVar m candidate)
varsState
Bool -> STM m ()
forall (m :: * -> *). MonadSTM m => Bool -> STM m ()
check (Bool -> STM m ()) -> Bool -> STM m ()
forall a b. (a -> b) -> a -> b
$
Bool -> Bool
not (Map upstreamPeer candidate -> Bool
forall k a. Map k a -> Bool
Map.null Map upstreamPeer candidate
states)
Bool -> Bool -> Bool
&& (candidate -> Bool) -> Map upstreamPeer candidate -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all candidate -> Bool
peerIsIdle Map upstreamPeer candidate
states
selection
selection <- STM m selection
getCurrentSelection
Map upstreamPeer candidate
candidates <- (StrictTVar m candidate -> STM m candidate)
-> Map upstreamPeer (StrictTVar m candidate)
-> STM m (Map upstreamPeer candidate)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Map upstreamPeer a -> f (Map upstreamPeer b)
traverse StrictTVar m candidate -> STM m candidate
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
StrictSTM.readTVar Map upstreamPeer (StrictTVar m candidate)
varsState
let ok :: candidate -> Bool
ok candidate
candidate =
Bool -> CandidateVersusSelection
WhetherCandidateIsBetter Bool
False
CandidateVersusSelection -> CandidateVersusSelection -> Bool
forall a. Eq a => a -> a -> Bool
== selection -> candidate -> CandidateVersusSelection
candidateOverSelection selection
selection candidate
candidate
Bool -> STM m ()
forall (m :: * -> *). MonadSTM m => Bool -> STM m ()
check (Bool -> STM m ()) -> Bool -> STM m ()
forall a b. (a -> b) -> a -> b
$ (candidate -> Bool) -> Map upstreamPeer candidate -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all candidate -> Bool
ok Map upstreamPeer candidate
candidates
TraceGsmEvent tracedSelection
-> STM m (TraceGsmEvent tracedSelection)
forall a. a -> STM m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TraceGsmEvent tracedSelection
-> STM m (TraceGsmEvent tracedSelection))
-> TraceGsmEvent tracedSelection
-> STM m (TraceGsmEvent tracedSelection)
forall a b. (a -> b) -> a -> b
$ Int -> tracedSelection -> TraceGsmEvent tracedSelection
forall selection. Int -> selection -> TraceGsmEvent selection
GsmEventEnterCaughtUp
(Map upstreamPeer candidate -> Int
forall k a. Map k a -> Int
Map.size Map upstreamPeer candidate
states)
(selection -> tracedSelection
cnvSelection selection
selection)
blockUntilHonestAvailabilityAssumption :: m ()
blockUntilHonestAvailabilityAssumption :: m ()
blockUntilHonestAvailabilityAssumption =
STM m () -> m ()
forall a. HasCallStack => STM m a -> m a
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
$ Bool -> STM m ()
forall (m :: * -> *). MonadSTM m => Bool -> STM m ()
check (Bool -> STM m ()) -> STM m Bool -> STM m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< STM m Bool
isHaaSatisfied
blockWhileHonestAvailabilityAssumption :: STM m ()
blockWhileHonestAvailabilityAssumption :: STM m ()
blockWhileHonestAvailabilityAssumption =
Bool -> STM m ()
forall (m :: * -> *). MonadSTM m => Bool -> STM m ()
check (Bool -> STM m ()) -> (Bool -> Bool) -> Bool -> STM m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not (Bool -> STM m ()) -> STM m Bool -> STM m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< STM m Bool
isHaaSatisfied
data TraceGsmEvent selection =
GsmEventEnterCaughtUp !Int !selection
|
GsmEventLeaveCaughtUp !selection !DurationFromNow
|
GsmEventPreSyncingToSyncing
|
GsmEventSyncingToPreSyncing
deriving (TraceGsmEvent selection -> TraceGsmEvent selection -> Bool
(TraceGsmEvent selection -> TraceGsmEvent selection -> Bool)
-> (TraceGsmEvent selection -> TraceGsmEvent selection -> Bool)
-> Eq (TraceGsmEvent selection)
forall selection.
Eq selection =>
TraceGsmEvent selection -> TraceGsmEvent selection -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall selection.
Eq selection =>
TraceGsmEvent selection -> TraceGsmEvent selection -> Bool
== :: TraceGsmEvent selection -> TraceGsmEvent selection -> Bool
$c/= :: forall selection.
Eq selection =>
TraceGsmEvent selection -> TraceGsmEvent selection -> Bool
/= :: TraceGsmEvent selection -> TraceGsmEvent selection -> Bool
Eq, Int -> TraceGsmEvent selection -> ShowS
[TraceGsmEvent selection] -> ShowS
TraceGsmEvent selection -> String
(Int -> TraceGsmEvent selection -> ShowS)
-> (TraceGsmEvent selection -> String)
-> ([TraceGsmEvent selection] -> ShowS)
-> Show (TraceGsmEvent selection)
forall selection.
Show selection =>
Int -> TraceGsmEvent selection -> ShowS
forall selection.
Show selection =>
[TraceGsmEvent selection] -> ShowS
forall selection.
Show selection =>
TraceGsmEvent selection -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall selection.
Show selection =>
Int -> TraceGsmEvent selection -> ShowS
showsPrec :: Int -> TraceGsmEvent selection -> ShowS
$cshow :: forall selection.
Show selection =>
TraceGsmEvent selection -> String
show :: TraceGsmEvent selection -> String
$cshowList :: forall selection.
Show selection =>
[TraceGsmEvent selection] -> ShowS
showList :: [TraceGsmEvent selection] -> ShowS
Show)
newtype WrapDurationUntilTooOld m blk = DurationUntilTooOld {
forall (m :: * -> *) blk.
WrapDurationUntilTooOld m blk
-> WithOrigin SlotNo -> m DurationFromNow
getDurationUntilTooOld :: Slot.WithOrigin Slot.SlotNo -> m DurationFromNow
}
realDurationUntilTooOld ::
( HardFork.HasHardForkHistory blk
, MonadSTM m
)
=> L.LedgerConfig blk
-> STM m (L.LedgerState blk)
-> NominalDiffTime
-> Clock.SystemTime m
-> m (WrapDurationUntilTooOld m blk)
realDurationUntilTooOld :: forall blk (m :: * -> *).
(HasHardForkHistory blk, MonadSTM m) =>
LedgerConfig blk
-> STM m (LedgerState blk)
-> NominalDiffTime
-> SystemTime m
-> m (WrapDurationUntilTooOld m blk)
realDurationUntilTooOld LedgerConfig blk
lcfg STM m (LedgerState blk)
getLedgerState NominalDiffTime
maxCaughtUpAge SystemTime m
systemTime = do
RunWithCachedSummary (HardForkIndices blk) m
runner <-
STM m (Summary (HardForkIndices blk))
-> m (RunWithCachedSummary (HardForkIndices blk) m)
forall (m :: * -> *) (xs :: [*]).
MonadSTM m =>
STM m (Summary xs) -> m (RunWithCachedSummary xs m)
HardFork.runWithCachedSummary
(STM m (Summary (HardForkIndices blk))
-> m (RunWithCachedSummary (HardForkIndices blk) m))
-> STM m (Summary (HardForkIndices blk))
-> m (RunWithCachedSummary (HardForkIndices blk) m)
forall a b. (a -> b) -> a -> b
$ LedgerConfig blk
-> LedgerState blk -> Summary (HardForkIndices blk)
forall blk.
HasHardForkHistory blk =>
LedgerConfig blk
-> LedgerState blk -> Summary (HardForkIndices blk)
HardFork.hardForkSummary LedgerConfig blk
lcfg (LedgerState blk -> Summary (HardForkIndices blk))
-> STM m (LedgerState blk) -> STM m (Summary (HardForkIndices blk))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> STM m (LedgerState blk)
getLedgerState
WrapDurationUntilTooOld m blk -> m (WrapDurationUntilTooOld m blk)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WrapDurationUntilTooOld m blk
-> m (WrapDurationUntilTooOld m blk))
-> WrapDurationUntilTooOld m blk
-> m (WrapDurationUntilTooOld m blk)
forall a b. (a -> b) -> a -> b
$ (WithOrigin SlotNo -> m DurationFromNow)
-> WrapDurationUntilTooOld m blk
forall (m :: * -> *) blk.
(WithOrigin SlotNo -> m DurationFromNow)
-> WrapDurationUntilTooOld m blk
DurationUntilTooOld ((WithOrigin SlotNo -> m DurationFromNow)
-> WrapDurationUntilTooOld m blk)
-> (WithOrigin SlotNo -> m DurationFromNow)
-> WrapDurationUntilTooOld m blk
forall a b. (a -> b) -> a -> b
$ \WithOrigin SlotNo
woSlot -> do
RelativeTime
now <- SystemTime m -> m RelativeTime
forall (m :: * -> *). SystemTime m -> m RelativeTime
Clock.systemTimeCurrent SystemTime m
systemTime
case WithOrigin SlotNo
woSlot of
WithOrigin SlotNo
Slot.Origin -> DurationFromNow -> m DurationFromNow
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DurationFromNow -> m DurationFromNow)
-> DurationFromNow -> m DurationFromNow
forall a b. (a -> b) -> a -> b
$ RelativeTime -> RelativeTime -> DurationFromNow
toDur RelativeTime
now (RelativeTime -> DurationFromNow)
-> RelativeTime -> DurationFromNow
forall a b. (a -> b) -> a -> b
$ NominalDiffTime -> RelativeTime
Clock.RelativeTime NominalDiffTime
0
Slot.At SlotNo
slot -> do
let qry :: Qry (RelativeTime, SlotLength)
qry = SlotNo -> Qry (RelativeTime, SlotLength)
Qry.slotToWallclock SlotNo
slot
STM m DurationFromNow -> m DurationFromNow
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM m DurationFromNow -> m DurationFromNow)
-> STM m DurationFromNow -> m DurationFromNow
forall a b. (a -> b) -> a -> b
$ RunWithCachedSummary (HardForkIndices blk) m
-> forall a. Qry a -> STM m (Either PastHorizonException a)
forall (xs :: [*]) (m :: * -> *).
RunWithCachedSummary xs m
-> forall a. Qry a -> STM m (Either PastHorizonException a)
HardFork.cachedRunQuery RunWithCachedSummary (HardForkIndices blk) m
runner Qry (RelativeTime, SlotLength)
qry STM m (Either PastHorizonException (RelativeTime, SlotLength))
-> (Either PastHorizonException (RelativeTime, SlotLength)
-> DurationFromNow)
-> STM m DurationFromNow
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
Left Qry.PastHorizon{} -> DurationFromNow
Already
Right (RelativeTime
onset, SlotLength
_slotLen) -> RelativeTime -> RelativeTime -> DurationFromNow
toDur RelativeTime
now RelativeTime
onset
where
toDur :: RelativeTime -> RelativeTime -> DurationFromNow
toDur
(Clock.RelativeTime NominalDiffTime
now)
(RelativeTime -> NominalDiffTime
Clock.getRelativeTime -> (NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
+ NominalDiffTime
maxCaughtUpAge) -> NominalDiffTime
limit)
= if NominalDiffTime
limit NominalDiffTime -> NominalDiffTime -> Bool
forall a. Ord a => a -> a -> Bool
<= NominalDiffTime
now then DurationFromNow
Already else NominalDiffTime -> DurationFromNow
After (NominalDiffTime
limit NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
- NominalDiffTime
now)
data MarkerFileView m = MarkerFileView {
forall (m :: * -> *). MarkerFileView m -> m Bool
hasMarkerFile :: m Bool
,
forall (m :: * -> *). MarkerFileView m -> m ()
removeMarkerFile :: m ()
,
forall (m :: * -> *). MarkerFileView m -> m ()
touchMarkerFile :: m ()
}
realMarkerFileView ::
MonadThrow m
=> ChainDB m blk
-> HasFS m h
-> MarkerFileView m
realMarkerFileView :: forall (m :: * -> *) blk h.
MonadThrow m =>
ChainDB m blk -> HasFS m h -> MarkerFileView m
realMarkerFileView !ChainDB m blk
_cdb HasFS m h
hasFS =
MarkerFileView {
m Bool
hasMarkerFile :: m Bool
hasMarkerFile :: m Bool
hasMarkerFile
,
removeMarkerFile :: m ()
removeMarkerFile = HasFS m h -> HasCallStack => FsPath -> m ()
forall (m :: * -> *) h. HasFS m h -> HasCallStack => FsPath -> m ()
removeFile HasFS m h
hasFS FsPath
markerFile
,
touchMarkerFile :: m ()
touchMarkerFile = do
HasFS m h -> HasCallStack => Bool -> FsPath -> m ()
forall (m :: * -> *) h.
HasFS m h -> HasCallStack => Bool -> FsPath -> m ()
createDirectoryIfMissing HasFS m h
hasFS Bool
True ([String] -> FsPath
mkFsPath [])
Bool
alreadyExists <- m Bool
hasMarkerFile
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
alreadyExists (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
HasFS m h -> FsPath -> OpenMode -> (Handle h -> m ()) -> m ()
forall (m :: * -> *) h a.
(HasCallStack, MonadThrow m) =>
HasFS m h -> FsPath -> OpenMode -> (Handle h -> m a) -> m a
withFile HasFS m h
hasFS FsPath
markerFile (AllowExisting -> OpenMode
WriteMode AllowExisting
MustBeNew) ((Handle h -> m ()) -> m ()) -> (Handle h -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \Handle h
_h ->
() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
}
where
hasMarkerFile :: m Bool
hasMarkerFile = HasFS m h -> HasCallStack => FsPath -> m Bool
forall (m :: * -> *) h.
HasFS m h -> HasCallStack => FsPath -> m Bool
doesFileExist HasFS m h
hasFS FsPath
markerFile
markerFile :: FsPath
markerFile :: FsPath
markerFile = [String] -> FsPath
mkFsPath [String
"CaughtUpMarker"]
data GsmNodeKernelArgs m blk = GsmNodeKernelArgs {
forall (m :: * -> *) blk. GsmNodeKernelArgs m blk -> StdGen
gsmAntiThunderingHerd :: StdGen
,
forall (m :: * -> *) blk.
GsmNodeKernelArgs m blk -> Maybe (WrapDurationUntilTooOld m blk)
gsmDurationUntilTooOld :: Maybe (WrapDurationUntilTooOld m blk)
,
forall (m :: * -> *) blk.
GsmNodeKernelArgs m blk -> MarkerFileView m
gsmMarkerFileView :: MarkerFileView m
,
forall (m :: * -> *) blk.
GsmNodeKernelArgs m blk -> NominalDiffTime
gsmMinCaughtUpDuration :: NominalDiffTime
}