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
    , plominPV
    , pv11PV
    , newestPV
    , knownPVs
    , futurePV
    ) where

import Codec.Serialise (Serialise)
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.  Remember to update
  the tests in `Spec.Versions` and `Spec.Data.Versions` when this happens.
-}

-- | 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, Int -> MajorProtocolVersion
MajorProtocolVersion -> Int
MajorProtocolVersion -> [MajorProtocolVersion]
MajorProtocolVersion -> MajorProtocolVersion
MajorProtocolVersion
-> MajorProtocolVersion -> [MajorProtocolVersion]
MajorProtocolVersion
-> MajorProtocolVersion
-> MajorProtocolVersion
-> [MajorProtocolVersion]
(MajorProtocolVersion -> MajorProtocolVersion)
-> (MajorProtocolVersion -> MajorProtocolVersion)
-> (Int -> MajorProtocolVersion)
-> (MajorProtocolVersion -> Int)
-> (MajorProtocolVersion -> [MajorProtocolVersion])
-> (MajorProtocolVersion
    -> MajorProtocolVersion -> [MajorProtocolVersion])
-> (MajorProtocolVersion
    -> MajorProtocolVersion -> [MajorProtocolVersion])
-> (MajorProtocolVersion
    -> MajorProtocolVersion
    -> MajorProtocolVersion
    -> [MajorProtocolVersion])
-> Enum MajorProtocolVersion
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: MajorProtocolVersion -> MajorProtocolVersion
succ :: MajorProtocolVersion -> MajorProtocolVersion
$cpred :: MajorProtocolVersion -> MajorProtocolVersion
pred :: MajorProtocolVersion -> MajorProtocolVersion
$ctoEnum :: Int -> MajorProtocolVersion
toEnum :: Int -> MajorProtocolVersion
$cfromEnum :: MajorProtocolVersion -> Int
fromEnum :: MajorProtocolVersion -> Int
$cenumFrom :: MajorProtocolVersion -> [MajorProtocolVersion]
enumFrom :: MajorProtocolVersion -> [MajorProtocolVersion]
$cenumFromThen :: MajorProtocolVersion
-> MajorProtocolVersion -> [MajorProtocolVersion]
enumFromThen :: MajorProtocolVersion
-> MajorProtocolVersion -> [MajorProtocolVersion]
$cenumFromTo :: MajorProtocolVersion
-> MajorProtocolVersion -> [MajorProtocolVersion]
enumFromTo :: MajorProtocolVersion
-> MajorProtocolVersion -> [MajorProtocolVersion]
$cenumFromThenTo :: MajorProtocolVersion
-> MajorProtocolVersion
-> MajorProtocolVersion
-> [MajorProtocolVersion]
enumFromThenTo :: MajorProtocolVersion
-> MajorProtocolVersion
-> MajorProtocolVersion
-> [MajorProtocolVersion]
Enum)
  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

-- According to https://cardano.org/hardforks/, PV 6 was called "Lobster".

-- | 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 Plomin HF was an intra-era HF where some new builtin functions were
-- introduced in Plutus V2 and V3.
plominPV :: MajorProtocolVersion
plominPV :: MajorProtocolVersion
plominPV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
10

-- | Not sure what this is going to be called yet
pv11PV :: MajorProtocolVersion
pv11PV :: MajorProtocolVersion
pv11PV = Int -> MajorProtocolVersion
MajorProtocolVersion Int
11

-- | The set of protocol versions that are "known", i.e. that have been released
-- and have actual differences associated with them.  This is currently only
-- used for testing, so efficiency is not parmount and a list is fine.
knownPVs :: [MajorProtocolVersion]
knownPVs :: [MajorProtocolVersion]
knownPVs =
    [ MajorProtocolVersion
shelleyPV
    , MajorProtocolVersion
allegraPV
    , MajorProtocolVersion
maryPV
    , MajorProtocolVersion
alonzoPV
    , MajorProtocolVersion
vasilPV
    , MajorProtocolVersion
valentinePV
    , MajorProtocolVersion
changPV
    , MajorProtocolVersion
plominPV
    , MajorProtocolVersion
pv11PV
    ]

-- We're sometimes in an intermediate state where we've added new builtins but
-- not yet released them (but intend to). This is used by some of the tests to
-- decide what PVs the test should include.  UPDATE THIS when we're expecting to
-- release new builtins in a forthcoming PV.
newestPV :: MajorProtocolVersion
newestPV :: MajorProtocolVersion
newestPV = MajorProtocolVersion
pv11PV

{-| 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 (at which point they should be moved to
  the PV named in `newestPV`).

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'
-}