Skip to content

Commit bf6c10d

Browse files
committed
Add roundtrip tests and fix SerialiseAsCBOR for PlutusScriptInEra
Fix serialiseToCBOR to extract raw script bytes from PlutusRunnable instead of using L.serialize' which adds CBOR framing that deserialiseFromCBOR does not expect. Add CBOR and TextEnvelope roundtrip tests for PlutusScriptInEra and AnyPlutusScript. Add haddocks for the text envelope functions.
1 parent aa48590 commit bf6c10d

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

  • cardano-api
    • src/Cardano/Api/Experimental/Plutus/Internal
    • test/cardano-api-test/Test/Cardano/Api/Transaction/Body/Plutus

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,11 @@ instance
117117
)
118118
=> SerialiseAsCBOR (PlutusScriptInEra (lang :: L.Language) era)
119119
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''.
120123
serialiseToCBOR (PlutusScriptInEra s) =
121-
L.serialize' (L.eraProtVerHigh @era) s
124+
SBS.fromShort . L.unPlutusBinary . L.plutusBinary $ L.plutusFromRunnable s
122125

123126
deserialiseFromCBOR _ bs = do
124127
let v = L.eraProtVerHigh @era
@@ -204,12 +207,17 @@ data AnyPlutusScriptLanguage where
204207
:: L.PlutusLanguage lang
205208
=> L.SLanguage lang -> AnyPlutusScriptLanguage
206209

210+
-- | Serialise an 'AnyPlutusScript' to a 'TextEnvelope'. The text envelope type
211+
-- is determined by the Plutus language version of the script.
207212
serialiseAnyPlutusScriptToTextEnvelope
208213
:: Maybe TextEnvelopeDescr -> AnyPlutusScript era -> TextEnvelope
209214
serialiseAnyPlutusScriptToTextEnvelope mbDescr (AnyPlutusScript script) =
210215
obtainLangConstraints (plutusScriptInEraSLanguage script) $
211216
serialiseToTextEnvelope mbDescr script
212217

218+
-- | Deserialise an 'AnyPlutusScript' from a 'TextEnvelope'. The text envelope type
219+
-- is matched against all known Plutus language versions derived from
220+
-- 'Plutus.nonNativeLanguages', so new language versions are picked up automatically.
213221
deserialiseAnyPlutusScriptFromTextEnvelope
214222
:: forall era
215223
. L.Era era

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

Lines changed: 32 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,27 @@ 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+
-- | Serialise an 'AnyPlutusScript' to a 'TextEnvelope' and deserialise it back.
71+
-- We compare the resulting 'TextEnvelope' values because 'AnyPlutusScript' is
72+
-- existentially quantified and does not have an 'Eq' instance.
73+
prop_roundtrip_any_plutus_script_text_envelope :: Property
74+
prop_roundtrip_any_plutus_script_text_envelope = property $ do
75+
scriptInEra <- forAll genPlutusScriptInEra
76+
let anyScript = Plutus.AnyPlutusScript scriptInEra
77+
envelope = serialiseAnyPlutusScriptToTextEnvelope Nothing anyScript
78+
anyScript' <-
79+
evalEither $ deserialiseAnyPlutusScriptFromTextEnvelope @(LedgerEra ConwayEra) envelope
80+
let envelope' = serialiseAnyPlutusScriptToTextEnvelope Nothing anyScript'
81+
envelope === envelope'
82+
5883
-- | This property checks that the redeemer pointer map is constructed correctly.
5984
-- Previously identical script purposes were being created and overwriting each other
6085
-- in the redeemer pointer map.
@@ -214,6 +239,12 @@ tests =
214239
testGroup
215240
"Test.Cardano.Api.Transaction.Body.Plutus.Scripts"
216241
[ testProperty "prop_compare_plutus_script_hashes" prop_compare_plutus_script_hashes
242+
, testProperty
243+
"prop_roundtrip_plutus_script_in_era_cbor"
244+
prop_roundtrip_plutus_script_in_era_cbor
245+
, testProperty
246+
"prop_roundtrip_any_plutus_script_text_envelope"
247+
prop_roundtrip_any_plutus_script_text_envelope
217248
, testProperty
218249
"prop_extractAllIndexedPlutusScriptWitnesses"
219250
prop_extractAllIndexedPlutusScriptWitnesses

0 commit comments

Comments
 (0)