module PlutusLedgerApi.Common.ProtocolVersions
    ( MajorProtocolVersion (..)
    -- ** Protocol Version aliases
    -- | Based on https://github.com/IntersectMBO/cardano-ledger/wiki/First-Block-of-Each-Era
    , shelleyPV
    , allegraPV
    , maryPV
    , alonzoPV
    , vasilPV
    , valentinePV
    , changPV
    , changPlus1PV
    , knownPVs
    , futurePV
    ) where

import Codec.Serialise (Serialise)
import Data.Set qualified as Set
import GHC.Generics (Generic)
import Prettyprinter

{- Note [Adding new builtins: protocol versions]

  *** ATTENTION! ***
  New built-in functions must initially be added under `futurePV` and should
  only be moved to an earlier MajorProtocolVersion once they have been fully
  implemented and costed and their release under the relevant protocol version
  has been officially approved.
-}

-- | This represents the major component of the Cardano protocol version.
-- The ledger can only supply the major component of the protocol version, not the minor
-- component, and Plutus should only need to care about the major component anyway.
-- This relies on careful understanding between us and the ledger as to what this means.
newtype MajorProtocolVersion = MajorProtocolVersion { MajorProtocolVersion -> Int
getMajorProtocolVersion :: Int }
  deriving newtype (MajorProtocolVersion -> MajorProtocolVersion -> Bool
(MajorProtocolVersion -> MajorProtocolVersion -> Bool)
-> (MajorProtocolVersion -> MajorProtocolVersion -> Bool)
-> Eq MajorProtocolVersion
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
== :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
$c/= :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
/= :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
Eq, Eq MajorProtocolVersion
Eq MajorProtocolVersion =>
(MajorProtocolVersion -> MajorProtocolVersion -> Ordering)
-> (MajorProtocolVersion -> MajorProtocolVersion -> Bool)
-> (MajorProtocolVersion -> MajorProtocolVersion -> Bool)
-> (MajorProtocolVersion -> MajorProtocolVersion -> Bool)
-> (MajorProtocolVersion -> MajorProtocolVersion -> Bool)
-> (MajorProtocolVersion
    -> MajorProtocolVersion -> MajorProtocolVersion)
-> (MajorProtocolVersion
    -> MajorProtocolVersion -> MajorProtocolVersion)
-> Ord MajorProtocolVersion
MajorProtocolVersion -> MajorProtocolVersion -> Bool
MajorProtocolVersion -> MajorProtocolVersion -> Ordering
MajorProtocolVersion
-> MajorProtocolVersion -> MajorProtocolVersion
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: MajorProtocolVersion -> MajorProtocolVersion -> Ordering
compare :: MajorProtocolVersion -> MajorProtocolVersion -> Ordering
$c< :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
< :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
$c<= :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
<= :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
$c> :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
> :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
$c>= :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
>= :: MajorProtocolVersion -> MajorProtocolVersion -> Bool
$cmax :: MajorProtocolVersion
-> MajorProtocolVersion -> MajorProtocolVersion
max :: MajorProtocolVersion
-> MajorProtocolVersion -> MajorProtocolVersion
$cmin :: MajorProtocolVersion
-> MajorProtocolVersion -> MajorProtocolVersion
min :: MajorProtocolVersion
-> MajorProtocolVersion -> MajorProtocolVersion
Ord, Int -> MajorProtocolVersion -> ShowS
[MajorProtocolVersion] -> ShowS
MajorProtocolVersion -> String
(Int -> MajorProtocolVersion -> ShowS)
-> (MajorProtocolVersion -> String)
-> ([MajorProtocolVersion] -> ShowS)
-> Show MajorProtocolVersion
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MajorProtocolVersion -> ShowS
showsPrec :: Int -> MajorProtocolVersion -> ShowS
$cshow :: MajorProtocolVersion -> String
show :: MajorProtocolVersion -> String
$cshowList :: [MajorProtocolVersion] -> ShowS
showList :: [MajorProtocolVersion] -> ShowS
Show, [MajorProtocolVersion] -> Encoding
MajorProtocolVersion -> Encoding
(MajorProtocolVersion -> Encoding)
-> (forall s. Decoder s MajorProtocolVersion)
-> ([MajorProtocolVersion] -> Encoding)
-> (forall s. Decoder s [MajorProtocolVersion])
-> Serialise MajorProtocolVersion
forall s. Decoder s [MajorProtocolVersion]
forall s. Decoder s MajorProtocolVersion
forall a.
(a -> Encoding)
-> (forall s. Decoder s a)
-> ([a] -> Encoding)
-> (forall s. Decoder s [a])
-> Serialise a
$cencode :: MajorProtocolVersion -> Encoding
encode :: MajorProtocolVersion -> Encoding
$cdecode :: forall s. Decoder s MajorProtocolVersion
decode :: forall s. Decoder s MajorProtocolVersion
$cencodeList :: [MajorProtocolVersion] -> Encoding
encodeList :: [MajorProtocolVersion] -> Encoding
$cdecodeList :: forall s. Decoder s [MajorProtocolVersion]
decodeList :: forall s. Decoder s [MajorProtocolVersion]
Serialise)
  deriving stock ((forall x. MajorProtocolVersion -> Rep MajorProtocolVersion x)
-> (forall x. Rep MajorProtocolVersion x -> MajorProtocolVersion)
-> Generic MajorProtocolVersion
forall x. Rep MajorProtocolVersion x -> MajorProtocolVersion
forall x. MajorProtocolVersion -> Rep MajorProtocolVersion x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. MajorProtocolVersion -> Rep MajorProtocolVersion x
from :: forall x. MajorProtocolVersion -> Rep MajorProtocolVersion x
$cto :: forall x. Rep MajorProtocolVersion x -> MajorProtocolVersion
to :: forall x. Rep MajorProtocolVersion x -> MajorProtocolVersion
Generic)

