Skip to content

Commit

Permalink
Typed validator interface: work on UX a bit (#3308)
Browse files Browse the repository at this point in the history
* Rename ScriptType -> ValidatorTypes

* Rename ScriptInstance -> TypedValidator

* Rename some non-exported fields

* Rename some more functions

* Split up validator and monetary policy modules

* Rename some variables to make more sense with the type renames

* Fixups

* Doc fixups

* Fix formatting

* Fix
  • Loading branch information
michaelpj committed Jun 8, 2021
1 parent a99221b commit 6f834b5
Show file tree
Hide file tree
Showing 50 changed files with 487 additions and 489 deletions.
12 changes: 6 additions & 6 deletions doc/plutus/tutorials/BasicApps.hs
Expand Up @@ -56,12 +56,12 @@ validateSplit SplitData{recipient1, recipient2, amount} _ ScriptContext{scriptCo
-- BLOCK3

data Split
instance Scripts.ScriptType Split where
instance Scripts.ValidatorTypes Split where
type instance RedeemerType Split = ()
type instance DatumType Split = SplitData

splitInstance :: Scripts.ScriptInstance Split
splitInstance = Scripts.validator @Split
splitValidator :: Scripts.TypedValidator Split
splitValidator = Scripts.mkTypedValidator @Split
$$(PlutusTx.compile [|| validateSplit ||])
$$(PlutusTx.compile [|| wrap ||]) where
wrap = Scripts.wrapValidator @SplitData @()
Expand Down Expand Up @@ -109,20 +109,20 @@ lockFunds :: SplitData -> Contract () SplitSchema T.Text ()
lockFunds s@SplitData{amount} = do
logInfo $ "Locking " <> Haskell.show amount
let tx = Constraints.mustPayToTheScript s (Ada.toValue amount)
void $ submitTxConstraints splitInstance tx
void $ submitTxConstraints splitValidator tx

-- BLOCK8

unlockFunds :: SplitData -> Contract () SplitSchema T.Text ()
unlockFunds SplitData{recipient1, recipient2, amount} = do
let contractAddress = (Ledger.scriptAddress (Scripts.validatorScript splitInstance))
let contractAddress = Scripts.validatorAddress splitValidator
utxos <- utxoAt contractAddress
let half = Ada.divide amount 2
tx =
collectFromScript utxos ()
<> Constraints.mustPayToPubKey recipient1 (Ada.toValue half)
<> Constraints.mustPayToPubKey recipient2 (Ada.toValue $ amount - half)
void $ submitTxConstraintsSpending splitInstance utxos tx
void $ submitTxConstraintsSpending splitValidator utxos tx

-- BLOCK9

Expand Down
10 changes: 5 additions & 5 deletions doc/plutus/tutorials/BasicValidators.hs
Expand Up @@ -12,7 +12,7 @@ import PlutusTx
import PlutusTx.Lift
import PlutusTx.Prelude

import Ledger hiding (ScriptType)
import Ledger hiding (validatorHash)
import Ledger.Ada
import Ledger.Typed.Scripts
import Ledger.Value
Expand Down Expand Up @@ -84,7 +84,7 @@ validatePayment _ _ ctx = check $ case fromData ctx of
_ -> False
-- BLOCK5
data DateValidator
instance ScriptType DateValidator where
instance ValidatorTypes DateValidator where
type instance RedeemerType DateValidator = Date
type instance DatumType DateValidator = EndDate
-- BLOCK6
Expand All @@ -94,8 +94,8 @@ validateDateTyped endDate date _ = beforeEnd date endDate
validateDateWrapped :: Data -> Data -> Data -> ()
validateDateWrapped = wrapValidator validateDateTyped
-- BLOCK7
dateInstance :: ScriptInstance DateValidator
dateInstance = validator @DateValidator
dateInstance :: TypedValidator DateValidator
dateInstance = mkTypedValidator @DateValidator
-- The first argument is the compiled validator.
$$(compile [|| validateDateTyped ||])
-- The second argument is a compiled wrapper.
Expand All @@ -105,7 +105,7 @@ dateInstance = validator @DateValidator
wrap = wrapValidator

dateValidatorHash :: ValidatorHash
dateValidatorHash = scriptHash dateInstance
dateValidatorHash = validatorHash dateInstance

dateValidator :: Validator
dateValidator = validatorScript dateInstance
Expand Down
3 changes: 1 addition & 2 deletions doc/plutus/tutorials/GameModel.hs
Expand Up @@ -300,7 +300,7 @@ wallets = [w1, w2, w3]
-- START gameTokenVal
gameTokenVal :: Value
gameTokenVal =
let sym = Scripts.monetaryPolicyHash G.scriptInstance
let sym = Scripts.forwardingMonetaryPolicyHash G.typedValidator
in G.token sym "guess"
-- END gameTokenVal

Expand Down Expand Up @@ -580,4 +580,3 @@ typeSignatures = id
chooseQ :: (Arbitrary a, Random a, Ord a) => (a, a) -> Quantification a
-- END chooseQ type
chooseQ = ContractModel.chooseQ

2 changes: 1 addition & 1 deletion doc/plutus/tutorials/basic-apps.rst
Expand Up @@ -74,7 +74,7 @@ You then need some boilerplate to compile the validator to a Plutus script (see
:start-after: BLOCK3
:end-before: BLOCK4

The ``ScriptType`` class defines the types of the validator, and ``splitInstance`` contains the compiled Plutus core code of ``validateSplit``.
The :hsobj:`Ledger.Typed.Scripts.Validators.ValidatorTypes` class defines the types of the validator, and ``splitValidator`` contains the compiled Plutus core code of ``validateSplit``.

Asking for input
----------------
Expand Down
4 changes: 2 additions & 2 deletions doc/plutus/tutorials/basic-validators.rst
Expand Up @@ -109,7 +109,7 @@ There is a higher-level interface in :hsmod:`Ledger.Typed.Scripts` which handles
To use it, we first need to define a datatype that we can use to identify the particular validator that we are working on.
This data type is empty, because we're just going to use it as a "name": it helps the Haskell type system know what to look for.

We then define an instance of :hsobj:`Ledger.Typed.Scripts.Validators.ScriptType` for our "name".
We then define an instance of :hsobj:`Ledger.Typed.Scripts.Validators.ValidatorTypes` for our "name".
This tells the compiler what the Haskell types for the redeemer and datum are, so that the compiler can check whether we're using the right ones later.

.. literalinclude:: BasicValidators.hs
Expand All @@ -125,7 +125,7 @@ This takes advantage of the information we provided in our ``ScriptType`` instan
:start-after: BLOCK6
:end-before: BLOCK7

Finally, we can use the :hsobj:`Ledger.Typed.Scripts.validator` function to get a :hsobj:`Ledger.Typed.Scripts.ScriptInstance`.
Finally, we can use the :hsobj:`Ledger.Typed.Scripts.Validators.mkTypedValidator` function to get a :hsobj:`Ledger.Typed.Scripts.Validators.TypedValidator`.
This packages up the compiled validator for us, letting us pull out the compiled version, the hash, the address, and a few other useful things.

.. literalinclude:: BasicValidators.hs
Expand Down
22 changes: 11 additions & 11 deletions marlowe/src/Language/Marlowe/Client.hs
Expand Up @@ -54,8 +54,8 @@ import qualified Ledger.Typed.Scripts as Scripts
import Ledger.Typed.Tx (TypedScriptTxOut (..), tyTxOutData)
import qualified Ledger.Value as Val
import Plutus.Contract
import Plutus.Contract.StateMachine (AsSMContractError (..), StateMachine (..), StateMachineClient (..),
StateMachineInstance (..), Void, WaitingResult (..), getStates)
import Plutus.Contract.StateMachine (AsSMContractError (..), StateMachine (..), StateMachineClient (..), Void,
WaitingResult (..), getStates)
import qualified Plutus.Contract.StateMachine as SM
import qualified Plutus.Contracts.Currency as Currency
import qualified PlutusTx as PlutusTx
Expand Down Expand Up @@ -153,8 +153,8 @@ marloweFollowContract = do
where
follow (ifrom, ito, params) = do
let client@StateMachineClient{scInstance} = mkMarloweClient params
let inst = validatorInstance scInstance
let address = Scripts.scriptAddress inst
let inst = SM.typedValidator scInstance
let address = Scripts.validatorAddress inst
AddressChangeResponse{acrTxns} <- addressChangeRequest
AddressChangeRequest
{ acreqSlotRangeFrom = ifrom
Expand All @@ -178,8 +178,8 @@ marloweFollowContract = do

updateHistoryFromTx StateMachineClient{scInstance, scChooser} params tx = do
logInfo @String $ "Updating history from tx" <> show (Ledger.eitherTx Ledger.txId Ledger.txId tx)
let inst = validatorInstance scInstance
let address = Scripts.scriptAddress inst
let inst = SM.typedValidator scInstance
let address = Scripts.validatorAddress inst
let utxo = outputsMapFromTxForAddress address tx
let states = getStates scInstance utxo
case findInput inst tx of
Expand Down Expand Up @@ -233,9 +233,9 @@ marlowePlutusContract = do
marloweContract = contract,
marloweState = emptyState slot }
let payValue = adaValueOf 0
let StateMachineInstance{validatorInstance} = scInstance
let SM.StateMachineInstance{SM.typedValidator} = scInstance
let tx = mustPayToTheScript marloweData payValue <> distributeRoleTokens
let lookups = Constraints.scriptInstanceLookups validatorInstance
let lookups = Constraints.typedValidatorLookups typedValidator
utx <- either (throwing _ConstraintResolutionError) pure (Constraints.mkTx lookups tx)
submitTxConfirmed utx
marlowePlutusContract
Expand Down Expand Up @@ -598,8 +598,8 @@ mkMarloweValidatorCode params =

type MarloweStateMachine = StateMachine MarloweData MarloweInput

scriptInstance :: MarloweParams -> Scripts.ScriptInstance MarloweStateMachine
scriptInstance params = Scripts.validator @MarloweStateMachine
typedValidator :: MarloweParams -> Scripts.TypedValidator MarloweStateMachine
typedValidator params = Scripts.mkTypedValidator @MarloweStateMachine
(mkMarloweValidatorCode params)
$$(PlutusTx.compile [|| wrap ||])
where
Expand All @@ -610,7 +610,7 @@ mkMachineInstance :: MarloweParams -> SM.StateMachineInstance MarloweData Marlow
mkMachineInstance params =
SM.StateMachineInstance
(SM.mkStateMachine Nothing (mkMarloweStateMachineTransition params) isFinal)
(scriptInstance params)
(typedValidator params)


mkMarloweClient :: MarloweParams -> SM.StateMachineClient MarloweData MarloweInput
Expand Down
2 changes: 1 addition & 1 deletion marlowe/test/Spec/Marlowe/AutoExecute.hs
Expand Up @@ -44,7 +44,7 @@ import PlutusTx.Lattice
import Ledger hiding (Value)
import qualified Ledger
import Ledger.Ada (lovelaceValueOf)
import Ledger.Typed.Scripts (scriptHash, validatorScript)
import Ledger.Typed.Scripts (validatorScript)
import qualified PlutusTx.Prelude as P
import Spec.Marlowe.Common
import Test.Tasty
Expand Down
10 changes: 5 additions & 5 deletions marlowe/test/Spec/Marlowe/Marlowe.hs
Expand Up @@ -43,7 +43,7 @@ import Language.Marlowe.Util
import Ledger (Slot (..), pubKeyHash, validatorHash)
import Ledger.Ada (lovelaceValueOf)
import Ledger.Constraints.TxConstraints (TxConstraints)
import Ledger.Typed.Scripts (scriptHash, validatorScript)
import qualified Ledger.Typed.Scripts as Scripts
import qualified Ledger.Value as Val
import Plutus.Contract.Test hiding ((.&&.))
import qualified Plutus.Contract.Test as T
Expand Down Expand Up @@ -217,16 +217,16 @@ uniqueContractHash = do
{ rolesCurrency = cs
, rolePayoutValidatorHash = validatorHash (rolePayoutScript cs) }

let hash1 = scriptHash $ scriptInstance (params "11")
let hash2 = scriptHash $ scriptInstance (params "22")
let hash3 = scriptHash $ scriptInstance (params "22")
let hash1 = Scripts.validatorHash $ typedValidator (params "11")
let hash2 = Scripts.validatorHash $ typedValidator (params "22")
let hash3 = Scripts.validatorHash $ typedValidator (params "22")
assertBool "Hashes must be different" (hash1 /= hash2)
assertBool "Hashes must be same" (hash2 == hash3)


validatorSize :: IO ()
validatorSize = do
let validator = validatorScript $ scriptInstance defaultMarloweParams
let validator = Scripts.validatorScript $ typedValidator defaultMarloweParams
let vsize = BS.length $ Write.toStrictByteString (Serialise.encode validator)
assertBool ("Validator is too large " <> show vsize) (vsize < 1100000)

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions plutus-benchmark/flat/Dataset.hs
Expand Up @@ -97,19 +97,19 @@ runQuote tm = do

contractsWithNames :: [ (Text, Term Name DefaultUni DefaultFun ()) ]
contractsWithNames = map (second (runQuote . nameDeBruijn . getTerm . Plutus.unScript . Plutus.unValidatorScript))
[ ("game-names", Plutus.validatorScript GameStateMachine.scriptInstance)
[ ("game-names", Plutus.validatorScript GameStateMachine.typedValidator)
, ("crowdfunding-names", Crowdfunding.contributionScript Crowdfunding.theCampaign)
, ("marlowe-names", Plutus.validatorScript $ Marlowe.scriptInstance Marlowe.defaultMarloweParams)
, ("marlowe-names", Plutus.validatorScript $ Marlowe.typedValidator Marlowe.defaultMarloweParams)
, ("vesting-names", Vesting.vestingScript vesting)
, ("escrow-names", Plutus.validatorScript $ Escrow.scriptInstance escrowParams)
, ("escrow-names", Plutus.validatorScript $ Escrow.typedValidator escrowParams)
, ("future-names", Future.validator theFuture Future.testAccounts) ]

contractsWithIndices ::
[ (Text, Term DeBruijn DefaultUni DefaultFun ()) ]
contractsWithIndices = map (second (getTerm . Plutus.unScript . Plutus.unValidatorScript))
[ ("game-indices", Plutus.validatorScript GameStateMachine.scriptInstance)
[ ("game-indices", Plutus.validatorScript GameStateMachine.typedValidator)
, ("crowdfunding-indices", Crowdfunding.contributionScript Crowdfunding.theCampaign)
, ("marlowe-indices", Plutus.validatorScript $ Marlowe.scriptInstance Marlowe.defaultMarloweParams)
, ("marlowe-indices", Plutus.validatorScript $ Marlowe.typedValidator Marlowe.defaultMarloweParams)
, ("vesting-indices", Vesting.vestingScript vesting)
, ("escrow-indices", Plutus.validatorScript $ Escrow.scriptInstance escrowParams)
, ("escrow-indices", Plutus.validatorScript $ Escrow.typedValidator escrowParams)
, ("future-indices", Future.validator theFuture Future.testAccounts) ]
10 changes: 5 additions & 5 deletions plutus-contract/src/Plutus/Contract/Effects/WriteTx.hs
Expand Up @@ -31,7 +31,7 @@ import Ledger.Constraints (TxConstraints)
import Ledger.Constraints.OffChain (ScriptLookups, UnbalancedTx)
import qualified Ledger.Constraints.OffChain as Constraints
import Ledger.Tx (Tx, txId)
import Ledger.Typed.Scripts (ScriptInstance, ScriptType (..))
import Ledger.Typed.Scripts (TypedValidator, ValidatorTypes (..))

import Wallet.API (WalletAPIError)

Expand Down Expand Up @@ -90,10 +90,10 @@ submitTxConstraints
, PlutusTx.IsData (DatumType a)
, AsContractError e
)
=> ScriptInstance a
=> TypedValidator a
-> TxConstraints (RedeemerType a) (DatumType a)
-> Contract w s e Tx
submitTxConstraints inst = submitTxConstraintsWith (Constraints.scriptInstanceLookups 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 @@ -104,12 +104,12 @@ submitTxConstraintsSpending
, PlutusTx.IsData (DatumType a)
, AsContractError e
)
=> ScriptInstance a
=> TypedValidator a
-> UtxoMap
-> TxConstraints (RedeemerType a) (DatumType a)
-> Contract w s e Tx
submitTxConstraintsSpending inst utxo =
let lookups = Constraints.scriptInstanceLookups inst <> Constraints.unspentOutputs utxo
let lookups = Constraints.typedValidatorLookups inst <> Constraints.unspentOutputs utxo
in submitTxConstraintsWith lookups

-- | Build a transaction that satisfies the constraints, then submit it to the
Expand Down
12 changes: 6 additions & 6 deletions plutus-contract/src/Plutus/Contract/StateMachine.hs
Expand Up @@ -220,7 +220,7 @@ waitForUpdateUntil ::
-> Slot
-> Contract w schema e (WaitingResult state)
waitForUpdateUntil StateMachineClient{scInstance, scChooser} timeoutSlot = do
let addr = Scripts.scriptAddress $ validatorInstance scInstance
let addr = Scripts.validatorAddress $ typedValidator scInstance
let go sl = do
txns <- acrTxns <$> addressChangeRequest AddressChangeRequest
{ acreqSlotRangeFrom = sl
Expand Down Expand Up @@ -257,7 +257,7 @@ waitForUpdate ::
=> StateMachineClient state i
-> Contract w schema e (Maybe (OnChainState state i))
waitForUpdate StateMachineClient{scInstance, scChooser} = do
let addr = Scripts.scriptAddress $ validatorInstance scInstance
let addr = Scripts.validatorAddress $ typedValidator scInstance
txns <- nextTransactionsAt addr
let states = txns >>= getStates scInstance . outputsMapFromTxForAddress addr
case states of
Expand Down Expand Up @@ -331,9 +331,9 @@ runInitialise ::
-- ^ The value locked by the contract at the beginning
-> Contract w schema e state
runInitialise StateMachineClient{scInstance} initialState initialValue = mapError (review _SMContractError) $ do
let StateMachineInstance{validatorInstance, stateMachine} = scInstance
let StateMachineInstance{typedValidator, stateMachine} = scInstance
tx = mustPayToTheScript initialState (initialValue <> SM.threadTokenValue stateMachine)
let lookups = Constraints.scriptInstanceLookups validatorInstance
let lookups = Constraints.typedValidatorLookups typedValidator
utx <- either (throwing _ConstraintResolutionError) pure (Constraints.mkTx lookups tx)
submitTxConfirmed utx
pure initialState
Expand All @@ -360,7 +360,7 @@ mkStep ::
-> input
-> Contract w schema e (Either (InvalidTransition state input) (StateMachineTransition state input))
mkStep client@StateMachineClient{scInstance} input = do
let StateMachineInstance{stateMachine, validatorInstance} = scInstance
let StateMachineInstance{stateMachine, typedValidator} = scInstance
StateMachine{smTransition} = stateMachine
maybeState <- getOnChainState client
case maybeState of
Expand All @@ -373,7 +373,7 @@ mkStep client@StateMachineClient{scInstance} input = do
case smTransition oldState input of
Just (newConstraints, newState) ->
let lookups =
Constraints.scriptInstanceLookups validatorInstance
Constraints.typedValidatorLookups typedValidator
<> Constraints.unspentOutputs utxo
outputConstraints =
if smFinal (SM.stateMachine scInstance) (stateData newState)
Expand Down
8 changes: 4 additions & 4 deletions plutus-contract/src/Plutus/Contract/StateMachine/OnChain.hs
Expand Up @@ -88,19 +88,19 @@ mkStateMachine smThreadToken smTransition smFinal =
, smThreadToken
}

instance ScriptType (StateMachine s i) where
instance ValidatorTypes (StateMachine s i) where
type instance RedeemerType (StateMachine s i) = i
type instance DatumType (StateMachine s i) = s

data StateMachineInstance s i = StateMachineInstance {
-- | The state machine specification.
stateMachine :: StateMachine s i,
stateMachine :: StateMachine s i,
-- | The validator code for this state machine.
validatorInstance :: ScriptInstance (StateMachine s i)
typedValidator :: TypedValidator (StateMachine s i)
}

machineAddress :: StateMachineInstance s i -> Address
machineAddress = scriptAddress . validatorInstance
machineAddress = validatorAddress . typedValidator

{-# INLINABLE mkValidator #-}
-- | Turn a state machine into a validator script.
Expand Down
1 change: 1 addition & 0 deletions plutus-ledger/plutus-ledger.cabal
Expand Up @@ -56,6 +56,7 @@ library
Ledger.Tokens
Ledger.Typed.Scripts
Ledger.Typed.Scripts.Validators
Ledger.Typed.Scripts.MonetaryPolicies
Ledger.Typed.Tx
Ledger.Typed.TypeUtils
reexported-modules:
Expand Down
4 changes: 2 additions & 2 deletions plutus-ledger/src/Ledger/Constraints.hs
Expand Up @@ -25,7 +25,7 @@ module Ledger.Constraints(
, ScriptLookups(..)
, MkTxError(..)
, UnbalancedTx
, scriptInstanceLookups
, typedValidatorLookups
, unspentOutputs
, monetaryPolicy
, otherScript
Expand All @@ -39,7 +39,7 @@ module Ledger.Constraints(

import Ledger.Constraints.OffChain (MkTxError (..), ScriptLookups (..), SomeLookupsAndConstraints (..),
UnbalancedTx, mkSomeTx, mkTx, monetaryPolicy, otherData, otherScript,
ownPubKeyHash, scriptInstanceLookups, unspentOutputs)
ownPubKeyHash, typedValidatorLookups, unspentOutputs)
import Ledger.Constraints.OnChain (checkScriptContext)
import Ledger.Constraints.TxConstraints

Expand Down

0 comments on commit 6f834b5

Please sign in to comment.