diff --git a/cardano-api/internal/Cardano/Api/Script.hs b/cardano-api/internal/Cardano/Api/Script.hs index 730265f95e..d396b14871 100644 --- a/cardano-api/internal/Cardano/Api/Script.hs +++ b/cardano-api/internal/Cardano/Api/Script.hs @@ -40,9 +40,8 @@ module Cardano.Api.Script , ScriptInAnyLang (..) , toScriptInAnyLang , exampleDoubleEncodedBytes - , isPlutusScriptDoubleEncoded + , removePlutusScriptDoubleEncoding , exampleDoubleEncodedBytesEncoding - , IsDoubleEncoded (..) -- * Scripts in an era , ScriptInEra (..) @@ -462,23 +461,19 @@ instance IsScriptLanguage lang => SerialiseAsCBOR (Script lang) where <$> deserialiseFromCBOR (AsPlutusScript AsPlutusScriptV3) bs -- | Previously we were double encoding the plutus script --- bytes. This decoder is used to check if the plutus --- script bytes are double encoded. If it is, it removes --- a layer of encoding to return the original plutus script bytes. -data IsDoubleEncoded - = -- | Original plutus script bytes - IsDoubleEncoded - Crypto.ByteString - | NotDoubleEncoded - -isPlutusScriptDoubleEncoded :: LBS.ByteString -> IsDoubleEncoded -isPlutusScriptDoubleEncoded plutusScriptBytes = +-- bytes. This function removes a layer of encoding to return +-- the original plutus script bytes if it exists. +removePlutusScriptDoubleEncoding :: LBS.ByteString -> Crypto.ByteString +removePlutusScriptDoubleEncoding plutusScriptBytes = case CBOR.deserialiseFromBytes CBOR.decodeBytes plutusScriptBytes of - Left _ -> NotDoubleEncoded - Right (_, needToEncode) -> - case CBOR.deserialiseFromBytes CBOR.decodeBytes $ LBS.fromStrict needToEncode of - Left _ -> NotDoubleEncoded - Right (_, final) -> IsDoubleEncoded $ CBOR.toStrictByteString $ CBOR.encodeBytes final + Left _ -> LBS.toStrict plutusScriptBytes + Right (_, unwrapped) -> + -- 'unwrapped' is potentially valid plutus bytes i.e it is no longer double encoded + case CBOR.deserialiseFromBytes CBOR.decodeBytes $ LBS.fromStrict unwrapped of + Left _ -> LBS.toStrict plutusScriptBytes + -- We were able to decode a cbor in cbor bytes value. Therefore the original bytes + -- were likely a double encoded plutus script so we can now return the unwrapped bytes. + Right{} -> unwrapped exampleDoubleEncodedBytes :: LBS.ByteString exampleDoubleEncodedBytes = LBS.fromStrict $ CBOR.toStrictByteString exampleDoubleEncodedBytesEncoding @@ -1044,9 +1039,7 @@ data PlutusScript lang where instance HasTypeProxy lang => SerialiseAsCBOR (PlutusScript lang) where serialiseToCBOR (PlutusScriptSerialised sbs) = SBS.fromShort sbs deserialiseFromCBOR _ bs = - case isPlutusScriptDoubleEncoded $ LBS.fromStrict bs of - NotDoubleEncoded -> Right $ PlutusScriptSerialised $ SBS.toShort bs - IsDoubleEncoded normalised -> Right $ PlutusScriptSerialised $ SBS.toShort normalised + Right $ PlutusScriptSerialised $ SBS.toShort $ removePlutusScriptDoubleEncoding $ LBS.fromStrict bs instance HasTypeProxy lang => HasTypeProxy (PlutusScript lang) where data AsType (PlutusScript lang) = AsPlutusScript (AsType lang) @@ -1364,18 +1357,16 @@ instance SBS.fromShort s deserialiseFromCBOR _ bs = do let v = Ledger.eraProtVerLow @(ShelleyLedgerEra era) - shortBsPlutusScript = PlutusScriptSerialised scriptShortBs - scriptShortBs = case isPlutusScriptDoubleEncoded $ LBS.fromStrict bs of - IsDoubleEncoded normalized -> SBS.toShort normalized - NotDoubleEncoded -> SBS.toShort bs + scriptShortBs = SBS.toShort $ removePlutusScriptDoubleEncoding $ LBS.fromStrict bs let plutusScript :: Plutus.Plutus (ToLedgerPlutusLanguage lang) - plutusScript = Plutus.Plutus $ Plutus.PlutusBinary scriptShortBs + plutusScript = PlutusScriptBinary scriptShortBs + plutusScriptInEra = PlutusScriptInEra $ PlutusScriptSerialised scriptShortBs case Plutus.decodePlutusRunnable v plutusScript of Left e -> Left $ CBOR.DecoderErrorCustom "PlutusLedgerApi.Common.ScriptDecodeError" (Text.pack . show $ pretty e) - Right{} -> Right $ PlutusScriptInEra shortBsPlutusScript + Right{} -> Right plutusScriptInEra -- ---------------------------------------------------------------------------- -- JSON serialisation diff --git a/cardano-api/test/cardano-api-test/Test/Cardano/Api/CBOR.hs b/cardano-api/test/cardano-api-test/Test/Cardano/Api/CBOR.hs index 4e5138f737..ebb83ff64a 100644 --- a/cardano-api/test/cardano-api-test/Test/Cardano/Api/CBOR.hs +++ b/cardano-api/test/cardano-api-test/Test/Cardano/Api/CBOR.hs @@ -17,6 +17,7 @@ import Cardano.Api.SerialiseTextEnvelope (TextEnvelopeDescr (TextEnvel import Cardano.Api.Shelley (AsType (..)) import qualified Data.ByteString.Base16 as Base16 +import qualified Data.ByteString.Lazy as LBS import qualified Data.ByteString.Short as SBS import Data.Proxy (Proxy (..)) import qualified Data.Text as T @@ -29,7 +30,6 @@ import Hedgehog (Property, forAll, property, tripping) import qualified Hedgehog as H import qualified Hedgehog.Extras as H import qualified Hedgehog.Gen as Gen -import Hedgehog.Internal.Property (failWith) import qualified Test.Hedgehog.Roundtrip.CBOR as H import Test.Hedgehog.Roundtrip.CBOR import Test.Tasty (TestTree, testGroup) @@ -248,14 +248,10 @@ prop_decode_only_wrapped_plutus_script_V3_CBOR = H.property $ do (AsScript AsPlutusScriptV3) prop_double_encoded_sanity_check :: Property -prop_double_encoded_sanity_check = H.property $ do - case isPlutusScriptDoubleEncoded exampleDoubleEncodedBytes of - NotDoubleEncoded -> - failWith Nothing $ - unlines - [ "Input expected to be double encoded" - ] - IsDoubleEncoded{} -> H.success +prop_double_encoded_sanity_check = H.propertyOnce $ do + let fixed = removePlutusScriptDoubleEncoding exampleDoubleEncodedBytes + + LBS.fromStrict fixed H./== exampleDoubleEncodedBytes prop_roundtrip_ScriptData_CBOR :: Property prop_roundtrip_ScriptData_CBOR = H.property $ do