Skip to content

Commit 92f337c

Browse files
committed
Add supportedLanguages
This is a feature that allows using plutus supported version per era in a type safe manner. * Add `supportedLanguages` to `EraPlutusContext` * Add `SupportedLanguage`, `mkSupportedBinaryPlutusScript` and `mkSupportedPlutusScript`.
1 parent 21b6bd9 commit 92f337c

File tree

6 files changed

+115
-4
lines changed

6 files changed

+115
-4
lines changed

eras/alonzo/impl/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## 1.14.0.0
44

5+
* Add `supportedLanguages` to `EraPlutusContext`
6+
* Add `SupportedLanguage`, `mkSupportedBinaryPlutusScript` and `mkSupportedPlutusScript`.
57
* Deprecate `inputs'`, `collateral'`, `outputs'`, `certs'`, `withdrawals'`, `txfee'`,
68
`vldt'`, `update'`, `reqSignerHashes'`, `adHash'`, `mint'`, `scriptIntegrityHash'`,
79
and `txnetworkid'`

eras/alonzo/impl/cardano-ledger-alonzo.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ library
101101
text,
102102
transformers,
103103
validation-selective,
104+
FailT,
104105

105106
if !impl(ghc >=9.2)
106107
ghc-options: -Wno-name-shadowing

