Skip to content

Commit c377787

Browse files
authored
Merge pull request #5021 from IntersectMBO/lehins/add-supported-languages
Add `SupportedLanguage`
2 parents 21b6bd9 + a693f52 commit c377787

File tree

20 files changed

+343
-207
lines changed

20 files changed

+343
-207
lines changed

eras/alonzo/impl/CHANGELOG.md

+5
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'`
@@ -16,6 +18,9 @@
1618

1719
### `testlib`
1820

21+
* Deprecated `mkPlutusScript'`
22+
* Change type signature of `genPlutusScript`, `genNativeScript`, `genAlonzoScript`, `alwaysSucceedsLang` and `alwaysFailsLang`.
23+
* Remove `TxInfoLanguage` and `mkTxInfoLanguage`
1924
* Added `Era` module with `AlonzoEraTest` class
2025

2126
## 1.13.0.0

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ library
7676
-Wunused-packages
7777

7878
build-depends:
79+
FailT,
7980
aeson >=2.2,
8081
base >=4.14 && <5,
8182
base64-bytestring,
@@ -142,7 +143,6 @@ library testlib
142143

143144
build-depends:
144145
HUnit,
145-
QuickCheck,
146146
base,
147147
bytestring,
148148
cardano-data:{cardano-data, testlib},

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

+96-4
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

+4
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/alonzo/impl/testlib/Test/Cardano/Ledger/Alonzo/Arbitrary.hs

