From c36601377a481fa721216a9d7fcdd54c9f73c40c Mon Sep 17 00:00:00 2001 From: Duncan Coutts Date: Thu, 3 Jun 2021 00:17:24 +0100 Subject: [PATCH] Split ScriptData out of the Script module It'll be getting larger once we add JSON serialisation. --- cardano-api/cardano-api.cabal | 1 + cardano-api/src/Cardano/Api/Script.hs | 78 +------------- cardano-api/src/Cardano/Api/ScriptData.hs | 124 ++++++++++++++++++++++ 3 files changed, 128 insertions(+), 75 deletions(-) create mode 100644 cardano-api/src/Cardano/Api/ScriptData.hs diff --git a/cardano-api/cardano-api.cabal b/cardano-api/cardano-api.cabal index 51eb78229bd..1aa89f03275 100644 --- a/cardano-api/cardano-api.cabal +++ b/cardano-api/cardano-api.cabal @@ -72,6 +72,7 @@ library Cardano.Api.ProtocolParameters Cardano.Api.Query Cardano.Api.Script + Cardano.Api.ScriptData Cardano.Api.SerialiseBech32 Cardano.Api.SerialiseCBOR Cardano.Api.SerialiseJSON diff --git a/cardano-api/src/Cardano/Api/Script.hs b/cardano-api/src/Cardano/Api/Script.hs index de59ca74017..1340a2fd30a 100644 --- a/cardano-api/src/Cardano/Api/Script.hs +++ b/cardano-api/src/Cardano/Api/Script.hs @@ -95,7 +95,6 @@ module Cardano.Api.Script ( import Prelude import Data.Word (Word64) -import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS import Data.ByteString.Short (ShortByteString) import qualified Data.ByteString.Short as SBS @@ -128,24 +127,22 @@ import Cardano.Slotting.Slot (SlotNo) import qualified Cardano.Ledger.Core as Ledger import qualified Cardano.Ledger.Era as Ledger -import qualified Cardano.Ledger.SafeHash as Ledger import qualified Cardano.Ledger.ShelleyMA.Timelocks as Timelock import Ouroboros.Consensus.Shelley.Eras (StandardCrypto) import qualified Cardano.Ledger.Keys as Shelley import qualified Shelley.Spec.Ledger.Scripts as Shelley -import qualified Cardano.Ledger.Alonzo.Data as Alonzo import qualified Cardano.Ledger.Alonzo.Language as Alonzo import qualified Cardano.Ledger.Alonzo.Scripts as Alonzo -import qualified Plutus.V1.Ledger.Api as Plutus import qualified Plutus.V1.Ledger.Examples as Plutus import Cardano.Api.Eras import Cardano.Api.HasTypeProxy import Cardano.Api.Hash import Cardano.Api.KeysShelley +import Cardano.Api.ScriptData import Cardano.Api.SerialiseCBOR import Cardano.Api.SerialiseJSON import Cardano.Api.SerialiseRaw @@ -669,6 +666,8 @@ instance Eq (ScriptWitness witctx era) where (==) _ _ = False +type ScriptRedeemer = ScriptData + data ScriptDatum witctx where ScriptDatumForTxIn :: ScriptData -> ScriptDatum WitCtxTxIn NoScriptDatumForMint :: ScriptDatum WitCtxMint @@ -720,77 +719,6 @@ deriving instance Eq (ScriptWitnessInCtx witctx) deriving instance Show (ScriptWitnessInCtx witctx) --- ---------------------------------------------------------------------------- --- Script data --- - -type ScriptRedeemer = ScriptData - -data ScriptData = ScriptDataConstructor Integer [ScriptData] - | ScriptDataMap [(ScriptData, ScriptData)] - | ScriptDataList [ScriptData] - | ScriptDataNumber Integer - | ScriptDataBytes BS.ByteString - deriving (Eq, Ord, Show) - -- Note the order of constructors is the same as the Plutus definitions - -- so that the Ord instance is consistent with the Plutus one. - -- This is checked by prop_ord_distributive_ScriptData - -instance HasTypeProxy ScriptData where - data AsType ScriptData = AsScriptData - proxyToAsType _ = AsScriptData - -toAlonzoData :: ScriptData -> Alonzo.Data ledgerera -toAlonzoData = Alonzo.Data . toPlutusData - -fromAlonzoData :: Alonzo.Data ledgerera -> ScriptData -fromAlonzoData = fromPlutusData . Alonzo.getPlutusData - - -toPlutusData :: ScriptData -> Plutus.Data -toPlutusData (ScriptDataConstructor int xs) - = Plutus.Constr int - [ toPlutusData x | x <- xs ] -toPlutusData (ScriptDataMap kvs) = Plutus.Map - [ (toPlutusData k, toPlutusData v) - | (k,v) <- kvs ] -toPlutusData (ScriptDataList xs) = Plutus.List - [ toPlutusData x | x <- xs ] -toPlutusData (ScriptDataNumber n) = Plutus.I n -toPlutusData (ScriptDataBytes bs) = Plutus.B bs - -fromPlutusData :: Plutus.Data -> ScriptData -fromPlutusData (Plutus.Constr int xs) - = ScriptDataConstructor int - [ fromPlutusData x | x <- xs ] -fromPlutusData (Plutus.Map kvs) = ScriptDataMap - [ (fromPlutusData k, fromPlutusData v) - | (k,v) <- kvs ] -fromPlutusData (Plutus.List xs) = ScriptDataList - [ fromPlutusData x | x <- xs ] -fromPlutusData (Plutus.I n) = ScriptDataNumber n -fromPlutusData (Plutus.B bs) = ScriptDataBytes bs - - -newtype instance Hash ScriptData = - ScriptDataHash (Alonzo.DataHash StandardCrypto) - deriving stock (Eq, Ord) - deriving (Show, IsString) via UsingRawBytesHex (Hash ScriptData) - -instance SerialiseAsRawBytes (Hash ScriptData) where - serialiseToRawBytes (ScriptDataHash dh) = - Crypto.hashToBytes (Ledger.extractHash dh) - - deserialiseFromRawBytes (AsHash AsScriptData) bs = - ScriptDataHash . Ledger.unsafeMakeSafeHash <$> Crypto.hashFromBytes bs - -instance ToJSON (Hash ScriptData) where - toJSON = toJSON . serialiseToRawBytesHexText - -instance Aeson.ToJSONKey (Hash ScriptData) where - toJSONKey = Aeson.toJSONKeyText serialiseToRawBytesHexText - - -- ---------------------------------------------------------------------------- -- Script execution units -- diff --git a/cardano-api/src/Cardano/Api/ScriptData.hs b/cardano-api/src/Cardano/Api/ScriptData.hs new file mode 100644 index 00000000000..83c223f0b64 --- /dev/null +++ b/cardano-api/src/Cardano/Api/ScriptData.hs @@ -0,0 +1,124 @@ +{-# LANGUAGE DerivingVia #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} + +module Cardano.Api.ScriptData ( + -- * Script data + ScriptData(..), + + -- * Internal conversion functions + toPlutusData, + fromPlutusData, + toAlonzoData, + fromAlonzoData, + + -- * Data family instances + AsType(..), + Hash(..), + ) where + +import Prelude + +import qualified Data.ByteString as BS +import Data.String (IsString) + +import qualified Data.Aeson as Aeson +import qualified Data.Aeson.Types as Aeson + +import qualified Cardano.Crypto.Hash.Class as Crypto + +import qualified Cardano.Ledger.SafeHash as Ledger + +import Ouroboros.Consensus.Shelley.Eras (StandardCrypto) + +import qualified Cardano.Ledger.Alonzo.Data as Alonzo + +import qualified Plutus.V1.Ledger.Api as Plutus + +import Cardano.Api.Eras +import Cardano.Api.HasTypeProxy +import Cardano.Api.Hash +import Cardano.Api.KeysShelley +import Cardano.Api.SerialiseJSON +import Cardano.Api.SerialiseRaw + + +-- ---------------------------------------------------------------------------- +-- Script data +-- + +data ScriptData = ScriptDataConstructor Integer [ScriptData] + | ScriptDataMap [(ScriptData, ScriptData)] + | ScriptDataList [ScriptData] + | ScriptDataNumber Integer + | ScriptDataBytes BS.ByteString + deriving (Eq, Ord, Show) + -- Note the order of constructors is the same as the Plutus definitions + -- so that the Ord instance is consistent with the Plutus one. + -- This is checked by prop_ord_distributive_ScriptData + +instance HasTypeProxy ScriptData where + data AsType ScriptData = AsScriptData + proxyToAsType _ = AsScriptData + + +-- ---------------------------------------------------------------------------- +-- Script data hash +-- + +newtype instance Hash ScriptData = + ScriptDataHash (Alonzo.DataHash StandardCrypto) + deriving stock (Eq, Ord) + deriving (Show, IsString) via UsingRawBytesHex (Hash ScriptData) + +instance SerialiseAsRawBytes (Hash ScriptData) where + serialiseToRawBytes (ScriptDataHash dh) = + Crypto.hashToBytes (Ledger.extractHash dh) + + deserialiseFromRawBytes (AsHash AsScriptData) bs = + ScriptDataHash . Ledger.unsafeMakeSafeHash <$> Crypto.hashFromBytes bs + +instance ToJSON (Hash ScriptData) where + toJSON = toJSON . serialiseToRawBytesHexText + +instance Aeson.ToJSONKey (Hash ScriptData) where + toJSONKey = Aeson.toJSONKeyText serialiseToRawBytesHexText + + +-- ---------------------------------------------------------------------------- +-- Conversion functions +-- + +toAlonzoData :: ScriptData -> Alonzo.Data ledgerera +toAlonzoData = Alonzo.Data . toPlutusData + +fromAlonzoData :: Alonzo.Data ledgerera -> ScriptData +fromAlonzoData = fromPlutusData . Alonzo.getPlutusData + + +toPlutusData :: ScriptData -> Plutus.Data +toPlutusData (ScriptDataConstructor int xs) + = Plutus.Constr int + [ toPlutusData x | x <- xs ] +toPlutusData (ScriptDataMap kvs) = Plutus.Map + [ (toPlutusData k, toPlutusData v) + | (k,v) <- kvs ] +toPlutusData (ScriptDataList xs) = Plutus.List + [ toPlutusData x | x <- xs ] +toPlutusData (ScriptDataNumber n) = Plutus.I n +toPlutusData (ScriptDataBytes bs) = Plutus.B bs + + +fromPlutusData :: Plutus.Data -> ScriptData +fromPlutusData (Plutus.Constr int xs) + = ScriptDataConstructor int + [ fromPlutusData x | x <- xs ] +fromPlutusData (Plutus.Map kvs) = ScriptDataMap + [ (fromPlutusData k, fromPlutusData v) + | (k,v) <- kvs ] +fromPlutusData (Plutus.List xs) = ScriptDataList + [ fromPlutusData x | x <- xs ] +fromPlutusData (Plutus.I n) = ScriptDataNumber n +fromPlutusData (Plutus.B bs) = ScriptDataBytes bs +