eras/alonzo/impl/src/Cardano/Ledger/Alonzo/Plutus/Context.hs

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
{-# LANGUAGE TypeFamilyDependencies #-}
99
{-# LANGUAGE UndecidableSuperClasses #-}
1010
-- Recursive definition constraints of `EraPlutusContext` and `EraPlutusTxInfo` lead to a wrongful
11-
-- redundant constraint warning in the definition of `lookupTxInfoResult`
11+
-- redundant constraint warning in the definition of `lookupTxInfoResult`.
12+
--
13+
-- Also `mkSupportedPlutusScript` has a constraint that is not required by the type system, but is
14+
-- necessary for the safety of the function.
1215
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
1316

1417
module Cardano.Ledger.Alonzo.Plutus.Context (
@@ -17,6 +20,11 @@ module Cardano.Ledger.Alonzo.Plutus.Context (
1720
EraPlutusContext (..),
1821
toPlutusWithContext,
1922
lookupTxInfoResultImpossible,
23+
SupportedLanguage (..),
24+
mkSupportedLanguageM,
25+
supportedLanguages,
26+
mkSupportedPlutusScript,
27+
mkSupportedBinaryPlutusScript,
2028

2129
-- * Language dependent translation
2230
PlutusTxInfo,
@@ -27,7 +35,7 @@ module Cardano.Ledger.Alonzo.Plutus.Context (
2735
where
2836

2937
import Cardano.Ledger.Alonzo.Scripts (
30-
AlonzoEraScript,
38+
AlonzoEraScript (eraMaxLanguage, mkPlutusScript),
3139
AsIxItem (..),
3240
PlutusPurpose,
3341
PlutusScript (..),
@@ -43,21 +51,26 @@ import Cardano.Ledger.Plutus (
4351
Data,
4452
ExUnits,
4553
Language (..),
46-
Plutus,
54+
Plutus (..),
4755
PlutusArgs,
56+
PlutusBinary,
4857
PlutusLanguage,
4958
PlutusRunnable,
5059
PlutusScriptContext,
5160
PlutusWithContext (..),
5261
SLanguage (..),
62+
asSLanguage,
5363
isLanguage,
64+
plutusLanguage,
5465
)
5566
import Cardano.Ledger.State (UTxO (..))
5667
import Cardano.Slotting.EpochInfo (EpochInfo)
5768
import Cardano.Slotting.Time (SystemStart)
5869
import Control.DeepSeq (NFData)
70+
import Control.Monad.Trans.Fail.String (errorFail)
5971
import Data.Aeson (ToJSON)
6072
import Data.Kind (Type)
73+
import Data.List.NonEmpty (NonEmpty, nonEmpty)
6174
import Data.Text (Text)
6275
import GHC.Stack
6376
import NoThunks.Class (NoThunks)
@@ -119,6 +132,8 @@ class
119132
-- be shared between execution of different scripts with the same language version.
120133
data TxInfoResult era :: Type
121134

135+
mkSupportedLanguage :: Language -> Maybe (SupportedLanguage era)
136+
122137
-- | Construct `PlutusTxInfo` for all supported languages in this era.
123138
mkTxInfoResult :: LedgerTxInfo era -> TxInfoResult era
124139

@@ -129,7 +144,9 @@ class
129144
-- unsupported plutus language version.
130145
lookupTxInfoResult ::
131146
EraPlutusTxInfo l era =>
132-
SLanguage l -> TxInfoResult era -> Either (ContextError era) (PlutusTxInfo l)
147+
SLanguage l ->
148+
TxInfoResult era ->
149+
Either (ContextError era) (PlutusTxInfo l)
133150

134151
mkPlutusWithContext ::
135152
PlutusScript era ->
@@ -193,3 +210,78 @@ type family PlutusTxInfo (l :: Language) where
193210
PlutusTxInfo 'PlutusV1 = PV1.TxInfo
194211
PlutusTxInfo 'PlutusV2 = PV2.TxInfo
195212
PlutusTxInfo 'PlutusV3 = PV3.TxInfo
213+
214+
-- | This is just like `mkPlutusScript`, except it is guaranteed to be total through the enforcement
215+
-- of support by the type system and `EraPlutusTxInfo` type class instances for supported plutus
216+
-- versions.
217+
mkSupportedPlutusScript ::
218+
forall l era.
219+
(HasCallStack, EraPlutusTxInfo l era) =>
220+
Plutus l ->
221+
PlutusScript era
222+
mkSupportedPlutusScript plutus =
223+
case mkPlutusScript plutus of
224+
Nothing ->
225+
error $
226+
"Impossible: "
227+
++ show plutus
228+
++ " language version should be supported by the "
229+
++ eraName @era
230+
Just plutusScript -> plutusScript
231+
232+
-- | This is just like `mkBinaryPlutusScript`, except it is guaranteed to be total through the enforcement
233+
-- of support by the type system and `EraPlutusTxInfo` type class instances (via calling `mkSupportedPlutusScript) for supported plutus
234+
-- versions.
235+
mkSupportedBinaryPlutusScript ::
236+
forall era.
237+
(HasCallStack, AlonzoEraScript era) =>
238+
SupportedLanguage era ->
239+
PlutusBinary ->
240+
PlutusScript era
241+
mkSupportedBinaryPlutusScript supportedLanguage plutus =
242+
case supportedLanguage of
243+
SupportedLanguage sLang ->
244+
mkSupportedPlutusScript (asSLanguage sLang (Plutus plutus))
245+
246+
data SupportedLanguage era where
247+
SupportedLanguage :: EraPlutusTxInfo l era => SLanguage l -> SupportedLanguage era
248+
249+
instance Show (SupportedLanguage era) where
250+
show (SupportedLanguage sLang) = "(SupportedLanguage (" ++ show sLang ++ "))"
251+
252+
instance Eq (SupportedLanguage era) where
253+
SupportedLanguage sLang1 == SupportedLanguage sLang2 =
254+
plutusLanguage sLang1 == plutusLanguage sLang2
255+
256+
instance Ord (SupportedLanguage era) where
257+
compare (SupportedLanguage sLang1) (SupportedLanguage sLang2) =
258+
compare (plutusLanguage sLang1) (plutusLanguage sLang2)
259+
260+
instance Era era => EncCBOR (SupportedLanguage era) where
261+
encCBOR (SupportedLanguage sLang) = encCBOR sLang
262+
263+
instance EraPlutusContext era => DecCBOR (SupportedLanguage era) where
264+
decCBOR = decCBOR >>= mkSupportedLanguageM
265+
266+
supportedLanguages ::
267+
forall era.
268+
(HasCallStack, EraPlutusContext era) =>
269+
NonEmpty (SupportedLanguage era)
270+
supportedLanguages =
271+
let langs =
272+
[ errorFail (mkSupportedLanguageM lang)
273+
| lang <- [minBound .. eraMaxLanguage @era]
274+
]
275+
in case nonEmpty langs of
276+
Nothing -> error "Impossible: there are no supported languages"
277+
Just neLangs -> neLangs
278+
279+
mkSupportedLanguageM ::
280+
forall era m.
281+
(EraPlutusContext era, MonadFail m) =>
282+
Language ->
283+
m (SupportedLanguage era)
284+
mkSupportedLanguageM lang =
285+
case mkSupportedLanguage lang of
286+
Nothing -> fail $ show lang ++ " language is not supported in " ++ eraName @era
287+
Just supportedLanguage -> pure supportedLanguage

eras/alonzo/impl/src/Cardano/Ledger/Alonzo/Plutus/TxInfo.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ instance EraPlutusContext AlonzoEra where
165165
newtype TxInfoResult AlonzoEra
166166
= AlonzoTxInfoResult (Either (ContextError AlonzoEra) (PlutusTxInfo 'PlutusV1))
167167

168+
mkSupportedLanguage = \case
169+
PlutusV1 -> Just $ SupportedLanguage SPlutusV1
170+
_lang -> Nothing
171+
168172
mkTxInfoResult = AlonzoTxInfoResult . toPlutusTxInfo SPlutusV1
169173

170174
lookupTxInfoResult SPlutusV1 (AlonzoTxInfoResult tirPlutusV1) = tirPlutusV1

eras/babbage/impl/src/Cardano/Ledger/Babbage/TxInfo.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import Cardano.Ledger.Alonzo.Plutus.Context (
3333
LedgerTxInfo (..),
3434
PlutusScriptPurpose,
3535
PlutusTxInfo,
36+
SupportedLanguage (..),
3637
lookupTxInfoResultImpossible,
3738
toPlutusWithContext,
3839
)
@@ -228,6 +229,11 @@ instance EraPlutusContext BabbageEra where
228229
(Either (ContextError BabbageEra) (PlutusTxInfo 'PlutusV1))
229230
(Either (ContextError BabbageEra) (PlutusTxInfo 'PlutusV2))
230231

232+
mkSupportedLanguage = \case
233+
PlutusV1 -> Just $ SupportedLanguage SPlutusV1
234+
PlutusV2 -> Just $ SupportedLanguage SPlutusV2
235+
_lang -> Nothing
236+
231237
mkTxInfoResult lti = BabbageTxInfoResult (toPlutusTxInfo SPlutusV1 lti) (toPlutusTxInfo SPlutusV2 lti)
232238

233239
lookupTxInfoResult SPlutusV1 (BabbageTxInfoResult tirPlutusV1 _) = tirPlutusV1

eras/conway/impl/src/Cardano/Ledger/Conway/TxInfo.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import Cardano.Ledger.Alonzo.Plutus.Context (
3737
LedgerTxInfo (..),
3838
PlutusTxCert,
3939
PlutusTxInfo,
40+
SupportedLanguage (..),
4041
toPlutusWithContext,
4142
)
4243
import Cardano.Ledger.Alonzo.Plutus.TxInfo (AlonzoContextError (..), TxOutSource (..))
@@ -137,6 +138,11 @@ instance EraPlutusContext ConwayEra where
137138
(Either (ContextError ConwayEra) (PlutusTxInfo 'PlutusV2))
138139
(Either (ContextError ConwayEra) (PlutusTxInfo 'PlutusV3))
139140

141+
mkSupportedLanguage = \case
142+
PlutusV1 -> Just $ SupportedLanguage SPlutusV1
143+
PlutusV2 -> Just $ SupportedLanguage SPlutusV2
144+
PlutusV3 -> Just $ SupportedLanguage SPlutusV3
145+
140146
mkTxInfoResult lti =
141147
ConwayTxInfoResult
142148
(toPlutusTxInfo SPlutusV1 lti)

0 commit comments

Comments
 (0)