|
| 1 | +--- |
| 2 | +sidebar_position: 3 |
| 3 | +--- |
| 4 | + |
| 5 | +# Use withdraw zero trick |
| 6 | + |
| 7 | +In this how-to we want to show how you can use the "wihtdraw zero trick" in Hydra. Until [CIP-112](https://cips.cardano.org/cip/CIP-0112) is implemented, there is only one way to run a script once per transaction - the so-called withdraw zero trick. Refer to the CIP or [this design pattern document](https://github.com/Anastasia-Labs/design-patterns/blob/main/stake-validator/STAKE-VALIDATOR.md) for more details about the general approach. |
| 8 | + |
| 9 | +The Hydra L2 ledger is mostly _isomorphic_ to the L1 Cardano ledger. This means that it honors all the same ledger rules and transactions use the exact same format. However, some things related to the Cardano Proof-of-Stake consensus are represented different because they would not make much sense on an L2. For exapmle, transactions that [register stake certificates](https://docs.cardano.org/developer-resources/transaction-tutorials/stake-transaction) or [withdraw rewards](https://docs.cardano.org/developer-resources/transaction-tutorials/withdraw-transaction) don't work as-is on Hydra. However, for the purpose of "transaction-level validation", the withdraw zero trick can still be used as the Hydra L2 ledger **mocks script reward accounts** on the fly. |
| 10 | + |
| 11 | +## Rewarding script |
| 12 | + |
| 13 | +We are going to use the [dummyRewardingScript](https://github.com/cardano-scaling/hydra/blob/master/hydra-plutus/src/Hydra/Contract/Dummy.hs#L42-L53) as an example, which only validates the fact that we are in a `RewardingScript` context. Using GHCI we can determine the stake address and write the `rewarding.plutus` text envelope file for `cardano-cli`: |
| 14 | + |
| 15 | +```haskell |
| 16 | +cabal repl hydra-plutus |
| 17 | +> import Prelude |
| 18 | +> import Hydra.Contract.Dummy |
| 19 | +> import Hydra.Cardano.Api |
| 20 | +> script = PlutusScript dummyRewardingScript |
| 21 | +> serialiseAddress $ makeStakeAddress (Testnet $ NetworkMagic 42) (StakeCredentialByScript $ hashScript script) |
| 22 | +"stake_test17rekjamvnjyn3c3tcjpxe7ea20g7aek9vdqkaa3jefknz3gc066pt" |
| 23 | +> writeFileTextEnvelope (File "../rewarding.plutus") Nothing script |
| 24 | +Right () |
| 25 | +``` |
| 26 | + |
| 27 | +## Withdraw zero transaction |
| 28 | + |
| 29 | +We can construct a transaction that withdraws zero lovelace from the rewarding script's "account". Usually, other purposes like spending a UTxO would require the reward script to run, but here we just assume there exists such a UTxO in the L2 state. You can initialize an [offline head](../configuration#offline-mode) for an easy demo set-up: |
| 30 | + |
| 31 | +<details> |
| 32 | + <summary>Setup with offline head</summary> |
| 33 | +``` |
| 34 | +cat > utxo.json <<EOF |
| 35 | +{ |
| 36 | + "0000000000000000000000000000000000000000000000000000000000000000#0": { |
| 37 | + "address": "addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z", |
| 38 | + "value": { |
| 39 | + "lovelace": 100000000 |
| 40 | + } |
| 41 | + } |
| 42 | +} |
| 43 | +EOF |
| 44 | +``` |
| 45 | + |
| 46 | +```shell |
| 47 | +cabal run hydra-node:exe:hydra-node -- \ |
| 48 | + --offline-head-seed 0001 \ |
| 49 | + --initial-utxo utxo.json \ |
| 50 | + --ledger-protocol-parameters hydra-cluster/config/protocol-parameters.json \ |
| 51 | + --hydra-signing-key demo/alice.sk |
| 52 | +``` |
| 53 | +</details> |
| 54 | + |
| 55 | +Then, build, sign and submit the transaction that runs the rewarding script: |
| 56 | + |
| 57 | +```shell title="Withdraw zero transaction" |
| 58 | +cardano-cli latest transaction build-raw \ |
| 59 | + --tx-in 0000000000000000000000000000000000000000000000000000000000000000#0 \ |
| 60 | + --tx-in-collateral 0000000000000000000000000000000000000000000000000000000000000000#0 \ |
| 61 | + --tx-out addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z+100000000 \ |
| 62 | + --withdrawal stake_test17zadf9dcekqn9cxkg3q68y56f4d6ujxsv8l6kq4kz2cuduc3gm35e+0 \ |
| 63 | + --withdrawal-script-file rewarding.plutus \ |
| 64 | + --withdrawal-redeemer-value "{}" \ |
| 65 | + --withdrawal-execution-units "(10000000000, 14000000)" \ |
| 66 | + --protocol-params-file hydra-cluster/config/protocol-parameters.json \ |
| 67 | + --fee 0 \ |
| 68 | + --out-file tx.json |
| 69 | + |
| 70 | +cardano-cli latest transaction sign \ |
| 71 | + --tx-body-file tx.json \ |
| 72 | + --signing-key-file hydra-cluster/config/credentials/alice-funds.sk \ |
| 73 | + --out-file tx-signed.json |
| 74 | + |
| 75 | +cat tx-signed.json | jq -c '{tag: "NewTx", transaction: .}' | websocat ws://localhost:4001 |
| 76 | +``` |
| 77 | + |
| 78 | +## Registering script - not needed! |
| 79 | + |
| 80 | +You might have noticed that registering the stake address was not needed - this is different than on the Cardano L1! |
| 81 | + |
| 82 | +While you don't need to do it, you can still submit a transaction that registers the stake address and the L2 ledger will just ignore it: |
| 83 | + |
| 84 | +```shell title="Register stake transaction" |
| 85 | +cardano-cli latest stake-address registration-certificate \ |
| 86 | + --stake-address stake_test17zadf9dcekqn9cxkg3q68y56f4d6ujxsv8l6kq4kz2cuduc3gm35e \ |
| 87 | + --key-reg-deposit-amt 2000000 \ |
| 88 | + --out-file reg.cert |
| 89 | + |
| 90 | +cardano-cli latest transaction build-raw \ |
| 91 | + --tx-in 0000000000000000000000000000000000000000000000000000000000000000#0 \ |
| 92 | + --tx-in-collateral 0000000000000000000000000000000000000000000000000000000000000000#0 \ |
| 93 | + --tx-out addr_test1vp5cxztpc6hep9ds7fjgmle3l225tk8ske3rmwr9adu0m6qchmx5z+98000000 \ |
| 94 | + --certificate reg.cert \ |
| 95 | + --certificate-script-file rewarding.plutus \ |
| 96 | + --certificate-redeemer-value "{}" \ |
| 97 | + --certificate-execution-units "(10000000000, 14000000)" \ |
| 98 | + --protocol-params-file hydra-cluster/config/protocol-parameters.json \ |
| 99 | + --fee 0 \ |
| 100 | + --out-file tx.json |
| 101 | + |
| 102 | +cardano-cli latest transaction sign \ |
| 103 | + --tx-body-file tx.json \ |
| 104 | + --signing-key-file hydra-cluster/config/credentials/alice-funds.sk \ |
| 105 | + --out-file tx-signed.json |
| 106 | + |
| 107 | +cat tx-signed.json | jq -c '{tag: "NewTx", transaction: .}' | websocat ws://localhost:4001 |
| 108 | +``` |
0 commit comments