diff --git a/cardano-api/cardano-api.cabal b/cardano-api/cardano-api.cabal index ae5590c301..6285925c43 100644 --- a/cardano-api/cardano-api.cabal +++ b/cardano-api/cardano-api.cabal @@ -317,8 +317,8 @@ test-suite cardano-api-test build-depends: QuickCheck, aeson >=1.5.6.0, - bytestring, base16-bytestring, + bytestring, cardano-api, cardano-api:gen, cardano-api:internal, diff --git a/cardano-api/internal/Cardano/Api/Script.hs b/cardano-api/internal/Cardano/Api/Script.hs index 9e4a17e748..8b9dd93410 100644 --- a/cardano-api/internal/Cardano/Api/Script.hs +++ b/cardano-api/internal/Cardano/Api/Script.hs @@ -459,23 +459,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 instance IsScriptLanguage lang => HasTextEnvelope (Script lang) where textEnvelopeType _ = @@ -1032,9 +1028,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) @@ -1352,18 +1346,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 679599cbd3..177918a60d 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 @@ -30,7 +31,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) @@ -249,14 +249,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