+41-28
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ import Cardano.Ledger.Alonzo (AlonzoEra)
3838
import Cardano.Ledger.Alonzo.Core
3939
import Cardano.Ledger.Alonzo.Genesis (AlonzoGenesis (..))
4040
import Cardano.Ledger.Alonzo.PParams (AlonzoPParams (AlonzoPParams), OrdExUnits (OrdExUnits))
41-
import Cardano.Ledger.Alonzo.Plutus.Context (ContextError)
41+
import Cardano.Ledger.Alonzo.Plutus.Context (
42+
EraPlutusContext (ContextError),
43+
EraPlutusTxInfo,
44+
SupportedLanguage (..),
45+
mkSupportedPlutusScript,
46+
supportedLanguages,
47+
)
4248
import Cardano.Ledger.Alonzo.Plutus.Evaluate (CollectError)
4349
import Cardano.Ledger.Alonzo.Plutus.TxInfo (AlonzoContextError)
4450
import Cardano.Ledger.Alonzo.Rules (
@@ -78,11 +84,11 @@ import Cardano.Ledger.Plutus.Language (
7884
PlutusLanguage,
7985
asSLanguage,
8086
plutusLanguage,
81-
withSLanguage,
8287
)
8388
import Cardano.Ledger.Shelley.Rules (PredicateFailure, ShelleyUtxowPredFailure)
8489
import Data.Functor.Identity (Identity)
8590
import Data.List.NonEmpty (NonEmpty ((:|)))
91+
import qualified Data.List.NonEmpty as NE (toList)
8692
import qualified Data.Map.Strict as Map
8793
import qualified Data.MapExtras as Map (fromElems)
8894
import qualified Data.Set as Set
@@ -196,41 +202,39 @@ instance
196202
genEraLanguage :: forall era. AlonzoEraScript era => Gen Language
197203
genEraLanguage = choose (minBound, eraMaxLanguage @era)
198204

205+
instance EraPlutusContext era => Arbitrary (SupportedLanguage era) where
206+
arbitrary = elements $ NE.toList (supportedLanguages @era)
207+
199208
instance
200-
( AlonzoEraScript era
209+
( EraPlutusContext era
201210
, Script era ~ AlonzoScript era
202211
, NativeScript era ~ Timelock era
203212
) =>
204213
Arbitrary (AlonzoScript era)
205214
where
206-
arbitrary = genEraLanguage @era >>= genAlonzoScript
215+
arbitrary = arbitrary >>= genAlonzoScript
207216

208217
genAlonzoScript ::
209-
( AlonzoEraScript era
218+
( EraPlutusContext era
210219
, Script era ~ AlonzoScript era
211220
, NativeScript era ~ Timelock era
212221
) =>
213-
Language ->
222+
SupportedLanguage era ->
214223
Gen (AlonzoScript era)
215224
genAlonzoScript lang =
216225
frequency
217-
[ (2, genPlutusScript lang)
218-
, (8, genNativeScript)
226+
[ (2, fromPlutusScript <$> genPlutusScript lang)
227+
, (8, fromNativeScript <$> genNativeScript)
219228
]
220229

221230
genNativeScript ::
222-
( AlonzoEraScript era
223-
, NativeScript era ~ Timelock era
224-
) =>
225-
Gen (AlonzoScript era)
226-
genNativeScript = TimelockScript <$> arbitrary
231+
Arbitrary (NativeScript era) =>
232+
Gen (NativeScript era)
233+
genNativeScript = arbitrary
227234

228235
genPlutusScript ::
229-
( AlonzoEraScript era
230-
, Script era ~ AlonzoScript era
231-
) =>
232-
Language ->
233-
Gen (AlonzoScript era)
236+
SupportedLanguage era ->
237+
Gen (PlutusScript era)
234238
genPlutusScript lang =
235239
frequency
236240
[ (5, alwaysSucceedsLang lang <$> elements [1, 2, 3])
@@ -436,25 +440,33 @@ instance Arbitrary AlonzoGenesis where
436440

437441
alwaysSucceeds ::
438442
forall l era.
439-
(HasCallStack, PlutusLanguage l, AlonzoEraScript era) =>
443+
(HasCallStack, EraPlutusTxInfo l era) =>
440444
Natural ->
441445
Script era
442-
alwaysSucceeds n = mkPlutusScript' (alwaysSucceedsPlutus @l n)
446+
alwaysSucceeds = fromPlutusScript . mkSupportedPlutusScript . alwaysSucceedsPlutus @l
443447

444448
alwaysFails ::
445449
forall l era.
446-
(HasCallStack, PlutusLanguage l, AlonzoEraScript era) =>
450+
(HasCallStack, EraPlutusTxInfo l era) =>
447451
Natural ->
448452
Script era
449-
alwaysFails n = mkPlutusScript' (alwaysFailsPlutus @l n)
453+
alwaysFails = fromPlutusScript . mkSupportedPlutusScript . alwaysFailsPlutus @l
450454

451-
alwaysSucceedsLang :: (HasCallStack, AlonzoEraScript era) => Language -> Natural -> Script era
452-
alwaysSucceedsLang lang n =
453-
withSLanguage lang $ \slang -> mkPlutusScript' $ asSLanguage slang (alwaysSucceedsPlutus n)
455+
alwaysSucceedsLang ::
456+
SupportedLanguage era ->
457+
Natural ->
458+
PlutusScript era
459+
alwaysSucceedsLang supportedLanguage n =
460+
case supportedLanguage of
461+
SupportedLanguage slang -> mkSupportedPlutusScript $ asSLanguage slang (alwaysSucceedsPlutus n)
454462

455-
alwaysFailsLang :: (HasCallStack, AlonzoEraScript era) => Language -> Natural -> Script era
456-
alwaysFailsLang lang n =
457-
withSLanguage lang $ \slang -> mkPlutusScript' $ asSLanguage slang (alwaysFailsPlutus n)
463+
alwaysFailsLang ::
464+
SupportedLanguage era ->
465+
Natural ->
466+
PlutusScript era
467+
alwaysFailsLang supportedLanguage n =
468+
case supportedLanguage of
469+
SupportedLanguage slang -> mkSupportedPlutusScript $ asSLanguage slang (alwaysFailsPlutus n)
458470

459471
-- | Partial version of `mkPlutusScript`
460472
mkPlutusScript' ::
@@ -468,3 +480,4 @@ mkPlutusScript' plutus =
468480
error $
469481
"Plutus version " ++ show (plutusLanguage plutus) ++ " is not supported in " ++ eraName @era
470482
Just plutusScript -> fromPlutusScript plutusScript
483+
{-# DEPRECATED mkPlutusScript' "In favor of `fromPlutusScript` . `mkSupportedPlutusScript`" #-}

0 commit comments

Comments
 (0)