Skip to content

Commit 0880e7e

Browse files
authored
Merge pull request #1156 from IntersectMBO/jordan/1240-has-text-envelope-any-plutus-script
Add text envelope serialisation for AnyPlutusScript
2 parents 527b170 + 9239e07 commit 0880e7e

4 files changed

Lines changed: 76 additions & 2 deletions

File tree

cardano-api/src/Cardano/Api/Experimental.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ module Cardano.Api.Experimental
6767
-- ** Plutus related
6868
, PlutusScriptInEra (..)
6969
, PlutusScriptOrReferenceInput (..)
70+
, serialiseAnyPlutusScriptToTextEnvelope
71+
, deserialiseAnyPlutusScriptFromTextEnvelope
7072
, IndexedPlutusScriptWitness (..)
7173
, PlutusScriptPurpose (..)
7274
, PlutusScriptDatum (..)

cardano-api/src/Cardano/Api/Experimental/Plutus.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ module Cardano.Api.Experimental.Plutus
22
( -- * Plutus Script
33
AnyPlutusScript (..)
44
, decodeAnyPlutusScript
5+
, serialiseAnyPlutusScriptToTextEnvelope
6+
, deserialiseAnyPlutusScriptFromTextEnvelope
57
, PlutusScriptInEra (..)
68
, AnyPlutusScriptLanguage (..)
79
, deserialisePlutusScriptInEra

cardano-api/src/Cardano/Api/Experimental/Plutus/Internal/Script.hs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
module Cardano.Api.Experimental.Plutus.Internal.Script
1212
( AnyPlutusScript (..)
1313
, decodeAnyPlutusScript
14+
, serialiseAnyPlutusScriptToTextEnvelope
15+
, deserialiseAnyPlutusScriptFromTextEnvelope
1416
, AnyPlutusScriptLanguage (..)
1517
, PlutusScriptInEra (..)
1618
, PlutusScriptOrReferenceInput (..)
@@ -115,8 +117,11 @@ instance
115117
)
116118
=> SerialiseAsCBOR (PlutusScriptInEra (lang :: L.Language) era)
117119
where
120+
-- The 'PlutusBinary' stored in the 'PlutusRunnable' already contains
121+
-- CBOR-wrapped Flat-encoded UPLC bytes (see 'Cardano.Ledger.Plutus.Language'),
122+
-- so we extract them directly rather than re-encoding with 'L.serialize''.
118123
serialiseToCBOR (PlutusScriptInEra s) =
119-
L.serialize' (L.eraProtVerHigh @era) s
124+
SBS.fromShort . L.unPlutusBinary . L.plutusBinary $ L.plutusFromRunnable s
120125

121126
deserialiseFromCBOR _ bs = do
122127
let v = L.eraProtVerHigh @era
@@ -179,6 +184,15 @@ data AnyPlutusScript era where
179184
:: (L.Era era, Typeable lang, L.PlutusLanguage lang)
180185
=> PlutusScriptInEra lang era -> AnyPlutusScript era
181186

187+
instance Show (AnyPlutusScript era) where
188+
show (AnyPlutusScript ps) = "AnyPlutusScript " ++ show ps
189+
190+
instance Eq (AnyPlutusScript era) where
191+
AnyPlutusScript (ps1 :: PlutusScriptInEra lang1 era) == AnyPlutusScript (ps2 :: PlutusScriptInEra lang2 era) =
192+
case eqT @lang1 @lang2 of
193+
Just Refl -> ps1 == ps2
194+
Nothing -> False
195+
182196
decodeAnyPlutusScript
183197
:: L.Era era
184198
=> ByteString
@@ -201,3 +215,32 @@ data AnyPlutusScriptLanguage where
201215
AnyPlutusScriptLanguage
202216
:: L.PlutusLanguage lang
203217
=> L.SLanguage lang -> AnyPlutusScriptLanguage
218+
219+
-- | Serialise an 'AnyPlutusScript' to a 'TextEnvelope'. The text envelope type
220+
-- is determined by the Plutus language version of the script.
221+
serialiseAnyPlutusScriptToTextEnvelope
222+
:: Maybe TextEnvelopeDescr -> AnyPlutusScript era -> TextEnvelope
223+
serialiseAnyPlutusScriptToTextEnvelope mbDescr (AnyPlutusScript script) =
224+
obtainLangConstraints (plutusScriptInEraSLanguage script) $
225+
serialiseToTextEnvelope mbDescr script
226+
227+
-- | Deserialise an 'AnyPlutusScript' from a 'TextEnvelope'. The text envelope type
228+
-- is matched against all known Plutus language versions derived from
229+
-- 'Plutus.nonNativeLanguages', so new language versions are picked up automatically.
230+
deserialiseAnyPlutusScriptFromTextEnvelope
231+
:: forall era
232+
. L.Era era
233+
=> TextEnvelope
234+
-> Either TextEnvelopeError (AnyPlutusScript era)
235+
deserialiseAnyPlutusScriptFromTextEnvelope =
236+
deserialiseFromTextEnvelopeAnyOf textEnvTypes
237+
where
238+
textEnvTypes :: [FromSomeType HasTextEnvelope (AnyPlutusScript era)]
239+
textEnvTypes =
240+
map
241+
( \l ->
242+
Plutus.withSLanguage l $ \(slang :: Plutus.SLanguage l) ->
243+
obtainLangConstraints slang $
244+
FromSomeType (asType @(PlutusScriptInEra l era)) AnyPlutusScript
245+
)
246+
Plutus.nonNativeLanguages

cardano-api/test/cardano-api-test/Test/Cardano/Api/Transaction/Body/Plutus/Scripts.hs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,26 @@ module Test.Cardano.Api.Transaction.Body.Plutus.Scripts
88
)
99
where
1010

