1

How can we reference the use of other scripts in a plutus validator?. Wat I was trying to making is an validator that only validates if an other predetermined plutus scripts also validates in the same transaction. What I tried is the following naive implementation with a type problem

{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE DeriveAnyClass      #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE NoImplicitPrelude   #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE TypeOperators       #-}

{-# OPTIONS_GHC -fno-warn-unused-imports #-}

module Onchain where

import           Control.Monad        hiding (fmap)
import           Data.Aeson           (ToJSON, FromJSON)
import           Data.Map             as Map
import           Data.Text            (Text)
import           Data.Void            (Void)
import           GHC.Generics         (Generic)
import           Plutus.Contract
import           PlutusTx             (Data (..))
import qualified PlutusTx
import           PlutusTx.Prelude     hiding (Semigroup(..), unless)
import           Ledger               hiding (singleton)
import           Ledger.Constraints   (TxConstraints)
import qualified Ledger.Constraints   as Constraints
import qualified Ledger.Typed.Scripts as Scripts
import           Ledger.Ada           as Ada
import           Playground.Contract  (printJson, printSchemas, ensureKnownCurrencies, stage, ToSchema)
import           Playground.TH        (mkKnownCurrencies, mkSchemaDefinitions)
import           Playground.Types     (KnownCurrency (..))
import           Prelude              (IO, Semigroup (..), Show (..), String)
import           Text.Printf          (printf)

data MyDatum = MyDatum
    { pubKey :: Integer
    } deriving (Show, Generic, FromJSON, ToJSON, ToSchema)

data MyRedeemer = MyRedeemer
    { privKey :: Integer
    } deriving (Generic, FromJSON, ToJSON, ToSchema)

data ContractInfo = ContractInfo
    { contractValHash :: ValidatorHash }

contractInfo = ContractInfo { contractValHash =  "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656"}

PlutusTx.makeIsDataIndexed ''MyDatum [('MyDatum, 0)]
PlutusTx.makeLift ''MyDatum
PlutusTx.makeIsDataIndexed ''MyRedeemer [('MyRedeemer, 0)]
PlutusTx.makeLift ''MyRedeemer
PlutusTx.makeLift ''ContractInfo

{-# INLINABLE mkValidator #-}
mkValidator :: ContractInfo -> MyDatum -> MyRedeemer -> ScriptContext -> Bool
mkValidator contractInfo _ _ ctx = traceIfFalse "Signature not there" $ signed
        where 
              info :: TxInfo
              info = scriptContextTxInfo ctx

              sigs :: [PubKeyHash]
              sigs = txInfoSignatories info
              
              pubkeyHash :: ValidatorHash
              pubkeyHash = contractValHash contractInfo
              
              signed :: Bool
              signed = pubkeyHash `elem` sigs -- THIS IS NOT WELL TYPED AND WILL NOT COMPILE SINCE pubkeyHash is actually of type ValidatorHash.

{-# INLINABLE mkValidator2 #-}
mkValidator2 :: BuiltinData -> BuiltinData -> BuiltinData -> ()
mkValidator2 _ _ _ = ()

data Typed
instance Scripts.ValidatorTypes Typed where
    type instance DatumType Typed = MyDatum
    type instance RedeemerType Typed = MyRedeemer

typedValidator :: Scripts.TypedValidator Typed
typedValidator = Scripts.mkTypedValidator @Typed
    ($$(PlutusTx.compile [|| mkValidator ||]) `PlutusTx.applyCode` PlutusTx.liftCode contractInfo)
    $$(PlutusTx.compile [|| wrap ||])
  where
    wrap = Scripts.wrapValidator @MyDatum @MyRedeemer

validator2 :: Validator
validator2 = mkValidatorScript $$(PlutusTx.compile [|| mkValidator2 ||])

validator :: Validator
validator = Scripts.validatorScript typedValidator

valHash :: Ledger.ValidatorHash
valHash = Scripts.validatorHash typedValidator

scrAddress :: Ledger.Address
scrAddress = scriptAddress validator

scrAddress2 :: Ledger.Address 
scrAddress2 = scriptAddress validator2


Where 67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656 is the ValidatorHash of the validator2 derived from printing scrAddress2. So the first validator mkValidator will validate only if the transaction also contains a validating consumption of an UTxO at the validator2 address? Now of course this will not validate since a validatorHash is not contained in the signature list of type txInfoSignatories :: [PubKeyHash]. But still this would be desirable to have right? I could use this with some minting policy.

On testnet I tried changing the type of contractValHash to PubKeyHash, but this does not work either since scripts have no signatures in the txInfoSignatories field.

enter image description here

Is it perhaps possible to access the TxInType field?

enter image description here

This contains a reference to a script validator (but not really in its compressed form, only in the lamba calculus form). enter image description here

1 Answer 1

1

I just had to sleep a night on it. Obviously one can look at the incoming addresses and lookup the validatorhash in the credentials there. For example use

filter (\x -> (ScriptCredential . addressCredential . txOutAddress) x == ValHash) $ txInfoInputs ctx

to get the transaction input of that script you want present.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.