Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLT-494: PlutusV2 TypedValidators #666

Merged
merged 3 commits into from
Aug 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions doc/plutus/tutorials/EscrowImpl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ pay inst escrow vl = do
pk <- ownFirstPaymentPubKeyHash
let tx = Constraints.mustPayToTheScript pk vl
<> Constraints.mustValidateIn (Ledger.interval 1 (escrowDeadline escrow))
utx <- mkTxConstraints (Constraints.plutusV1TypedValidatorLookups inst) tx >>= adjustUnbalancedTx
utx <- mkTxConstraints (Constraints.typedValidatorLookups inst) tx >>= adjustUnbalancedTx
getCardanoTxId <$> submitUnbalancedTx utx

newtype RedeemSuccess = RedeemSuccess TxId
Expand Down Expand Up @@ -311,7 +311,7 @@ redeem inst escrow = mapError (review _EscrowError) $ do
else if foldMap (view Tx.ciTxOutValue) unspentOutputs `lt` targetTotal escrow
then throwing _RedeemFailed NotEnoughFundsAtAddress
else do
utx <- mkTxConstraints ( Constraints.plutusV1TypedValidatorLookups inst
utx <- mkTxConstraints ( Constraints.typedValidatorLookups inst
<> Constraints.unspentOutputs unspentOutputs
) tx >>= adjustUnbalancedTx
RedeemSuccess . getCardanoTxId <$> submitUnbalancedTx utx
Expand Down Expand Up @@ -343,7 +343,7 @@ refund inst escrow = do
<> Constraints.mustValidateIn (from (Haskell.succ $ escrowDeadline escrow))
if Constraints.modifiesUtxoSet tx'
then do
utx <- mkTxConstraints ( Constraints.plutusV1TypedValidatorLookups inst
utx <- mkTxConstraints ( Constraints.typedValidatorLookups inst
<> Constraints.unspentOutputs unspentOutputs
) tx' >>= adjustUnbalancedTx
RefundSuccess . getCardanoTxId <$> submitUnbalancedTx utx
Expand Down
4 changes: 2 additions & 2 deletions plutus-contract/src/Plutus/Contract/Request.hs
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ submitTxConstraints
=> TypedValidator a
-> TxConstraints (RedeemerType a) (DatumType a)
-> Contract w s e CardanoTx
submitTxConstraints inst = submitTxConstraintsWith (Constraints.plutusV1TypedValidatorLookups inst)
submitTxConstraints inst = submitTxConstraintsWith (Constraints.typedValidatorLookups inst)

-- | Build a transaction that satisfies the constraints using the UTXO map
-- to resolve any input constraints (see 'Ledger.Constraints.TxConstraints.InputConstraint')
Expand All @@ -900,7 +900,7 @@ submitTxConstraintsSpending
-> TxConstraints (RedeemerType a) (DatumType a)
-> Contract w s e CardanoTx
submitTxConstraintsSpending inst utxo =
let lookups = Constraints.plutusV1TypedValidatorLookups inst <> Constraints.unspentOutputs utxo
let lookups = Constraints.typedValidatorLookups inst <> Constraints.unspentOutputs utxo
in submitTxConstraintsWith lookups

{-| A variant of 'mkTx' that runs in the 'Contract' monad, throwing errors and
Expand Down
4 changes: 2 additions & 2 deletions plutus-contract/src/Plutus/Contract/StateMachine.hs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ runInitialiseWith customLookups customConstraints StateMachineClient{scInstance}
ttConstraints ThreadToken{ttOutRef} =
mustMintValueWithRedeemer red (SM.threadTokenValueOrZero scInstance)
<> mustSpendPubKeyOutput ttOutRef
lookups = Constraints.plutusV1TypedValidatorLookups typedValidator
lookups = Constraints.typedValidatorLookups typedValidator
<> foldMap (plutusV1MintingPolicy . curPolicy . ttOutRef) (smThreadToken stateMachine)
<> Constraints.unspentOutputs utxo
<> customLookups
Expand Down Expand Up @@ -538,7 +538,7 @@ mkStep client@StateMachineClient{scInstance} input = do
Just (newConstraints, newState) ->
let isFinal = smFinal stateMachine (stateData newState)
lookups =
Constraints.plutusV1TypedValidatorLookups typedValidator
Constraints.typedValidatorLookups typedValidator
<> Constraints.unspentOutputs utxo
<> if isFinal then foldMap (plutusV1MintingPolicy . curPolicy . ttOutRef) (smThreadToken stateMachine) else mempty
red = Ledger.Redeemer (PlutusTx.toBuiltinData (Scripts.validatorHash typedValidator, Burn))
Expand Down
10 changes: 4 additions & 6 deletions plutus-contract/test/Spec/Contract/TxConstraints.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ import Plutus.Contract as Con
import Plutus.Contract.Test (TracePredicate, assertValidatedTransactionCount, assertValidatedTransactionCountOfTotal,
checkPredicate, checkPredicateOptions, defaultCheckOptions, minLogLevel, valueAtAddress,
w1, walletFundsChange, (.&&.))
import Plutus.Script.Utils.Typed (Any)
import Plutus.Script.Utils.V1.Address qualified as PV1
import Plutus.Script.Utils.V1.Typed.Scripts qualified as PV1
import Plutus.Script.Utils.V1.Typed.TypeUtils (Any)
import Plutus.Script.Utils.V2.Address qualified as PV2
import Plutus.Script.Utils.V2.Typed.Scripts qualified as PV2
import Plutus.Trace.Emulator (ContractInstanceTag, EmulatorTrace, activateContract)
Expand All @@ -62,10 +62,8 @@ tag :: ContractInstanceTag
tag = "instance 1"

tests :: TestTree
tests = testGroup "contract tx constraints" []
tests = testGroup "contract tx constraints"

disabledTests :: TestTree
disabledTests = testGroup "contract tx constraints"
-- Testing package plutus-ledger-constraints

[ checkPredicate "mustReferenceOutput returns False on-chain when used for unlocking funds in a PlutusV1 script"
Expand All @@ -86,10 +84,10 @@ disabledTests = testGroup "contract tx constraints"

-- Testing package plutus-tx-constraints

, checkPredicate "Tx.Constraints.mustReferenceOutput returns False on-chain when used for unlocking funds in a PlutusV1 script"
, checkPredicate "Tx.Constraints.mustReferenceOutput fails when trying to unlock funds in a PlutusV1 script"
(walletFundsChange w1 (Ada.adaValueOf (-5))
.&&. valueAtAddress mustReferenceOutputV1ValidatorAddress (== Ada.adaValueOf 5)
.&&. assertValidatedTransactionCountOfTotal 1 2
.&&. assertValidatedTransactionCountOfTotal 1 1
) $ do
void $ activateContract w1 mustReferenceOutputTxV1ConTest tag
void $ Trace.waitNSlots 2
Expand Down
6 changes: 3 additions & 3 deletions plutus-contract/test/Spec/TxConstraints/MustSpendAtLeast.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Test.Tasty (TestTree, testGroup)

import Ledger qualified
import Ledger.Ada qualified as Ada
import Ledger.Constraints.OffChain qualified as Constraints (ownPaymentPubKeyHash, plutusV1TypedValidatorLookups,
import Ledger.Constraints.OffChain qualified as Constraints (ownPaymentPubKeyHash, typedValidatorLookups,
unspentOutputs)
import Ledger.Constraints.OnChain.V1 qualified as Constraints (checkScriptContext)
import Ledger.Constraints.TxConstraints qualified as Constraints (collectFromTheScript, mustIncludeDatum,
Expand Down Expand Up @@ -45,13 +45,13 @@ scriptBalance = 25_000_000

mustSpendAtLeastContract :: Integer -> Integer -> Ledger.PaymentPubKeyHash-> Contract () Empty ContractError ()
mustSpendAtLeastContract offAmt onAmt pkh = do
let lookups1 = Constraints.plutusV1TypedValidatorLookups typedValidator
let lookups1 = Constraints.typedValidatorLookups typedValidator
tx1 = Constraints.mustPayToTheScript onAmt (Ada.lovelaceValueOf scriptBalance)
ledgerTx1 <- submitTxConstraintsWith lookups1 tx1
awaitTxConfirmed $ Tx.getCardanoTxId ledgerTx1

utxos <- utxosAt scrAddress
let lookups2 = Constraints.plutusV1TypedValidatorLookups typedValidator
let lookups2 = Constraints.typedValidatorLookups typedValidator
<> Constraints.unspentOutputs utxos
<> Constraints.ownPaymentPubKeyHash pkh
tx2 =
Expand Down
11 changes: 5 additions & 6 deletions plutus-contract/test/Spec/TxConstraints/RequiredSigner.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import Data.String (fromString)
import Ledger qualified
import Ledger.Ada qualified as Ada
import Ledger.CardanoWallet as CW
import Ledger.Constraints.OffChain qualified as Constraints (paymentPubKey, plutusV1TypedValidatorLookups,
unspentOutputs)
import Ledger.Constraints.OffChain qualified as Constraints (paymentPubKey, typedValidatorLookups, unspentOutputs)
import Ledger.Constraints.OnChain.V1 qualified as Constraints
import Ledger.Constraints.TxConstraints qualified as Constraints (collectFromTheScript, mustBeSignedBy,
mustIncludeDatum, mustPayToTheScript,
Expand Down Expand Up @@ -47,14 +46,14 @@ tests =

mustBeSignedByContract :: Ledger.PaymentPubKey -> Ledger.PaymentPubKeyHash -> Contract () Empty ContractError ()
mustBeSignedByContract pk pkh = do
let lookups1 = Constraints.plutusV1TypedValidatorLookups mustBeSignedByTypedValidator
let lookups1 = Constraints.typedValidatorLookups mustBeSignedByTypedValidator
tx1 = Constraints.mustPayToTheScript () (Ada.lovelaceValueOf 25_000_000)
ledgerTx1 <- submitTxConstraintsWith lookups1 tx1
awaitTxConfirmed $ Tx.getCardanoTxId ledgerTx1

utxos <- utxosAt (Ledger.scriptHashAddress $ Scripts.validatorHash mustBeSignedByTypedValidator)
let lookups2 =
Constraints.plutusV1TypedValidatorLookups mustBeSignedByTypedValidator
Constraints.typedValidatorLookups mustBeSignedByTypedValidator
<> Constraints.unspentOutputs utxos
<> Constraints.paymentPubKey pk
tx2 =
Expand All @@ -67,14 +66,14 @@ mustBeSignedByContract pk pkh = do

withoutOffChainMustBeSignedByContract :: Ledger.PaymentPubKey -> Ledger.PaymentPubKeyHash -> Contract () Empty ContractError ()
withoutOffChainMustBeSignedByContract pk pkh = do
let lookups1 = Constraints.plutusV1TypedValidatorLookups mustBeSignedByTypedValidator
let lookups1 = Constraints.typedValidatorLookups mustBeSignedByTypedValidator
tx1 = Constraints.mustPayToTheScript () (Ada.lovelaceValueOf 25_000_000)
ledgerTx1 <- submitTxConstraintsWith lookups1 tx1
awaitTxConfirmed $ Tx.getCardanoTxId ledgerTx1

utxos <- utxosAt (Ledger.scriptHashAddress $ Scripts.validatorHash mustBeSignedByTypedValidator)
let lookups2 =
Constraints.plutusV1TypedValidatorLookups mustBeSignedByTypedValidator
Constraints.typedValidatorLookups mustBeSignedByTypedValidator
<> Constraints.unspentOutputs utxos
<> Constraints.paymentPubKey pk
tx2 =
Expand Down
2 changes: 1 addition & 1 deletion plutus-contract/test/Spec/TxConstraints/TimeValidity.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ contract :: Contract () Empty ContractError ()
contract = do
now <- Con.currentTime
logInfo @String $ "now: " ++ show now
let lookups1 = Constraints.plutusV1TypedValidatorLookups $ typedValidator deadline
let lookups1 = Constraints.typedValidatorLookups $ typedValidator deadline
tx1 = Constraints.mustPayToTheScript () (Ada.lovelaceValueOf 25000000)
ledgerTx1 <- submitTxConstraintsWith lookups1 tx1
awaitTxConfirmed $ Tx.getCardanoTxId ledgerTx1
Expand Down
2 changes: 1 addition & 1 deletion plutus-ledger-constraints/src/Ledger/Constraints.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module Ledger.Constraints(
, OC.mkSomeTx
-- ** Lookups
, OC.ScriptLookups(..)
, OC.plutusV1TypedValidatorLookups
, OC.typedValidatorLookups
, OC.unspentOutputs
, OC.plutusV1MintingPolicy
, OC.plutusV2MintingPolicy
Expand Down
55 changes: 26 additions & 29 deletions plutus-ledger-constraints/src/Ledger/Constraints/OffChain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
module Ledger.Constraints.OffChain(
-- * Lookups
ScriptLookups(..)
, plutusV1TypedValidatorLookups
, typedValidatorLookups
, generalise
, unspentOutputs
, plutusV1MintingPolicy
Expand Down Expand Up @@ -104,7 +104,6 @@ import Ledger.Tx qualified as Tx
import Ledger.Tx.CardanoAPI qualified as C
import Ledger.Typed.Scripts (Any, ConnectionError (UnknownRef), TypedValidator,
ValidatorTypes (DatumType, RedeemerType))
import Ledger.Typed.Scripts qualified as Scripts
import Ledger.Typed.Scripts qualified as Typed
import Ledger.Validation (evaluateMinLovelaceOutput, fromPlutusTxOutUnsafe)
import Plutus.Script.Utils.Scripts qualified as P
Expand All @@ -120,29 +119,29 @@ import PlutusTx.Numeric qualified as N

data ScriptLookups a =
ScriptLookups
{ slMPS :: Map MintingPolicyHash MintingPolicy
{ slMPS :: Map MintingPolicyHash MintingPolicy
-- ^ Minting policies that the script interacts with
, slTxOutputs :: Map TxOutRef ChainIndexTxOut
, slTxOutputs :: Map TxOutRef ChainIndexTxOut
-- ^ Unspent outputs that the script may want to spend
, slOtherScripts :: Map ValidatorHash (Validator, Language)
, slOtherScripts :: Map ValidatorHash (Validator, Language)
-- ^ Validators of scripts other than "our script"
, slOtherData :: Map DatumHash Datum
, slOtherData :: Map DatumHash Datum
-- ^ Datums that we might need
, slPaymentPubKeyHashes :: Set PaymentPubKeyHash
, slPaymentPubKeyHashes :: Set PaymentPubKeyHash
-- ^ Public keys that we might need
, slTypedPlutusV1Validator :: Maybe (TypedValidator a)
, slTypedValidator :: Maybe (TypedValidator a)
-- ^ The script instance with the typed validator hash & actual compiled program
, slOwnPaymentPubKeyHash :: Maybe PaymentPubKeyHash
, slOwnPaymentPubKeyHash :: Maybe PaymentPubKeyHash
-- ^ The contract's payment public key hash, used for depositing tokens etc.
, slOwnStakePubKeyHash :: Maybe StakePubKeyHash
, slOwnStakePubKeyHash :: Maybe StakePubKeyHash
-- ^ The contract's stake public key hash (optional)
} deriving stock (Show, Generic)
deriving anyclass (ToJSON, FromJSON)

generalise :: ScriptLookups a -> ScriptLookups Any
generalise sl =
let validator = fmap Scripts.generalise (slTypedPlutusV1Validator sl)
in sl{slTypedPlutusV1Validator = validator}
let validator = fmap Typed.generalise (slTypedValidator sl)
in sl{slTypedValidator = validator}

instance Semigroup (ScriptLookups a) where
l <> r =
Expand All @@ -153,7 +152,7 @@ instance Semigroup (ScriptLookups a) where
, slOtherData = slOtherData l <> slOtherData r
, slPaymentPubKeyHashes = slPaymentPubKeyHashes l <> slPaymentPubKeyHashes r
-- 'First' to match the semigroup instance of Map (left-biased)
, slTypedPlutusV1Validator = fmap getFirst $ (First <$> slTypedPlutusV1Validator l) <> (First <$> slTypedPlutusV1Validator r)
, slTypedValidator = fmap getFirst $ (First <$> slTypedValidator l) <> (First <$> slTypedValidator r)
, slOwnPaymentPubKeyHash =
fmap getFirst $ (First <$> slOwnPaymentPubKeyHash l)
<> (First <$> slOwnPaymentPubKeyHash r)
Expand All @@ -173,14 +172,14 @@ instance Monoid (ScriptLookups a) where
-- If called multiple times, only the first typed validator is kept:
--
-- @
-- plutusV1TypedValidatorLookups tv1 <> plutusV1TypedValidatorLookups tv2 <> ...
-- == plutusV1TypedValidatorLookups tv1
-- typedValidatorLookups tv1 <> typedValidatorLookups tv2 <> ...
-- == typedValidatorLookups tv1
-- @
plutusV1TypedValidatorLookups :: TypedValidator a -> ScriptLookups a
plutusV1TypedValidatorLookups inst =
typedValidatorLookups :: TypedValidator a -> ScriptLookups a
typedValidatorLookups inst =
mempty
{ slMPS = Map.singleton (Scripts.forwardingMintingPolicyHash inst) (Scripts.forwardingMintingPolicy inst)
, slTypedPlutusV1Validator = Just inst
{ slMPS = Map.singleton (Typed.forwardingMintingPolicyHash inst) (Typed.forwardingMintingPolicy inst)
, slTypedValidator = Just inst
}

-- | A script lookups value that uses the map of unspent outputs to resolve
Expand Down Expand Up @@ -518,8 +517,8 @@ addOwnInput
=> ScriptInputConstraint (RedeemerType a)
-> m ()
addOwnInput ScriptInputConstraint{icRedeemer, icTxOutRef} = do
ScriptLookups{slTxOutputs, slTypedPlutusV1Validator} <- ask
inst <- maybe (throwError TypedValidatorMissing) pure slTypedPlutusV1Validator
ScriptLookups{slTxOutputs, slTypedValidator} <- ask
inst <- maybe (throwError TypedValidatorMissing) pure slTypedValidator
typedOutRef <-
either (throwError . TypeCheckFailed) pure
$ runExcept @Typed.ConnectionError
Expand All @@ -529,8 +528,7 @@ addOwnInput ScriptInputConstraint{icRedeemer, icTxOutRef} = do
datum <- ciTxOut ^? Tx.ciTxOutScriptDatum . _2 . _Just
pure (Tx.toTxOut ciTxOut, datum)
Typed.typeScriptTxOutRef inst icTxOutRef txOut datum
-- TODO Needs to work with PlutusV1 AND PlutusV2.
let txIn = Scripts.makeTypedScriptTxIn PlutusV1 inst icRedeemer typedOutRef
let txIn = Typed.makeTypedScriptTxIn inst icRedeemer typedOutRef
vl = Tx.txOutValue $ Typed.tyTxOutTxOut $ Typed.tyTxOutRefOut typedOutRef
unbalancedTx . tx . Tx.inputs %= (Typed.tyTxInTxIn txIn :)
valueSpentInputs <>= provided vl
Expand All @@ -546,8 +544,8 @@ addOwnOutput
=> ScriptOutputConstraint (DatumType a)
-> m ()
addOwnOutput ScriptOutputConstraint{ocDatum, ocValue} = do
ScriptLookups{slTypedPlutusV1Validator} <- ask
inst <- maybe (throwError TypedValidatorMissing) pure slTypedPlutusV1Validator
ScriptLookups{slTypedValidator} <- ask
inst <- maybe (throwError TypedValidatorMissing) pure slTypedValidator
let txOut = Typed.makeTypedScriptTxOut inst ocDatum ocValue
dsV = Datum (toBuiltinData ocDatum)
unbalancedTx . tx . Tx.outputs %= (Typed.tyTxOutTxOut txOut :)
Expand Down Expand Up @@ -752,13 +750,12 @@ resolveScriptTxOut
=> ChainIndexTxOut -> m (Maybe ((ValidatorHash, Validator, Language), (DatumHash, Datum), Value))
resolveScriptTxOut
Tx.ScriptChainIndexTxOut
{ Tx._ciTxOutValidator = (vh, v)
{ Tx._ciTxOutValidator = (vh, _)
, Tx._ciTxOutScriptDatum = (dh, d)
, Tx._ciTxOutValue
} = do
-- first check in the 'ChainIndexTx' for the validator, then
-- look for it in the 'slOtherScripts map.
(validator, pv) <- maybe (lookupValidator vh) (pure . (, PlutusV1)) v
-- Look for the validator in the 'slOtherScripts map so we also get the language.
(validator, pv) <- lookupValidator vh
koslambrou marked this conversation as resolved.
Show resolved Hide resolved

-- first check in the 'ChainIndexTxOut' for the datum, then
-- look for it in the 'slOtherData' map.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ mustIncludeDatum = singleton . MustIncludeDatum
-- output with @d@ and @v@ and adds @d@ in the transaction's datum witness set.
-- The script address is derived from the typed validator that is provided in
-- the 'Ledger.Constraints.OffChain.ScriptLookups' with
-- 'Ledger.Constraints.OffChain.plutusV1TypedValidatorLookups'.
-- 'Ledger.Constraints.OffChain.typedValidatorLookups'.
--
-- If used in 'Ledger.Constraints.OnChain', this constraint verifies that @d@ is
-- part of the datum witness set and that the new script transaction output with
Expand Down
7 changes: 4 additions & 3 deletions plutus-ledger/src/Ledger/Index.hs
Original file line number Diff line number Diff line change
Expand Up @@ -455,10 +455,11 @@ mkPV1TxInInfo TxIn{txInRef} = do
mkPV2TxInfo :: ValidationMonad m => Tx -> m PV2.TxInfo
mkPV2TxInfo tx = do
slotCfg <- pSlotConfig . vctxParams <$> ask
txins <- traverse mkPV2TxInInfo $ view inputs tx
txIns <- traverse mkPV2TxInInfo $ view inputs tx
txRefIns <- traverse mkPV2TxInInfo $ view referenceInputs tx
let ptx = PV2.TxInfo
{ PV2.txInfoInputs = txins
, PV2.txInfoReferenceInputs = []
{ PV2.txInfoInputs = txIns
, PV2.txInfoReferenceInputs = txRefIns
, PV2.txInfoOutputs = txOutV1ToTxOutV2 <$> txOutputs tx
-- See note [Mint and Fee fields must have ada symbol]
, PV2.txInfoMint = Ada.lovelaceValueOf 0 <> txMint tx
Expand Down
Loading