Copyright | © 2018-2020 IOHK |
---|---|
License | Apache-2.0 |
Safe Haskell | None |
Language | Haskell2010 |
Contains tools for converting between
SlotNo
,
EpochNo
,
SlotInEpoch
,
UTCTime
.
Synopsis
- data Qry :: Type -> Type
- currentEpoch :: MonadIO m => TimeInterpreter m -> m EpochNo
- epochOf :: SlotNo -> Qry EpochNo
- slotToUTCTime :: SlotNo -> Qry UTCTime
- slotToRelTime :: SlotNo -> Qry RelativeTime
- toSlotId :: SlotNo -> Qry SlotId
- slotRangeFromRelativeTimeRange :: Range RelativeTime -> Qry ( Range SlotNo )
- slotRangeFromTimeRange :: Range UTCTime -> Qry ( Maybe ( Range SlotNo ))
- firstSlotInEpoch :: EpochNo -> Qry SlotNo
- ongoingSlotAt :: RelativeTime -> Qry SlotNo
- ceilingSlotAt :: RelativeTime -> Qry SlotNo
- timeOfEpoch :: EpochNo -> Qry ( UTCTime , UTCTime )
- getStartTime :: Qry StartTime
- data RelativeTime
- toRelativeTime :: StartTime -> UTCTime -> Maybe RelativeTime
- toRelativeTimeRange :: Range UTCTime -> StartTime -> Maybe ( Range RelativeTime )
- fromRelativeTime :: RelativeTime -> Qry UTCTime
- addRelTime :: NominalDiffTime -> RelativeTime -> RelativeTime
- data SystemStart
- getSystemStart :: TimeInterpreter m -> SystemStart
- currentRelativeTime :: MonadIO m => TimeInterpreter n -> m RelativeTime
- getCurrentTimeRelativeFromStart :: StartTime -> IO RelativeTime
- data TimeInterpreter m
- mkSingleEraInterpreter :: HasCallStack => StartTime -> SlottingParameters -> TimeInterpreter Identity
- mkTimeInterpreter :: Monad m => Tracer m TimeInterpreterLog -> StartTime -> m ( Interpreter eras) -> TimeInterpreter ( ExceptT PastHorizonException m)
-
data
PastHorizonException
=
PastHorizon
{
- pastHorizonCallStack :: CallStack
- pastHorizonExpression :: Some ClosedExpr
- pastHorizonSummary :: [ EraSummary ]
- interpretQuery :: HasCallStack => Monad m => TimeInterpreter m -> Qry a -> m a
- data TimeInterpreterLog = MsgInterpreterPastHorizon ( Maybe String ) StartTime PastHorizonException
- data EpochInfo (m :: Type -> Type )
- toEpochInfo :: forall m. Applicative m => TimeInterpreter m -> m ( EpochInfo ( ExceptT PastHorizonException Identity ))
- unsafeExtendSafeZone :: TimeInterpreter ( ExceptT PastHorizonException IO ) -> TimeInterpreter IO
- neverFails :: String -> TimeInterpreter ( ExceptT PastHorizonException IO ) -> TimeInterpreter IO
- snapshot :: TimeInterpreter ( ExceptT PastHorizonException IO ) -> IO ( TimeInterpreter ( Either PastHorizonException ))
- hoistTimeInterpreter :: ( forall a. m a -> n a) -> TimeInterpreter m -> TimeInterpreter n
- expectAndThrowFailures :: TimeInterpreter ( ExceptT PastHorizonException IO ) -> TimeInterpreter IO
Queries
data Qry :: Type -> Type Source #
A query for time, slot and epoch conversions. Can be interpreted using
interpretQuery
.
Differences to the underlying consensus
Qry
HF.Qry
can only be interpreted in a
single era. If you have
q1 = epochOf someSlotInByron q2 = epochOf someSlotInShelley
HF.interpretQuery
could interpret both individually, but
q3 = q1 >> q2
would fail.
This wrapper exists to fix this.
We also provide
QStartTime
.
currentEpoch :: MonadIO m => TimeInterpreter m -> m EpochNo Source #
Note: This fails when the node is far enough behind that we in the present are beyond its safe zone.
slotToRelTime :: SlotNo -> Qry RelativeTime Source #
Query the relative time at which a slot starts.
slotRangeFromRelativeTimeRange :: Range RelativeTime -> Qry ( Range SlotNo ) Source #
Transforms the given inclusive time range into an inclusive slot range.
ongoingSlotAt :: RelativeTime -> Qry SlotNo Source #
ceilingSlotAt :: RelativeTime -> Qry SlotNo Source #
timeOfEpoch :: EpochNo -> Qry ( UTCTime , UTCTime ) Source #
Query the absolute times at which an epoch starts and ends.
Querying the end time of
this
epoch is preferable to querying the start
time of the
next
epoch, because the next epoch may be outside the forecast
range, and result in
PastHorizonException
.
getStartTime :: Qry StartTime Source #
Query the blockchain start time. This is part of the
TimeInterpreter
environment.
Blockchain-relative times
data RelativeTime Source #
RelativeTime
is time relative to the
SystemStart
Instances
toRelativeTime :: StartTime -> UTCTime -> Maybe RelativeTime Source #
Same as
toRelativeTime
, but has error handling for times before
the system start. No other functions in this module will accept UTC times.
toRelativeTimeRange :: Range UTCTime -> StartTime -> Maybe ( Range RelativeTime ) Source #
This function returns a chain-relative time range if (and only if) the specified UTC time range intersects with the life of the blockchain.
If, on the other hand, the specified time range terminates before the start
of the blockchain, this function returns
Nothing
.
fromRelativeTime :: RelativeTime -> Qry UTCTime Source #
Query the absolute time corresponding to a blockchain-relative time.
addRelTime :: NominalDiffTime -> RelativeTime -> RelativeTime Source #
Blockchain-absolute times
data SystemStart Source #
System start
Slots are counted from the system start.
Instances
getSystemStart :: TimeInterpreter m -> SystemStart Source #
What's the time?
currentRelativeTime :: MonadIO m => TimeInterpreter n -> m RelativeTime Source #
The current system time, compared to the blockchain start time of the given
TimeInterpreter
.
If the current time is before the system start (this would only happen when launching testnets), the relative time is reported as 0.
getCurrentTimeRelativeFromStart :: StartTime -> IO RelativeTime Source #
The current system time, compared to the given blockchain start time.
If the current time is before the system start (this would only happen when launching testnets), let's just say we're in epoch 0.
TODO: Use io-sim-classes for easier testing.
Running queries
data TimeInterpreter m Source #
A
TimeInterpreter
is a way for the wallet to run things of type
Qry a
,
with a system start time as context.
mkSingleEraInterpreter :: HasCallStack => StartTime -> SlottingParameters -> TimeInterpreter Identity Source #
An
Interpreter
for a single era, where the
SlottingParameters
cannot
change.
Queries will never fail with
mkSingleEraInterpreter
.
mkTimeInterpreter :: Monad m => Tracer m TimeInterpreterLog -> StartTime -> m ( Interpreter eras) -> TimeInterpreter ( ExceptT PastHorizonException m) Source #
Set up a
TimeInterpreter
for a given start time, and an
Interpreter
queried from the ledger layer.
data PastHorizonException Source #
We tried to convert something that is past the horizon
That is, we tried to convert something that is past the point in time beyond which we lack information due to uncertainty about the next hard fork.
PastHorizon | |
|
Instances
interpretQuery :: HasCallStack => Monad m => TimeInterpreter m -> Qry a -> m a Source #
Run a query.
data TimeInterpreterLog Source #
MsgInterpreterPastHorizon | |
|
Instances
Eq TimeInterpreterLog Source # | |
Defined in Cardano.Wallet.Primitive.Slotting (==) :: TimeInterpreterLog -> TimeInterpreterLog -> Bool Source # (/=) :: TimeInterpreterLog -> TimeInterpreterLog -> Bool Source # |
|
Show TimeInterpreterLog Source # | |
Defined in Cardano.Wallet.Primitive.Slotting |
|
ToText TimeInterpreterLog Source # | |
Defined in Cardano.Wallet.Primitive.Slotting toText :: TimeInterpreterLog -> Text Source # |
|
HasSeverityAnnotation TimeInterpreterLog Source # | |
Defined in Cardano.Wallet.Primitive.Slotting getSeverityAnnotation :: TimeInterpreterLog -> Severity |
EpochInfo
data EpochInfo (m :: Type -> Type ) Source #
Information about epochs
Different epochs may have different sizes and different slot lengths. This
information is encapsulated by
EpochInfo
. It is parameterized over a monad
m
because the information about how long each epoch is may depend on
information derived from the blockchain itself. It ultimately requires acess
to state, and so either uses the monad for that or uses the monad to reify
failure due to cached state information being too stale for the current
query.
toEpochInfo :: forall m. Applicative m => TimeInterpreter m -> m ( EpochInfo ( ExceptT PastHorizonException Identity )) Source #
Combinators for running queries
unsafeExtendSafeZone :: TimeInterpreter ( ExceptT PastHorizonException IO ) -> TimeInterpreter IO Source #
Extend the safe zone to make the TimeInterpreter return predictions where
it otherwise would have failed with
PastHorizonException
. This should be
used with great caution, and if we can get away from it, that would also be
great. Also ADP-575.
From the underlying ouroboros-consensus function:
UNSAFE: extend the safe zone of the current era of the given
Interpreter
to be
unbounded
, ignoring any future hard forks.
This only has effect when the
Interpreter
was obtained in an era that was
not the final one
(in the final era, this is a no-op). The
Interpreter
will be made to believe that the current era is the final era, making its
horizon unbounded, and thus never returning a
PastHorizonException
.
Use of this function is
strongly discouraged
, as it will ignore any future
hard forks, and the results produced by the
Interpreter
can thus be
incorrect.
neverFails :: String -> TimeInterpreter ( ExceptT PastHorizonException IO ) -> TimeInterpreter IO Source #
Takes a motivation of why
TimeInterpreter
shouldn't fail interpreting
queries.
Unexpected
PastHorizonException
s will be thrown in IO, and traced with
Error severity along with the provided motivation.
snapshot :: TimeInterpreter ( ExceptT PastHorizonException IO ) -> IO ( TimeInterpreter ( Either PastHorizonException )) Source #
Pre-fetches a snapshot of the epoch history from the node, such that the
resulting
TimeInterpreter
doesn't require
IO
.
Please consider not using this function, as it disables all logging.
hoistTimeInterpreter :: ( forall a. m a -> n a) -> TimeInterpreter m -> TimeInterpreter n Source #
Change the underlying monad of the TimeInterpreter with a natural transformation.
expectAndThrowFailures :: TimeInterpreter ( ExceptT PastHorizonException IO ) -> TimeInterpreter IO Source #
Makes
PastHorizonException
be thrown in
IO
.
Will
not
cause
PastHorizonException
to be tracer with Error severity,
unlike
neverFails
.