11-
import Cardano.Api (AlonzoEraOnwards (..))
11+
import Cardano.Api (AlonzoEraOnwards (..), proxyToAsType)
1212
import Cardano.Api qualified as Api
1313
import Cardano.Api.Experimental
1414
import Cardano.Api.Experimental.AnyScriptWitness
1515
import Cardano.Api.Experimental.Plutus hiding (AnyPlutusScript (..))
16+
import Cardano.Api.Experimental.Plutus qualified as Plutus
1617
import Cardano.Api.Experimental.Tx qualified as Exp
1718
import Cardano.Api.Ledger qualified as L
19+
import Cardano.Api.Serialise.Cbor (SerialiseAsCBOR (..))
1820

1921
import Cardano.Ledger.Conway qualified as L
2022
import Cardano.Ledger.Core qualified as L
23+
import Cardano.Ledger.Plutus.Language qualified as L
2124

2225
import Prelude
2326

2427
import Data.Function
2528
import Data.List qualified as List
2629
import Data.Map.Strict qualified as Map
30+
import Data.Proxy (Proxy (..))
2731

2832
import Test.Gen.Cardano.Api.Experimental qualified as Exp
2933
import Test.Gen.Cardano.Api.Typed
@@ -55,6 +59,23 @@ prop_compare_plutus_script_hashes = property $ do
5559

5660
hash === anyScriptHash
5761

62+
prop_roundtrip_plutus_script_in_era_cbor :: Property
63+
prop_roundtrip_plutus_script_in_era_cbor = property $ do
64+
scriptInEra <- forAll genPlutusScriptInEra
65+
tripping
66+
scriptInEra
67+
serialiseToCBOR
68+
(deserialiseFromCBOR (proxyToAsType (Proxy @(PlutusScriptInEra L.PlutusV3 (LedgerEra ConwayEra)))))
69+
70+
prop_roundtrip_any_plutus_script_text_envelope :: Property
71+
prop_roundtrip_any_plutus_script_text_envelope = property $ do
72+
scriptInEra <- forAll genPlutusScriptInEra
73+
let anyScript = Plutus.AnyPlutusScript scriptInEra
74+
tripping
75+
anyScript
76+
(serialiseAnyPlutusScriptToTextEnvelope Nothing)
77+
(deserialiseAnyPlutusScriptFromTextEnvelope @(LedgerEra ConwayEra))
78+
5879
-- | This property checks that the redeemer pointer map is constructed correctly.
5980
-- Previously identical script purposes were being created and overwriting each other
6081
-- in the redeemer pointer map.
@@ -214,6 +235,12 @@ tests =
214235
testGroup
215236
"Test.Cardano.Api.Transaction.Body.Plutus.Scripts"
216237
[ testProperty "prop_compare_plutus_script_hashes" prop_compare_plutus_script_hashes
238+
, testProperty
239+
"prop_roundtrip_plutus_script_in_era_cbor"
240+
prop_roundtrip_plutus_script_in_era_cbor
241+
, testProperty
242+
"prop_roundtrip_any_plutus_script_text_envelope"
243+
prop_roundtrip_any_plutus_script_text_envelope
217244
, testProperty
218245
"prop_extractAllIndexedPlutusScriptWitnesses"
219246
prop_extractAllIndexedPlutusScriptWitnesses

0 commit comments

Comments
 (0)