Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Haddocks for certain aspects of the HFC status quo #428

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ module Ouroboros.Consensus.HardFork.Combinator.Abstract.SingleEraBlock (
) where

import Codec.Serialise
import Data.Either (isRight)
import Data.Function (on)
import Data.Proxy
import Data.SOP.BasicFunctors
import Data.SOP.Constraint
import Data.SOP.Index
import Data.SOP.Match
import Data.SOP.Strict
import qualified Data.Text as Text
import Data.Void
Expand Down Expand Up @@ -117,7 +116,10 @@ newtype EraIndex xs = EraIndex {
}

instance Eq (EraIndex xs) where
EraIndex era == EraIndex era' = isRight (matchNS era era')
(==) = (==) `on` eraIndexToInt

instance Ord (EraIndex xs) where
compare = compare `on` eraIndexToInt

instance All SingleEraBlock xs => Show (EraIndex xs) where
show = hcollapse . hcmap proxySingle getEraName . getEraIndex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,42 @@ deriving anyclass instance
CanHardFork xs
=> NoThunks (Ticked (LedgerState (HardForkBlock xs)))

-- | = HFC ticking
--
-- This is the place where era transitions happen, ie when we have @st ::
-- 'LedgerState' ('HardForkBlock' xs)@ and, for a valid @slotNo@,
--
-- @
-- tickedSt :: 'Ticked' ('LedgerState' ('HardForkBlock' xs))
-- tickedSt = 'applyChainTick' cfg slotNo st
-- @
--
-- we have the corresponding era indices
--
-- @
-- ixSt, ixTickedSt :: 'EraIndex' xs
-- ixSt =
-- 'eraIndexFromNS' . State.'State.tip' . 'hardForkLedgerStatePerEra' $ st
-- ixTickedState =
-- 'eraIndexFromNS' . State.'State.tip' . 'tickedHardForkLedgerStatePerEra' $ tickedSt
-- @
--
-- and we always have
--
-- >>> ixSt <= ixTickedSt
-- True
--
-- with inequality exactly if we ticked across an era boundary.
--
-- == Ticking alone can't reveal era transitions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording of this subheading seems off to me:

Ticking alone can't reveal era transitions

It seems like there are two things worth explaining/referencing:

  • The transition must have been predicted by singleEraTransition at least one safe zone before it happened.

  • Ticking is currently unable to change the output of singleEraTransition.

Right now, the text of this subheading could be interpreted as either of those two things. Is that ambiguity intentional?

Also, the text seems to call the first one a "reflection" of the second one, which I hesitate to agree with.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ticking is currently unable to change the output of singleEraTransition.

This is what I wanted to talk about here in this subsection, but I didn't phrase it like this as you can't apply singleEraTransition to the output of ticking.

I didn't intend to talk about safe zones here (but that could definitely happen in a different subsection, will add that 👍). In my mind, these two topics are orthogonal:

  • This subsection is about how era transitions can become known (currently, only via block application, not via ticking).
  • Safe zones are about when an era transition can become known.

Also, the text seems to call the first one a "reflection" of the second one, which I hesitate to agree with.

Yeah, I didn't want to imply that, hopefully, separating safe zones to its own section will make that more clear.

--
-- Note however that if we performed an era transition (ie @ixSt < ixTickedSt@),
-- it must have already been known via 'singleEraTransition' for @st@; or more
-- concretely, @'mostRecentTransitionInfo' cfg st@ must have already returned
-- 'TransitionKnown'. This is a reflection of the fact that ticking alone
-- currently can't make a transition become known. Also see
-- <https://github.com/input-output-hk/ouroboros-consensus/issues/413> for
-- future work to reconsider this fact.
instance CanHardFork xs => IsLedger (LedgerState (HardForkBlock xs)) where
type LedgerErr (LedgerState (HardForkBlock xs)) = HardForkLedgerError xs

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,25 @@ import Ouroboros.Consensus.TypeFamilyWrappers
-------------------------------------------------------------------------------}

data EraTranslation xs = EraTranslation {
-- | For each pair @(x, y)@ of subsequent eras, describe how to construct
-- the initial ledger state for @y@ from the ledger state resulting from the last block in @x@.
--
-- When ticking across an era boundary, the HFC will first invoke this and
-- then tick the resulting ledger state (in @y@) to the requested slot.
--
-- The resulting ledger state must summarize every relevant aspect of what
-- came before the new era. This is intentionally vague; for example,
-- ticking in @y@ might work rather differently than in @x@, and so certain
-- aspects of the ticking logic of @x@ might need to happen as part of
-- 'translateLedgerState'. For a concrete example in Cardano, see
-- 'translateLedgerStateBabbageToConwayWrapper'.
translateLedgerState :: InPairs (RequiringBoth WrapLedgerConfig (Translate LedgerState)) xs
-- | For each pair @(x, y)@ of subsequent eras, describe how to construct
-- the initial chain-dependent state for @y@ from the chain-dep state after the last header
-- in @x@.
--
-- When ticking across an era boundary, the HFC will first invoke this and
-- then tick the resulting chain-dep state (in @y@) to the requested slot.
, translateChainDepState :: InPairs (RequiringBoth WrapConsensusConfig (Translate WrapChainDepState)) xs
, crossEraForecast :: InPairs (RequiringBoth WrapLedgerConfig (CrossEraForecaster LedgerState WrapLedgerView)) xs
}
Expand Down
7 changes: 5 additions & 2 deletions sop-extras/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Revision history for sop-extras
# sop-extras Changelog

## 0.1.0.0 -- YYYY-mm-dd
# Changelog entries

<a id='changelog-0.1.0.0'></a>
## 0.1.0.0 — 2023-09-07

* First version. Released on an unsuspecting world.
3 changes: 3 additions & 0 deletions sop-extras/changelog.d/20231012_142650_alexander.esgen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Non-Breaking

- Add `Ord (EraIndex xs)` instance
13 changes: 13 additions & 0 deletions sop-extras/changelog.d/scriv.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[scriv]
format = md
insert_marker = Changelog entries
md_header_level = 2
version = literal: sop-extras.cabal: version
categories = Patch, Non-Breaking, Breaking
end_marker = scriv-end-here
fragment_directory = changelog.d
ghrel_template = {{body}}
main_branches = master, main, develop
new_fragment_template = file: new_fragment.${config:format}.j2
output_file = CHANGELOG.${config:format}
skip_fragments = README.*
7 changes: 5 additions & 2 deletions strict-sop-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Revision history for strict-sop-core
# strict-sop-core Changelog

## 0.1.0.0 -- YYYY-mm-dd
# Changelog entries

<a id='changelog-0.1.0.0'></a>
## 0.1.0.0 — 2023-09-07

* First version. Released on an unsuspecting world.
13 changes: 13 additions & 0 deletions strict-sop-core/changelog.d/scriv.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[scriv]
format = md
insert_marker = Changelog entries
md_header_level = 2
version = literal: strict-sop-core.cabal: version
categories = Patch, Non-Breaking, Breaking
end_marker = scriv-end-here
fragment_directory = changelog.d
ghrel_template = {{body}}
main_branches = master, main, develop
new_fragment_template = file: new_fragment.${config:format}.j2
output_file = CHANGELOG.${config:format}
skip_fragments = README.*