HeliosLang / compiler

Helios is a DSL for writing Cardano smart contracts. This library lets you compile Helios scripts and build Cardano transactions.
https://www.hyperion-bt.org/helios-book
BSD 3-Clause "New" or "Revised" License
142 stars 31 forks source link

Using tx.minted inside a validator causes a runtime error #34

Closed lley154 closed 1 year ago

lley154 commented 1 year ago

I have a validator that will generate a runtime error when I try to use tx.minted using a Helio tx built transaction. Oddly, if I build a similar transaction using cardano-cli, it succeeds.

Code verion: @hyperionbt/helios - npm version: v0.9.7

Tx-submit-error: https://github.com/lley154/littercoin/blob/preprod-6.11/testing/mint-issue/submit-error.txt

Source code: https://github.com/lley154/littercoin/blob/preprod-6.11/src/lcValidator.hl Line: 113 (or 112)

Tx.dump-before-final: https://github.com/lley154/littercoin/blob/preprod-6.11/testing/mint-issue/tx-before-final.txt

Tx.dump-after-final: https://github.com/lley154/littercoin/blob/preprod-6.11/testing/mint-issue/tx-after-final.txt

lcValidator IR: https://github.com/lley154/littercoin/blob/preprod-6.11/testing/mint-issue/lcValidatorIR.txt lcValidator.hl: https://github.com/lley154/littercoin/blob/preprod-6.11/src/lcValidator.hl

lcMint IR: https://github.com/lley154/littercoin/blob/preprod-6.11/testing/mint-issue/lcMintIR.txt lcMint.hl: https://github.com/lley154/littercoin/blob/preprod-6.11/src/lcMint.hl

Next.js app: mintLC line 403: https://github.com/lley154/littercoin/blob/preprod-6.11/app/pages/index.tsx

cbor working (cardano-cli builder): https://github.com/lley154/littercoin/blob/preprod-6.11/testing/mint-issue/cbor.working.txt

cbor not working (helios tx builder): https://github.com/lley154/littercoin/blob/preprod-6.11/testing/mint-issue/cbor.notworking.txt

lley154 commented 1 year ago

A secondary issue is that the costs from the cost model estimates (either via Helios redeemerCostTracker or cardano-cli) indicates that I should be well below cpu and memory execution units limits. This is suppose be to be deterministic, meaning that I should not find out surprises later after submitting that the execution costs are now higher and over budget compared to what was calculated beforehand.
image

christianschmitz commented 1 year ago

Let's first try to tackle the difference in calculated ex-budget for redeeming from the validator between cardano-cli and helios.

First we should try to make the transactions as equivalent as possible. Right now the Helios tx has more inputs than the cardano-cli tx (although I don't think that's the issue because the validator script doesn't actually access the inputs).

Another difference I notice is that the outputs of the working transaction don't contain the staking part in their addresses, and the outputs of the non-working transaction do contain the staking part. Although unlikely, that might be giving the problem (I haven't done much testing of smart contract interacting with addresses containing a staking part).

christianschmitz commented 1 year ago

Another thing I notice is that you seem to be minting 25 littercoins, whereas the inline datum attached to the output states 5 littercoins more (so 10 in total).

So I assume you intend to use tx.minted == lcMintVal, and only actually mint 5 littercoins?

christianschmitz commented 1 year ago

Could you print the number of littercoins being minted when building the tx using helios?: print(tx.minted.get(lcAssetClass).show())

christianschmitz commented 1 year ago

I've added the STRICT_BABBAGE global boolean flag to helios.js in the dev branch. If you set that to true the TxOutputs should be serialized exactly the same as cardano-cli. For the order of the TxOutputs I recommend you call tx.addOutput in the same order that the outputs appear in the cardano-cli transaction.

lley154 commented 1 year ago

Hi Christian,

I re-tested the mint transaction with the STRICT_BABBAGE set to true but the mint-tx still fails when using the helios tx builder but succeeds when using cardano-cli. I’ve include the latest results below. I also added the print statement, but don’t seem to see it any output. Also, please ignore the datum discrepancy noted above since this was caused by me changing the lc mint amounts in the exported cbor file. We can use the following cbor files below which are direct outputs from the txs.