instance Pretty MajorProtocolVersion where
    pretty :: forall ann. MajorProtocolVersion -> Doc ann
pretty (MajorProtocolVersion Int
v) = Int -> Doc ann
forall ann. Int -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Int
v

-- | Shelley era was introduced in protocol version 2.0
shelleyPV :: MajorProtocolVersion
shelleyPV :: MajorProtocolVersion
shelleyPV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
2

-- | Allegra era was introduced in protocol version 3.0
allegraPV :: MajorProtocolVersion
allegraPV :: MajorProtocolVersion
allegraPV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
3

-- | Mary era was introduced in protocol version 4.0
maryPV :: MajorProtocolVersion
maryPV :: MajorProtocolVersion
maryPV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
4

-- | Alonzo era was introduced in protocol version 5.0
alonzoPV :: MajorProtocolVersion
alonzoPV :: MajorProtocolVersion
alonzoPV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
5

-- | The Vasil HF introduced the Babbage era and Plutus V2
vasilPV :: MajorProtocolVersion
vasilPV :: MajorProtocolVersion
vasilPV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
7

-- | Valentine was an intra-era HF where builtin functions @VerifyEcdsaSecp256k1Signature@ and
-- @VerifySchnorrSecp256k1Signature@ were enabled.
valentinePV :: MajorProtocolVersion
valentinePV :: MajorProtocolVersion
valentinePV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
8

-- | The Chang HF introduced the Conway era and Plutus V3
changPV :: MajorProtocolVersion
changPV :: MajorProtocolVersion
changPV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
9

-- | The Chang+1 HF will be an intra-era HF where some new builtin functions
-- are introduced in Plutus V2 and V3.
changPlus1PV :: MajorProtocolVersion
changPlus1PV :: MajorProtocolVersion
changPlus1PV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
10

-- | The set of protocol versions that are "known", i.e. that have been released
-- and have actual differences associated with them.
knownPVs :: Set.Set MajorProtocolVersion
knownPVs :: Set MajorProtocolVersion
knownPVs =
  [MajorProtocolVersion] -> Set MajorProtocolVersion
forall a. Ord a => [a] -> Set a
Set.fromList
    [ MajorProtocolVersion
shelleyPV
    , MajorProtocolVersion
allegraPV
    , MajorProtocolVersion
maryPV
    , MajorProtocolVersion
alonzoPV
    , MajorProtocolVersion
vasilPV
    , MajorProtocolVersion
valentinePV
    , MajorProtocolVersion
changPV
    , MajorProtocolVersion
changPlus1PV
    ]

-- | This is a placeholder for when we don't yet know what protocol version will
-- be used for something. It's a very high protocol version that should never
-- appear in reality.  New builtins should always be given this protocol version
-- until they've been finalised.
--
-- We should not assign names to future protocol versions until it's
-- confirmed that they are correct, otherwise we could accidentally
-- associate something with the wrong protocol version.
futurePV :: MajorProtocolVersion
futurePV :: MajorProtocolVersion
futurePV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
forall a. Bounded a => a
maxBound

{- Note [Mapping of protocol versions and ledger languages to semantics variants]
Semantics variants depend on both the protocol version and the ledger language.

Here's a table specifying the mapping in full:

  pv pre-Conway post-Conway
ll
1       A           B
2       A           B
3       C           C

I.e. for example

- post-Conway 'PlutusV1' corresponds to 'DefaultFunSemanticsVariantB'
- pre-Conway  'PlutusV2' corresponds to 'DefaultFunSemanticsVariantA'
- post-Conway 'PlutusV3' corresponds to 'DefaultFunSemanticsVariantC'
-}