8
8
{-# LANGUAGE TypeFamilyDependencies #-}
9
9
{-# LANGUAGE UndecidableSuperClasses #-}
10
10
-- 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.
12
15
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
13
16
14
17
module Cardano.Ledger.Alonzo.Plutus.Context (
@@ -17,6 +20,11 @@ module Cardano.Ledger.Alonzo.Plutus.Context (
17
20
EraPlutusContext (.. ),
18
21
toPlutusWithContext ,
19
22
lookupTxInfoResultImpossible ,
23
+ SupportedLanguage (.. ),
24
+ mkSupportedLanguageM ,
25
+ supportedLanguages ,
26
+ mkSupportedPlutusScript ,
27
+ mkSupportedBinaryPlutusScript ,
20
28
21
29
-- * Language dependent translation
22
30
PlutusTxInfo ,
@@ -27,7 +35,7 @@ module Cardano.Ledger.Alonzo.Plutus.Context (
27
35
where
28
36
29
37
import Cardano.Ledger.Alonzo.Scripts (
30
- AlonzoEraScript ,
38
+ AlonzoEraScript ( eraMaxLanguage , mkPlutusScript ) ,
31
39
AsIxItem (.. ),
32
40
PlutusPurpose ,
33
41
PlutusScript (.. ),
@@ -43,21 +51,26 @@ import Cardano.Ledger.Plutus (
43
51
Data ,
44
52
ExUnits ,
45
53
Language (.. ),
46
- Plutus ,
54
+ Plutus ( .. ) ,
47
55
PlutusArgs ,
56
+ PlutusBinary ,
48
57
PlutusLanguage ,
49
58
PlutusRunnable ,
50
59
PlutusScriptContext ,
51
60
PlutusWithContext (.. ),
52
61
SLanguage (.. ),
62
+ asSLanguage ,
53
63
isLanguage ,
64
+ plutusLanguage ,
54
65
)
55
66
import Cardano.Ledger.State (UTxO (.. ))
56
67
import Cardano.Slotting.EpochInfo (EpochInfo )
57
68
import Cardano.Slotting.Time (SystemStart )
58
69
import Control.DeepSeq (NFData )
70
+ import Control.Monad.Trans.Fail.String (errorFail )
59
71
import Data.Aeson (ToJSON )
60
72
import Data.Kind (Type )
73
+ import Data.List.NonEmpty (NonEmpty , nonEmpty )
61
74
import Data.Text (Text )
62
75
import GHC.Stack
63
76
import NoThunks.Class (NoThunks )
@@ -119,6 +132,8 @@ class
119
132
-- be shared between execution of different scripts with the same language version.
120
133
data TxInfoResult era :: Type
121
134
135
+ mkSupportedLanguage :: Language -> Maybe (SupportedLanguage era )
136
+
122
137
-- | Construct `PlutusTxInfo` for all supported languages in this era.
123
138
mkTxInfoResult :: LedgerTxInfo era -> TxInfoResult era
124
139
@@ -129,7 +144,9 @@ class
129
144
-- unsupported plutus language version.
130
145
lookupTxInfoResult ::
131
146
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 )
133
150
134
151
mkPlutusWithContext ::
135
152
PlutusScript era ->
@@ -193,3 +210,78 @@ type family PlutusTxInfo (l :: Language) where
193
210
PlutusTxInfo 'PlutusV1 = PV1. TxInfo
194
211
PlutusTxInfo 'PlutusV2 = PV2. TxInfo
195
212
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
0 commit comments