diff --git a/ouroboros-consensus-cardano/changelog.d/20241014_170244_alexander.esgen_cardano_hf_trigger.md b/ouroboros-consensus-cardano/changelog.d/20241014_170244_alexander.esgen_cardano_hf_trigger.md new file mode 100644 index 0000000000..98b680ebc7 --- /dev/null +++ b/ouroboros-consensus-cardano/changelog.d/20241014_170244_alexander.esgen_cardano_hf_trigger.md @@ -0,0 +1,16 @@ +### Breaking + +- Changed `CardanoHardTriggers` to contain `CardanoHardForkTrigger`s which are a + simpler version of the previous `TriggerHardForkAt`. In particular, this will + affect call sites of `protocolInfoCardano`. + + Migration notes: + + - Change `TriggerHardForkAtEpoch` to `CardanoTriggerHardForkAtEpoch`. + - Change `TriggerHardForkAtVersion` to `CardanoTriggerHardForkAtDefaultVersion`. + + This constructor does not take a version argument, but rather defaults to + the corresponding first ledger protocol version. We are not aware of any + use case that requires a different value, but if there is, it is still + possible to manually modify the returned `LedgerConfig`s of + `protocolInfoCardano` directly. diff --git a/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano.hs b/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano.hs index 6d8768be45..f7cc3177da 100644 --- a/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano.hs +++ b/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano.hs @@ -8,6 +8,7 @@ module Ouroboros.Consensus.Cardano ( , ProtocolCardano , ProtocolShelley -- * Abstract over the various protocols + , CardanoHardForkTrigger (..) , CardanoHardForkTriggers (..) , module X ) where diff --git a/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano/Node.hs b/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano/Node.hs index 11bcfe7e78..8124973887 100644 --- a/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano/Node.hs +++ b/ouroboros-consensus-cardano/src/ouroboros-consensus-cardano/Ouroboros/Consensus/Cardano/Node.hs @@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} +{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-} @@ -33,6 +34,7 @@ module Ouroboros.Consensus.Cardano.Node ( CardanoHardForkConstraints + , CardanoHardForkTrigger (..) , CardanoHardForkTriggers (.., CardanoHardForkTriggers', triggerHardForkShelley, triggerHardForkAllegra, triggerHardForkMary, triggerHardForkAlonzo, triggerHardForkBabbage, triggerHardForkConway) , CardanoProtocolParams (..) , MaxMajorProtVer (..) @@ -518,17 +520,42 @@ instance CardanoHardForkConstraints c ProtocolInfo -------------------------------------------------------------------------------} +-- | When to trigger a hard fork to a Cardano era. +data CardanoHardForkTrigger blk = + -- | Trigger the hard fork when the ledger protocol version is updated to + -- the default for that era (@'L.eraProtVerLow' \@('ShelleyBlockLedgerEra' + -- blk)@). Also see 'TriggerHardForkAtVersion'. + CardanoTriggerHardForkAtDefaultVersion + | + -- | Trigger the hard fork at the given epoch. For testing only. Also see + -- 'TriggerHardForkAtEpoch'. + CardanoTriggerHardForkAtEpoch EpochNo + deriving stock (Show) + +toTriggerHardFork :: + forall blk. L.Era (ShelleyBlockLedgerEra blk) + => CardanoHardForkTrigger blk + -> TriggerHardFork +toTriggerHardFork = \case + CardanoTriggerHardForkAtDefaultVersion -> + TriggerHardForkAtVersion $ + SL.getVersion (L.eraProtVerLow @(ShelleyBlockLedgerEra blk)) + CardanoTriggerHardForkAtEpoch epochNo -> + TriggerHardForkAtEpoch epochNo + newtype CardanoHardForkTriggers = CardanoHardForkTriggers { - getCardanoHardForkTriggers :: NP (K TriggerHardFork) (CardanoShelleyEras StandardCrypto) + getCardanoHardForkTriggers :: + NP CardanoHardForkTrigger (CardanoShelleyEras StandardCrypto) } pattern CardanoHardForkTriggers' :: - TriggerHardFork - -> TriggerHardFork - -> TriggerHardFork - -> TriggerHardFork - -> TriggerHardFork - -> TriggerHardFork + (c ~ StandardCrypto) + => CardanoHardForkTrigger (ShelleyBlock (TPraos c) (ShelleyEra c)) + -> CardanoHardForkTrigger (ShelleyBlock (TPraos c) (AllegraEra c)) + -> CardanoHardForkTrigger (ShelleyBlock (TPraos c) (MaryEra c)) + -> CardanoHardForkTrigger (ShelleyBlock (TPraos c) (AlonzoEra c)) + -> CardanoHardForkTrigger (ShelleyBlock (Praos c) (BabbageEra c)) + -> CardanoHardForkTrigger (ShelleyBlock (Praos c) (ConwayEra c)) -> CardanoHardForkTriggers pattern CardanoHardForkTriggers' { triggerHardForkShelley @@ -539,12 +566,12 @@ pattern CardanoHardForkTriggers' { , triggerHardForkConway } = CardanoHardForkTriggers - ( K triggerHardForkShelley - :* K triggerHardForkAllegra - :* K triggerHardForkMary - :* K triggerHardForkAlonzo - :* K triggerHardForkBabbage - :* K triggerHardForkConway + ( triggerHardForkShelley + :* triggerHardForkAllegra + :* triggerHardForkMary + :* triggerHardForkAlonzo + :* triggerHardForkBabbage + :* triggerHardForkConway :* Nil ) {-# COMPLETE CardanoHardForkTriggers' #-} @@ -684,7 +711,7 @@ protocolInfoCardano paramsCardano partialLedgerConfigByron :: PartialLedgerConfig ByronBlock partialLedgerConfigByron = ByronPartialLedgerConfig { byronLedgerConfig = ledgerConfigByron - , byronTriggerHardFork = triggerHardForkShelley + , byronTriggerHardFork = toTriggerHardFork triggerHardForkShelley } kByron :: SecurityParam @@ -737,7 +764,7 @@ protocolInfoCardano paramsCardano partialLedgerConfigShelley = mkPartialLedgerConfigShelley transitionConfigShelley - triggerHardForkAllegra + (toTriggerHardFork triggerHardForkAllegra) kShelley :: SecurityParam kShelley = SecurityParam $ sgSecurityParam genesisShelley @@ -759,7 +786,7 @@ protocolInfoCardano paramsCardano partialLedgerConfigAllegra = mkPartialLedgerConfigShelley transitionConfigAllegra - triggerHardForkMary + (toTriggerHardFork triggerHardForkMary) -- Mary @@ -778,7 +805,7 @@ protocolInfoCardano paramsCardano partialLedgerConfigMary = mkPartialLedgerConfigShelley transitionConfigMary - triggerHardForkAlonzo + (toTriggerHardFork triggerHardForkAlonzo) -- Alonzo @@ -797,7 +824,7 @@ protocolInfoCardano paramsCardano partialLedgerConfigAlonzo = mkPartialLedgerConfigShelley transitionConfigAlonzo - triggerHardForkBabbage + (toTriggerHardFork triggerHardForkBabbage) -- Babbage @@ -826,7 +853,7 @@ protocolInfoCardano paramsCardano partialLedgerConfigBabbage = mkPartialLedgerConfigShelley transitionConfigBabbage - triggerHardForkConway + (toTriggerHardFork triggerHardForkConway) -- Conway diff --git a/ouroboros-consensus-cardano/src/unstable-cardano-testlib/Test/Consensus/Cardano/ProtocolInfo.hs b/ouroboros-consensus-cardano/src/unstable-cardano-testlib/Test/Consensus/Cardano/ProtocolInfo.hs index ec7c890606..e3943da9f6 100644 --- a/ouroboros-consensus-cardano/src/unstable-cardano-testlib/Test/Consensus/Cardano/ProtocolInfo.hs +++ b/ouroboros-consensus-cardano/src/unstable-cardano-testlib/Test/Consensus/Cardano/ProtocolInfo.hs @@ -1,7 +1,6 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} -{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} @@ -14,9 +13,8 @@ module Test.Consensus.Cardano.ProtocolInfo ( , ShelleySlotLengthInSeconds (..) -- ** Hard-fork specification , Era (..) - , HardForkSpec (..) , hardForkInto - , stayInByron + , hardForkOnDefaultProtocolVersions -- * ProtocolInfo elaboration , mkSimpleTestProtocolInfo , mkTestProtocolInfo @@ -31,6 +29,7 @@ import qualified Cardano.Ledger.BaseTypes as SL import qualified Cardano.Protocol.TPraos.OCert as SL import qualified Cardano.Slotting.Time as Time import Data.Proxy (Proxy (..)) +import Data.SOP.Strict import Data.Word (Word64) import Ouroboros.Consensus.Block.Forging (BlockForging) import Ouroboros.Consensus.BlockchainTime (SlotLength) @@ -39,9 +38,8 @@ import Ouroboros.Consensus.Byron.Node (ByronLeaderCredentials, byronPbftSignatureThreshold, byronSoftwareVersion) import Ouroboros.Consensus.Cardano.Block (CardanoBlock) import Ouroboros.Consensus.Cardano.Node (CardanoHardForkConstraints, - CardanoHardForkTriggers (..), CardanoProtocolParams (..), - TriggerHardFork (TriggerHardForkAtEpoch, TriggerHardForkNotDuringThisExecution), - protocolInfoCardano) + CardanoHardForkTrigger (..), CardanoHardForkTriggers (..), + CardanoProtocolParams (..), protocolInfoCardano) import Ouroboros.Consensus.Config (emptyCheckpointsMap) import Ouroboros.Consensus.Config.SecurityParam (SecurityParam (..)) import Ouroboros.Consensus.Node.ProtocolInfo (NumCoreNodes (..), @@ -77,19 +75,6 @@ instance ToSlotLength ByronSlotLengthInSeconds where instance ToSlotLength ShelleySlotLengthInSeconds where toSlotLength (ShelleySlotLengthInSeconds n) = Time.slotLengthFromSec $ fromIntegral n --- | This data structure is used to specify if and when hardforks should take --- place, and the version used at each era. See 'stayInByron' and 'hardForkInto' --- for examples. -data HardForkSpec = - HardForkSpec { - shelleyHardForkSpec :: TriggerHardFork - , allegraHardForkSpec :: TriggerHardFork - , maryHardForkSpec :: TriggerHardFork - , alonzoHardForkSpec :: TriggerHardFork - , babbageHardForkSpec :: TriggerHardFork - , conwayHardForkSpec :: TriggerHardFork - } - data Era = Byron | Shelley | Allegra @@ -99,52 +84,37 @@ data Era = Byron | Conway deriving (Show, Eq, Ord, Enum) -selectEra :: Era -> HardForkSpec -> TriggerHardFork -selectEra Byron _ = error "Byron is the first era, therefore there is no hard fork spec." -selectEra Shelley HardForkSpec { shelleyHardForkSpec } = shelleyHardForkSpec -selectEra Allegra HardForkSpec { allegraHardForkSpec } = allegraHardForkSpec -selectEra Mary HardForkSpec { maryHardForkSpec } = maryHardForkSpec -selectEra Alonzo HardForkSpec { alonzoHardForkSpec } = alonzoHardForkSpec -selectEra Babbage HardForkSpec { babbageHardForkSpec } = babbageHardForkSpec -selectEra Conway HardForkSpec { conwayHardForkSpec } = conwayHardForkSpec - -stayInByron :: HardForkSpec -stayInByron = - HardForkSpec { - shelleyHardForkSpec = TriggerHardForkNotDuringThisExecution - , allegraHardForkSpec = TriggerHardForkNotDuringThisExecution - , maryHardForkSpec = TriggerHardForkNotDuringThisExecution - , alonzoHardForkSpec = TriggerHardForkNotDuringThisExecution - , babbageHardForkSpec = TriggerHardForkNotDuringThisExecution - , conwayHardForkSpec = TriggerHardForkNotDuringThisExecution - } - protocolVersionZero :: SL.ProtVer protocolVersionZero = SL.ProtVer versionZero 0 where versionZero :: SL.Version versionZero = SL.natVersion @0 -hardForkInto :: Era -> HardForkSpec -hardForkInto Byron = stayInByron +hardForkOnDefaultProtocolVersions :: CardanoHardForkTriggers +hardForkOnDefaultProtocolVersions = + CardanoHardForkTriggers + $ hpure CardanoTriggerHardForkAtDefaultVersion + +hardForkInto :: Era -> CardanoHardForkTriggers +hardForkInto Byron = hardForkOnDefaultProtocolVersions hardForkInto Shelley = - stayInByron - { shelleyHardForkSpec = TriggerHardForkAtEpoch 0 } + hardForkOnDefaultProtocolVersions + { triggerHardForkShelley = CardanoTriggerHardForkAtEpoch 0 } hardForkInto Allegra = (hardForkInto Shelley) - { allegraHardForkSpec = TriggerHardForkAtEpoch 0 } + { triggerHardForkAllegra = CardanoTriggerHardForkAtEpoch 0 } hardForkInto Mary = (hardForkInto Allegra) - { maryHardForkSpec = TriggerHardForkAtEpoch 0 } + { triggerHardForkMary = CardanoTriggerHardForkAtEpoch 0 } hardForkInto Alonzo = (hardForkInto Mary) - { alonzoHardForkSpec = TriggerHardForkAtEpoch 0 } + { triggerHardForkAlonzo = CardanoTriggerHardForkAtEpoch 0 } hardForkInto Babbage = (hardForkInto Alonzo) - { babbageHardForkSpec = TriggerHardForkAtEpoch 0 } + { triggerHardForkBabbage = CardanoTriggerHardForkAtEpoch 0 } hardForkInto Conway = (hardForkInto Babbage) - { conwayHardForkSpec = TriggerHardForkAtEpoch 0 } + { triggerHardForkConway = CardanoTriggerHardForkAtEpoch 0 } {------------------------------------------------------------------------------- ProtocolInfo elaboration @@ -167,9 +137,10 @@ hardForkInto Conway = -- If you want to tweak the resulting protocol info further see -- 'mkTestProtocolInfo'. -- --- The resulting 'ProtocolInfo' contains a ledger state. The 'HardForkSpec' --- parameter will determine to which era this ledger state belongs. See --- 'HardForkSpec' for more details on how to specify a value of this type. +-- The resulting 'ProtocolInfo' contains a ledger state. The +-- 'CardanoHardForkTriggers' parameter will determine to which era this ledger +-- state belongs. See 'hardForkInto' and 'hardForkOnDefaultProtocolVersions' for +-- more details on how to specify a value of this type. -- mkSimpleTestProtocolInfo :: forall c @@ -180,7 +151,7 @@ mkSimpleTestProtocolInfo :: -> ByronSlotLengthInSeconds -> ShelleySlotLengthInSeconds -> SL.ProtVer - -> HardForkSpec + -> CardanoHardForkTriggers -> ProtocolInfo (CardanoBlock c) mkSimpleTestProtocolInfo decentralizationParam @@ -188,20 +159,20 @@ mkSimpleTestProtocolInfo byronSlotLenghtInSeconds shelleySlotLengthInSeconds protocolVersion - hardForkSpec + hardForkTriggers = fst $ mkTestProtocolInfo @IO (CoreNodeId 0, coreNodeShelley) shelleyGenesis - byronProtocolVersion + aByronProtocolVersion SL.NeutralNonce genesisByron generatedSecretsByron (Just $ PBftSignatureThreshold 1) protocolVersion - hardForkSpec + hardForkTriggers where - byronProtocolVersion = + aByronProtocolVersion = CC.Update.ProtocolVersion 0 0 0 coreNodeShelley = runGen initSeed $ Shelley.genCoreNode initialKESPeriod @@ -258,8 +229,8 @@ mkTestProtocolInfo :: -> SL.ProtVer -- ^ See 'protocolInfoCardano' for the details of what is the -- relation between this version and any 'TriggerHardForkAtVersion' - -- that __might__ appear in the 'HardForkSpec' parameter. - -> HardForkSpec + -- that __might__ appear in the 'CardanoHardForkTriggers' parameter. + -> CardanoHardForkTriggers -- ^ Specification of the era to which the initial state should hard-fork to. -> (ProtocolInfo (CardanoBlock c), m [BlockForging m (CardanoBlock c)]) mkTestProtocolInfo @@ -271,7 +242,7 @@ mkTestProtocolInfo generatedSecretsByron aByronPbftSignatureThreshold protocolVersion - hardForkSpec + hardForkTriggers = protocolInfoCardano (CardanoProtocolParams @@ -286,14 +257,7 @@ mkTestProtocolInfo shelleyBasedInitialNonce = initialNonce , shelleyBasedLeaderCredentials = [leaderCredentialsShelley] } - CardanoHardForkTriggers' { - triggerHardForkShelley = selectEra Shelley hardForkSpec - , triggerHardForkAllegra = selectEra Allegra hardForkSpec - , triggerHardForkMary = selectEra Mary hardForkSpec - , triggerHardForkAlonzo = selectEra Alonzo hardForkSpec - , triggerHardForkBabbage = selectEra Babbage hardForkSpec - , triggerHardForkConway = selectEra Conway hardForkSpec - } + hardForkTriggers ( L.mkLatestTransitionConfig shelleyGenesis -- These example genesis objects might need to become more diff --git a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Protocol/Cardano.hs b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Protocol/Cardano.hs index 0cf3610a59..422b71dfb9 100644 --- a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Protocol/Cardano.hs +++ b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Protocol/Cardano.hs @@ -32,7 +32,6 @@ import Control.Monad.Trans.Except (ExceptT) import Control.Monad.Trans.Except.Extra (firstExceptT) import Ouroboros.Consensus.Cardano import qualified Ouroboros.Consensus.Cardano as Consensus -import qualified Ouroboros.Consensus.Cardano.CanHardFork as Consensus import Ouroboros.Consensus.Cardano.Condense () import Ouroboros.Consensus.Cardano.Node (CardanoProtocolParams (..)) import Ouroboros.Consensus.Config (emptyCheckpointsMap) @@ -108,17 +107,11 @@ mkConsensusProtocolCardano NodeByronProtocolConfiguration { -- not-yet-ready eras in released node versions without mainnet nodes -- prematurely advertising that they could hard fork into the new era. npcTestShelleyHardForkAtEpoch, - npcTestShelleyHardForkAtVersion, npcTestAllegraHardForkAtEpoch, - npcTestAllegraHardForkAtVersion, npcTestMaryHardForkAtEpoch, - npcTestMaryHardForkAtVersion, npcTestAlonzoHardForkAtEpoch, - npcTestAlonzoHardForkAtVersion, npcTestBabbageHardForkAtEpoch, - npcTestBabbageHardForkAtVersion, - npcTestConwayHardForkAtEpoch, - npcTestConwayHardForkAtVersion + npcTestConwayHardForkAtEpoch } files = do byronGenesis <- @@ -213,42 +206,36 @@ mkConsensusProtocolCardano NodeByronProtocolConfiguration { -- But we also provide an override to allow for simpler test setups -- such as triggering at the 0 -> 1 transition . -- - Nothing -> Consensus.TriggerHardForkAtVersion - (maybe 2 fromIntegral npcTestShelleyHardForkAtVersion) + Nothing -> Consensus.CardanoTriggerHardForkAtDefaultVersion -- Alternatively, for testing we can transition at a specific epoch. -- - Just epochNo -> Consensus.TriggerHardForkAtEpoch epochNo + Just epochNo -> Consensus.CardanoTriggerHardForkAtEpoch epochNo -- Shelley to Allegra hard fork parameters , triggerHardForkAllegra = case npcTestAllegraHardForkAtEpoch of - Nothing -> Consensus.TriggerHardForkAtVersion - (maybe 3 fromIntegral npcTestAllegraHardForkAtVersion) - Just epochNo -> Consensus.TriggerHardForkAtEpoch epochNo + Nothing -> Consensus.CardanoTriggerHardForkAtDefaultVersion + Just epochNo -> Consensus.CardanoTriggerHardForkAtEpoch epochNo -- Allegra to Mary hard fork parameters , triggerHardForkMary = case npcTestMaryHardForkAtEpoch of - Nothing -> Consensus.TriggerHardForkAtVersion - (maybe 4 fromIntegral npcTestMaryHardForkAtVersion) - Just epochNo -> Consensus.TriggerHardForkAtEpoch epochNo + Nothing -> Consensus.CardanoTriggerHardForkAtDefaultVersion + Just epochNo -> Consensus.CardanoTriggerHardForkAtEpoch epochNo -- Mary to Alonzo hard fork parameters , triggerHardForkAlonzo = case npcTestAlonzoHardForkAtEpoch of - Nothing -> Consensus.TriggerHardForkAtVersion - (maybe 5 fromIntegral npcTestAlonzoHardForkAtVersion) - Just epochNo -> Consensus.TriggerHardForkAtEpoch epochNo + Nothing -> Consensus.CardanoTriggerHardForkAtDefaultVersion + Just epochNo -> Consensus.CardanoTriggerHardForkAtEpoch epochNo -- Alonzo to Babbage hard fork parameters , triggerHardForkBabbage = case npcTestBabbageHardForkAtEpoch of - Nothing -> Consensus.TriggerHardForkAtVersion - (maybe 7 fromIntegral npcTestBabbageHardForkAtVersion) - Just epochNo -> Consensus.TriggerHardForkAtEpoch epochNo + Nothing -> Consensus.CardanoTriggerHardForkAtDefaultVersion + Just epochNo -> Consensus.CardanoTriggerHardForkAtEpoch epochNo -- Babbage to Conway hard fork parameters , triggerHardForkConway = case npcTestConwayHardForkAtEpoch of - Nothing -> Consensus.TriggerHardForkAtVersion - (maybe 9 fromIntegral npcTestConwayHardForkAtVersion) - Just epochNo -> Consensus.TriggerHardForkAtEpoch epochNo + Nothing -> Consensus.CardanoTriggerHardForkAtDefaultVersion + Just epochNo -> Consensus.CardanoTriggerHardForkAtEpoch epochNo } transitionLedgerConfig emptyCheckpointsMap diff --git a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Types.hs b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Types.hs index e82c0e59b6..13ce5530d0 100644 --- a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Types.hs +++ b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Node/Types.hs @@ -200,17 +200,6 @@ data NodeHardForkProtocolConfiguration = -- , npcTestShelleyHardForkAtEpoch :: Maybe EpochNo - -- | For testing purposes we support specifying that the hard fork - -- happens at a given major protocol version. For example this can be - -- used to cause the Shelley hard fork to occur at the transition from - -- protocol version 0 to version 1 (rather than the default of from 1 to - -- 2) which can make the test setup simpler. - -- - -- Obviously if this is used, all the nodes in the test cluster must be - -- configured the same, or they will disagree. - -- - , npcTestShelleyHardForkAtVersion :: Maybe Word - -- | For testing purposes we support specifying that the hard fork -- happens at an exact epoch number (ie the first epoch of the new era). -- @@ -219,14 +208,6 @@ data NodeHardForkProtocolConfiguration = -- , npcTestAllegraHardForkAtEpoch :: Maybe EpochNo - -- | For testing purposes we support specifying that the hard fork - -- happens at a given major protocol version. - -- - -- Obviously if this is used, all the nodes in the test cluster must be - -- configured the same, or they will disagree. - -- - , npcTestAllegraHardForkAtVersion :: Maybe Word - -- | For testing purposes we support specifying that the hard fork -- happens at an exact epoch number (ie the first epoch of the new era). -- @@ -235,15 +216,6 @@ data NodeHardForkProtocolConfiguration = -- , npcTestMaryHardForkAtEpoch :: Maybe EpochNo - -- | For testing purposes we support specifying that the hard fork - -- happens at a given major protocol version. - -- - -- Obviously if this is used, all the nodes in the test cluster must be - -- configured the same, or they will disagree. - -- - -- - , npcTestMaryHardForkAtVersion :: Maybe Word - -- | For testing purposes we support specifying that the hard fork -- happens at an exact epoch number (ie the first epoch of the new era). -- @@ -252,33 +224,9 @@ data NodeHardForkProtocolConfiguration = -- , npcTestAlonzoHardForkAtEpoch :: Maybe EpochNo - -- | For testing purposes we support specifying that the hard fork - -- happens at a given major protocol version. - -- - -- Obviously if this is used, all the nodes in the test cluster must be - -- configured the same, or they will disagree. - -- - , npcTestAlonzoHardForkAtVersion :: Maybe Word - , npcTestBabbageHardForkAtEpoch :: Maybe EpochNo - -- | For testing purposes we support specifying that the hard fork - -- happens at a given major protocol version. - -- - -- Obviously if this is used, all the nodes in the test cluster must be - -- configured the same, or they will disagree. - -- - , npcTestBabbageHardForkAtVersion :: Maybe Word - , npcTestConwayHardForkAtEpoch :: Maybe EpochNo - - -- | For testing purposes we support specifying that the hard fork - -- happens at a given major protocol version. - -- - -- Obviously if this is used, all the nodes in the test cluster must be - -- configured the same, or they will disagree. - -- - , npcTestConwayHardForkAtVersion :: Maybe Word } deriving (Eq, Show) diff --git a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBAnalyser/Block/Cardano.hs b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBAnalyser/Block/Cardano.hs index 14564611b9..341f0bcc08 100644 --- a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBAnalyser/Block/Cardano.hs +++ b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBAnalyser/Block/Cardano.hs @@ -32,7 +32,6 @@ import qualified Cardano.Crypto.Hash.Class as CryptoClass import Cardano.Crypto.Raw (Raw) import qualified Cardano.Ledger.Api.Era as L import qualified Cardano.Ledger.Api.Transition as SL -import Cardano.Ledger.Binary.Version (getVersion) import Cardano.Ledger.Core (TxOut) import Cardano.Ledger.Crypto import qualified Cardano.Ledger.Shelley.LedgerState as Shelley.LedgerState @@ -61,7 +60,7 @@ import Ouroboros.Consensus.Cardano import Ouroboros.Consensus.Cardano.Block (CardanoEras) import qualified Ouroboros.Consensus.Cardano.Block as Cardano.Block import Ouroboros.Consensus.Cardano.Node (CardanoProtocolParams (..), - TriggerHardFork (..), protocolInfoCardano) + protocolInfoCardano) import Ouroboros.Consensus.Config (emptyCheckpointsMap) import Ouroboros.Consensus.HardFork.Combinator (HardForkBlock (..), OneEraBlock (..), OneEraHash (..), getHardForkState, @@ -233,19 +232,20 @@ instance Aeson.FromJSON CardanoConfig where triggers <- do let parseTrigger :: forall blk era. (IsShelleyBlock blk, ShelleyBlockLedgerEra blk ~ era) - => (Aeson.Parser :.: K TriggerHardFork) blk - parseTrigger = Comp $ fmap K $ - (fmap TriggerHardForkAtEpoch <$> (v Aeson..:? nm)) - Aeson..!= TriggerHardForkAtVersion (getVersion (L.eraProtVerLow @era)) + => (Aeson.Parser :.: CardanoHardForkTrigger) blk + parseTrigger = Comp $ + (fmap CardanoTriggerHardForkAtEpoch <$> (v Aeson..:? nm)) + Aeson..!= CardanoTriggerHardForkAtDefaultVersion where nm = fromString $ "Test" <> L.eraName @era <> "HardForkAtEpoch" triggers <- hsequence' $ hcpure (Proxy @IsShelleyBlock) parseTrigger - let isBad :: NP (K TriggerHardFork) xs -> Bool + let isBad :: NP CardanoHardForkTrigger xs -> Bool isBad = \case - K TriggerHardForkAtVersion{} :* K TriggerHardForkAtEpoch{} :* _ -> True - K{} :* np -> isBad np + CardanoTriggerHardForkAtDefaultVersion + :* CardanoTriggerHardForkAtEpoch{} :* _ -> True + _ :* np -> isBad np Nil -> False fmap (\() -> triggers) $ when (isBad triggers) $ fail $ "if the Cardano config file sets a Test*HardForkEpoch," diff --git a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBSynthesizer/Orphans.hs b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBSynthesizer/Orphans.hs index 15eb18bf86..bda73a8f30 100644 --- a/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBSynthesizer/Orphans.hs +++ b/ouroboros-consensus-cardano/src/unstable-cardano-tools/Cardano/Tools/DBSynthesizer/Orphans.hs @@ -55,17 +55,11 @@ instance FromJSON NodeHardForkProtocolConfiguration where <$> v .:? "TestEnableDevelopmentHardForkEras" .!= False <*> v .:? "TestShelleyHardForkAtEpoch" - <*> v .:? "TestShelleyHardForkAtVersion" <*> v .:? "TestAllegraHardForkAtEpoch" - <*> v .:? "TestAllegraHardForkAtVersion" <*> v .:? "TestMaryHardForkAtEpoch" - <*> v .:? "TestMaryHardForkAtVersion" <*> v .:? "TestAlonzoHardForkAtEpoch" - <*> v .:? "TestAlonzoHardForkAtVersion" <*> v .:? "TestBabbageHardForkAtEpoch" - <*> v .:? "TestBabbageHardForkAtVersion" <*> v .:? "TestConwayHardForkAtEpoch" - <*> v .:? "TestConwayHardForkAtVersion" instance FromJSON NodeByronProtocolConfiguration where parseJSON = withObject "NodeByronProtocolConfiguration" $ \v -> diff --git a/ouroboros-consensus-cardano/test/cardano-test/Test/Consensus/Cardano/SupportsSanityCheck.hs b/ouroboros-consensus-cardano/test/cardano-test/Test/Consensus/Cardano/SupportsSanityCheck.hs index 96bcde5f95..fa91ae7ac2 100644 --- a/ouroboros-consensus-cardano/test/cardano-test/Test/Consensus/Cardano/SupportsSanityCheck.hs +++ b/ouroboros-consensus-cardano/test/cardano-test/Test/Consensus/Cardano/SupportsSanityCheck.hs @@ -1,6 +1,7 @@ {-# LANGUAGE NamedFieldPuns #-} module Test.Consensus.Cardano.SupportsSanityCheck (tests) where +import Ouroboros.Consensus.Cardano (CardanoHardForkTriggers) import Ouroboros.Consensus.Cardano.Block import Ouroboros.Consensus.Config import Ouroboros.Consensus.HardFork.Combinator.Basics @@ -53,14 +54,14 @@ genSimpleTestProtocolInfo = do (byronSlotLength setup) (shelleySlotLength setup) protocolVersionZero - (hardForkSpec setup) + (hardForkTriggers setup) data SimpleTestProtocolInfoSetup = SimpleTestProtocolInfoSetup { decentralizationParam :: Shelley.DecentralizationParam , securityParam :: SecurityParam , byronSlotLength :: ByronSlotLengthInSeconds , shelleySlotLength :: ShelleySlotLengthInSeconds - , hardForkSpec :: HardForkSpec + , hardForkTriggers :: CardanoHardForkTriggers } instance Arbitrary SimpleTestProtocolInfoSetup where @@ -70,7 +71,7 @@ instance Arbitrary SimpleTestProtocolInfoSetup where <*> genSecurityParam <*> genByronSlotLength <*> genShelleySlotLength - <*> genHardForkSpec + <*> genHardForkTriggers where genSecurityParam = SecurityParam <$> Gen.choose (8, 12) @@ -78,5 +79,5 @@ instance Arbitrary SimpleTestProtocolInfoSetup where ByronSlotLengthInSeconds <$> Gen.choose (1, 4) genShelleySlotLength = ShelleySlotLengthInSeconds <$> Gen.choose (1, 4) - genHardForkSpec = + genHardForkTriggers = hardForkInto <$> Gen.chooseEnum (Byron, Conway) diff --git a/ouroboros-consensus-cardano/test/cardano-test/Test/ThreadNet/Cardano.hs b/ouroboros-consensus-cardano/test/cardano-test/Test/ThreadNet/Cardano.hs index 861f3d617e..f0dccc8304 100644 --- a/ouroboros-consensus-cardano/test/cardano-test/Test/ThreadNet/Cardano.hs +++ b/ouroboros-consensus-cardano/test/cardano-test/Test/ThreadNet/Cardano.hs @@ -6,14 +6,18 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} +{-# LANGUAGE ViewPatterns #-} module Test.ThreadNet.Cardano (tests) where +import qualified Cardano.Chain.Block as CC import qualified Cardano.Chain.Common as CC.Common import qualified Cardano.Chain.Genesis as CC.Genesis import Cardano.Chain.ProtocolConstants (kEpochSlots) import Cardano.Chain.Slotting (unEpochSlots) import qualified Cardano.Chain.Update as CC.Update +import qualified Cardano.Chain.Update.Validation.Interface as CC +import qualified Cardano.Ledger.Api.Era as L import qualified Cardano.Ledger.BaseTypes as SL import qualified Cardano.Ledger.Shelley.API as SL import qualified Cardano.Ledger.Shelley.Core as SL @@ -30,15 +34,18 @@ import Data.Word (Word64) import Lens.Micro import Ouroboros.Consensus.Block.Forging (BlockForging) import Ouroboros.Consensus.BlockchainTime +import Ouroboros.Consensus.Byron.Ledger (LedgerState (..)) import Ouroboros.Consensus.Byron.Ledger.Block (ByronBlock) import Ouroboros.Consensus.Byron.Ledger.Conversions import Ouroboros.Consensus.Byron.Node import Ouroboros.Consensus.Cardano.Block import Ouroboros.Consensus.Cardano.Condense () -import Ouroboros.Consensus.Cardano.Node import Ouroboros.Consensus.Config.SecurityParam +import Ouroboros.Consensus.HardFork.Combinator import Ouroboros.Consensus.HardFork.Combinator.Serialisation.Common (isHardForkNodeToNodeEnabled) +import Ouroboros.Consensus.HardFork.Combinator.State (Current (..)) +import Ouroboros.Consensus.Ledger.Extended (ExtLedgerState (..)) import Ouroboros.Consensus.Ledger.SupportsMempool (extractTxs) import Ouroboros.Consensus.Node.NetworkProtocolVersion import Ouroboros.Consensus.Node.ProtocolInfo @@ -47,8 +54,8 @@ import Ouroboros.Consensus.Protocol.PBFT import Ouroboros.Consensus.Shelley.Ledger.SupportsProtocol () import Ouroboros.Consensus.Shelley.Node import Ouroboros.Consensus.Util.IOLike (IOLike) -import Test.Consensus.Cardano.ProtocolInfo (HardForkSpec (..), - mkTestProtocolInfo) +import Test.Consensus.Cardano.ProtocolInfo + (hardForkOnDefaultProtocolVersions, mkTestProtocolInfo) import Test.QuickCheck import Test.Tasty import Test.Tasty.QuickCheck @@ -360,7 +367,7 @@ prop_simple_cardano_convergence TestSetup else -- this new version must not induce the hard fork if accepted CC.Update.ProtocolVersion - (SL.getVersion byronMajorVersion) (byronInitialMinorVersion + 1) 0 + byronMajorVersion (byronInitialMinorVersion + 1) 0 -- Classifying test cases @@ -466,7 +473,7 @@ mkProtocolCardanoAndHardForkTxs protocolInfo :: ProtocolInfo (CardanoBlock c) blockForging :: m [BlockForging m (CardanoBlock c)] - (protocolInfo, blockForging) = + (setByronProtVer -> protocolInfo, blockForging) = mkTestProtocolInfo (coreNodeId, coreNodeShelley) genesisShelley @@ -478,76 +485,26 @@ mkProtocolCardanoAndHardForkTxs -- window so that the forks induced by -- the network partition are as deep -- as possible. - (SL.ProtVer conwayMajorVersion 0) -- During the tests, we - -- want to hard fork all - -- the way to Conway, so we - -- need to signal that we - -- support that era. This - -- version will have to be - -- changed if this test has - -- to hard fork to eras - -- beyond Conway. - HardForkSpec { - shelleyHardForkSpec = TriggerHardForkAtVersion $ SL.getVersion shelleyMajorVersion - , allegraHardForkSpec = TriggerHardForkAtVersion $ SL.getVersion allegraMajorVersion - , maryHardForkSpec = TriggerHardForkAtVersion $ SL.getVersion maryMajorVersion - , alonzoHardForkSpec = TriggerHardForkAtVersion $ SL.getVersion alonzoMajorVersion - , babbageHardForkSpec = TriggerHardForkAtVersion $ SL.getVersion babbageMajorVersion - , conwayHardForkSpec = TriggerHardForkAtVersion $ SL.getVersion conwayMajorVersion - } + -- This test only enters the Shelley era. + (SL.ProtVer shelleyMajorVersion 0) + hardForkOnDefaultProtocolVersions {------------------------------------------------------------------------------- Constants -------------------------------------------------------------------------------} --- | The major protocol version of Byron in this test --- --- On mainnet, the Byron era spans multiple major versions: 0 for Classic and 1 --- for OBFT. So Shelley is 2. But in this test, we start with OBFT as major --- version 0: the nodes are running OBFT from slot 0 and the Byron ledger --- defaults to an initial version of 0. So Shelley is 1 in this test. -byronMajorVersion :: SL.Version -byronMajorVersion = SL.natVersion @0 - --- | The major protocol version of Shelley in this test --- --- See 'byronMajorVersion' -shelleyMajorVersion :: SL.Version -shelleyMajorVersion = SL.natVersion @1 - --- | The major protocol version of Allegra in this test --- --- See 'byronMajorVersion' -allegraMajorVersion :: SL.Version -allegraMajorVersion = SL.natVersion @2 - --- | The major protocol version of Mary in this test --- --- See 'byronMajorVersion' -maryMajorVersion :: SL.Version -maryMajorVersion = SL.natVersion @3 - --- | The major protocol version of Alonzo in this test --- -alonzoMajorVersion :: SL.Version -alonzoMajorVersion = SL.natVersion @4 - --- | The major protocol version of Babbage in this test --- -babbageMajorVersion :: SL.Version -babbageMajorVersion = SL.natVersion @5 +-- | The major protocol version of the Byron era in this test. +byronMajorVersion :: Integral a => a +byronMajorVersion = SL.getVersion shelleyMajorVersion - 1 --- | The major protocol version of Conway in this test --- -conwayMajorVersion :: SL.Version -conwayMajorVersion = SL.natVersion @6 - --- | The initial minor protocol version of Byron in this test --- --- See 'byronMajorVersion' byronInitialMinorVersion :: Num a => a byronInitialMinorVersion = 0 +-- | The (first) major protocol version of the Shelley era, as used by +-- 'hardForkOnDefaultProtocolVersions'. +shelleyMajorVersion :: SL.Version +shelleyMajorVersion = L.eraProtVerLow @(ShelleyEra StandardCrypto) + {------------------------------------------------------------------------------- Miscellany -------------------------------------------------------------------------------} @@ -555,3 +512,26 @@ byronInitialMinorVersion = 0 byronEpochSize :: SecurityParam -> Word64 byronEpochSize (SecurityParam k) = unEpochSlots $ kEpochSlots $ CC.Common.BlockCount k + +-- | By default, the initial major Byron protocol version is @0@, but we want to +-- set it to 'byronMajorVersion'. +setByronProtVer :: ProtocolInfo (CardanoBlock c) -> ProtocolInfo (CardanoBlock c) +setByronProtVer = + modifyInitLedger $ modifyExtLedger $ modifyHFLedgerState $ \st -> + let cvs = byronLedgerState st + us = (CC.cvsUpdateState cvs) { + CC.adoptedProtocolVersion = + CC.Update.ProtocolVersion byronMajorVersion byronInitialMinorVersion 0 + } + in st { byronLedgerState = cvs { CC.cvsUpdateState = us } } + where + modifyInitLedger f pinfo = pinfo { pInfoInitLedger = f (pInfoInitLedger pinfo) } + modifyExtLedger f elgr = elgr { ledgerState = f (ledgerState elgr ) } + + modifyHFLedgerState :: + (LedgerState x -> LedgerState x) + -> LedgerState (HardForkBlock (x : xs)) + -> LedgerState (HardForkBlock (x : xs)) + modifyHFLedgerState f (HardForkLedgerState (HardForkState (TZ st))) = + HardForkLedgerState (HardForkState (TZ st {currentState = f (currentState st)})) + modifyHFLedgerState _ st = st