diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Protocol.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Protocol.hs index 08ce27780f6..03d2b63be6c 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Protocol.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Protocol.hs @@ -59,18 +59,14 @@ import Shelley.Spec.Ledger.Keys (GenDelegs) import Shelley.Spec.Ledger.LedgerState ( EpochState (..), NewEpochState (..), - getGKeys, _delegationState, _dstate, _genDelegs, ) import Shelley.Spec.Ledger.OCert (OCertSignable) -import Shelley.Spec.Ledger.OverlaySchedule - ( OverlaySchedule, - ) -import Shelley.Spec.Ledger.PParams (PParams) +import Shelley.Spec.Ledger.PParams (PParams, PParams' (..)) import qualified Shelley.Spec.Ledger.STS.Prtcl as STS.Prtcl -import Shelley.Spec.Ledger.STS.Tick (TICK, TickEnv (..)) +import Shelley.Spec.Ledger.STS.Tick (TICK) import qualified Shelley.Spec.Ledger.STS.Tickn as STS.Tickn import Shelley.Spec.Ledger.Serialization (decodeRecordNamed) import Shelley.Spec.Ledger.Slot (SlotNo) @@ -78,7 +74,6 @@ import Shelley.Spec.Ledger.Slot (SlotNo) -- | Data required by the Transitional Praos protocol from the Shelley ledger. data LedgerView era = LedgerView { lvProtParams :: PParams era, - lvOverlaySched :: OverlaySchedule era, lvPoolDistr :: PoolDistr era, lvGenDelegs :: GenDelegs era } @@ -90,26 +85,23 @@ instance Era era => FromCBOR (LedgerView era) where fromCBOR = decodeRecordNamed "LedgerView" - (const 4) + (const 3) ( LedgerView <$> fromCBOR <*> fromCBOR <*> fromCBOR - <*> fromCBOR ) instance Era era => ToCBOR (LedgerView era) where toCBOR LedgerView { lvProtParams, - lvOverlaySched, lvPoolDistr, lvGenDelegs } = mconcat - [ encodeListLen 4, + [ encodeListLen 3, toCBOR lvProtParams, - toCBOR lvOverlaySched, toCBOR lvPoolDistr, toCBOR lvGenDelegs ] @@ -124,12 +116,12 @@ mkPrtclEnv :: STS.Prtcl.PrtclEnv era mkPrtclEnv LedgerView - { lvOverlaySched, + { lvProtParams, lvPoolDistr, lvGenDelegs } = STS.Prtcl.PrtclEnv - lvOverlaySched + (_d lvProtParams) lvPoolDistr lvGenDelegs @@ -137,13 +129,10 @@ view :: ShelleyState era -> LedgerView era view NewEpochState { nesPd, - nesOsched, nesEs } = LedgerView { lvProtParams = esPp nesEs, - lvOverlaySched = - nesOsched, lvPoolDistr = nesPd, lvGenDelegs = _genDelegs . _dstate @@ -210,10 +199,7 @@ futureLedgerView globals ss slot = res = flip runReader globals . applySTS @(TICK era) - $ TRC (tickEnv, ss, slot) - tickEnv = - TickEnv - (getGKeys ss) + $ TRC ((), ss, slot) -- $chainstate -- diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Types.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Types.hs index 8e30072fb22..be58b38c550 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Types.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Types.hs @@ -64,7 +64,6 @@ import Shelley.Spec.Ledger.LedgerState as X EpochState (..), KeyPairs, LedgerState (..), - NewEpochEnv (..), NewEpochState (..), PState (..), RewardUpdate (..), @@ -95,7 +94,7 @@ import Shelley.Spec.Ledger.STS.Ocert as X (OCertEnv (..)) import Shelley.Spec.Ledger.STS.Pool as X (POOL, PoolEnv (..)) import Shelley.Spec.Ledger.STS.PoolReap as X (POOLREAP) import Shelley.Spec.Ledger.STS.Ppup as X (PPUP, PPUPEnv (..)) -import Shelley.Spec.Ledger.STS.Tick as X (TICK, TickEnv (..)) +import Shelley.Spec.Ledger.STS.Tick as X (TICK) import Shelley.Spec.Ledger.STS.Utxo as X (UTXO, UtxoEnv (..)) import Shelley.Spec.Ledger.STS.Utxow as X (UTXOW) import Shelley.Spec.Ledger.Scripts as X diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Validation.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Validation.hs index a03c343493c..cfe225d68b0 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Validation.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Validation.hs @@ -54,22 +54,15 @@ chainChecks globals pp bh = STS.chainChecks (maxMajorPV globals) pp bh Applying blocks -------------------------------------------------------------------------------} -mkTickEnv :: - ShelleyState era -> - STS.TickEnv era -mkTickEnv = STS.TickEnv . LedgerState.getGKeys - mkBbodyEnv :: ShelleyState era -> STS.BbodyEnv era mkBbodyEnv LedgerState.NewEpochState - { LedgerState.nesOsched, - LedgerState.nesEs + { LedgerState.nesEs } = STS.BbodyEnv - { STS.bbodySlots = nesOsched, - STS.bbodyPp = LedgerState.esPp nesEs, + { STS.bbodyPp = LedgerState.esPp nesEs, STS.bbodyAccount = LedgerState.esAccountState nesEs } @@ -93,7 +86,7 @@ applyTickTransition :: applyTickTransition globals state hdr = (either err id) . flip runReader globals . applySTS @(STS.TICK era) - $ TRC (mkTickEnv state, state, hdr) + $ TRC ((), state, hdr) where err :: Show a => a -> b err msg = error $ "Panic! applyHeaderTransition failed: " <> (show msg) diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Wallet.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Wallet.hs index 0f844f4e30f..86eeb778e51 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Wallet.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/API/Wallet.hs @@ -44,6 +44,7 @@ import Shelley.Spec.Ledger.LedgerState stakeDistr, ) import Shelley.Spec.Ledger.OverlaySchedule (isOverlaySlot) +import Shelley.Spec.Ledger.PParams (PParams, PParams' (..)) import Shelley.Spec.Ledger.Rewards ( NonMyopic (..), StakeShare (..), @@ -153,20 +154,19 @@ getLeaderSchedule :: ChainDepState era -> KeyHash 'StakePool era -> SignKeyVRF era -> + PParams era -> Set SlotNo -getLeaderSchedule globals ss cds poolHash key = Set.filter isLeader epochSlots +getLeaderSchedule globals ss cds poolHash key pp = Set.filter isLeader epochSlots where isLeader slotNo = let y = VRF.evalCertified () (mkSeed seedL slotNo epochNonce) key - in not (isOverlaySlot slotNo overlaySched) + in not (isOverlaySlot a (_d pp) slotNo) && checkLeaderValue (VRF.certifiedOutput y) stake f stake = maybe 0 individualPoolStake $ Map.lookup poolHash poolDistr - overlaySched = nesOsched ss poolDistr = unPoolDistr $ nesPd ss TicknState epochNonce _ = csTickn cds currentEpoch = nesEL ss ei = epochInfo globals f = activeSlotCoeff globals epochSlots = Set.fromList [a .. b] - where - (a, b) = runIdentity $ epochInfoRange ei currentEpoch + (a, b) = runIdentity $ epochInfoRange ei currentEpoch diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/ByronTranslation.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/ByronTranslation.hs index 0ee34210bf0..92f1e5be37f 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/ByronTranslation.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/ByronTranslation.hs @@ -21,18 +21,15 @@ import qualified Cardano.Crypto.Hashing as Hashing import Cardano.Ledger.Crypto (ADDRHASH) import Cardano.Ledger.Era import qualified Cardano.Ledger.Val as Val -import Control.Monad.Reader (runReader) import qualified Data.ByteString.Short as SBS import qualified Data.Map.Strict as Map import Data.Maybe (fromMaybe) import GHC.Stack (HasCallStack) import Shelley.Spec.Ledger.API -import Shelley.Spec.Ledger.BaseTypes import Shelley.Spec.Ledger.Coin (word64ToCoin) import Shelley.Spec.Ledger.EpochBoundary import Shelley.Spec.Ledger.Genesis import Shelley.Spec.Ledger.LedgerState -import Shelley.Spec.Ledger.OverlaySchedule import Shelley.Spec.Ledger.Rewards import Shelley.Spec.Ledger.Slot import Shelley.Spec.Ledger.UTxO @@ -91,19 +88,17 @@ translateToShelleyLedgerState :: forall era. (Era era, ADDRHASH (Crypto era) ~ Crypto.Blake2b_224) => ShelleyGenesis era -> - Globals -> EpochNo -> Byron.ChainValidationState -> ShelleyState era -translateToShelleyLedgerState genesisShelley globals epochNo cvs = +translateToShelleyLedgerState genesisShelley epochNo cvs = NewEpochState { nesEL = epochNo, nesBprev = BlocksMade Map.empty, nesBcur = BlocksMade Map.empty, nesEs = epochState, nesRu = SNothing, - nesPd = PoolDistr Map.empty, - nesOsched = oSchedule + nesPd = PoolDistr Map.empty } where pparams :: PParams era @@ -159,34 +154,16 @@ translateToShelleyLedgerState genesisShelley globals epochNo cvs = _pstate = emptyPState } } - oSchedule :: OverlaySchedule era - oSchedule = - flip runReader globals $ - overlaySchedule - epochNo - (Map.keysSet (sgGenDelegs genesisShelley)) - pparams -- | We construct a 'LedgerView' using the Shelley genesis config in the same -- way as 'translateToShelleyLedgerState'. mkInitialShelleyLedgerView :: forall era. ShelleyGenesis era -> - Globals -> - EpochNo -> LedgerView era -mkInitialShelleyLedgerView genesisShelley globals epochNo = +mkInitialShelleyLedgerView genesisShelley = LedgerView { lvProtParams = sgProtocolParams genesisShelley, - lvOverlaySched = oSchedule, lvPoolDistr = PoolDistr Map.empty, lvGenDelegs = GenDelegs $ sgGenDelegs genesisShelley } - where - oSchedule :: OverlaySchedule era - oSchedule = - flip runReader globals $ - overlaySchedule - epochNo - (Map.keysSet (sgGenDelegs genesisShelley)) - (sgProtocolParams genesisShelley) diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/LedgerState.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/LedgerState.hs index 972152d6ce2..4e8d955ae99 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/LedgerState.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/LedgerState.hs @@ -83,7 +83,6 @@ module Shelley.Spec.Ledger.LedgerState createRUpd, -- NewEpochState (..), - NewEpochEnv (..), getGKeys, updateNES, ) @@ -154,7 +153,6 @@ import Shelley.Spec.Ledger.Keys VKey, asWitness, ) -import Shelley.Spec.Ledger.OverlaySchedule import Shelley.Spec.Ledger.PParams ( PParams, PParams' (..), @@ -545,9 +543,7 @@ data NewEpochState era = NewEpochState -- | Possible reward update nesRu :: !(StrictMaybe (RewardUpdate era)), -- | Stake distribution within the stake pool - nesPd :: !(PoolDistr era), - -- | Overlay schedule for PBFT vs Praos - nesOsched :: !(OverlaySchedule era) + nesPd :: !(PoolDistr era) } deriving (Show, Eq, Generic) @@ -556,41 +552,31 @@ instance (Era era) => NFData (NewEpochState era) instance NoUnexpectedThunks (NewEpochState era) instance Era era => ToCBOR (NewEpochState era) where - toCBOR (NewEpochState e bp bc es ru pd os) = - encodeListLen 7 <> toCBOR e <> toCBOR bp <> toCBOR bc <> toCBOR es + toCBOR (NewEpochState e bp bc es ru pd) = + encodeListLen 6 <> toCBOR e <> toCBOR bp <> toCBOR bc <> toCBOR es <> toCBOR ru <> toCBOR pd - <> toCBOR os instance Era era => FromCBOR (NewEpochState era) where fromCBOR = do - decodeRecordNamed "NewEpochState" (const 7) $ do + decodeRecordNamed "NewEpochState" (const 6) $ do e <- fromCBOR bp <- fromCBOR bc <- fromCBOR es <- fromCBOR ru <- fromCBOR pd <- fromCBOR - os <- fromCBOR - pure $ NewEpochState e bp bc es ru pd os + pure $ NewEpochState e bp bc es ru pd getGKeys :: NewEpochState era -> Set (KeyHash 'Genesis era) getGKeys nes = Map.keysSet genDelegs where - NewEpochState _ _ _ es _ _ _ = nes + NewEpochState _ _ _ es _ _ = nes EpochState _ _ ls _ _ _ = es LedgerState _ (DPState (DState _ _ _ _ (GenDelegs genDelegs) _) _) = ls -data NewEpochEnv era = NewEpochEnv - { neeS :: SlotNo, - neeGkeys :: Set (KeyHash 'Genesis era) - } - deriving (Show, Eq, Generic) - -instance NoUnexpectedThunks (NewEpochEnv era) - -- | The state associated with a 'Ledger'. data LedgerState era = LedgerState { -- | The current unspent transaction outputs. @@ -965,8 +951,7 @@ updateNES (EpochState acnt ss _ pr pp nm) ru pd - osched ) bcur ls = - NewEpochState eL bprev bcur (EpochState acnt ss ls pr pp nm) ru pd osched + NewEpochState eL bprev bcur (EpochState acnt ss ls pr pp nm) ru pd diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/OverlaySchedule.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/OverlaySchedule.hs index d7b33e27475..0f1741242e2 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/OverlaySchedule.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/OverlaySchedule.hs @@ -6,19 +6,15 @@ module Shelley.Spec.Ledger.OverlaySchedule ( -- * Overlay schedule - OverlaySchedule, - compactOverlaySchedule, - decompactOverlaySchedule, - emptyOverlaySchedule, isOverlaySlot, + classifyOverlaySlot, lookupInOverlaySchedule, - overlaySchedule, - overlayScheduleHelper, - overlayScheduleIsEmpty, - overlayScheduleToMap, -- * OBftSlot OBftSlot (..), + + -- * Testing + overlaySlots, ) where @@ -33,20 +29,12 @@ import Cardano.Binary import Cardano.Ledger.Era (Era) import Cardano.Prelude (NFData, NoUnexpectedThunks) import Cardano.Slotting.Slot -import Control.Monad.Trans.Reader (asks) -import Data.List.NonEmpty (NonEmpty) -import qualified Data.List.NonEmpty as NonEmpty -import Data.Map.Strict (Map) -import qualified Data.Map.Strict as Map -import Data.Set (Set) -import qualified Data.Set as Set import GHC.Generics (Generic) import Shelley.Spec.Ledger.BaseTypes import Shelley.Spec.Ledger.Keys ( KeyHash (..), KeyRole (..), ) -import Shelley.Spec.Ledger.PParams (PParams, _d) import Shelley.Spec.Ledger.Slot data OBftSlot era @@ -76,109 +64,62 @@ instance NoUnexpectedThunks (OBftSlot era) instance NFData (OBftSlot era) -newtype OverlaySchedule era = OverlaySchedule (Map SlotNo (OBftSlot era)) - deriving stock (Show, Eq) - deriving newtype (NoUnexpectedThunks, NFData) - -emptyOverlaySchedule :: OverlaySchedule era -emptyOverlaySchedule = OverlaySchedule Map.empty +isOverlaySlot :: + SlotNo -> -- starting slot + UnitInterval -> -- decentralization parameter + SlotNo -> -- slot to check + Bool +isOverlaySlot firstSlotNo dval slot = step s < step (s + 1) + where + s = fromIntegral $ slot -* firstSlotNo + d = unitIntervalToRational dval + step :: Rational -> Integer + step x = ceiling (x * d) + +classifyOverlaySlot :: + SlotNo -> -- first slot of the epoch + [KeyHash 'Genesis era] -> -- genesis Nodes + UnitInterval -> -- decentralization parameter + ActiveSlotCoeff -> -- active slot coefficent + SlotNo -> -- overlay slot to classify + OBftSlot era +classifyOverlaySlot firstSlotNo gkeys dval ascValue slot = + if isActive + then + let genesisIdx = (position `div` ascInv) `mod` (fromIntegral $ length gkeys) + in gkeys `getAtIndex` genesisIdx + else NonActiveSlot + where + d = unitIntervalToRational dval + position = ceiling (fromIntegral (slot -* firstSlotNo) * d) + isActive = position `mod` ascInv == 0 + getAtIndex ls i = if i < length ls then ActiveSlot (ls !! i) else NonActiveSlot + ascInv = floor (1 / (unitIntervalToRational . activeSlotVal $ ascValue)) lookupInOverlaySchedule :: - SlotNo -> - OverlaySchedule era -> + SlotNo -> -- first slot of the epoch + [KeyHash 'Genesis era] -> -- genesis Nodes + UnitInterval -> -- decentralization parameter + ActiveSlotCoeff -> -- active slot coefficent + SlotNo -> -- slot to lookup Maybe (OBftSlot era) -lookupInOverlaySchedule slot (OverlaySchedule oSched) = Map.lookup slot oSched - -overlayScheduleIsEmpty :: OverlaySchedule era -> Bool -overlayScheduleIsEmpty (OverlaySchedule oSched) = Map.null oSched - --- | Overlay schedule --- This is just a very simple round-robin, evenly spaced schedule. -overlaySchedule :: - EpochNo -> - Set (KeyHash 'Genesis era) -> - PParams era -> - ShelleyBase (OverlaySchedule era) -overlaySchedule e gkeys pp = do - ei <- asks epochInfo - slotsPerEpoch <- epochInfoSize ei e - firstSlotNo <- epochInfoFirst ei e - asc <- asks activeSlotCoeff - pure $ overlayScheduleHelper slotsPerEpoch firstSlotNo gkeys (_d pp) asc - -overlayScheduleHelper :: +lookupInOverlaySchedule firstSlotNo gkeys dval ascValue slot = + if isOverlaySlot firstSlotNo dval slot + then Just $ classifyOverlaySlot firstSlotNo gkeys dval ascValue slot + else Nothing + +-- | Return the list of overlaySlots for a given epoch. +-- Note that this linear in the size of the epoch, and should probably +-- only be used for testing. +-- If something more performant is needed, we could probably use +-- [start + floor(x/d) | x <- [0 .. (spe -1)], floor(x/d) < spe] +-- but we would need to make sure that this is equivalent. +overlaySlots :: + SlotNo -> -- starting slot + UnitInterval -> -- decentralization parameter EpochSize -> - -- | First slot of the epoch - SlotNo -> - Set (KeyHash 'Genesis era) -> - -- | Decentralization parameter @d@ - UnitInterval -> - ActiveSlotCoeff -> - OverlaySchedule era -overlayScheduleHelper slotsPerEpoch firstSlotNo gkeys d asc - | dval == 0 = - OverlaySchedule $ Map.empty - | otherwise = - OverlaySchedule $ Map.union active inactive + [SlotNo] +overlaySlots start d (EpochSize spe) = + [SlotNo x | x <- [unSlotNo start .. end], isOverlaySlot start d (SlotNo x)] where - dval = intervalValue d - numActive = dval * fromIntegral slotsPerEpoch - dInv = 1 / dval - ascValue = (intervalValue . activeSlotVal) asc - toRelativeSlotNo x = (Duration . floor) (dInv * fromInteger x) - toSlotNo x = firstSlotNo +* toRelativeSlotNo x - genesisSlots = [toSlotNo x | x <- [0 .. (floor numActive - 1)]] - numInactivePerActive = floor (1 / ascValue) - 1 - activitySchedule = cycle (True : replicate numInactivePerActive False) - unassignedSched = zip activitySchedule genesisSlots - genesisCycle = if Set.null gkeys then [] else cycle (Set.toList gkeys) - active = - Map.fromList $ - fmap - (\(gk, (_, s)) -> (s, ActiveSlot gk)) - (zip genesisCycle (filter fst unassignedSched)) - inactive = - Map.fromList $ - fmap - (\x -> (snd x, NonActiveSlot)) - (filter (not . fst) unassignedSched) - -overlayScheduleToMap :: OverlaySchedule era -> Map SlotNo (OBftSlot era) -overlayScheduleToMap (OverlaySchedule oSched) = oSched - --- | Convert the overlay schedule to a representation that is more compact --- when serialised to a bytestring, but less efficient for lookups. --- --- Each genesis key hash will only be stored once, instead of each time it is --- assigned to a slot. -compactOverlaySchedule :: - OverlaySchedule era -> - Map (OBftSlot era) (NonEmpty SlotNo) -compactOverlaySchedule (OverlaySchedule oSched) = - Map.foldrWithKey' - ( \slot obftSlot -> - Map.insertWith (<>) obftSlot (pure slot) - ) - Map.empty - oSched - --- | Inverse of 'compactOverlaySchedule' -decompactOverlaySchedule :: - Map (OBftSlot era) (NonEmpty SlotNo) -> - OverlaySchedule era -decompactOverlaySchedule compact = - OverlaySchedule $ - Map.fromList - [ (slot, obftSlot) - | (obftSlot, slots) <- Map.toList compact, - slot <- NonEmpty.toList slots - ] - -instance Era era => ToCBOR (OverlaySchedule era) where - toCBOR = toCBOR . compactOverlaySchedule - -instance Era era => FromCBOR (OverlaySchedule era) where - fromCBOR = decompactOverlaySchedule <$> fromCBOR - -isOverlaySlot :: SlotNo -> OverlaySchedule c -> Bool -isOverlaySlot slot (OverlaySchedule oslots) = Map.member slot oslots + end = unSlotNo start + spe - 1 diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Bbody.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Bbody.hs index 6b6f5d9c4d6..2330efd9f18 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Bbody.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Bbody.hs @@ -20,18 +20,20 @@ where import Cardano.Ledger.Era (Era) import Cardano.Prelude (NoUnexpectedThunks (..)) +import Control.Monad.Trans.Reader (asks) import Control.State.Transition ( Embed (..), STS (..), TRC (..), TransitionRule, judgmentContext, + liftSTS, trans, (?!), ) import qualified Data.Sequence.Strict as StrictSeq import GHC.Generics (Generic) -import Shelley.Spec.Ledger.BaseTypes (ShelleyBase) +import Shelley.Spec.Ledger.BaseTypes (ShelleyBase, epochInfo) import Shelley.Spec.Ledger.BlockChain ( BHBody (..), BHeader (..), @@ -50,12 +52,10 @@ import Shelley.Spec.Ledger.LedgerState ( AccountState, LedgerState, ) -import Shelley.Spec.Ledger.OverlaySchedule - ( OverlaySchedule, - isOverlaySlot, - ) -import Shelley.Spec.Ledger.PParams (PParams) +import Shelley.Spec.Ledger.OverlaySchedule (isOverlaySlot) +import Shelley.Spec.Ledger.PParams (PParams, PParams' (..)) import Shelley.Spec.Ledger.STS.Ledgers (LEDGERS, LedgersEnv (..)) +import Shelley.Spec.Ledger.Slot (epochInfoEpoch, epochInfoFirst) import Shelley.Spec.Ledger.Tx (TxBody) data BBODY era @@ -65,8 +65,7 @@ data BbodyState era deriving (Eq, Show) data BbodyEnv era = BbodyEnv - { bbodySlots :: OverlaySchedule era, - bbodyPp :: PParams era, + { bbodyPp :: PParams era, bbodyAccount :: AccountState } @@ -114,7 +113,7 @@ bbodyTransition :: bbodyTransition = judgmentContext >>= \( TRC - ( BbodyEnv oslots pp account, + ( BbodyEnv pp account, BbodyState ls b, Block (BHeader bhb _) txsSeq ) @@ -136,7 +135,19 @@ bbodyTransition = -- delegate. However, this would only entail an overhead of 7 counts, and it's -- easier than differentiating here. let hkAsStakePool = coerceKeyRole . poolIDfromBHBody $ bhb - pure $ BbodyState ls' (incrBlocks (isOverlaySlot (bheaderSlotNo bhb) oslots) hkAsStakePool b) + slot = bheaderSlotNo bhb + firstSlotNo <- liftSTS $ do + ei <- asks epochInfo + e <- epochInfoEpoch ei slot + epochInfoFirst ei e + pure $ + BbodyState + ls' + ( incrBlocks + (isOverlaySlot firstSlotNo (_d pp) slot) + hkAsStakePool + b + ) instance ( Era era, diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Chain.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Chain.hs index bfe68f33bec..d942bf4e88f 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Chain.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Chain.hs @@ -95,18 +95,14 @@ import Shelley.Spec.Ledger.LedgerState emptyDState, emptyPPUPState, emptyPState, - getGKeys, updateNES, _genDelegs, ) import Shelley.Spec.Ledger.OCert (OCertSignable) -import Shelley.Spec.Ledger.OverlaySchedule import Shelley.Spec.Ledger.PParams ( PParams, + PParams' (..), ProtVer (..), - _maxBBSize, - _maxBHSize, - _protocolVersion, ) import Shelley.Spec.Ledger.Rewards (emptyNonMyopic) import Shelley.Spec.Ledger.STS.Bbody (BBODY, BbodyEnv (..), BbodyState (..)) @@ -117,7 +113,7 @@ import Shelley.Spec.Ledger.STS.Prtcl PrtlSeqFailure, prtlSeqChecks, ) -import Shelley.Spec.Ledger.STS.Tick (TICK, TickEnv (..)) +import Shelley.Spec.Ledger.STS.Tick (TICK) import Shelley.Spec.Ledger.STS.Tickn import Shelley.Spec.Ledger.Slot (EpochNo) import Shelley.Spec.Ledger.Tx (TxBody) @@ -162,11 +158,10 @@ initialShelleyState :: UTxO era -> Coin -> Map (KeyHash 'Genesis era) (GenDelegPair era) -> - OverlaySchedule era -> PParams era -> Nonce -> ChainState era -initialShelleyState lab e utxo reserves genDelegs os pp initNonce = +initialShelleyState lab e utxo reserves genDelegs pp initNonce = ChainState ( NewEpochState e @@ -190,7 +185,6 @@ initialShelleyState lab e utxo reserves genDelegs os pp initNonce = ) SNothing (PoolDistr Map.empty) - os ) cs initNonce @@ -261,7 +255,7 @@ chainTransition = Right () -> pure () Left e -> failBecause $ PrtclSeqFailure e - let NewEpochState _ _ _ (EpochState _ _ _ _ pp _) _ _ _ = nes + let NewEpochState _ _ _ (EpochState _ _ _ _ pp _) _ _ = nes maxpv <- liftSTS $ asks maxMajorPV case chainChecks maxpv pp bh of @@ -269,13 +263,12 @@ chainTransition = Left e -> failBecause e let s = bheaderSlotNo $ bhbody bh - let gkeys = getGKeys nes nes' <- - trans @(TICK era) $ TRC (TickEnv gkeys, nes, s) + trans @(TICK era) $ TRC ((), nes, s) - let NewEpochState e1 _ _ _ _ _ _ = nes - NewEpochState e2 _ bcur es _ _pd osched = nes' + let NewEpochState e1 _ _ _ _ _ = nes + NewEpochState e2 _ bcur es _ _pd = nes' let EpochState account _ ls _ pp' _ = es let LedgerState _ (DPState (DState _ _ _ _ _genDelegs _) (PState _ _ _)) = ls @@ -293,14 +286,14 @@ chainTransition = PrtclState cs' etaV' etaC' <- trans @(PRTCL era) $ TRC - ( PrtclEnv osched _pd _genDelegs eta0', + ( PrtclEnv (_d pp') _pd _genDelegs eta0', PrtclState cs etaV etaC, bh ) BbodyState ls' bcur' <- trans @(BBODY era) $ - TRC (BbodyEnv osched pp' account, BbodyState ls bcur, block) + TRC (BbodyEnv pp' account, BbodyState ls bcur, block) let nes'' = updateNES nes' bcur' ls' bhb = bhbody bh diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/NewEpoch.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/NewEpoch.hs index a826709c754..d94b28414b0 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/NewEpoch.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/NewEpoch.hs @@ -28,7 +28,6 @@ import Shelley.Spec.Ledger.Coin import Shelley.Spec.Ledger.Delegation.Certificates import Shelley.Spec.Ledger.EpochBoundary import Shelley.Spec.Ledger.LedgerState -import Shelley.Spec.Ledger.OverlaySchedule import Shelley.Spec.Ledger.STS.Epoch import Shelley.Spec.Ledger.STS.Mir import Shelley.Spec.Ledger.Slot @@ -53,7 +52,7 @@ instance type Signal (NEWEPOCH era) = EpochNo - type Environment (NEWEPOCH era) = NewEpochEnv era + type Environment (NEWEPOCH era) = () type BaseM (NEWEPOCH era) = ShelleyBase type PredicateFailure (NEWEPOCH era) = NewEpochPredicateFailure era @@ -67,7 +66,6 @@ instance emptyEpochState SNothing (PoolDistr Map.empty) - emptyOverlaySchedule ] transitionRules = [newEpochTransition] @@ -78,8 +76,8 @@ newEpochTransition :: TransitionRule (NEWEPOCH era) newEpochTransition = do TRC - ( NewEpochEnv _s gkeys, - src@(NewEpochState (EpochNo eL) _ bcur es ru _pd _osched), + ( _, + src@(NewEpochState (EpochNo eL) _ bcur es ru _pd), e@(EpochNo e_) ) <- judgmentContext @@ -95,9 +93,8 @@ newEpochTransition = do es'' <- trans @(MIR era) $ TRC ((), es', ()) es''' <- trans @(EPOCH era) $ TRC ((), es'', e) - let EpochState _acnt ss _ls _pr pp _ = es''' + let EpochState _acnt ss _ls _pr _ _ = es''' pd' = calculatePoolDistr (_pstakeSet ss) - osched' <- liftSTS $ overlaySchedule e gkeys pp pure $ NewEpochState e @@ -106,7 +103,6 @@ newEpochTransition = do es''' SNothing pd' - osched' calculatePoolDistr :: SnapShot era -> PoolDistr era calculatePoolDistr (SnapShot (Stake stake) delegs poolParams) = diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Overlay.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Overlay.hs index 29cd209d419..ce74a10993c 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Overlay.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Overlay.hs @@ -24,10 +24,10 @@ import Cardano.Ledger.Era import Cardano.Prelude ( MonadError (..), NoUnexpectedThunks (..), - asks, unless, ) import Control.Iterate.SetAlgebra (dom, eval, range) +import Control.Monad.Trans.Reader (asks) import Control.State.Transition import Data.Coerce (coerce) import Data.Map.Strict (Map) @@ -40,7 +40,9 @@ import Shelley.Spec.Ledger.BaseTypes Nonce, Seed, ShelleyBase, + UnitInterval, activeSlotCoeff, + epochInfo, ) import Shelley.Spec.Ledger.BlockChain ( BHBody (..), @@ -71,17 +73,16 @@ import Shelley.Spec.Ledger.Keys import Shelley.Spec.Ledger.OCert (OCertSignable) import Shelley.Spec.Ledger.OverlaySchedule ( OBftSlot (..), - OverlaySchedule, lookupInOverlaySchedule, ) import Shelley.Spec.Ledger.STS.Ocert (OCERT, OCertEnv (..)) -import Shelley.Spec.Ledger.Slot (SlotNo) +import Shelley.Spec.Ledger.Slot (SlotNo, epochInfoEpoch, epochInfoFirst) data OVERLAY era data OverlayEnv era = OverlayEnv - (OverlaySchedule era) + UnitInterval -- the decentralization paramater @d@ from the protocal parameters (PoolDistr era) (GenDelegs era) Nonce @@ -245,17 +246,22 @@ overlayTransition :: overlayTransition = judgmentContext >>= \( TRC - ( OverlayEnv osched pd (GenDelegs genDelegs) eta0, + ( OverlayEnv dval pd (GenDelegs genDelegs) eta0, cs, bh@(BHeader bhb _) ) ) -> do let vk = bheaderVk bhb vkh = hashKey vk + slot = bheaderSlotNo bhb asc <- liftSTS $ asks activeSlotCoeff + firstSlotNo <- liftSTS $ do + ei <- asks epochInfo + e <- epochInfoEpoch ei slot + epochInfoFirst ei e - case lookupInOverlaySchedule (bheaderSlotNo bhb) osched of + case lookupInOverlaySchedule firstSlotNo (Map.keys genDelegs) dval asc slot of Nothing -> praosVrfChecks eta0 pd asc bhb ?!: id Just NonActiveSlot -> diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Prtcl.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Prtcl.hs index da64a0633c2..ab717cb4fdf 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Prtcl.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Prtcl.hs @@ -41,6 +41,7 @@ import Shelley.Spec.Ledger.BaseTypes ( Nonce, Seed, ShelleyBase, + UnitInterval, ) import Shelley.Spec.Ledger.BlockChain ( BHBody (..), @@ -61,7 +62,6 @@ import Shelley.Spec.Ledger.Keys VRFSignable, ) import Shelley.Spec.Ledger.OCert (OCertSignable) -import Shelley.Spec.Ledger.OverlaySchedule (OverlaySchedule) import Shelley.Spec.Ledger.STS.Overlay (OVERLAY, OverlayEnv (..)) import Shelley.Spec.Ledger.STS.Updn (UPDN, UpdnEnv (..), UpdnState (..)) import Shelley.Spec.Ledger.Serialization (decodeRecordNamed) @@ -103,7 +103,7 @@ instance Era era => NoUnexpectedThunks (PrtclState era) data PrtclEnv era = PrtclEnv - (OverlaySchedule era) + UnitInterval -- the decentralization paramater @d@ from the protocal parameters (PoolDistr era) (GenDelegs era) Nonce @@ -161,7 +161,7 @@ prtclTransition :: TransitionRule (PRTCL era) prtclTransition = do TRC - ( PrtclEnv osched pd dms eta0, + ( PrtclEnv dval pd dms eta0, PrtclState cs etaV etaC, bh ) <- @@ -179,7 +179,7 @@ prtclTransition = do ) cs' <- trans @(OVERLAY era) $ - TRC (OverlayEnv osched pd dms eta0, cs, bh) + TRC (OverlayEnv dval pd dms eta0, cs, bh) pure $ PrtclState diff --git a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Tick.hs b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Tick.hs index 259ead0fff6..85a7930002a 100644 --- a/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Tick.hs +++ b/shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/STS/Tick.hs @@ -9,7 +9,6 @@ module Shelley.Spec.Ledger.STS.Tick ( TICK, - TickEnv (..), State, TickPredicateFailure (..), PredicateFailure, @@ -22,17 +21,15 @@ import Control.Iterate.SetAlgebra (eval, (⨃)) import Control.Monad.Trans.Reader (asks) import Control.State.Transition import qualified Data.Map.Strict as Map -import Data.Set (Set) import GHC.Generics (Generic) import Shelley.Spec.Ledger.BaseTypes (ShelleyBase, epochInfo) -import Shelley.Spec.Ledger.Keys (GenDelegs (..), KeyHash, KeyRole (..)) +import Shelley.Spec.Ledger.Keys (GenDelegs (..)) import Shelley.Spec.Ledger.LedgerState ( DPState (..), DState (..), EpochState (..), FutureGenDeleg (..), LedgerState (..), - NewEpochEnv (..), NewEpochState (..), ) import Shelley.Spec.Ledger.STS.NewEpoch (NEWEPOCH) @@ -41,9 +38,6 @@ import Shelley.Spec.Ledger.Slot (SlotNo, epochInfoEpoch) data TICK era -data TickEnv era - = TickEnv (Set (KeyHash 'Genesis era)) - data TickPredicateFailure era = NewEpochFailure (PredicateFailure (NEWEPOCH era)) -- Subtransition Failures | RupdFailure (PredicateFailure (RUPD era)) -- Subtransition Failures @@ -61,7 +55,7 @@ instance type Signal (TICK era) = SlotNo - type Environment (TICK era) = TickEnv era + type Environment (TICK era) = () type BaseM (TICK era) = ShelleyBase type PredicateFailure (TICK era) = TickPredicateFailure era @@ -102,16 +96,14 @@ bheadTransition :: (Era era) => TransitionRule (TICK era) bheadTransition = do - TRC (TickEnv gkeys, nes@(NewEpochState _ bprev _ es _ _ _), slot) <- + TRC ((), nes@(NewEpochState _ bprev _ es _ _), slot) <- judgmentContext epoch <- liftSTS $ do ei <- asks epochInfo epochInfoEpoch ei slot - nes' <- - trans @(NEWEPOCH era) $ - TRC (NewEpochEnv slot gkeys, nes, epoch) + nes' <- trans @(NEWEPOCH era) $ TRC ((), nes, epoch) ru'' <- trans @(RUPD era) $ TRC (RupdEnv bprev es, nesRu nes', slot) diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/bench/BenchValidation.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/bench/BenchValidation.hs index 4b77a239f02..60f36fde06d 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/bench/BenchValidation.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/bench/BenchValidation.hs @@ -172,7 +172,7 @@ instance Show UpdateInputs where show (UpdateInputs _globals vl bh st) = show vl ++ "\n" ++ show bh ++ "\n" ++ show st instance NFData (LedgerView era) where - rnf (LedgerView _pp _ov _pool _delegs) = () + rnf (LedgerView _pp _pool _delegs) = () instance Era era => NFData (BHeader era) where rnf (BHeader _ _) = () diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/shelley-spec-ledger-test.cabal b/shelley/chain-and-ledger/shelley-spec-ledger-test/shelley-spec-ledger-test.cabal index d436693c26f..719d7eb4d95 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/shelley-spec-ledger-test.cabal +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/shelley-spec-ledger-test.cabal @@ -114,6 +114,7 @@ test-suite shelley-spec-ledger-test Test.Shelley.Spec.Ledger.Examples.PoolReReg Test.Shelley.Spec.Ledger.Examples.Updates Test.Shelley.Spec.Ledger.Fees + Test.Shelley.Spec.Ledger.LegacyOverlay Test.Shelley.Spec.Ledger.MultiSigExamples Test.Shelley.Spec.Ledger.PropertyTests Test.Shelley.Spec.Ledger.Rewards diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Block.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Block.hs index 84b3ee3bd1c..c920cc4f334 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Block.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Block.hs @@ -43,7 +43,7 @@ import Shelley.Spec.Ledger.Keys hashKey, ) import Shelley.Spec.Ledger.OCert (KESPeriod (..), currentIssueNo, kesPeriod) -import Shelley.Spec.Ledger.OverlaySchedule +import Shelley.Spec.Ledger.OverlaySchedule (lookupInOverlaySchedule) import Shelley.Spec.Ledger.STS.Prtcl (PrtclState (..)) import Shelley.Spec.Ledger.STS.Tickn (TicknState (..)) import Shelley.Spec.Ledger.Slot (SlotNo (..)) @@ -89,7 +89,7 @@ genBlock $ selectNextSlotWithLeader ge origChainState firstConsideredSlot -- Now we need to compute the KES period and get the set of hot keys. - let NewEpochState _ _ _ es _ _ _ = chainNes chainSt + let NewEpochState _ _ _ es _ _ = chainNes chainSt EpochState acnt _ ls _ pp _ = es kp@(KESPeriod kesPeriod_) = runShelleyBase $ kesPeriod nextSlot cs = chainOCertIssue chainSt @@ -174,7 +174,7 @@ selectNextSlotWithLeader Maybe (ChainState era, AllIssuerKeys era 'BlockIssuer) selectLeaderForSlot slotNo = (chainSt,) - <$> case lookupInOverlaySchedule slotNo overlaySched of + <$> case lookupInOverlaySchedule firstEpochSlot (Map.keys cores) d f slotNo of Nothing -> coerce <$> List.find @@ -190,16 +190,17 @@ selectNextSlotWithLeader where chainSt = tickChainState slotNo origChainState epochNonce = chainEpochNonce chainSt - overlaySched = nesOsched $ chainNes chainSt poolDistr = unPoolDistr . nesPd . chainNes $ chainSt dpstate = (_delegationState . esLState . nesEs . chainNes) chainSt (GenDelegs cores) = (_genDelegs . _dstate) dpstate + firstEpochSlot = slotFromEpoch (epochFromSlotNo slotNo) + f = activeSlotCoeff testGlobals + d = (_d . esPp . nesEs . chainNes) chainSt isLeader poolHash vrfKey = let y = VRF.evalCertified @(VRF (Crypto era)) () (mkSeed seedL slotNo epochNonce) vrfKey stake = maybe 0 individualPoolStake $ Map.lookup poolHash poolDistr - f = activeSlotCoeff testGlobals - in case lookupInOverlaySchedule slotNo overlaySched of + in case lookupInOverlaySchedule firstEpochSlot (Map.keys cores) d f slotNo of Nothing -> checkLeaderValue (VRF.certifiedOutput y) stake f Just (ActiveSlot x) | coerceKeyRole x == poolHash -> True _ -> False diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Trace/Chain.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Trace/Chain.hs index 7259f548b96..a90a98b7b24 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Trace/Chain.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Generator/Trace/Chain.hs @@ -29,7 +29,7 @@ import Control.State.Transition.Trace.Generator.QuickCheck ) import Data.Functor.Identity (runIdentity) import Data.Map.Strict (Map) -import qualified Data.Map.Strict as Map (elems, fromList, keysSet) +import qualified Data.Map.Strict as Map (elems, fromList) import Data.Proxy import Numeric.Natural (Natural) import Shelley.Spec.Ledger.API @@ -51,7 +51,6 @@ import Shelley.Spec.Ledger.Keys coerceKeyRole, ) import Shelley.Spec.Ledger.LedgerState (esAccountState, nesEs, _treasury) -import Shelley.Spec.Ledger.OverlaySchedule (overlaySchedule) import Shelley.Spec.Ledger.STS.Chain (chainNes, initialShelleyState) import qualified Shelley.Spec.Ledger.STS.Chain as STS (ChainState (ChainState)) import Shelley.Spec.Ledger.Slot (BlockNo (..), EpochNo (..), SlotNo (..)) @@ -67,7 +66,7 @@ import Test.Shelley.Spec.Ledger.Generator.Core (GenEnv (..)) import Test.Shelley.Spec.Ledger.Generator.Presets (genUtxo0, genesisDelegs0) import Test.Shelley.Spec.Ledger.Generator.Update (genPParams) import Test.Shelley.Spec.Ledger.Shrinkers (shrinkBlock) -import Test.Shelley.Spec.Ledger.Utils (maxLLSupply, mkHash, runShelleyBase) +import Test.Shelley.Spec.Ledger.Utils (maxLLSupply, mkHash) -- The CHAIN STS at the root of the STS allows for generating blocks of transactions -- with meaningful delegation certificates, protocol and application updates, withdrawals etc. @@ -105,12 +104,6 @@ mkGenesisChainState constants (IRC _slotNo) = do utxo0 <- genUtxo0 constants pParams <- genPParams constants - let osched_ = - runShelleyBase $ - overlaySchedule - epoch0 - (Map.keysSet delegs0) - pParams pure . Right . withRewards $ initialShelleyState @@ -119,7 +112,6 @@ mkGenesisChainState constants (IRC _slotNo) = do utxo0 (maxLLSupply Val.~~ balance utxo0) delegs0 - osched_ pParams (hashHeaderToNonce (lastByronHeaderHash p)) where diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Serialisation/Generators.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Serialisation/Generators.hs index 24572127c1b..1000151e035 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Serialisation/Generators.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/src/Test/Shelley/Spec/Ledger/Serialisation/Generators.hs @@ -38,7 +38,7 @@ import qualified Cardano.Crypto.Hash as Hash import Cardano.Ledger.Crypto (DSIGN) import Cardano.Ledger.Era (Crypto, Era) import Cardano.Slotting.Block (BlockNo (..)) -import Cardano.Slotting.Slot (EpochNo (..), EpochSize (..), SlotNo (..)) +import Cardano.Slotting.Slot (EpochNo (..), SlotNo (..)) import Control.Iterate.SetAlgebra (biMapFromList) import qualified Data.ByteString.Char8 as BS import Data.Coerce (coerce) @@ -85,7 +85,6 @@ import Shelley.Spec.Ledger.MetaData ) import qualified Shelley.Spec.Ledger.MetaData as MD import Shelley.Spec.Ledger.OCert (KESPeriod (..)) -import Shelley.Spec.Ledger.OverlaySchedule import Shelley.Spec.Ledger.PParams (ProtVer) import Shelley.Spec.Ledger.Rewards ( Likelihood (..), @@ -578,16 +577,6 @@ instance Era era => Arbitrary (OBftSlot era) where instance Arbitrary ActiveSlotCoeff where arbitrary = mkActiveSlotCoeff <$> arbitrary -instance Era era => Arbitrary (OverlaySchedule era) where - arbitrary = - -- Pick the parameters from specific random to avoid huge overlay schedules - overlayScheduleHelper - <$> (EpochSize <$> choose (1, 100)) - <*> (SlotNo <$> choose (0, 100000)) - <*> arbitrary - <*> arbitrary - <*> arbitrary - instance Arbitrary Likelihood where arbitrary = Likelihood <$> arbitrary diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Combinators.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Combinators.hs index 96e2f4e9b90..65f0685e5af 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Combinators.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Combinators.hs @@ -92,7 +92,6 @@ import Shelley.Spec.Ledger.STS.Chain (ChainState (..)) import Shelley.Spec.Ledger.TxBody (MIRPot (..), PoolParams (..), RewardAcnt (..), TxBody (..)) import Shelley.Spec.Ledger.UTxO (txins, txouts) import qualified Cardano.Ledger.Val as Val -import Test.Shelley.Spec.Ledger.Examples.Federation (overlayScheduleFor) import Test.Shelley.Spec.Ledger.Utils (epochFromSlotNo, getBlockNonce) -- | = Evolve Nonces - Frozen @@ -579,7 +578,6 @@ newEpoch b cs = cs' nes' = nes { nesEL = e, - nesOsched = overlayScheduleFor e pp, nesBprev = (nesBcur nes), nesBcur = BlocksMade Map.empty } diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Federation.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Federation.hs index baff8476415..db5f5d8b877 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Federation.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Federation.hs @@ -15,7 +15,6 @@ module Test.Shelley.Spec.Ledger.Examples.Federation coreNodeIssuerKeys, coreNodeKeysBySchedule, genDelegs, - overlayScheduleFor, ) where @@ -37,15 +36,11 @@ import Shelley.Spec.Ledger.Keys hashVerKeyVRF, vKey, ) +import Shelley.Spec.Ledger.BaseTypes (Globals (..)) import Shelley.Spec.Ledger.OCert (KESPeriod (..)) import Shelley.Spec.Ledger.OverlaySchedule -import Shelley.Spec.Ledger.PParams - ( PParams, - ) -import Shelley.Spec.Ledger.Slot - ( EpochNo (..), - SlotNo (..), - ) +import Shelley.Spec.Ledger.PParams (PParams, PParams' (..)) +import Shelley.Spec.Ledger.Slot (SlotNo (..)) import Test.Shelley.Spec.Ledger.Generator.Core ( AllIssuerKeys (..), ) @@ -103,51 +98,36 @@ coreNodeIssuerKeys :: AllIssuerKeys era 'GenesisDelegate coreNodeIssuerKeys = snd . (coreNodes @era !!) -coreNodeKeysForSlot :: - forall era. - (HasCallStack, Era era) => - Map SlotNo (OBftSlot era) -> - Word64 -> - AllIssuerKeys era 'GenesisDelegate -coreNodeKeysForSlot overlay slot = case Map.lookup (SlotNo slot) overlay of - Nothing -> error $ "coreNodesForSlot: Cannot find keys for slot " <> show slot - Just NonActiveSlot -> error $ "coreNodesForSlot: Non-active slot " <> show slot - Just (ActiveSlot gkh) -> - case Data.List.find (\((_, gk), _) -> hashKey gk == gkh) coreNodes of - Nothing -> - error $ - "coreNodesForSlot: Cannot find key hash in coreNodes: " - <> show gkh - Just ((_, _), ak) -> ak - --- | === Overlay Schedule --- Retrieve the overlay schedule for a given epoch and protocol parameters. -overlayScheduleFor :: Era era => EpochNo -> PParams era -> OverlaySchedule era -overlayScheduleFor e pp = - runShelleyBase $ - overlaySchedule - e - (Map.keysSet genDelegs) - pp - -- | === Keys by Overlay Schedule -- Retrieve all the keys associated with a core node -- for a given slot and protocol parameters. -- It will return an error if there is not a core node scheduled -- for the given slot. coreNodeKeysBySchedule :: + forall era. (HasCallStack, Era era) => PParams era -> Word64 -> AllIssuerKeys era 'GenesisDelegate -coreNodeKeysBySchedule = coreNodeKeysForSlot . fullOSched +coreNodeKeysBySchedule pp slot = + case lookupInOverlaySchedule + firstSlot + (Map.keys genDelegs) + (_d pp) + (activeSlotCoeff testGlobals) + slot' of + Nothing -> error $ "coreNodesForSlot: Cannot find keys for slot " <> show slot + Just NonActiveSlot -> error $ "coreNodesForSlot: Non-active slot " <> show slot + Just (ActiveSlot gkh) -> + case Data.List.find (\((_, gk), _) -> hashKey gk == gkh) coreNodes of + Nothing -> + error $ + "coreNodesForSlot: Cannot find key hash in coreNodes: " + <> show gkh + Just ((_, _), ak) -> ak where - fullOSched pp = - Map.unions $ - [ overlayScheduleToMap $ - overlayScheduleFor e pp - | e <- [0 .. 10] - ] + slot' = SlotNo slot + firstSlot = slotFromEpoch . epochFromSlotNo $ slot' -- | === Genesis Delegation Mapping -- The map from genesis/core node (verification) key hashes diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Init.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Init.hs index ab1fa154598..b2c0376983d 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Init.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Examples/Init.hs @@ -42,7 +42,7 @@ import Shelley.Spec.Ledger.Slot ) import Shelley.Spec.Ledger.UTxO (UTxO (..), balance) import qualified Cardano.Ledger.Val as Val -import Test.Shelley.Spec.Ledger.Examples.Federation (genDelegs, overlayScheduleFor) +import Test.Shelley.Spec.Ledger.Examples.Federation (genDelegs) import Test.Shelley.Spec.Ledger.Utils (maxLLSupply, mkHash, unsafeMkUnitInterval) -- === Initial Protocol Parameters @@ -105,6 +105,5 @@ initSt utxo = utxo (maxLLSupply Val.~~ (balance utxo)) genDelegs - (overlayScheduleFor (EpochNo 0) ppEx) ppEx (nonce0 @era) diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/LegacyOverlay.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/LegacyOverlay.hs new file mode 100644 index 00000000000..d4662e5d0d6 --- /dev/null +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/LegacyOverlay.hs @@ -0,0 +1,94 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeApplications #-} + +module Test.Shelley.Spec.Ledger.LegacyOverlay + ( legacyOverlayTest, + ) +where + +import Cardano.Slotting.Slot +import qualified Data.Map.Strict as Map +import Data.Map.Strict (Map) +import Data.Ratio ((%)) +import qualified Data.Set as Set +import Data.Set (Set) +import Shelley.Spec.Ledger.BaseTypes +import Shelley.Spec.Ledger.Keys + ( KeyHash (..), + KeyRole (..), + ) +import Shelley.Spec.Ledger.OverlaySchedule (OBftSlot (..), classifyOverlaySlot, overlaySlots) +import Shelley.Spec.Ledger.Slot +import Test.Shelley.Spec.Ledger.ConcreteCryptoTypes (C) +import Test.Shelley.Spec.Ledger.Examples.Federation (genDelegs) +import Test.Shelley.Spec.Ledger.Utils +import Test.Tasty.QuickCheck + +legacyOverlay :: + EpochSize -> + SlotNo -> + -- | First slot of the epoch + Set (KeyHash 'Genesis era) -> + UnitInterval -> + -- | Decentralization parameter @d@ + ActiveSlotCoeff -> + Map SlotNo (OBftSlot era) +legacyOverlay slotsPerEpoch firstSlotNo gkeys d asc + | dval == 0 = Map.empty + | otherwise = Map.union active inactive + where + dval = intervalValue d + numActive = dval * fromIntegral slotsPerEpoch + dInv = 1 / dval + ascValue = (intervalValue . activeSlotVal) asc + toRelativeSlotNo x = (Duration . floor) (dInv * fromInteger x) + toSlotNo x = firstSlotNo +* toRelativeSlotNo x + genesisSlots = [toSlotNo x | x <- [0 .. (floor numActive - 1)]] + numInactivePerActive = floor (1 / ascValue) - 1 + activitySchedule = cycle (True : replicate numInactivePerActive False) + unassignedSched = zip activitySchedule genesisSlots + genesisCycle = if Set.null gkeys then [] else cycle (Set.toList gkeys) + active = + Map.fromList $ + fmap + (\(gk, (_, s)) -> (s, ActiveSlot gk)) + (zip genesisCycle (filter fst unassignedSched)) + inactive = + Map.fromList $ + fmap + (\x -> (snd x, NonActiveSlot)) + (filter (not . fst) unassignedSched) + +mainnetEpochSize :: EpochSize +mainnetEpochSize = EpochSize 432000 + +makeConcreteOverlay :: + SlotNo -> -- first slot of the epoch + [KeyHash 'Genesis era] -> -- genesis Nodes + UnitInterval -> -- decentralization parameter + ActiveSlotCoeff -> -- active slot coefficent + EpochSize -> -- slots per epoch + Map SlotNo (OBftSlot era) +makeConcreteOverlay start gkeys dval asc spe = + Map.fromList $ + map + (\s -> (s, classifyOverlaySlot start gkeys dval asc s)) + (overlaySlots start dval spe) + +legacyOverlayTest :: Property +legacyOverlayTest = property $ do + d <- choose (0, 100) + e <- choose (0, 100) + let dval = unsafeMkUnitInterval (d % 100) + asc = mkActiveSlotCoeff . unsafeMkUnitInterval $ 1 % 20 + EpochSize spe = mainnetEpochSize + start = SlotNo $ e * spe + os = + legacyOverlay + mainnetEpochSize + start + (Map.keysSet (genDelegs @C)) + dval + asc + pure $ os === makeConcreteOverlay start (Map.keys (genDelegs @C)) dval asc mainnetEpochSize diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/PropertyTests.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/PropertyTests.hs index 33868720478..94fc40405dc 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/PropertyTests.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/PropertyTests.hs @@ -8,6 +8,7 @@ import Test.Shelley.Spec.Ledger.Address.Bootstrap ( bootstrapHashTest, ) import Test.Shelley.Spec.Ledger.ByronTranslation (testGroupByronTranslation) +import Test.Shelley.Spec.Ledger.LegacyOverlay (legacyOverlayTest) import Test.Shelley.Spec.Ledger.Rules.ClassifyTraces ( onlyValidChainSignalsAreGenerated, onlyValidLedgerSignalsAreGenerated, @@ -55,7 +56,8 @@ minimalPropertyTests = "Deserialize stake address reference" [ TQC.testProperty "wstake reference from bytestrings" propDeserializeAddrStakeReference, TQC.testProperty "stake reference from short bytestring" propDeserializeAddrStakeReferenceShortIncrediblyLongName - ] + ], + TQC.testProperty "legacy overlay schedule" legacyOverlayTest ] -- | 'TestTree' of property-based testing properties. diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Rules/TestChain.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Rules/TestChain.hs index 5dd4b373d36..55bc666c88f 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Rules/TestChain.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Rules/TestChain.hs @@ -50,7 +50,6 @@ import Shelley.Spec.Ledger.LedgerState import Shelley.Spec.Ledger.STS.Chain (ChainState (..), totalAda, totalAdaPots) import Shelley.Spec.Ledger.STS.Ledger (LedgerEnv (..)) import Shelley.Spec.Ledger.STS.PoolReap (PoolreapState (..)) -import Shelley.Spec.Ledger.STS.Tick (TickEnv (TickEnv)) import Shelley.Spec.Ledger.Tx import Shelley.Spec.Ledger.TxBody import Shelley.Spec.Ledger.UTxO (balance, totalDeposits, txins, txouts, pattern UTxO) @@ -465,7 +464,7 @@ chainSstWithTick ledgerTr = _ b@(Block bh _) ) = - case runShelleyBase (applySTSTest @(TICK C) (TRC (TickEnv (getGKeys nes), nes, (bheaderSlotNo . bhbody) bh))) of + case runShelleyBase (applySTSTest @(TICK C) (TRC ((), nes, (bheaderSlotNo . bhbody) bh))) of Left pf -> error ("chainSstWithTick.applyTick Predicate failure " <> show pf) Right nes' -> diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Serialisation/Golden/Encoding.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Serialisation/Golden/Encoding.hs index a4931aca6f9..26d548cfab2 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Serialisation/Golden/Encoding.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/Serialisation/Golden/Encoding.hs @@ -33,7 +33,6 @@ import qualified Data.ByteString.Base16.Lazy as Base16 import qualified Data.ByteString.Char8 as BS (pack) import Data.Coerce (coerce) import Data.IP (toIPv4) -import Data.List.NonEmpty (NonEmpty ((:|))) import qualified Data.Map.Strict as Map import qualified Data.Maybe as Maybe (fromJust) import Data.Proxy @@ -131,7 +130,6 @@ import Shelley.Spec.Ledger.LedgerState ) import qualified Shelley.Spec.Ledger.MetaData as MD import Shelley.Spec.Ledger.OCert (KESPeriod (..), OCertSignable (..), pattern OCert) -import Shelley.Spec.Ledger.OverlaySchedule import Shelley.Spec.Ledger.PParams ( PParams' (..), PParamsUpdate, @@ -1296,8 +1294,6 @@ tests = ) :: StrictMaybe (RewardUpdate C) pd = (PoolDistr Map.empty) :: PoolDistr C - compactOs = Map.singleton (ActiveSlot (testGKeyHash p)) (SlotNo 1 :| []) - os = decompactOverlaySchedule compactOs nes = NewEpochState e @@ -1306,18 +1302,16 @@ tests = es ru pd - os in checkEncodingCBOR "new_epoch_state" nes - ( T (TkListLen 7) + ( T (TkListLen 6) <> S e <> S (BlocksMade bs) <> S (BlocksMade bs) <> S es <> S ru <> S pd - <> S compactOs ) ] where diff --git a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/UnitTests.hs b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/UnitTests.hs index ff55144ea4d..2d464905baa 100644 --- a/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/UnitTests.hs +++ b/shelley/chain-and-ledger/shelley-spec-ledger-test/test/Test/Shelley/Spec/Ledger/UnitTests.hs @@ -60,7 +60,6 @@ import Shelley.Spec.Ledger.LedgerState _dstate, _rewards, ) -import Shelley.Spec.Ledger.OverlaySchedule import Shelley.Spec.Ledger.PParams import Shelley.Spec.Ledger.STS.Delegs (DelegsPredicateFailure (..)) import Shelley.Spec.Ledger.STS.Delpl (DelplPredicateFailure (..)) @@ -155,26 +154,6 @@ pp = _minPoolCost = Coin 100 } -testOverlayScheduleZero :: Assertion -testOverlayScheduleZero = - let os = - runShelleyBase $ - overlaySchedule - (EpochNo 0) - mempty - (emptyPParams {_d = unsafeMkUnitInterval 0}) - in assertBool "Overlay schedule is not empty" (overlayScheduleIsEmpty os) - -testNoGenesisOverlay :: Assertion -testNoGenesisOverlay = - let os = - runShelleyBase $ - overlaySchedule - (EpochNo 0) - mempty - (emptyPParams {_d = unsafeMkUnitInterval 0.5}) - in assertBool "Overlay schedule is not empty" (overlayScheduleIsEmpty os) - testVRFCheckWithActiveSlotCoeffOne :: Assertion testVRFCheckWithActiveSlotCoeffOne = checkLeaderValue @@ -187,11 +166,7 @@ testsPParams :: TestTree testsPParams = testGroup "Test the protocol parameters." - [ testCase "Overlay Schedule when d is zero" $ - testOverlayScheduleZero, - testCase "generate overlay schedule without genesis nodes" $ - testNoGenesisOverlay, - testCase "VRF checks when the activeSlotCoeff is one" $ + [ testCase "VRF checks when the activeSlotCoeff is one" $ testVRFCheckWithActiveSlotCoeffOne ]