As you can see, the main differences now are the ordering of the tx outputs and the using addresses with staking keys.

I have changed the application design to avoid having a mint and validator in the same transaction, so this will unblock me for now. But do think there is something amiss. I also saw a similar behavior where I got an unexplained cpu/mem limit error when trying to use tx.value_sent_to(). I suspect it is an old fashion null pointer exception somewhere that then causes the plutus runtime engine to go nuts and triggers cpu/mem errors.

Npm version: "@hyperionbt/helios": "^0.10.1"

Cbor not working (helio tx builder): https://github.com/lley154/littercoin/blob/preprod-6.12/testing/mint-issue/cbor.notworking.helios-2022-12-22.txt

Cbor working (cardano-cli): https://github.com/lley154/littercoin/blob/preprod-6.12/testing/mint-issue/cbor.working-cli-2022-12-22.txt

Testing log 2022-12-22: https://github.com/lley154/littercoin/blob/preprod-6.12/testing/mint-issue/mint-tx-testing-log.txt

christianschmitz commented 1 year ago

The number if inputs in both transactions is still different (2 for the cardano-cli tx, and 4 for the helios tx).

Could you try and make that the same?

lley154 commented 1 year ago

Current list of inputs for a failing mint-tx using Helios Tx builder image

I looked up each of these via cardano-cli to setup 4 similar inputs.

1st input -> Ada only 2nd input -> Ada only 3rd input -> smart contract with datum + ada + littercoin 4th input -> Ada only image

So I used txs from: image

So the transaction looked like:

$CARDANO_CLI transaction build \ --babbage-era \ --cardano-mode \ $network \ --change-address "$admin_utxo_addr" \ --tx-in-collateral "$admin_utxo_collateral_in" \ --tx-in "17991ed21641cdb9e8ade9d2411b1a639eceb7e761c05b61c12cd8e7b1fcda7b#0" \ --tx-in "$admin_utxo_in" \ --tx-in "$lc_validator_utxo_tx_in" \ --tx-in "fc43cabb12782a07de1067414cdd80c7e4b020c9245d6ecd2e0490129c7b61bc#0" \ --spending-tx-in-reference "$LC_VAL_REF_SCRIPT" \ --spending-plutus-script-v2 \ --spending-reference-tx-in-inline-datum-present \ --spending-reference-tx-in-redeemer-file "$redeemer_val_file_path" \ --mint "$lc_amount $lc_mint_mph.$lc_token_name" \ --mint-tx-in-reference "$LC_MINT_REF_SCRIPT" \ --mint-plutus-script-v2 \ --mint-reference-tx-in-redeemer-file "$WORK/redeemer-mint.json" \ --policy-id "$lc_mint_mph" \ --tx-out "$lc_validator_script_addr+$total_ada + 1 $thread_token_mph.$thread_token_name" \ --tx-out-inline-datum-file "$WORK/lc-datum-out.json" \ --tx-out "$user_addr+$MIN_ADA_OUTPUT_TX + $lc_amount $lc_mint_mph.$lc_token_name" \ --required-signer-hash $admin_pkh \ --protocol-params-file "$WORK/pparms.json" \ --out-file $WORK/mint-tx-alonzo.body

Interestingly, when I ran it I got the following error below…

