Python-Cardano / pycardano

A lightweight Cardano library in Python
https://pycardano.readthedocs.io
MIT License
214 stars 65 forks source link

StakeRegistration and StakeDelegation certificates not witnessed when using ScriptHash rather than StakeKeyHash. #378

Open SCMusson opened 1 day ago

SCMusson commented 1 day ago

Describe the bug TransactionBuilder.build_and_sign does not seem to correctly build the witness set if the Certificates are constructed using ScriptHash rather than StakeKeyHash.

I am attempting to recreate the plutus pioneer program week 8 task in opshin/pycardano. If I'm not mistaken this task requires the stake registration and stake delegation certificates to be created with a ScriptHash. I can't seem to find any methods to add certificates other than to set TransactionBuilder.certificates directly.

I'm currently working like so:

# Build and hash script
plutus_script = build(script_path, staking_user.verification_key.hash())
script_hash = pycardano.plutus_script_hash(plutus_script)

#Create addresses, and credentials
stake_address = pycardano.Address(staking_part = script_hash)
script_payment_address = pycardano.Address(payment_part = staking_user.verification_key.hash(), staking_part = script_hash)

stake_credentials = pycardano.StakeCredential(script_hash)
stake_registration = pycardano.StakeRegistration(stake_credentials)
pool_id = bytes(decode('pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy'))
pool_keyhash = pycardano.PoolKeyHash(pool_id)
stake_delegation = pycardano.StakeDelegation(stake_credentials, pool_keyhash)

builder = pycardano.TransactionBuilder(context)
builder.add_input_address(staking_user.address)
builder.certificates = [stake_registration, stake_delegation]
builder.add_output(pycardano.TransactionOutput(address=script_payment_address, amount = pycardano.Value(), datum = pycardano.Unit()))
tx = builder.build_and_sign(
        signing_keys = [staking_user.signing_key],
        change_address = script_payment_address,
)

The equivalent cardano-cli commands are:

cardano-cli transaction build \
    --babbage-era \
    --testnet-magic 42 \
    --change-address $(cat $script_payment_addr) \
    --out-file $body \
    --tx-in $txin \
    --tx-in-collateral $txin \
    --certificate-file $registration \
    --certificate-file $delegation \
    --certificate-script-file $script \
    --certificate-redeemer-file /workspace/code/Week08/assets/unit.json \
    --protocol-params-file $pp

cardano-cli transaction sign \
    --testnet-magic 42 \
    --tx-body-file $body \
    --out-file $signed \
    --signing-key-file /workspace/cardano-private-testnet-setup/private-testnet/stake-delegator-keys/payment1.skey

particularly I can't seem to find any methods or arguments equivalent to the --certificate-script-file option. My understanding is that a script witness needs to be created for the plutus script but I can't seem to find a clean way of adding the script or adding it to the witness set.

Environment and software version (please complete the following information):

nielstron commented 1 day ago

A corresponding function likely has to be added similar to the minting script file and withdrawal script file fields - simply because they were never used by anyone so far.

nielstron commented 1 day ago

For reference I added a similar function for withdrawals a while ago here: https://github.com/Python-Cardano/pycardano/pull/308

SCMusson commented 1 day ago

It doesn't look like it will be too tricky, I'll scrape a pull request together