0

Given the following smart contract:

{-# INLINEABLE mkValidator #-}
mkValidator :: PubKeyHash -> BuiltinData -> ScriptContext -> Bool
mkValidator beneficiary _ ctx =
  traceIfFalse "tx not signed by beneficiary" signedByBeneficiary
  where
    info :: Ledger.TxInfo
    info = scriptContextTxInfo ctx

    signedByBeneficiary :: Bool
    signedByBeneficiary = txSignedBy info beneficiary

It only allows consumption of its' UTxO if the transaction is signed by a key that's part of the UTxO's datum.

I've sent some funds to the script address and verified the datum is correct.

Now I'm trying to create a transaction that consumes a UTxO from the script address with the cardano-cli transaction build command. However, the command runs the script validator locally before I've had a chance to sign the transaction. Therefore, the command fails with error PT5: tx not signed by beneficiary. This is expected because during that validation, the signature is not available in the ScriptContext.

How can I, either disable the local validator check, or attach a signature to the ScriptContext so the validator succeeds? I've tried the --required-signer option on the cardano-cli transaction build command but to no luck.


The failing command:

cardano-cli transaction build \
--alonzo-era \
--testnet-magic 1097911063 \
--tx-in 213b67f21034e4f4684b871da9a8c7a1ed867ff2eef02232c064e2004b7dc316#1 \
--tx-in-script-file Owner.plutus \
--tx-in-datum-value "\"$(cardano-cli address key-hash --payment-verification-key-file payment.vkey)\"" \
--tx-in-redeemer-value 0 \
--tx-in-collateral 213b67f21034e4f4684b871da9a8c7a1ed867ff2eef02232c064e2004b7dc316#0 \
--change-address $(cat payment.addr) \
--protocol-params-file pparams.json \
--out-file tx.build
2
  • How are you constructing the --required-signer part of the command? It should be able to solve the problem you have.
    – Montario
    Commented Jan 15, 2022 at 14:16
  • I have payment.vkey and payment.skey. While the verification key (vkey) was used to create the datum value, I used the signing key (skey) for the required signer: --required-signer payment.skey. Since the ordering matters, I used the option right after the --tx-in-redeemer-value option. Commented Jan 16, 2022 at 11:51

1 Answer 1

2

I am afraid that via the cardano-cli, you will not be able to do that. Indeed the cli evaluates the execution units before you get to sign the transaction.

Signatories are however available in the script context from a Plutus standpoint. Right now, I don't know any other way than doing it "the Haskell way" and by pre-constructing the transaction via the very same Haskell libraries used by the cardano-ledger. This will allow you to construct the script context necessary for your script to validate. A way to approach this is typically by running your script considering an unlimited budget, and then, replace this "unlimited budget" with the actual cost of execution that your observed -- hoping that this won't change the cost.

Incidentally, calculating script execution for a transaction is a kind of chicken-and-egg situation. For example, you need to know the execution cost of your script in order to balance your transaction for fees, but adjusting outputs for fees may also change the execution cost of your script. To avoid this, the cardano-cli was designed in a way that makes this process easy and deterministic. Yet, it comes with some drawbacks for scripts like yours which require some extra context.

Another option is to raise this as an issue to the team working on the cardano-cli (Github issues) to let them know of the design issue.

2

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.