/usr/local/bin/cardano-cli transaction build --babbage-era --cardano-mode --testnet-magic 1 --change-address addr_test1vzu6hnmgvageu2qyypy25yfqwg222tndt5eg3d6j68p8dqspgdxn7 --tx-in-collateral ff5141fe2535284719b2261e78a97b2c3e7111210b6af56b5f6107a2938ee382#0 --tx-in 17991ed21641cdb9e8ade9d2411b1a639eceb7e761c05b61c12cd8e7b1fcda7b#0 --tx-in 17991ed21641cdb9e8ade9d2411b1a639eceb7e761c05b61c12cd8e7b1fcda7b#0 --tx-in d36e0a777ac7234a1dcf30a485dea1c68b81f1286f3c016e35ed5598652976e8#1 --tx-in fc43cabb12782a07de1067414cdd80c7e4b020c9245d6ecd2e0490129c7b61bc#0 --spending-tx-in-reference c5ce3dd5330ba04702afff35e31fd01cc6176b003bcb2a11515e29c402940ba5#2 --spending-plutus-script-v2 --spending-reference-tx-in-inline-datum-present --spending-reference-tx-in-redeemer-file /home/lawrence/src/littercoin/scripts/preprod/data/redeemer-val-mint.json --mint '25 6969422d5c16017d6bf45123e754c03529a7f4a4e4dce894db812c65.4c6974746572636f696e' --mint-tx-in-reference c5ce3dd5330ba04702afff35e31fd01cc6176b003bcb2a11515e29c402940ba5#3 --mint-plutus-script-v2 --mint-reference-tx-in-redeemer-file /home/lawrence/src/littercoin/work/redeemer-mint.json --policy-id 6969422d5c16017d6bf45123e754c03529a7f4a4e4dce894db812c65 --tx-out 'addr_test1wqsd2067dgex6506suqmvtrsxcr20pytd0nwkd30hhqmpmga7p7dq+10000000 + 1 1fb4cbbaafc9e44d17ea51ca27b1a05d50a923fd5e34dcdf59086565.54687265616420546f6b656e204c6974746572636f696e' --tx-out-inline-datum-file /home/lawrence/src/littercoin/work/lc-datum-out.json --tx-out 'addr_test1vq5s7k4kwqz4rrfe8mm9jz9tpm7c5u93yfwwsaw708yxs5sm70qjg+2000000 + 25 6969422d5c16017d6bf45123e754c03529a7f4a4e4dce894db812c65.4c6974746572636f696e' --required-signer-hash b9abcf6867519e28042048aa11207214a52e6d5d3288b752d1c27682 --protocol-params-file /home/lawrence/src/littercoin/work/pparms.json --out-file /home/lawrence/src/littercoin/work/mint-tx-alonzo.body Command failed: transaction build Error: Error translating the transaction context: RdmrPtrPointsToNothing (RdmrPtr Spend 3)

christianschmitz commented 1 year ago

Even though the 3 non-littercoin inputs only contain Ada, could it be that one of them is locked in a smart contract?

Also: the --spending-* options should come after the 3rd input, not after the last

lley154 commented 1 year ago

The 3 Ada only utxos were only locked at a wallet address. I also decided to clean out the utxos and retry the transaction using Helios Tx builder with only 2 inputs but got the same error.
image

lley154 commented 1 year ago

I also used the exact same inputs and was able to submit the transaction using cardano-cli. We're reducing step by step the differences between a working cbor and not working cbor which helpful. Here is the latest cbors with 2 identical inputs.

Cbor working (cardano-cli): https://github.com/lley154/littercoin/blob/preprod-6.13/testing/mint-issue/cbor-working.cli-2022-12-22.2inputs.txt

Cbor not-working (helios Tx builder): https://github.com/lley154/littercoin/blob/preprod-6.13/testing/mint-issue/cbor-notworking.helios-2022-12-22.2inputs.txt

christianschmitz commented 1 year ago

Sorry I've had to little time to look more into this.

I think I noticed the outputs are still in a different order. I'm assuming that that impacts the execution budget calculation. Are you able to make two transactions with exactly the same order of the outputs ?

christianschmitz commented 1 year ago

I finally found the error.

Cardano-node always includes the lovelace amount in any Value in the ScriptContext, even if it is zero. Of course for minted assets the amount of lovelace is always zero, so this is redundant.

lley154 commented 1 year ago

Nice work! Thank you. I'll try a retest when I am able to.

christianschmitz commented 1 year ago

I haven't merged the solution yet. Will do so in a few hours.

christianschmitz commented 1 year ago

I've just released v0.10.15 of Helios, which should fix this error

I'll let you close this issue once you've tested it

lley154 commented 1 year ago

I tested it and it is now working - thank you!!! I can now check the minted value of a tx inside a spending validator. Here is a working tx on preprod: https://preprod.cexplorer.io/tx/30b8d6f27aaf0d9e489359c204dabf0710f3c752339bba9d7a113ee9ebe71308