input-output-hk / plutus-testing-tool

Central place to get all the information about the Plutus Testing Tool
0 stars 0 forks source link

[Issue]: Feedback on developing and testing with Plutus #9

Open RSoulatIOHK opened 4 months ago

RSoulatIOHK commented 4 months ago

Your contact information

RSoulatIOHK

Issue description

Feedback to triage/discuss:

Ali-Hill commented 4 months ago

Issues With Development in Plutus

This new way to write off-chain code has additional complexity that I don't think is needed for general use cases. One example of this is that you now have to construct the witness header and witness for transactions. See Example 1 that shows this complexity does not exist in the cooked validators library.

Example 1:

This example is from the escrow example in the cardano-node-emulator:

https://github.com/IntersectMBO/cardano-node-emulator/blob/main/cardano-node-emulator/test/Plutus/Examples/Escrow.hs

Cooked Validators:

redeem ::
    MonadBlockChain m
    => Pl.TypedValidator Escrow
    -> Wallet
    -> EscrowParams Datum
    -> m RedeemSuccess
redeem inst submitter escrow = do
    outputs <-
      runUtxoSearch $
        utxosAtSearch (Pl.validatorAddress inst)
    current <- currentTime
    let
      uouts = map snd outputs
      deadline = escrowDeadline escrow
    validityInterval <- slotRangeBefore (deadline - 1)
    if (snd current) >= deadline
    then throwError $ FailWith "Deadline Passed"
    else if foldMap txOutValue uouts `lt` targetTotal escrow
      then throwError $ FailWith "Not enough funds at address"
      else do
        tx <- (validateTxSkel $
                txSkelTemplate
                  { txSkelOpts = def {txOptEnsureMinAda = True},
                    txSkelSigners = [submitter],
                    txSkelIns = Map.fromList (map (\ (or , _) -> ( or , TxSkelRedeemerForScript Redeem)) outputs),
                    txSkelOuts = map (\case
                                        PaymentPubKeyTarget pk vl -> paysPK (L.unPaymentPubKeyHash pk) vl
                                        ScriptTarget _ _ _ -> error "can't use script with cooked")
                                        (escrowTargets escrow)
                    ,
                    txSkelValidityRange = validityInterval
                  })
        return (RedeemSuccess (L.getCardanoTxId tx))

Cardano API

mkRedeemTx
  :: (E.MonadEmulator m)
  => EscrowParams Datum
  -> m (C.CardanoBuildTx, Ledger.UtxoIndex)
mkRedeemTx escrow = do
  let escrowAddr = mkEscrowAddress escrow
  unspentOutputs <- E.utxosAt escrowAddr
  slotConfig <- asks pSlotConfig
  current <- fst <$> E.currentTimeRange
  if current >= escrowDeadline escrow
    then throwError $ E.CustomError $ show (RedeemFailed DeadlinePassed)
    else
      if C.fromCardanoValue (foldMap Ledger.cardanoTxOutValue (C.unUTxO unspentOutputs))
        `lt` targetTotal escrow
        then throwError $ E.CustomError $ show (RedeemFailed NotEnoughFundsAtAddress)
        else
          let
            validityRange = toValidityRange slotConfig $ Interval.to $ escrowDeadline escrow - 1000
            txOuts = map mkTxOutput (escrowTargets escrow)
            witnessHeader =
              C.toCardanoTxInScriptWitnessHeader
                (Ledger.getValidator <$> Scripts.vValidatorScript (typedValidator escrow))
            redeemer = toHashableScriptData Redeem
            witness =
              C.BuildTxWith $
                C.ScriptWitness C.ScriptWitnessForSpending $
                  witnessHeader C.InlineScriptDatum redeemer C.zeroExecutionUnits
            txIns = (,witness) <$> Map.keys (C.unUTxO unspentOutputs)
            utx =
              E.emptyTxBodyContent
                { C.txIns = txIns
                , C.txOuts = txOuts
                , C.txValidityLowerBound = fst validityRange
                , C.txValidityUpperBound = snd validityRange
                }
           in
            pure (C.CardanoBuildTx utx, unspentOutputs)