{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts   #-}
{-# LANGUAGE LambdaCase         #-}
{-# LANGUAGE MonoLocalBinds     #-}
{-# LANGUAGE NamedFieldPuns     #-}
{-# LANGUAGE NoImplicitPrelude  #-}
{-# LANGUAGE OverloadedStrings  #-}
{-# LANGUAGE ViewPatterns       #-}
{-# OPTIONS_GHC -Wno-simplifiable-class-constraints #-}
{-# OPTIONS_GHC -fno-specialise #-}
{-# OPTIONS_GHC -fno-omit-interface-pragmas #-}
module Ledger.Tx.Constraints.OnChain.V2
    ( checkScriptContext
    , checkOwnInputConstraint
    , checkOwnOutputConstraint
    ) where

import Ledger qualified
import Ledger.Address (PaymentPubKeyHash (unPaymentPubKeyHash))
import Ledger.Credential (Credential (ScriptCredential))
import Ledger.Tx.Constraints.TxConstraints (ScriptInputConstraint (ScriptInputConstraint, icRedeemer, icReferenceTxOutRef, icTxOutRef),
                                            ScriptOutputConstraint (ScriptOutputConstraint, ocDatum, ocReferenceScriptHash, ocValue),
                                            TxConstraint (MustBeSignedBy, MustIncludeDatumInTx, MustIncludeDatumInTxWithHash, MustMintValue, MustPayToAddress, MustProduceAtLeast, MustReferenceOutput, MustSatisfyAnyOf, MustSpendAtLeast, MustSpendPubKeyOutput, MustSpendScriptOutput, MustUseOutputAsCollateral, MustValidateInTimeRange),
                                            TxConstraintFun (MustSpendScriptOutputWithMatchingDatumAndValue),
                                            TxConstraintFuns (TxConstraintFuns),
                                            TxConstraints (TxConstraints, txConstraintFuns, txConstraints, txOwnInputs, txOwnOutputs),
                                            TxOutDatum (TxOutDatumHash, TxOutDatumInTx, TxOutDatumInline))
import Ledger.Tx.Constraints.ValidityInterval (toPlutusInterval)
import Plutus.Script.Utils.V2.Contexts (ScriptContext (ScriptContext, scriptContextTxInfo), ScriptPurpose (Spending),
                                        TxInInfo (TxInInfo, txInInfoOutRef, txInInfoResolved),
                                        TxInfo (txInfoData, txInfoInputs, txInfoMint, txInfoRedeemers, txInfoValidRange),
                                        TxOut (TxOut, txOutAddress, txOutDatum), findOwnInput)
import Plutus.Script.Utils.V2.Contexts qualified as PV2
import Plutus.Script.Utils.Value qualified as Value
import Plutus.V1.Ledger.Interval (contains)
import Plutus.V1.Ledger.Value (leq)
import Plutus.V2.Ledger.Tx (OutputDatum (NoOutputDatum, OutputDatum, OutputDatumHash))
import PlutusTx (ToData (toBuiltinData))
import PlutusTx.AssocMap qualified as AMap
import PlutusTx.Prelude (Bool (False, True), Eq ((==)), Maybe (Just, Nothing), all, any, elem, fmap, isJust, maybe,
                         traceIfFalse, ($), (&&), (.), (>>))

{-# INLINABLE checkScriptContext #-}
-- | Does the 'ScriptContext' satisfy the constraints?
checkScriptContext :: forall i o. (ToData i, ToData o) => TxConstraints i o -> ScriptContext -> Bool
checkScriptContext :: TxConstraints i o -> ScriptContext -> Bool
checkScriptContext TxConstraints{[TxConstraint]
txConstraints :: [TxConstraint]
txConstraints :: forall i o. TxConstraints i o -> [TxConstraint]
txConstraints, txConstraintFuns :: forall i o. TxConstraints i o -> TxConstraintFuns
txConstraintFuns = TxConstraintFuns [TxConstraintFun]
txCnsFuns, [ScriptInputConstraint i]
txOwnInputs :: [ScriptInputConstraint i]
txOwnInputs :: forall i o. TxConstraints i o -> [ScriptInputConstraint i]
txOwnInputs, [ScriptOutputConstraint o]
txOwnOutputs :: [ScriptOutputConstraint o]
txOwnOutputs :: forall i o. TxConstraints i o -> [ScriptOutputConstraint o]
txOwnOutputs} ScriptContext
ptx =
    BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L!" -- "checkScriptContext failed"
    (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (TxConstraint -> Bool) -> [TxConstraint] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (ScriptContext -> TxConstraint -> Bool
checkTxConstraint ScriptContext
ptx) [TxConstraint]
txConstraints
    Bool -> Bool -> Bool
&& (TxConstraintFun -> Bool) -> [TxConstraintFun] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (ScriptContext -> TxConstraintFun -> Bool
checkTxConstraintFun ScriptContext
ptx) [TxConstraintFun]
txCnsFuns
    Bool -> Bool -> Bool
&& (ScriptInputConstraint i -> Bool)
-> [ScriptInputConstraint i] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (ScriptContext -> ScriptInputConstraint i -> Bool
forall i.
ToData i =>
ScriptContext -> ScriptInputConstraint i -> Bool
checkOwnInputConstraint ScriptContext
ptx) [ScriptInputConstraint i]
txOwnInputs
    Bool -> Bool -> Bool
&& (ScriptOutputConstraint o -> Bool)
-> [ScriptOutputConstraint o] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (ScriptContext -> ScriptOutputConstraint o -> Bool
forall o.
ToData o =>
ScriptContext -> ScriptOutputConstraint o -> Bool
checkOwnOutputConstraint ScriptContext
ptx) [ScriptOutputConstraint o]
txOwnOutputs

{-# INLINABLE checkOwnInputConstraint #-}
checkOwnInputConstraint
    :: ToData i
    => ScriptContext
    -> ScriptInputConstraint i
    -> Bool
checkOwnInputConstraint :: ScriptContext -> ScriptInputConstraint i -> Bool
checkOwnInputConstraint ScriptContext
ctx ScriptInputConstraint{TxOutRef
icTxOutRef :: TxOutRef
icTxOutRef :: forall a. ScriptInputConstraint a -> TxOutRef
icTxOutRef, i
icRedeemer :: i
icRedeemer :: forall a. ScriptInputConstraint a -> a
icRedeemer, Maybe TxOutRef
icReferenceTxOutRef :: Maybe TxOutRef
icReferenceTxOutRef :: forall a. ScriptInputConstraint a -> Maybe TxOutRef
icReferenceTxOutRef} =
    BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L0" -- "Input constraint"
    (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ScriptContext -> TxConstraint -> Bool
checkTxConstraint ScriptContext
ctx (TxOutRef -> Redeemer -> Maybe TxOutRef -> TxConstraint
MustSpendScriptOutput TxOutRef
icTxOutRef (BuiltinData -> Redeemer
Ledger.Redeemer (BuiltinData -> Redeemer) -> BuiltinData -> Redeemer
forall a b. (a -> b) -> a -> b
$ i -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData i
icRedeemer) Maybe TxOutRef
icReferenceTxOutRef)

{-# INLINABLE checkOwnOutputConstraint #-}
checkOwnOutputConstraint
    :: ToData o
    => ScriptContext
    -> ScriptOutputConstraint o
    -> Bool
checkOwnOutputConstraint :: ScriptContext -> ScriptOutputConstraint o -> Bool
checkOwnOutputConstraint ScriptContext
ctx ScriptOutputConstraint{TxOutDatum o
ocDatum :: TxOutDatum o
ocDatum :: forall a. ScriptOutputConstraint a -> TxOutDatum a
ocDatum, Value
ocValue :: Value
ocValue :: forall a. ScriptOutputConstraint a -> Value
ocValue, Maybe ScriptHash
ocReferenceScriptHash :: Maybe ScriptHash
ocReferenceScriptHash :: forall a. ScriptOutputConstraint a -> Maybe ScriptHash
ocReferenceScriptHash} =
    let d :: TxOutDatum Datum
d = (o -> Datum) -> TxOutDatum o -> TxOutDatum Datum
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (BuiltinData -> Datum
Ledger.Datum (BuiltinData -> Datum) -> (o -> BuiltinData) -> o -> Datum
forall b c a. (b -> c) -> (a -> b) -> a -> c
. o -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData) TxOutDatum o
ocDatum
    in BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L1" -- "Output constraint"
    (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Bool -> (TxInInfo -> Bool) -> Maybe TxInInfo -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (\TxInInfo{txInInfoResolved :: TxInInfo -> TxOut
txInInfoResolved=TxOut{Address
txOutAddress :: Address
txOutAddress :: TxOut -> Address
txOutAddress}} ->
                        ScriptContext -> TxConstraint -> Bool
checkTxConstraint ScriptContext
ctx (Address
-> Maybe (TxOutDatum Datum)
-> Maybe ScriptHash
-> Value
-> TxConstraint
MustPayToAddress Address
txOutAddress (TxOutDatum Datum -> Maybe (TxOutDatum Datum)
forall a. a -> Maybe a
Just TxOutDatum Datum
d) Maybe ScriptHash
ocReferenceScriptHash Value
ocValue))
        (ScriptContext -> Maybe TxInInfo
findOwnInput ScriptContext
ctx)

{-# INLINABLE checkTxConstraint #-}
checkTxConstraint :: ScriptContext -> TxConstraint -> Bool
checkTxConstraint :: ScriptContext -> TxConstraint -> Bool
checkTxConstraint ctx :: ScriptContext
ctx@ScriptContext{TxInfo
scriptContextTxInfo :: TxInfo
scriptContextTxInfo :: ScriptContext -> TxInfo
scriptContextTxInfo} = \case
    MustIncludeDatumInTx Datum
dv ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L2" -- "Missing datum"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Datum
dv Datum -> [Datum] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Map DatumHash Datum -> [Datum]
forall k v. Map k v -> [v]
AMap.elems (TxInfo -> Map DatumHash Datum
txInfoData TxInfo
scriptContextTxInfo)
    MustValidateInTimeRange ValidityInterval POSIXTime
interval ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L3" -- "Wrong validation interval"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ValidityInterval POSIXTime -> Interval POSIXTime
forall a. ValidityInterval a -> Interval a
toPlutusInterval ValidityInterval POSIXTime
interval Interval POSIXTime -> Interval POSIXTime -> Bool
forall a. Ord a => Interval a -> Interval a -> Bool
`contains` TxInfo -> Interval POSIXTime
txInfoValidRange TxInfo
scriptContextTxInfo
    MustBeSignedBy PaymentPubKeyHash
pkh ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L4" -- "Missing signature"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ TxInfo
scriptContextTxInfo TxInfo -> PubKeyHash -> Bool
`PV2.txSignedBy` PaymentPubKeyHash -> PubKeyHash
unPaymentPubKeyHash PaymentPubKeyHash
pkh
    MustSpendAtLeast Value
vl ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L5" -- "Spent value not OK"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Value
vl Value -> Value -> Bool
`leq` TxInfo -> Value
PV2.valueSpent TxInfo
scriptContextTxInfo
    MustProduceAtLeast Value
vl ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L6" -- "Produced value not OK"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Value
vl Value -> Value -> Bool
`leq` TxInfo -> Value
PV2.valueProduced TxInfo
scriptContextTxInfo
    MustSpendPubKeyOutput TxOutRef
txOutRef ->
        let isNoOutputDatum :: OutputDatum -> Bool
isNoOutputDatum OutputDatum
NoOutputDatum = Bool
True
            isNoOutputDatum OutputDatum
_             = Bool
False
        in
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L7" -- "Public key output not spent"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Bool -> (TxInInfo -> Bool) -> Maybe TxInInfo -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (OutputDatum -> Bool
isNoOutputDatum (OutputDatum -> Bool)
-> (TxInInfo -> OutputDatum) -> TxInInfo -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxOut -> OutputDatum
txOutDatum (TxOut -> OutputDatum)
-> (TxInInfo -> TxOut) -> TxInInfo -> OutputDatum
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxInInfo -> TxOut
txInInfoResolved) (TxOutRef -> TxInfo -> Maybe TxInInfo
PV2.findTxInByTxOutRef TxOutRef
txOutRef TxInfo
scriptContextTxInfo)
    MustSpendScriptOutput TxOutRef
txOutRef Redeemer
rdmr Maybe TxOutRef
mRefTxOutRef ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L8" -- "Script output not spent"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Redeemer -> Maybe Redeemer
forall a. a -> Maybe a
Just Redeemer
rdmr Maybe Redeemer -> Maybe Redeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptPurpose -> Map ScriptPurpose Redeemer -> Maybe Redeemer
forall k v. Eq k => k -> Map k v -> Maybe v
AMap.lookup (TxOutRef -> ScriptPurpose
Spending TxOutRef
txOutRef) (TxInfo -> Map ScriptPurpose Redeemer
txInfoRedeemers TxInfo
scriptContextTxInfo)
        Bool -> Bool -> Bool
&& Maybe TxInInfo -> Bool
forall a. Maybe a -> Bool
isJust (TxOutRef -> TxInfo -> Maybe TxInInfo
PV2.findTxInByTxOutRef TxOutRef
txOutRef TxInfo
scriptContextTxInfo)
        Bool -> Bool -> Bool
&& Bool -> (TxOutRef -> Bool) -> Maybe TxOutRef -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (\TxOutRef
ref -> Maybe TxInInfo -> Bool
forall a. Maybe a -> Bool
isJust (TxOutRef -> TxInfo -> Maybe TxInInfo
PV2.findTxRefInByTxOutRef TxOutRef
ref TxInfo
scriptContextTxInfo)) Maybe TxOutRef
mRefTxOutRef
    MustMintValue MintingPolicyHash
mps Redeemer
_ TokenName
tn Integer
v Maybe TxOutRef
mRefTxOutRef ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"L9" -- "Value minted not OK"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Value -> CurrencySymbol -> TokenName -> Integer
Value.valueOf (TxInfo -> Value
txInfoMint TxInfo
scriptContextTxInfo) (MintingPolicyHash -> CurrencySymbol
Value.mpsSymbol MintingPolicyHash
mps) TokenName
tn Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
v
        Bool -> Bool -> Bool
&& Bool -> (TxOutRef -> Bool) -> Maybe TxOutRef -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (\TxOutRef
ref -> Maybe TxInInfo -> Bool
forall a. Maybe a -> Bool
isJust (TxOutRef -> TxInfo -> Maybe TxInInfo
PV2.findTxRefInByTxOutRef TxOutRef
ref TxInfo
scriptContextTxInfo)) Maybe TxOutRef
mRefTxOutRef
    MustPayToAddress Address
addr Maybe (TxOutDatum Datum)
mdv Maybe ScriptHash
_refScript Value
vl ->
        let outs :: [TxOut]
outs = TxInfo -> [TxOut]
PV2.txInfoOutputs TxInfo
scriptContextTxInfo
            hsh :: Datum -> Maybe DatumHash
hsh Datum
dv = Datum -> TxInfo -> Maybe DatumHash
PV2.findDatumHash Datum
dv TxInfo
scriptContextTxInfo
            checkOutput :: TxOutDatum Datum -> TxOut -> Bool
checkOutput (TxOutDatumHash Datum
_) TxOut{txOutDatum :: TxOut -> OutputDatum
txOutDatum=OutputDatumHash DatumHash
_} =
                -- The datum is not added in the tx body with so we can't verify
                -- that the tx output's datum hash is the correct one w.r.t the
                -- provide datum.
                Bool
True
            checkOutput (TxOutDatumInTx Datum
dv) TxOut{txOutDatum :: TxOut -> OutputDatum
txOutDatum=OutputDatumHash DatumHash
dh} =
                Datum -> Maybe DatumHash
hsh Datum
dv Maybe DatumHash -> Maybe DatumHash -> Bool
forall a. Eq a => a -> a -> Bool
== DatumHash -> Maybe DatumHash
forall a. a -> Maybe a
Just DatumHash
dh
            checkOutput (TxOutDatumInline Datum
dv) TxOut{txOutDatum :: TxOut -> OutputDatum
txOutDatum=OutputDatum Datum
d} =
                Datum
dv Datum -> Datum -> Bool
forall a. Eq a => a -> a -> Bool
== Datum
d
            checkOutput TxOutDatum Datum
_ TxOut
_ = Bool
False
        in
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"La" -- "MustPayToAddress"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Value
vl Value -> Value -> Bool
`leq` TxInfo -> Address -> Value
PV2.valuePaidTo TxInfo
scriptContextTxInfo Address
addr
            Bool -> Bool -> Bool
&& Bool
-> (TxOutDatum Datum -> Bool) -> Maybe (TxOutDatum Datum) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (\TxOutDatum Datum
dv -> (TxOut -> Bool) -> [TxOut] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (TxOutDatum Datum -> TxOut -> Bool
checkOutput TxOutDatum Datum
dv) [TxOut]
outs) Maybe (TxOutDatum Datum)
mdv
    MustIncludeDatumInTxWithHash DatumHash
dvh Datum
dv ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"Lc" -- "missing datum"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ DatumHash -> TxInfo -> Maybe Datum
PV2.findDatum DatumHash
dvh TxInfo
scriptContextTxInfo Maybe Datum -> Maybe Datum -> Bool
forall a. Eq a => a -> a -> Bool
== Datum -> Maybe Datum
forall a. a -> Maybe a
Just Datum
dv
    MustSatisfyAnyOf [[TxConstraint]]
xs ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"Ld" -- "MustSatisfyAnyOf"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ([TxConstraint] -> Bool) -> [[TxConstraint]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((TxConstraint -> Bool) -> [TxConstraint] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (ScriptContext -> TxConstraint -> Bool
checkTxConstraint ScriptContext
ctx)) [[TxConstraint]]
xs
    MustUseOutputAsCollateral TxOutRef
_ ->
        Bool
True -- TxInfo does not have the collateral inputs
    MustReferenceOutput TxOutRef
txOutRef ->
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"Lf" -- "Output not referenced"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Maybe TxInInfo -> Bool
forall a. Maybe a -> Bool
isJust (TxOutRef -> TxInfo -> Maybe TxInInfo
PV2.findTxRefInByTxOutRef TxOutRef
txOutRef TxInfo
scriptContextTxInfo)

{-# INLINABLE checkTxConstraintFun #-}
checkTxConstraintFun :: ScriptContext -> TxConstraintFun -> Bool
checkTxConstraintFun :: ScriptContext -> TxConstraintFun -> Bool
checkTxConstraintFun ScriptContext{TxInfo
scriptContextTxInfo :: TxInfo
scriptContextTxInfo :: ScriptContext -> TxInfo
scriptContextTxInfo} = \case
    MustSpendScriptOutputWithMatchingDatumAndValue ValidatorHash
vh Datum -> Bool
datumPred Value -> Bool
valuePred Redeemer
rdmr ->
        let findDatum :: OutputDatum -> Maybe Datum
findDatum OutputDatum
NoOutputDatum        = Maybe Datum
forall a. Maybe a
Nothing
            findDatum (OutputDatumHash DatumHash
dh) = DatumHash -> TxInfo -> Maybe Datum
PV2.findDatum DatumHash
dh TxInfo
scriptContextTxInfo
            findDatum (OutputDatum Datum
d)      = Datum -> TxInfo -> Maybe DatumHash
PV2.findDatumHash Datum
d TxInfo
scriptContextTxInfo Maybe DatumHash -> Maybe Datum -> Maybe Datum
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Datum -> Maybe Datum
forall a. a -> Maybe a
Just Datum
d
            txOutIsMatch :: TxOut -> Bool
txOutIsMatch (TxOut (Ledger.Address (ScriptCredential ValidatorHash
vh') Maybe StakingCredential
_) Value
val (OutputDatum -> Maybe Datum
findDatum -> Just Datum
d) Maybe ScriptHash
_refScript) =
                ValidatorHash
vh ValidatorHash -> ValidatorHash -> Bool
forall a. Eq a => a -> a -> Bool
== ValidatorHash
vh' Bool -> Bool -> Bool
&& Value -> Bool
valuePred Value
val Bool -> Bool -> Bool
&& Datum -> Bool
datumPred Datum
d
            txOutIsMatch TxOut
_ = Bool
False
            rdmrIsMatch :: TxOutRef -> Bool
rdmrIsMatch TxOutRef
txOutRef = Redeemer -> Maybe Redeemer
forall a. a -> Maybe a
Just Redeemer
rdmr Maybe Redeemer -> Maybe Redeemer -> Bool
forall a. Eq a => a -> a -> Bool
== ScriptPurpose -> Map ScriptPurpose Redeemer -> Maybe Redeemer
forall k v. Eq k => k -> Map k v -> Maybe v
AMap.lookup (TxOutRef -> ScriptPurpose
Spending TxOutRef
txOutRef) (TxInfo -> Map ScriptPurpose Redeemer
txInfoRedeemers TxInfo
scriptContextTxInfo)
        in
        BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"Le" -- "MustSpendScriptOutputWithMatchingDatumAndValue"
        (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (TxInInfo -> Bool) -> [TxInInfo] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (TxOut -> Bool
txOutIsMatch (TxOut -> Bool) -> (TxInInfo -> TxOut) -> TxInInfo -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxInInfo -> TxOut
txInInfoResolved) (TxInfo -> [TxInInfo]
txInfoInputs TxInfo
scriptContextTxInfo)
        Bool -> Bool -> Bool
&& (TxInInfo -> Bool) -> [TxInInfo] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (TxOutRef -> Bool
rdmrIsMatch (TxOutRef -> Bool) -> (TxInInfo -> TxOutRef) -> TxInInfo -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxInInfo -> TxOutRef
txInInfoOutRef) (TxInfo -> [TxInInfo]
txInfoInputs TxInfo
scriptContextTxInfo)