Open RSoulatIOHK opened 7 months ago
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.
Lack of many key library functions for writing and testing contracts. A few obvious examples that should be in a library are:
toTxOutValue :: Value -> C.TxOutValue C.BabbageEra
toHashableScriptData :: (PlutusTx.ToData a) => a -> C.HashableScriptData
toTxOutInlineDatum :: (PlutusTx.ToData a) => a -> C.TxOutDatum C.CtxTx C.BabbageEra
toValidityRange :: SlotConfig -> Interval.Interval POSIXTime -> (C.TxValidityLowerBound C.BabbageEra, C.TxValidityUpperBound C.BabbageEra)
Many different definitions of key types such as Value
, PaymentPubKeyHash
, TxOut
etc., leading to users having to convert back and forth all the time. It would be great to have a list of libraries of a concrete list of functions that can provide users an easier way to work with these types. Often it can take hours to figure out how to get from one version of a type to another and sometimes it is impossible. Examples of these are:
pkh = Ledger.PaymentPubKeyHash $ fromJust $ Ledger.cardanoPubKeyHash wallet
currentlyLocked = C.fromCardanoValue (foldMap Ledger.cardanoTxOutValue (C.unUTxO unspentOutputs))
I think the issue of many different definition of key types across the libraries is exacerbated by the issue of the fact that there is no single library containing the key functions needed for converting between types.
It would be good to be able to debug CEK machine errors as currently it can difficult to figure out why a transaction is failing. Previous techniques such as the use of traceIfFalse
do not seem to work anymore and the validation error code is no longer returned to the user
There is a lack of up to date documentation, examples and tutorials for developing contracts in the latest version of Plutus and Cardano API. In the old Plutus-apps we had around 20 different examples showcasing various contracts and now we have 2 examples in the equivalent repo. As far as I know there is only 1 other public example which Alasdair Hill has written in a separate repo. The solution to this is not simple as we can't just copy the old examples as many of them relied on the state machine model which is no longer supported.
Example 1:
This example is from the escrow example in the cardano-node-emulator:
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)
Your contact information
RSoulatIOHK
Issue description
Feedback to triage/discuss: