Skip to content

Commit

Permalink
Provide 'MustSatisfyAnyOf' constructor for TxContraints.
Browse files Browse the repository at this point in the history
  It is actually useful in some cases to be able to perform a disjunction of constraints, and while it is possible to resort to 'Bool' in some cases, when using internal libraries like e.g. the state-machine, we are stuck with the TxConstraints API and therefore, unable to express some useful conditions.
  • Loading branch information
KtorZ committed Aug 6, 2021
1 parent d9a7800 commit 3f7fa68
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
9 changes: 9 additions & 0 deletions plutus-ledger/src/Ledger/Constraints/OffChain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ data MkTxError =
| OwnPubKeyMissing
| TypedValidatorMissing
| DatumWrongHash DatumHash Datum
| CannotSatisfyAny
deriving stock (Eq, Show, Generic)
deriving anyclass (ToJSON, FromJSON)

Expand All @@ -425,6 +426,7 @@ instance Pretty MkTxError where
OwnPubKeyMissing -> "Own public key is missing"
TypedValidatorMissing -> "Script instance is missing"
DatumWrongHash h d -> "Wrong hash for datum" <+> pretty d <> colon <+> pretty h
CannotSatisfyAny -> "Cannot satisfy any of the required constraints"

lookupTxOutRef
:: ( MonadReader (ScriptLookups a) m
Expand Down Expand Up @@ -535,3 +537,10 @@ processConstraint = \case
unless (datumHash dv == dvh)
(throwError $ DatumWrongHash dvh dv)
unbalancedTx . tx . Tx.datumWitnesses . at dvh .= Just dv
MustSatisfyAnyOf xs -> do
s <- get
let tryNext [] =
throwError CannotSatisfyAny
tryNext (h:q) = do
processConstraint h `catchError` \_ -> put s >> tryNext q
tryNext xs
5 changes: 4 additions & 1 deletion plutus-ledger/src/Ledger/Constraints/OnChain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ checkOwnOutputConstraint ctx@ScriptContext{scriptContextTxInfo} OutputConstraint

{-# INLINABLE checkTxConstraint #-}
checkTxConstraint :: ScriptContext -> TxConstraint -> Bool
checkTxConstraint ScriptContext{scriptContextTxInfo} = \case
checkTxConstraint ctx@ScriptContext{scriptContextTxInfo} = \case
MustIncludeDatum dv ->
traceIfFalse "L2" -- "Missing datum"
$ dv `elem` fmap snd (txInfoData scriptContextTxInfo)
Expand Down Expand Up @@ -92,6 +92,9 @@ checkTxConstraint ScriptContext{scriptContextTxInfo} = \case
MustHashDatum dvh dv ->
traceIfFalse "Lc" -- "MustHashDatum"
$ V.findDatum dvh scriptContextTxInfo == Just dv
MustSatisfyAnyOf xs ->
traceIfFalse "Ld" -- "MustSatisfyAnyOf"
$ any (checkTxConstraint ctx) xs

{-# INLINABLE checkScriptContext #-}
-- | Does the 'ScriptContext' satisfy the constraints?
Expand Down
8 changes: 8 additions & 0 deletions plutus-ledger/src/Ledger/Constraints/TxConstraints.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ data TxConstraint =
| MustPayToPubKey PubKeyHash Value
| MustPayToOtherScript ValidatorHash Datum Value
| MustHashDatum DatumHash Datum
| MustSatisfyAnyOf [TxConstraint]
deriving stock (Haskell.Show, Generic, Haskell.Eq)
deriving anyclass (ToJSON, FromJSON)

Expand Down Expand Up @@ -77,6 +78,8 @@ instance Pretty TxConstraint where
hang 2 $ vsep ["must pay to script:", pretty vlh, pretty dv, pretty vl]
MustHashDatum dvh dv ->
hang 2 $ vsep ["must hash datum:", pretty dvh, pretty dv]
MustSatisfyAnyOf xs ->
hang 2 $ vsep ["must satisfy one of:", prettyList xs]

data InputConstraint a =
InputConstraint
Expand Down Expand Up @@ -244,6 +247,10 @@ mustSpendScriptOutput txOutref = singleton . MustSpendScriptOutput txOutref
mustHashDatum :: DatumHash -> Datum -> TxConstraints i o
mustHashDatum dvh = singleton . MustHashDatum dvh

{-# INLINABLE mustSatisfyAnyOf #-}
mustSatisfyAnyOf :: forall i o. [TxConstraints i o] -> TxConstraints i o
mustSatisfyAnyOf = singleton . MustSatisfyAnyOf . concatMap txConstraints

{-# INLINABLE isSatisfiable #-}
-- | Are the constraints satisfiable?
isSatisfiable :: forall i o. TxConstraints i o -> Bool
Expand Down Expand Up @@ -304,6 +311,7 @@ modifiesUtxoSet TxConstraints{txConstraints, txOwnOutputs, txOwnInputs} =
MustMintValue{} -> True
MustPayToPubKey _ vl -> not (isZero vl)
MustPayToOtherScript _ _ vl -> not (isZero vl)
MustSatisfyAnyOf xs -> any requiresInputOutput xs
_ -> False
in any requiresInputOutput txConstraints
|| not (null txOwnOutputs)
Expand Down

0 comments on commit 3f7fa68

Please sign in to comment.