Skip to content

Commit

Permalink
Provide 'MustSatisfyAnyOf' constructor for TxContraints. (#3706)
Browse files Browse the repository at this point in the history
* Provide 'MustSatisfyAnyOf' constructor for TxContraints.

  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.

* re-generate the plutus-use-cases tests as needed.
  • Loading branch information
KtorZ authored Aug 12, 2021
1 parent 9e1c04a commit 0e75f03
Show file tree
Hide file tree
Showing 8 changed files with 31,447 additions and 29,844 deletions.
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 @@ -414,6 +414,7 @@ data MkTxError =
| OwnPubKeyMissing
| TypedValidatorMissing
| DatumWrongHash DatumHash Datum
| CannotSatisfyAny
deriving stock (Eq, Show, Generic)
deriving anyclass (ToJSON, FromJSON)

Expand All @@ -428,6 +429,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 @@ -538,3 +540,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 any 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
Loading

0 comments on commit 0e75f03

Please sign in to comment.