Closed hasufell closed 2 years ago
@hasufell hmm how was MyDatum
passed in the cli? I suspect the addrHash
is probably actually a PubKey
and is being compared against addr
which is actually a PubKeyHash
.
see: cardano-cli address key-hash
for getting the hash instead from a PubKey
hmm how was MyDatum passed in the cli?
As a JSON string.
I suspect the addrHash is probably actually a PubKey and is being compared against addr which is actually a PubKeyHash. see: cardano-cli address key-hash for getting the hash instead from a PubKey
I tried all that too, I still get
Command failed: transaction build Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) failed with The Plutus script evaluation failed: An error has occurred: User error:
The provided Plutus code called 'error'.
This suggests that it doesn't deserialize well, according to https://github.com/input-output-hk/plutus/issues/3938
So, IMO, something is wrong with the structure, not the data.
I'm having the same problem. [TacoBell from Discord]
Are we able to write any dynamic values to the command line so we can get something to debug when trying to submit the unlock transaction?
I've been trying to print the datum in the playground where I input the pre-defined wallet pubkey hashes as a commitment, sth like:
newtype MyDatum = MyDatum BuiltinByteString
PlutusTx.makeLift ''MyDatum
PlutusTx.unstableMakeIsData ''MyDatum
lock :: AsContractError e => (PubKeyHash, Value) -> Contract w Schema e ()
lock (addr, lockedFunds) = do
let hash = sha3_256 $ getPubKeyHash addr
let tx = Constraints.mustPayToTheScript (MyDatum hash) lockedFunds
logInfo @Prelude.String (Prelude.show (Aeson.encode ((MyDatum hash))))
...
So the input PubKeyHash from the playground is fabc30d46356151102cc57d427d338b8790b2244c1250159685400dd
. The resulting aesonified datum will be: "09ea34dc60bad8c4d1e07043120e6a62f580fedcbdc0fb7ac4610a28429e066e"
.
I have no idea how to go from the pubkey hash to that datum. I converted to sha3_256 on the command-line and then ran cardano-cli transaction hash-script-data --script-data-value "\"$1\""
, but that yielded a different hash.
@hasufell one way would be to go from MyDatum -> BuiltinData -> Cardano.Api.ScriptData
before encoding into json which translates into the shape that the node expects. This also applies for Redeemer
-- note: unwrapping PubKeyHash or extra hashing is not required
newtype MyDatum = MyDatum PubKeyHash
let datum = MyDatum pkh
scriptData = fromPlutusData $ builtinDataToData $ toBuiltinData datum
scriptDataJson = scriptDataToJson ScriptDataJsonDetailedSchema scriptData
LBS.writeFile "datum-file" $ Aeson.encode scriptDataJson
Then you could get the datum hash with
cardano-cli transaction hash-script-data --script-data-file datum-file
or use it to build a tx
cardano-cli transaction build ... --tx-in-datum-file datum-file ...
One more thing to note is that including txInfoSignatories
from cardano-cli
received support since version 1.30.0
using the --required-signer payment.skey
Tested on testnet, plutus rev 58c093a49eb7a369865e361179d649264fc817a4
@luigy I tried the code you suggested and it outputs:
{"constructor":0,"fields":[{"bytes":"8e3dac9f8357279fd7b4e851211eb23fb4edb4de77f78959f0899f48b6d8d1e2"}]}
However, using cardano-cli transaction hash-script-data --script-data-file datum-file
on it still yields a different hash than I got above. Maybe that hash wasn't correct to begin with. I'm not sure how to debug that further.
Then I went on using --tx-in-datum-file
instead of --tx-in-datum-value
for the testnet use case and I get better errors with the input, such as:
SON schema error within the script data: {"constructor":0,"fields":[{"_nothing":[]}]}
JSON object does not match the schema.
Expected a single field named "int", "bytes", "string", "list" or "map".
Unexpected object field(s): {"_nothing":[]}
I tried to use both {"bytes":"$1"}
and {"constructor":0,"fields":[{"bytes":"$1"}]}
when constructing datum hash and redeemer values... and I still get
Command failed: transaction build Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) failed with The Plutus script evaluation failed: An error has occurred: User error:
The provided Plutus code called 'error'.
{"constructor":0,"fields":[{"bytes":"8e3dac9f8357279fd7b4e851211eb23fb4edb4de77f78959f0899f48b6d8d1e2"}]}
@hasufell the length doesn't look right to me is it actually using PubKeyHash? what plutus rev is in use?
Right vkey <- readFileTextEnvelope (AsVerificationKey AsPaymentKey) "payment.vkey"
let vkeyhash = PubKeyHash $ toBuiltin $ Api.serialiseToRawBytes $ Api.verificationKeyHash vkey
datum = MyDatum vkeyhash
scriptData = fromPlutusData $ builtinDataToData $ toBuiltinData datum
scriptDataJson = scriptDataToJson ScriptDataJsonDetailedSchema scriptData
LBS.writeFile "datum-file" $ Aeson.encode scriptDataJson
print vkeyhash
-- 1e95b74d0ee6e70126374fbacaef351cbad2fa5adeaa98f38c6ffa7f
-- {"constructor":0,"fields":[{"bytes":"1e95b74d0ee6e70126374fbacaef351cbad2fa5adeaa98f38c6ffa7f"}]}
@hasufell the length doesn't look right to me is it actually using PubKeyHash? what plutus rev is in use?
plutus-starter-devcontainer/v1.0.9
. The commitment that was inserted into the input field in plutus playground is the PubKeyHash that the plutus playground shows for Wallet 2:
In fact... I'm not 100% sure what this PubKeyHash
is really referring to anyway.
Also, I have to note that I run sha3_256
on the pubkeyhash :) (as described earlier)
Without it, I get fabc30d46356151102cc57d427d338b8790b2244c1250159685400dd
So I still haven't gotten any further. To reiterate my questions:
txInfoSignatories
(the [PubKeyHash]
)? And how would you get that from the command line? Sth like:
cat root.prv | cardano-address key child 1852H/1815H/0H/0/0 > addr.prv
cat addr.prv | cardano-address key public --with-chain-code > addr.xvk
cardano-cli address key-hash --payment-verification-key-file addr.xvk
The provided Plutus code called 'error'
?newtype MyDatum = MyDatum BuiltinByteString
and newtype MyRedeemer = MyRedeemer { _nothing :: () }
, what is the correct JSON you have to pass to cardano-cli transaction build
?
plutus-starter-devcontainer/v1.0.9.
@hasufell oh I see that would certainly be missing the latest hashing fixes for PubKey* and others for working with a non emulated node and would recommend updating to something like https://github.com/input-output-hk/plutus/commit/58c093a49eb7a369865e361179d649264fc817a4 which I've verified against
PubKeyHash
on the plutus sidecardano-cli
I'm also in the process of figuring out how to get better error messages reported --tx-in-redeemer-file
and the file can be generated similarly like shown for datumhmm though I suspect you might also be missing --required-signer payment.skey
on your cardano-cli transaction build
command which is what the validateSpend
is checking against in the txInfoSignatories
and hence you were seeing the errors 2.
Make sure to update newtype MyDatum = MyDatum BuiltinByteString
into newtype MyDatum = MyDatum PubKeyHash
and the validateSpend
accordingly
@luigy
I tried using your commit (cardano-cli is built via 959cd83b27e96715ba28a56f85e1d503bf13d41f
though I believe), switched everything to reading files (redeemer/datum), added --required-signer
(using the 1852H/1815H/0H/0/0
derivation path) and use the following json encoding for datum/redeemer:
newtype MyDatum = MyDatum { fromMyDatum :: BuiltinByteString }
-> "{\"constructor\":0,\"fields\":[{\"bytes\":\"abcdef0123\"}]}"
newtype MyRedeemer = MyRedeemer { _nothing :: () }
-> "{\"constructor\":0,\"fields\":[]}"
I'm not sure I can use newtype MyDatum = MyDatum PubKeyHash
, because the pubkey hash is hashed again via sha3_256
on purpose.
That's why validateSpend is this:
validateSpend :: ValidatorType Burner
validateSpend (MyDatum addrHash) _myRedeemerValue ScriptContext { scriptContextTxInfo = txinfo } =
traceIfFalse "owner has not signed" (addrHash `elem` fmap (sha3_256 . getPubKeyHash) (txInfoSignatories txinfo))
And all that works perfectly fine on playground and in the test suite.
To give more information on how I create the transactions via cli
To create the pubkey, I use:
cat root.prv |
cardano-address key child "1852H/1815H/0H/0/0" > addr.prv
cat addr.prv |
cardano-address key public --with-chain-code > addr.xvk
cardano-cli address key-hash --payment-verification-key-file addr.xvk
To create the skey and vkey for the transaction signatures and the required-signer signature, I use:
# for required signer, derivation path is 1852H/1815H/0H/0/0
cat root.prv |
cardano-address key child "$derivation_path" > addr.prv
cardano-cli key convert-cardano-address-key --shelley-payment-key --signing-key-file "addr.prv" --out-file "key.skey"
cardano-cli key verification-key --signing-key-file "key.skey" --verification-key-file "key.vkey"
To create the datum hash, I use:
# this hakes the json file as input, containing e.g. '{"constructor":0,"fields":[{"bytes":"abcdef"}]}'
cardano-cli transaction hash-script-data --script-data-file "$1"
I create the lock transaction with something like this:
cardano-cli transaction build \
--alonzo-era \
--tx-in "$tx_in" \
--tx-out "$addr+$amount" \
$([ -n "$datum_hash" ] && echo "--tx-out-datum-hash=$datum_hash") \
--change-address "$change_addr" \
$([ "$NETWORK" = "testnet" ] && echo --testnet-magic="${TESTNET_MAGIC}" || echo "--mainnet") \
--protocol-params-file "pparams.json" \
--witness-override 2 \
--required-signer="$6" \
--out-file "$tx_out"
The redeem transaction is built with something like this:
cardano-cli transaction build \
--alonzo-era \
--tx-in "$tx_in" \
--tx-in-script-file "$script_file" \
--tx-in-datum-file "$datum_file" \
--tx-in-redeemer-file "$redeemer_file" \
--tx-in-collateral "$tx_in_collateral" \
--change-address "$change_address" \
--protocol-params-file "pparams.json" \
$([ "$NETWORK" = "testnet" ] && echo --testnet-magic="${TESTNET_MAGIC}" || echo "--mainnet") \
--witness-override 2 \
--required-signer="$8" \
--out-file "$tx_out"
Now, I can successfully lock. But redeeming still causes the infamous and hard to debug error:
Command failed: transaction build Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) failed with:
The Plutus script evaluation failed: An error has occurred: User error:
The provided Plutus code called 'error'
@hasufell nice, thanks for the detailed response. Will try to take a look at this soon and can even pair up if you would like to build an example for future reference. Feel free to ping me on the Community discord if you're there
@hasufell this is what the lock I tried looks like:
funds=98000000 # 98 ADA
cardano-cli transaction build \
--alonzo-era \
--tx-in "$txid#$txix" \
--tx-out $(cat $scriptaddr)+$funds \
--tx-out-datum-hash $datumhash \
--change-address $useraddr \
--required-signer $requiredsigner \
$magic \
--out-file $txdraft
and the unlock:
cardano-cli transaction build \
--alonzo-era \
--protocol-params-file $protocolparams \
--tx-in $script_txid#$script_txix \
--tx-in-script-file $script \
--tx-in-datum-file $datumfile \
--tx-in-redeemer-file $redeemerfile \
--tx-in-collateral $collateral_txid#$collateral_txix \
--required-signer $requiredsigner \
--change-address $useraddr \
$magic \
--out-file $txunlockraw
@luigy still doesn't work for me. With latest cardano-node etc I get:
Command failed: transaction build Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) failed with:
The Plutus script evaluation failed: An error has occurred: User error:
The provided Plutus code called 'error'.
Caused by: [ (force (builtin headList)) (con list (data) []) ]
The full code is here: https://git.io/JPD3v
Feel free to ping me on the Community discord if you're there
I tried. But the server has some weird captcha verification, which is broken.
Ok, I was able to track down the issue further.
As described above, we use a redeemer dummy type, because whether redeeming works or not is supposed to be discovered by the txInfoSignatories
, not the redeemer datum:
-- | Redeemer holds no data, since the address is taken from the context.
newtype MyRedeemer = MyRedeemer { _nothing :: () }
PlutusTx.makeLift ''MyRedeemer
PlutusTx.unstableMakeIsData ''MyRedeemer
I followed down the code of cardano-api in the node, which apparently does the json encoding/decoding: https://github.com/input-output-hk/cardano-node/blob/d95ef21062a50acf8f35f1f5d94f8a8a70f7510b/cardano-api/src/Cardano/Api/ScriptData.hs#L431
In a repl, I was then able to generate the the json from the node code directly:
> Data.Aeson.encode $ scriptDataToJson ScriptDataJsonDetailedSchema $ (fromPlutusData $ builtinDataToData $ toBuiltinData (MyRedeemer ()))
"{\"constructor\":0,\"fields\":[{\"constructor\":0,\"fields\":[]}]}"
In my code, I tried the json values ""
, "{\"constructor\":0,\"fields\":[]}"
and some other combinations, but none of them match the above. After fixing that, I could submit the redeem transaction and got a different error:
the script for transaction input 0 (in the order of the TxIds) failed with:
The Plutus script evaluation failed: An error has occurred: User error:
The provided Plutus code called 'error'.
Script debugging logs: owner has not signed
PT5
This is much better. Now the script actually tells me that it couldn't find the signature in the txInfoSignatories
. After further tests, these apparently evaluate to an empty list, although I'm passing --required-signer
to cardano-cli transaction build
.
So that's at least some progress.
@hasufell nice, well done. With the new error you might be bumping into a bug that was fixed by https://github.com/input-output-hk/cardano-node/pull/3319 in which PaymentExtendedKeys
were being dropped from requiredSignatories list. I skimmed through how your keys are being converted and it might be the case
https://github.com/hasufell/proof-of-burn-cardano/blob/26bfa911a371d37e69812321bc787df933e03d92/docker/cardano-cli/wallet.sh#L343
https://github.com/input-output-hk/cardano-node/blob/d95ef21062a50acf8f35f1f5d94f8a8a70f7510b/cardano-cli/src/Cardano/CLI/Shelley/Run/Key.hs#L533
Ok, I was able to track down the issue further.
As described above, we use a redeemer dummy type, because whether redeeming works or not is supposed to be discovered by the
txInfoSignatories
, not the redeemer datum:-- | Redeemer holds no data, since the address is taken from the context. newtype MyRedeemer = MyRedeemer { _nothing :: () } PlutusTx.makeLift ''MyRedeemer PlutusTx.unstableMakeIsData ''MyRedeemer
I followed down the code of cardano-api in the node, which apparently does the json encoding/decoding: https://github.com/input-output-hk/cardano-node/blob/d95ef21062a50acf8f35f1f5d94f8a8a70f7510b/cardano-api/src/Cardano/Api/ScriptData.hs#L431
In a repl, I was then able to generate the the json from the node code directly:
> Data.Aeson.encode $ scriptDataToJson ScriptDataJsonDetailedSchema $ (fromPlutusData $ builtinDataToData $ toBuiltinData (MyRedeemer ())) "{\"constructor\":0,\"fields\":[{\"constructor\":0,\"fields\":[]}]}"
In my code, I tried the json values
""
,"{\"constructor\":0,\"fields\":[]}"
and some other combinations, but none of them match the above. After fixing that, I could submit the redeem transaction and got a different error:the script for transaction input 0 (in the order of the TxIds) failed with: The Plutus script evaluation failed: An error has occurred: User error: The provided Plutus code called 'error'. Script debugging logs: owner has not signed PT5
This is much better. Now the script actually tells me that it couldn't find the signature in the
txInfoSignatories
. After further tests, these apparently evaluate to an empty list, although I'm passing--required-signer
tocardano-cli transaction build
.So that's at least some progress.
I was also stuck with the same issue (wrong redeemer format), we are also not using the redeemer and were passing [] as a dummy redeemer value. For the longest time, we were looking into the Datums because we were not using the redeemer so we didn't think the problem was there, if not were for your finding we would still be looking.
This was the error we were getting:
The Plutus script evaluation failed: An error has occurred: User error:
The provided Plutus code called 'error'.
Caused by: [ (builtin unConstrData) (con data #80) ]
@hasufell nice, well done. With the new error you might be bumping into a bug that was fixed by input-output-hk/cardano-node#3319 in which
PaymentExtendedKeys
were being dropped from requiredSignatories list. I skimmed through how your keys are being converted and it might be the case https://github.com/hasufell/proof-of-burn-cardano/blob/26bfa911a371d37e69812321bc787df933e03d92/docker/cardano-cli/wallet.sh#L343 https://github.com/input-output-hk/cardano-node/blob/d95ef21062a50acf8f35f1f5d94f8a8a70f7510b/cardano-cli/src/Cardano/CLI/Shelley/Run/Key.hs#L533
I rebuilt with that commit and it indeed fixed it and I could submit the redeem transaction to testnet and it apparently validated correctly and I got my funds back.
So, to reiterate (I'll probably write an article on it too):
Data.Aeson.encode . scriptDataToJson ScriptDataJsonDetailedSchema . fromPlutusData . builtinDataToData . toBuiltinData
to figure out the final encodingcardano-cli transaction build --tx-in-redeemer-file $FILE1 --tx-in-datum-file $FILE2
with files that contain the json content from the step above when constructing transactions (details: there are two json schemas for decoding... the extended one ScriptDataJsonDetailedSchema
is used when reading files as opposed to direct json strings and has better errors in my experience)9dd31b3f8f17fba30882e98bb02810a7a504ba38
, so txInfoSignatories
are not droppedPT<int>
error, it didn't even manage to evaluate, but failed during decodingcardano-cli address key-hash --payment-verification-key "$(echo "<your recovery phrase>" | cardano-address key from-recovery-phrase Shelley | cardano-address key child "1852H/1815H/0H/0/0" | cardano-address key public --with-chain-code)"
(make sure to include it via cardano-cli transaction build --required-signer=key.skey
, which requires the signing key of the same derivation path... I also had to set --witness-override 2
, not sure if that's still needed)Thanks for all your help.
@AngelCastilloB glad to hear
Nice! :tada:
I have a validator that is fairly straight forward:
I compiled this plutus script, built a transaction manually and can lock funds successfully. I do this via wallet api, cardano-cli and other cli tools, because plutus isn't complete yet.
Now I want to lock funds for myself, so I can redeem them, but in order to do that I need to understand the exact format/encoding/hashing of
txInfoSignatories
. I've been searching for hours and tried many variations, using the wallet pubkey, account pubkey, address pubkey, hashing with Blake2b_224 etc. pp.I find it hard to find in the documentation 1) what exact pubkey is this and 2) what exact hash/format is this and how can I create this hash from the command line given that I have full access to the wallet that signed the transaction.
All my attempts so far redeeming the funds ended with:
Thanks.