{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE UndecidableInstances #-}

module Cardano.Api.Experimental.Plutus.Internal.ScriptWitness
  ( PlutusScriptWitness (..)

    -- * Constructing a plutus script witness.
  , PlutusScriptOrReferenceInput (..)
  , ScriptRedeemer
  , PlutusScriptPurpose (..)
  , PlutusScriptDatum (..)
  , NoScriptDatum (..)

    -- * Helpers
  , getSpendingPlutusWitnessData
  , getPlutusScriptRunnable
  , getPlutusScriptWitnessLanguage
  )
where

import Cardano.Api.Experimental.Plutus.Internal.Script
import Cardano.Api.Ledger qualified as L
import Cardano.Api.Plutus.Internal.Script (ExecutionUnits)
import Cardano.Api.Plutus.Internal.ScriptData

import Cardano.Ledger.Plutus.Data qualified as Plutus
import Cardano.Ledger.Plutus.Language qualified as L

import GHC.IsList

{-
To construct a plutus script witness you need:
1. The plutus script or reference input
2. A redeemer
3. The thing being witnessed

This is true regardless of the plutus script version.

-}

type ScriptRedeemer = HashableScriptData

-- | This is a Plutus script witness. It possesses:
-- 1. The plutus script or reference input
-- 2. The script redeemer
-- 3. The execution units
-- 4. Potentially a script datum. See the PlutusScriptDatum type family for more details.
--
-- Note that Plutus script witnesses do not exist on their own. They must witness something
-- and a redeemer pointer must be constucted to point to the thing being witnessed.
-- See 'IndexedPlutusScriptWitness' for more details.
data PlutusScriptWitness (lang :: L.Language) (purpose :: PlutusScriptPurpose) era where
  PlutusScriptWitness
    :: L.SLanguage lang
    -> PlutusScriptOrReferenceInput lang era
    -> PlutusScriptDatum lang purpose
    -> ScriptRedeemer
    -> ExecutionUnits
    -> PlutusScriptWitness lang purpose era

deriving instance Show (PlutusScriptWitness lang purpose era)

instance Eq (PlutusScriptWitness L.PlutusV1 SpendingScript era) where
  == :: PlutusScriptWitness 'PlutusV1 'SpendingScript era
-> PlutusScriptWitness 'PlutusV1 'SpendingScript era -> Bool
(==) (PlutusScriptWitness SLanguage 'PlutusV1
s1 PlutusScriptOrReferenceInput 'PlutusV1 era
l1 PlutusScriptDatum 'PlutusV1 'SpendingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage 'PlutusV1
s2 PlutusScriptOrReferenceInput 'PlutusV1 era
l2 PlutusScriptDatum 'PlutusV1 'SpendingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput 'PlutusV1 era
l1 PlutusScriptOrReferenceInput 'PlutusV1 era
-> PlutusScriptOrReferenceInput 'PlutusV1 era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput 'PlutusV1 era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum 'PlutusV1 'SpendingScript
d1 PlutusScriptDatum 'PlutusV1 'SpendingScript
-> PlutusScriptDatum 'PlutusV1 'SpendingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum 'PlutusV1 'SpendingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage 'PlutusV1
s1 SLanguage 'PlutusV1 -> SLanguage 'PlutusV1 -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage 'PlutusV1
s2

instance Eq (PlutusScriptWitness L.PlutusV2 SpendingScript era) where
  == :: PlutusScriptWitness 'PlutusV2 'SpendingScript era
-> PlutusScriptWitness 'PlutusV2 'SpendingScript era -> Bool
(==) (PlutusScriptWitness SLanguage 'PlutusV2
s1 PlutusScriptOrReferenceInput 'PlutusV2 era
l1 PlutusScriptDatum 'PlutusV2 'SpendingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage 'PlutusV2
s2 PlutusScriptOrReferenceInput 'PlutusV2 era
l2 PlutusScriptDatum 'PlutusV2 'SpendingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput 'PlutusV2 era
l1 PlutusScriptOrReferenceInput 'PlutusV2 era
-> PlutusScriptOrReferenceInput 'PlutusV2 era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput 'PlutusV2 era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum 'PlutusV2 'SpendingScript
d1 PlutusScriptDatum 'PlutusV2 'SpendingScript
-> PlutusScriptDatum 'PlutusV2 'SpendingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum 'PlutusV2 'SpendingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage 'PlutusV2
s1 SLanguage 'PlutusV2 -> SLanguage 'PlutusV2 -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage 'PlutusV2
s2

instance Eq (PlutusScriptWitness L.PlutusV3 SpendingScript era) where
  == :: PlutusScriptWitness 'PlutusV3 'SpendingScript era
-> PlutusScriptWitness 'PlutusV3 'SpendingScript era -> Bool
(==) (PlutusScriptWitness SLanguage 'PlutusV3
s1 PlutusScriptOrReferenceInput 'PlutusV3 era
l1 PlutusScriptDatum 'PlutusV3 'SpendingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage 'PlutusV3
s2 PlutusScriptOrReferenceInput 'PlutusV3 era
l2 PlutusScriptDatum 'PlutusV3 'SpendingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput 'PlutusV3 era
l1 PlutusScriptOrReferenceInput 'PlutusV3 era
-> PlutusScriptOrReferenceInput 'PlutusV3 era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput 'PlutusV3 era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum 'PlutusV3 'SpendingScript
d1 PlutusScriptDatum 'PlutusV3 'SpendingScript
-> PlutusScriptDatum 'PlutusV3 'SpendingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum 'PlutusV3 'SpendingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage 'PlutusV3
s1 SLanguage 'PlutusV3 -> SLanguage 'PlutusV3 -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage 'PlutusV3
s2

instance Eq (PlutusScriptWitness L.PlutusV4 SpendingScript era) where
  == :: PlutusScriptWitness 'PlutusV4 'SpendingScript era
-> PlutusScriptWitness 'PlutusV4 'SpendingScript era -> Bool
(==) (PlutusScriptWitness SLanguage 'PlutusV4
s1 PlutusScriptOrReferenceInput 'PlutusV4 era
l1 PlutusScriptDatum 'PlutusV4 'SpendingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage 'PlutusV4
s2 PlutusScriptOrReferenceInput 'PlutusV4 era
l2 PlutusScriptDatum 'PlutusV4 'SpendingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput 'PlutusV4 era
l1 PlutusScriptOrReferenceInput 'PlutusV4 era
-> PlutusScriptOrReferenceInput 'PlutusV4 era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput 'PlutusV4 era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum 'PlutusV4 'SpendingScript
d1 PlutusScriptDatum 'PlutusV4 'SpendingScript
-> PlutusScriptDatum 'PlutusV4 'SpendingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum 'PlutusV4 'SpendingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage 'PlutusV4
s1 SLanguage 'PlutusV4 -> SLanguage 'PlutusV4 -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage 'PlutusV4
s2

instance Eq (PlutusScriptWitness lang MintingScript era) where
  == :: PlutusScriptWitness lang 'MintingScript era
-> PlutusScriptWitness lang 'MintingScript era -> Bool
(==) (PlutusScriptWitness SLanguage lang
s1 PlutusScriptOrReferenceInput lang era
l1 PlutusScriptDatum lang 'MintingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage lang
s2 PlutusScriptOrReferenceInput lang era
l2 PlutusScriptDatum lang 'MintingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput lang era
l1 PlutusScriptOrReferenceInput lang era
-> PlutusScriptOrReferenceInput lang era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput lang era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum lang 'MintingScript
d1 PlutusScriptDatum lang 'MintingScript
-> PlutusScriptDatum lang 'MintingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum lang 'MintingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage lang
s1 SLanguage lang -> SLanguage lang -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage lang
s2

instance Eq (PlutusScriptWitness lang WithdrawingScript era) where
  == :: PlutusScriptWitness lang 'WithdrawingScript era
-> PlutusScriptWitness lang 'WithdrawingScript era -> Bool
(==) (PlutusScriptWitness SLanguage lang
s1 PlutusScriptOrReferenceInput lang era
l1 PlutusScriptDatum lang 'WithdrawingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage lang
s2 PlutusScriptOrReferenceInput lang era
l2 PlutusScriptDatum lang 'WithdrawingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput lang era
l1 PlutusScriptOrReferenceInput lang era
-> PlutusScriptOrReferenceInput lang era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput lang era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum lang 'WithdrawingScript
d1 PlutusScriptDatum lang 'WithdrawingScript
-> PlutusScriptDatum lang 'WithdrawingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum lang 'WithdrawingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage lang
s1 SLanguage lang -> SLanguage lang -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage lang
s2

instance Eq (PlutusScriptWitness lang CertifyingScript era) where
  == :: PlutusScriptWitness lang 'CertifyingScript era
-> PlutusScriptWitness lang 'CertifyingScript era -> Bool
(==) (PlutusScriptWitness SLanguage lang
s1 PlutusScriptOrReferenceInput lang era
l1 PlutusScriptDatum lang 'CertifyingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage lang
s2 PlutusScriptOrReferenceInput lang era
l2 PlutusScriptDatum lang 'CertifyingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput lang era
l1 PlutusScriptOrReferenceInput lang era
-> PlutusScriptOrReferenceInput lang era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput lang era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum lang 'CertifyingScript
d1 PlutusScriptDatum lang 'CertifyingScript
-> PlutusScriptDatum lang 'CertifyingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum lang 'CertifyingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage lang
s1 SLanguage lang -> SLanguage lang -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage lang
s2

instance Eq (PlutusScriptWitness lang ProposingScript era) where
  == :: PlutusScriptWitness lang 'ProposingScript era
-> PlutusScriptWitness lang 'ProposingScript era -> Bool
(==) (PlutusScriptWitness SLanguage lang
s1 PlutusScriptOrReferenceInput lang era
l1 PlutusScriptDatum lang 'ProposingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage lang
s2 PlutusScriptOrReferenceInput lang era
l2 PlutusScriptDatum lang 'ProposingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput lang era
l1 PlutusScriptOrReferenceInput lang era
-> PlutusScriptOrReferenceInput lang era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput lang era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum lang 'ProposingScript
d1 PlutusScriptDatum lang 'ProposingScript
-> PlutusScriptDatum lang 'ProposingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum lang 'ProposingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage lang
s1 SLanguage lang -> SLanguage lang -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage lang
s2

instance Eq (PlutusScriptWitness lang VotingScript era) where
  == :: PlutusScriptWitness lang 'VotingScript era
-> PlutusScriptWitness lang 'VotingScript era -> Bool
(==) (PlutusScriptWitness SLanguage lang
s1 PlutusScriptOrReferenceInput lang era
l1 PlutusScriptDatum lang 'VotingScript
d1 ScriptRedeemer
r1 ExecutionUnits
eu1) (PlutusScriptWitness SLanguage lang
s2 PlutusScriptOrReferenceInput lang era
l2 PlutusScriptDatum lang 'VotingScript
d2 ScriptRedeemer
r2 ExecutionUnits
eu2) =
    PlutusScriptOrReferenceInput lang era
l1 PlutusScriptOrReferenceInput lang era
-> PlutusScriptOrReferenceInput lang era -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptOrReferenceInput lang era
l2 Bool -> Bool -> Bool
&& PlutusScriptDatum lang 'VotingScript
d1 PlutusScriptDatum lang 'VotingScript
-> PlutusScriptDatum lang 'VotingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatum lang 'VotingScript
d2 Bool -> Bool -> Bool
&& ScriptRedeemer
r1 ScriptRedeemer -> ScriptRedeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptRedeemer
r2 Bool -> Bool -> Bool
&& ExecutionUnits
eu1 ExecutionUnits -> ExecutionUnits -> Bool
forall a. Eq a => a -> a -> Bool
== ExecutionUnits
eu2 Bool -> Bool -> Bool
&& SLanguage lang
s1 SLanguage lang -> SLanguage lang -> Bool
forall a. Eq a => a -> a -> Bool
== SLanguage lang
s2

getPlutusScriptWitnessLanguage :: PlutusScriptWitness lang purpose era -> L.Language
getPlutusScriptWitnessLanguage :: forall (lang :: Language) (purpose :: PlutusScriptPurpose) era.
PlutusScriptWitness lang purpose era -> Language
getPlutusScriptWitnessLanguage (PlutusScriptWitness SLanguage lang
l PlutusScriptOrReferenceInput lang era
_ PlutusScriptDatum lang purpose
_ ScriptRedeemer
_ ExecutionUnits
_) =
  case SLanguage lang
l of
    SLanguage lang
L.SPlutusV1 -> SLanguage lang -> Language
forall (l :: Language) (proxy :: Language -> *).
PlutusLanguage l =>
proxy l -> Language
L.plutusLanguage SLanguage lang
l
    SLanguage lang
L.SPlutusV2 -> SLanguage lang -> Language
forall (l :: Language) (proxy :: Language -> *).
PlutusLanguage l =>
proxy l -> Language
L.plutusLanguage SLanguage lang
l
    SLanguage lang
L.SPlutusV3 -> SLanguage lang -> Language
forall (l :: Language) (proxy :: Language -> *).
PlutusLanguage l =>
proxy l -> Language
L.plutusLanguage SLanguage lang
l
    SLanguage lang
L.SPlutusV4 -> SLanguage lang -> Language
forall (l :: Language) (proxy :: Language -> *).
PlutusLanguage l =>
proxy l -> Language
L.plutusLanguage SLanguage lang
l

getSpendingPlutusWitnessData
  :: forall era lang
   . L.Era era
  => PlutusScriptWitness lang SpendingScript era
  -> L.TxDats era
getSpendingPlutusWitnessData :: forall era (lang :: Language).
Era era =>
PlutusScriptWitness lang 'SpendingScript era -> TxDats era
getSpendingPlutusWitnessData (PlutusScriptWitness SLanguage lang
L.SPlutusV1 PlutusScriptOrReferenceInput lang era
_ PlutusScriptDatum lang 'SpendingScript
d ScriptRedeemer
_ ExecutionUnits
_) =
  case PlutusScriptDatum lang 'SpendingScript
d of
    SpendingScriptDatum PlutusScriptDatumF lang 'SpendingScript
sd ->
      let Data era
d' :: Plutus.Data era = ScriptRedeemer -> Data era
forall ledgerera. Era ledgerera => ScriptRedeemer -> Data ledgerera
toAlonzoData ScriptRedeemer
PlutusScriptDatumF lang 'SpendingScript
sd
       in Map DataHash (Data era) -> TxDats era
forall era. Era era => Map DataHash (Data era) -> TxDats era
L.TxDats (Map DataHash (Data era) -> TxDats era)
-> Map DataHash (Data era) -> TxDats era
forall a b. (a -> b) -> a -> b
$ [Item (Map DataHash (Data era))] -> Map DataHash (Data era)
forall l. IsList l => [Item l] -> l
fromList [(Data era -> DataHash
forall era. Data era -> DataHash
Plutus.hashData Data era
d', Data era
d')]
    PlutusScriptDatum lang 'SpendingScript
InlineDatum -> TxDats era
forall a. Monoid a => a
mempty
    PlutusScriptDatum lang 'SpendingScript
NoScriptDatum -> TxDats era
forall a. Monoid a => a
mempty
getSpendingPlutusWitnessData (PlutusScriptWitness SLanguage lang
L.SPlutusV2 PlutusScriptOrReferenceInput lang era
_ PlutusScriptDatum lang 'SpendingScript
d ScriptRedeemer
_ ExecutionUnits
_) =
  case PlutusScriptDatum lang 'SpendingScript
d of
    SpendingScriptDatum PlutusScriptDatumF lang 'SpendingScript
sd ->
      let Data era
d' :: Plutus.Data era = ScriptRedeemer -> Data era
forall ledgerera. Era ledgerera => ScriptRedeemer -> Data ledgerera
toAlonzoData ScriptRedeemer
PlutusScriptDatumF lang 'SpendingScript
sd
       in Map DataHash (Data era) -> TxDats era
forall era. Era era => Map DataHash (Data era) -> TxDats era
L.TxDats (Map DataHash (Data era) -> TxDats era)
-> Map DataHash (Data era) -> TxDats era
forall a b. (a -> b) -> a -> b
$ [Item (Map DataHash (Data era))] -> Map DataHash (Data era)
forall l. IsList l => [Item l] -> l
fromList [(Data era -> DataHash
forall era. Data era -> DataHash
Plutus.hashData Data era
d', Data era
d')]
    PlutusScriptDatum lang 'SpendingScript
InlineDatum -> TxDats era
forall a. Monoid a => a
mempty
    PlutusScriptDatum lang 'SpendingScript
NoScriptDatum -> TxDats era
forall a. Monoid a => a
mempty
getSpendingPlutusWitnessData (PlutusScriptWitness SLanguage lang
L.SPlutusV3 PlutusScriptOrReferenceInput lang era
_ PlutusScriptDatum lang 'SpendingScript
d ScriptRedeemer
_ ExecutionUnits
_) =
  case PlutusScriptDatum lang 'SpendingScript
d of
    SpendingScriptDatum PlutusScriptDatumF lang 'SpendingScript
mSd -> case PlutusScriptDatumF lang 'SpendingScript
mSd of
      Just ScriptRedeemer
sd ->
        let Data era
d' :: Plutus.Data era = ScriptRedeemer -> Data era
forall ledgerera. Era ledgerera => ScriptRedeemer -> Data ledgerera
toAlonzoData ScriptRedeemer
sd
         in Map DataHash (Data era) -> TxDats era
forall era. Era era => Map DataHash (Data era) -> TxDats era
L.TxDats (Map DataHash (Data era) -> TxDats era)
-> Map DataHash (Data era) -> TxDats era
forall a b. (a -> b) -> a -> b
$ [Item (Map DataHash (Data era))] -> Map DataHash (Data era)
forall l. IsList l => [Item l] -> l
fromList [(Data era -> DataHash
forall era. Data era -> DataHash
Plutus.hashData Data era
d', Data era
d')]
      Maybe ScriptRedeemer
PlutusScriptDatumF lang 'SpendingScript
Nothing -> TxDats era
forall a. Monoid a => a
mempty
    PlutusScriptDatum lang 'SpendingScript
InlineDatum -> TxDats era
forall a. Monoid a => a
mempty
    PlutusScriptDatum lang 'SpendingScript
NoScriptDatum -> TxDats era
forall a. Monoid a => a
mempty
getSpendingPlutusWitnessData (PlutusScriptWitness SLanguage lang
L.SPlutusV4 PlutusScriptOrReferenceInput lang era
_ PlutusScriptDatum lang 'SpendingScript
d ScriptRedeemer
_ ExecutionUnits
_) =
  case PlutusScriptDatum lang 'SpendingScript
d of
    SpendingScriptDatum PlutusScriptDatumF lang 'SpendingScript
mSd -> case PlutusScriptDatumF lang 'SpendingScript
mSd of
      Just ScriptRedeemer
sd ->
        let Data era
d' :: Plutus.Data era = ScriptRedeemer -> Data era
forall ledgerera. Era ledgerera => ScriptRedeemer -> Data ledgerera
toAlonzoData ScriptRedeemer
sd
         in Map DataHash (Data era) -> TxDats era
forall era. Era era => Map DataHash (Data era) -> TxDats era
L.TxDats (Map DataHash (Data era) -> TxDats era)
-> Map DataHash (Data era) -> TxDats era
forall a b. (a -> b) -> a -> b
$ [Item (Map DataHash (Data era))] -> Map DataHash (Data era)
forall l. IsList l => [Item l] -> l
fromList [(Data era -> DataHash
forall era. Data era -> DataHash
Plutus.hashData Data era
d', Data era
d')]
      Maybe ScriptRedeemer
PlutusScriptDatumF lang 'SpendingScript
Nothing -> TxDats era
forall a. Monoid a => a
mempty
    PlutusScriptDatum lang 'SpendingScript
InlineDatum -> TxDats era
forall a. Monoid a => a
mempty
    PlutusScriptDatum lang 'SpendingScript
NoScriptDatum -> TxDats era
forall a. Monoid a => a
mempty

getPlutusScriptRunnable :: PlutusScriptWitness lang purpose era -> Maybe (L.PlutusRunnable lang)
getPlutusScriptRunnable :: forall (lang :: Language) (purpose :: PlutusScriptPurpose) era.
PlutusScriptWitness lang purpose era -> Maybe (PlutusRunnable lang)
getPlutusScriptRunnable (PlutusScriptWitness SLanguage lang
_ (PScript (PlutusScriptInEra PlutusRunnable lang
plutusScriptRunnable)) PlutusScriptDatum lang purpose
_ ScriptRedeemer
_ ExecutionUnits
_) =
  PlutusRunnable lang -> Maybe (PlutusRunnable lang)
forall a. a -> Maybe a
Just PlutusRunnable lang
plutusScriptRunnable
getPlutusScriptRunnable (PlutusScriptWitness SLanguage lang
_ PReferenceScript{} PlutusScriptDatum lang purpose
_ ScriptRedeemer
_ ExecutionUnits
_) = Maybe (PlutusRunnable lang)
forall a. Maybe a
Nothing

-- | Every Plutus script has a purpose that indicates
-- what that script is witnessing.
data PlutusScriptPurpose
  = -- | Witnesses a transaction input
    SpendingScript
  | -- | Witnesses a minting policy
    MintingScript
  | -- | Witnesses a withdrawal
    WithdrawingScript
  | -- | Witnesses a certificate
    CertifyingScript
  | -- | Witnesses a proposal
    ProposingScript
  | -- | Witnesses a vote
    VotingScript

data NoScriptDatum = NoScriptDatumAllowed deriving (Int -> NoScriptDatum -> ShowS
[NoScriptDatum] -> ShowS
NoScriptDatum -> String
(Int -> NoScriptDatum -> ShowS)
-> (NoScriptDatum -> String)
-> ([NoScriptDatum] -> ShowS)
-> Show NoScriptDatum
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NoScriptDatum -> ShowS
showsPrec :: Int -> NoScriptDatum -> ShowS
$cshow :: NoScriptDatum -> String
show :: NoScriptDatum -> String
$cshowList :: [NoScriptDatum] -> ShowS
showList :: [NoScriptDatum] -> ShowS
Show, NoScriptDatum -> NoScriptDatum -> Bool
(NoScriptDatum -> NoScriptDatum -> Bool)
-> (NoScriptDatum -> NoScriptDatum -> Bool) -> Eq NoScriptDatum
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NoScriptDatum -> NoScriptDatum -> Bool
== :: NoScriptDatum -> NoScriptDatum -> Bool
$c/= :: NoScriptDatum -> NoScriptDatum -> Bool
/= :: NoScriptDatum -> NoScriptDatum -> Bool
Eq)

-- | The PlutusScriptDatum type family is used to determine if a script datum is allowed
-- for a given plutus script purpose and version. This change was proposed in CIP-69
-- https://github.com/cardano-foundation/CIPs/tree/master/CIP-0069
type family PlutusScriptDatumF (lang :: L.Language) (purpose :: PlutusScriptPurpose) where
  PlutusScriptDatumF L.PlutusV1 SpendingScript = HashableScriptData
  PlutusScriptDatumF L.PlutusV2 SpendingScript = HashableScriptData
  PlutusScriptDatumF L.PlutusV3 SpendingScript = Maybe HashableScriptData -- CIP-69
  PlutusScriptDatumF L.PlutusV4 SpendingScript = Maybe HashableScriptData -- CIP-69
  PlutusScriptDatumF L.PlutusV1 MintingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV2 MintingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV3 MintingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV4 MintingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV1 WithdrawingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV2 WithdrawingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV3 WithdrawingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV4 WithdrawingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV1 CertifyingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV2 CertifyingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV3 CertifyingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV4 CertifyingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV1 ProposingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV2 ProposingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV3 ProposingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV4 ProposingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV1 VotingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV2 VotingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV3 VotingScript = NoScriptDatum
  PlutusScriptDatumF L.PlutusV4 VotingScript = NoScriptDatum

data PlutusScriptDatum (lang :: L.Language) (purpose :: PlutusScriptPurpose) where
  SpendingScriptDatum
    :: PlutusScriptDatumF lang SpendingScript -> PlutusScriptDatum lang SpendingScript
  InlineDatum :: PlutusScriptDatum lang purpose
  NoScriptDatum
    :: PlutusScriptDatum lang purpose

instance Eq (PlutusScriptDatumF lang SpendingScript) => Eq (PlutusScriptDatum lang SpendingScript) where
  == :: PlutusScriptDatum lang 'SpendingScript
-> PlutusScriptDatum lang 'SpendingScript -> Bool
(==) (SpendingScriptDatum PlutusScriptDatumF lang 'SpendingScript
d1) (SpendingScriptDatum PlutusScriptDatumF lang 'SpendingScript
d2) = PlutusScriptDatumF lang 'SpendingScript
d1 PlutusScriptDatumF lang 'SpendingScript
-> PlutusScriptDatumF lang 'SpendingScript -> Bool
forall a. Eq a => a -> a -> Bool
== PlutusScriptDatumF lang 'SpendingScript
d2
  (==) PlutusScriptDatum lang 'SpendingScript
InlineDatum PlutusScriptDatum lang 'SpendingScript
InlineDatum = Bool
True
  (==) PlutusScriptDatum lang 'SpendingScript
NoScriptDatum PlutusScriptDatum lang 'SpendingScript
NoScriptDatum = Bool
True
  (==) PlutusScriptDatum lang 'SpendingScript
_ PlutusScriptDatum lang 'SpendingScript
_ = Bool
False

--
instance Eq (PlutusScriptDatum lang MintingScript) where
  == :: PlutusScriptDatum lang 'MintingScript
-> PlutusScriptDatum lang 'MintingScript -> Bool
(==) PlutusScriptDatum lang 'MintingScript
InlineDatum PlutusScriptDatum lang 'MintingScript
InlineDatum = Bool
True
  (==) PlutusScriptDatum lang 'MintingScript
NoScriptDatum PlutusScriptDatum lang 'MintingScript
NoScriptDatum = Bool
True
  (==) PlutusScriptDatum lang 'MintingScript
_ PlutusScriptDatum lang 'MintingScript
_ = Bool
False

instance Eq (PlutusScriptDatum lang WithdrawingScript) where
  == :: PlutusScriptDatum lang 'WithdrawingScript
-> PlutusScriptDatum lang 'WithdrawingScript -> Bool
(==) PlutusScriptDatum lang 'WithdrawingScript
InlineDatum PlutusScriptDatum lang 'WithdrawingScript
InlineDatum = Bool
True
  (==) PlutusScriptDatum lang 'WithdrawingScript
NoScriptDatum PlutusScriptDatum lang 'WithdrawingScript
NoScriptDatum = Bool
True
  (==) PlutusScriptDatum lang 'WithdrawingScript
_ PlutusScriptDatum lang 'WithdrawingScript
_ = Bool
False

instance Eq (PlutusScriptDatum lang CertifyingScript) where
  == :: PlutusScriptDatum lang 'CertifyingScript
-> PlutusScriptDatum lang 'CertifyingScript -> Bool
(==) PlutusScriptDatum lang 'CertifyingScript
InlineDatum PlutusScriptDatum lang 'CertifyingScript
InlineDatum = Bool
True
  (==) PlutusScriptDatum lang 'CertifyingScript
NoScriptDatum PlutusScriptDatum lang 'CertifyingScript
NoScriptDatum = Bool
True
  (==) PlutusScriptDatum lang 'CertifyingScript
_ PlutusScriptDatum lang 'CertifyingScript
_ = Bool
False

instance Eq (PlutusScriptDatum lang ProposingScript) where
  == :: PlutusScriptDatum lang 'ProposingScript
-> PlutusScriptDatum lang 'ProposingScript -> Bool
(==) PlutusScriptDatum lang 'ProposingScript
InlineDatum PlutusScriptDatum lang 'ProposingScript
InlineDatum = Bool
True
  (==) PlutusScriptDatum lang 'ProposingScript
NoScriptDatum PlutusScriptDatum lang 'ProposingScript
NoScriptDatum = Bool
True
  (==) PlutusScriptDatum lang 'ProposingScript
_ PlutusScriptDatum lang 'ProposingScript
_ = Bool
False

instance Eq (PlutusScriptDatum lang VotingScript) where
  == :: PlutusScriptDatum lang 'VotingScript
-> PlutusScriptDatum lang 'VotingScript -> Bool
(==) PlutusScriptDatum lang 'VotingScript
InlineDatum PlutusScriptDatum lang 'VotingScript
InlineDatum = Bool
True
  (==) PlutusScriptDatum lang 'VotingScript
NoScriptDatum PlutusScriptDatum lang 'VotingScript
NoScriptDatum = Bool
True
  (==) PlutusScriptDatum lang 'VotingScript
_ PlutusScriptDatum lang 'VotingScript
_ = Bool
False

instance Show (PlutusScriptDatum lang purpose) where
  show :: PlutusScriptDatum lang purpose -> String
show = \case
    SpendingScriptDatum PlutusScriptDatumF lang 'SpendingScript
_d -> String
"Datum"
    PlutusScriptDatum lang purpose
InlineDatum -> String
"InlineDatum"
    PlutusScriptDatum lang purpose
NoScriptDatum -> String
"NoScriptDatum"