Skip to content

Commit b2daec6

Browse files
authored
Add docs on a script UTxO commit (#2195)
Resolves #1653 <!-- Describe your change here --> --- <!-- Consider each and tick it off one way or the other --> * [ ] CHANGELOG updated or not needed * [ ] Documentation updated or not needed * [ ] Haddocks updated or not needed * [ ] No new TODOs introduced or explained herafter
2 parents 4eb760a + bdccbc1 commit b2daec6

File tree

8 files changed

+254
-8
lines changed

8 files changed

+254
-8
lines changed

docs/docs/how-to/commit-blueprint.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ cardano-cli query protocol-parameters \
9393
--testnet-magic 1 \
9494
--socket-path testnets/preprod/node.socket \
9595
--out-file pp-preprod.json
96-
9796
```
9897

9998
## Step 5
@@ -127,7 +126,7 @@ Press `i` to initialize the `head`. Once the head is in the `Initializing` state
127126

128127
This is the valid JSON request:
129128

130-
```shell
129+
```json
131130
{
132131
"blueprintTx": {
133132
"cborHex": "84a3008182582014ab373afb1112d925b0f6a84518ac26d4a8cfcc99231e1f47e6996182e843a900018182581d6069830961c6af9095b0f2648dff31fa9545d8f0b6623db865eb78fde81a007a12000200a0f5f6",
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
# Commit a Script UTxO into a Head
6+
7+
This guide provides a walkthrough on how to commit a UTxO from a script into a Hydra Head.
8+
9+
A **Script UTxO** is a special kind of Unspent Transaction Output (UTxO) that isn't controlled by a simple private key. Instead, it is locked by a script - a small program that runs on the blockchain. To spend the funds in a Script UTxO, you must provide data (a "redeemer" and "datum") that satisfies the conditions defined in that script.
10+
11+
Committing a script UTxO to a Hydra Head is a powerful feature that allows for more complex on-chain validation logic to be brought into the Head. This is useful for scenarios where you need to enforce specific rules on how funds can be spent, even within the Head's off-chain environment.
12+
13+
This tutorial will guide you through the entire process, which involves creating a script, locking an on-chain UTxO with it, and then preparing a special "blueprint" transaction to commit this script UTxO into an open Head.
14+
15+
## Prerequisites
16+
17+
This tutorial assumes you are familiar with the process of committing a standard UTxO to a Hydra Head. If you are not, please first read the [Commit using a blueprint](./commit-blueprint.md) tutorial.
18+
19+
You will also need:
20+
21+
- A running `cardano-node` connected to a testnet.
22+
- `cardano-cli` in your `PATH`.
23+
- `hydra-node` and `hydra-tui` in your `PATH`.
24+
25+
## Step 1: Set Up Your Environment
26+
27+
To avoid specifying the network identifier and the path to the node's socket in every command, you can set the following environment variables in your shell. Make sure to replace the values with the ones that are appropriate for your setup (e.g., for the pre-production testnet, the magic is `1`).
28+
29+
```shell
30+
export CARDANO_NODE_SOCKET_PATH=<path-to>/node.socket
31+
export CARDANO_TESTNET_MAGIC=1
32+
export CREDENTIALS_PATH=hydra-cluster/config/credentials
33+
```
34+
35+
## Step 2: Create the script
36+
37+
For this tutorial, we will use a simple "always true" validator script. This script will always succeed, regardless of the redeemer or datum.
38+
39+
Create a file named `always-true.plutus` with the following content:
40+
41+
```json
42+
{
43+
"type": "PlutusScriptV2",
44+
"description": "Always true validator",
45+
"cborHex": "49480100002221200101"
46+
}
47+
```
48+
49+
## Step 3: Create the script address
50+
51+
Now, we need to create an address for this script. We can do this using `cardano-cli`:
52+
53+
```shell
54+
cardano-cli address build \
55+
--payment-script-file always-true.plutus \
56+
--testnet-magic $CARDANO_TESTNET_MAGIC \
57+
--out-file script.addr
58+
```
59+
60+
This will create a file named `script.addr` containing the script address. You can inspect the address using `cat`:
61+
62+
```shell
63+
cat script.addr
64+
```
65+
66+
## Step 4: Lock funds in the script address
67+
68+
Before we can commit a script UTxO, we need to create one. This is done by sending funds to the script address.
69+
70+
First, we need a UTxO in a wallet to fund the transaction. The following command will find the first available UTxO in a wallet funded by `alice-funds.sk`, and export its transaction input (`TxIn`) to an environment variable.
71+
72+
```shell
73+
export UTXO_TXIX=$(cardano-cli query utxo --address $(cardano-cli address build --payment-verification-key-file ${CREDENTIALS_PATH}/alice-funds.vk --testnet-magic $CARDANO_TESTNET_MAGIC) --testnet-magic $CARDANO_TESTNET_MAGIC --output-json | jq -r 'keys[0]')
74+
echo "Captured funding UTxO TxIn: $UTXO_TXIX"
75+
```
76+
77+
Now that we have a funding UTxO, we can build the transaction to lock 10 ADA at the script address.
78+
79+
First, create a file named `datum.json` that contains the datum. For this example, we will just use the integer `42`.
80+
81+
```json
82+
{
83+
"constructor": 0,
84+
"fields": [
85+
{
86+
"int": 42
87+
}
88+
]
89+
}
90+
```
91+
92+
Now, build the transaction:
93+
94+
```shell
95+
cardano-cli conway transaction build \
96+
--tx-in $UTXO_TXIX \
97+
--tx-out $(cat script.addr)+10000000 \
98+
--tx-out-inline-datum-file datum.json \
99+
--change-address $(cardano-cli address build --payment-verification-key-file ${CREDENTIALS_PATH}/alice-funds.vk --testnet-magic $CARDANO_TESTNET_MAGIC) \
100+
--testnet-magic $CARDANO_TESTNET_MAGIC \
101+
--out-file tx.raw
102+
```
103+
104+
Note that we are also providing an inline datum via the `datum.json` file. Even though our script does not use it, a datum is required for all script UTxOs.
105+
106+
Now, sign and submit the transaction:
107+
108+
```shell
109+
cardano-cli conway transaction sign \
110+
--tx-body-file tx.raw \
111+
--signing-key-file ${CREDENTIALS_PATH}/alice-funds.sk \
112+
--out-file tx.signed
113+
114+
cardano-cli conway transaction submit \
115+
--tx-file tx.signed \
116+
--testnet-magic $CARDANO_TESTNET_MAGIC
117+
```
118+
119+
Once the transaction is confirmed, you can query the script address to find the transaction input (`TxIn`) of the script UTxO we just created.
120+
121+
```shell
122+
export SCRIPT_UTXO_TXIX=$(cardano-cli query utxo --address $(cat script.addr) --testnet-magic $CARDANO_TESTNET_MAGIC --output-json | jq -r 'keys[0]')
123+
echo "Captured script UTxO TxIn: $SCRIPT_UTXO_TXIX"
124+
```
125+
126+
## Step 5: Prepare the Blueprint
127+
128+
Now we are ready to prepare the commit. We will create a blueprint transaction that spends the script UTxO. Note that this transaction is not meant to be signed and submitted to the Cardano network. It is just a blueprint that we will send to the `hydra-node` to get a properly drafted commit transaction.
129+
130+
We use `cardano-cli ... build-raw` to construct this blueprint because it gives us full control over the transaction structure without trying to automatically balance it or calculate fees, which is perfect for a blueprint.
131+
132+
For a script UTxO, the blueprint only needs to declare the script UTxO as an input. The `hydra-node` will use this, along with the UTxO context provided in the next step, to build the full commit transaction.
133+
134+
```shell
135+
cardano-cli conway transaction build-raw \
136+
--tx-in $SCRIPT_UTXO_TXIX \
137+
--tx-in-script-file always-true.plutus \
138+
--tx-in-inline-datum-present \
139+
--tx-in-redeemer-value 42 \
140+
--tx-in-execution-units '(1000000, 100000)' \
141+
--tx-out $(cardano-cli address build --payment-verification-key-file ${CREDENTIALS_PATH}/alice-funds.vk --testnet-magic $CARDANO_TESTNET_MAGIC)+10000000 \
142+
--fee 0 \
143+
--out-file tx.json
144+
```
145+
146+
A real-world script, like one written in [Aiken](https://aiken-lang.org/), would use the datum to carry state and the redeemer to provide input for validation. Our "always-true" script doesn't actually check any of these, but they are still required fields for a valid transaction that spends a script UTxO. Note that we use `--tx-in-inline-datum-present` because the datum was already included on-chain when we created the script UTxO. We also provide `--tx-in-execution-units`. This is required for any script spend to tell the network how much computational resource to budget for the script's execution. Since our script does nothing, we can use `(0, 0)`.
147+
148+
## Step 6: Prepare the commit
149+
150+
This final step brings everything together. We will start a `hydra-node`, initialize a Head, and then send our blueprint and UTxO context to the `/commit` endpoint.
151+
152+
**1. Start the Hydra Node and TUI**
153+
154+
In a **new terminal**, start a single-party `hydra-node`.
155+
```shell
156+
hydra-node \
157+
--node-id 1 \
158+
--api-port 4001 \
159+
--hydra-signing-key ${CREDENTIALS_PATH}/../alice.sk \
160+
--cardano-signing-key ${CREDENTIALS_PATH}/alice.sk \
161+
--ledger-protocol-parameters devnet/protocol-parameters.json \
162+
--testnet-magic $CARDANO_TESTNET_MAGIC \
163+
--node-socket $CARDANO_NODE_SOCKET_PATH
164+
```
165+
166+
In another **new terminal**, start the `hydra-tui`.
167+
```shell
168+
hydra-tui \
169+
--connect 0.0.0.0:4001 \
170+
--cardano-signing-key ${CREDENTIALS_PATH}/alice-funds.sk
171+
```
172+
In the TUI, press `i` to initialize the Head. Once the state is `Initializing`, you can quit the TUI (`q`) and proceed.
173+
174+
**2. Send the Commit Request**
175+
176+
Now, we will build the commit request. This request contains two parts: the `utxo` context (which must include the script) and the `blueprintTx` (which provides the witness information).
177+
178+
```shell
179+
# Set variables
180+
BLUEPRINT_JSON=$(cat tx.json)
181+
UTXO_JSON=$(cardano-cli query utxo --tx-in ${SCRIPT_UTXO_TXIX} --testnet-magic $CARDANO_TESTNET_MAGIC --output-json)
182+
183+
# Create the request body
184+
jq -n \
185+
--argjson utxo "${UTXO_JSON}" \
186+
--argjson blueprintTx "${BLUEPRINT_JSON}" \
187+
'{ "utxo": $utxo, "blueprintTx": $blueprintTx }' \
188+
> commit-request.json
189+
```
190+
191+
Now, use `curl` to send the request to the `hydra-node`, which will respond with a drafted commit transaction:
192+
193+
```shell
194+
curl -X POST --data @commit-request.json http://127.0.0.1:4001/commit > commit-tx.json
195+
```
196+
197+
**3. Sign and Submit**
198+
199+
This is the final step. The `commit-tx.json` file now contains a valid, balanced transaction drafted by the `hydra-node`. We just need to sign it with both our funds key and our party key, and then submit it.
200+
201+
```shell
202+
cardano-cli conway transaction sign \
203+
--tx-body-file commit-tx.json \
204+
--signing-key-file ${CREDENTIALS_PATH}/alice-funds.sk \
205+
--signing-key-file ${CREDENTIALS_PATH}/alice.sk \
206+
--out-file signed-tx.json
207+
208+
cardano-cli conway transaction submit \
209+
--tx-file signed-tx.json \
210+
--testnet-magic $CARDANO_TESTNET_MAGIC
211+
```
212+
213+
And that's it! After the transaction is confirmed on-chain, your script UTxO will be committed to the Head.
214+
215+
## Bonus: Experimenting with a Failing Script
216+
217+
It can be very insightful to see what happens when a script validator fails. To demonstrate this, you can create an "always false" validator and see how `cardano-cli`'s local validation prevents you from even building a transaction that uses it.
218+
219+
**1. Create the `always-false.plutus` script**
220+
221+
Create a new file named `always-false.plutus` with the following content. This is a valid Plutus script that is guaranteed to fail validation.
222+
223+
```json
224+
{
225+
"type": "PlutusScriptV2",
226+
"description": "Always false validator",
227+
"cborHex": "49480100002221200100"
228+
}
229+
```
230+
231+
**2. Lock funds with the failing script**
232+
233+
Follow the same steps as in **Step 3** and **Step 4** of the main tutorial, but use `always-false.plutus` instead of `always-true.plutus` to create a new script address and lock a new UTxO in it.
234+
235+
**3. Attempt to build a blueprint**
236+
237+
Now, try to run the `build-raw` command from **Step 5** using the UTxO locked by the failing script.
238+
239+
**Expected Result: Failure**
240+
241+
You will find that the `cardano-cli conway transaction build-raw` command itself will fail. It will produce an error message similar to this:
242+
243+
```shell
244+
Command failed: transaction build-raw Error: A script in the transaction has failed.
245+
```
246+
247+
This is a powerful feature of `cardano-cli`. It evaluates the scripts locally *before* creating the transaction. By catching the script failure at this early stage, it prevents you from submitting a transaction that would be guaranteed to fail on the blockchain, saving you time and the transaction fees.

docs/docs/how-to/incremental-commit.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 4
2+
sidebar_position: 5
33
---
44

55
# Commit funds to an open Head

docs/docs/how-to/incremental-decommit.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 5
2+
sidebar_position: 6
33
---
44

55
# Decommit funds

docs/docs/how-to/operating-hydra.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 6
2+
sidebar_position: 7
33
---
44

55
# Operate a Hydra node

docs/docs/how-to/sideload-snapshot.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22

3-
sidebar_position: 7
3+
sidebar_position: 8
44
---
55

66
# Sideload Snapshot

docs/docs/how-to/submit-transaction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 2
2+
sidebar_position: 3
33
---
44

55
# Submit a transaction

docs/docs/how-to/withdraw-zero.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
sidebar_position: 3
2+
sidebar_position: 4
33
---
44

55
# Use withdraw zero trick

0 commit comments

Comments
 (0)