Proof composition with Ticket App
Hylé enables proof composition, allowing you to use different proving systems in a single operation. This eliminates constraints on provers and significantly boosts interoperability and efficiency. Read this introduction to proof composability to understand how this works.
In this guide, we’ll build a Ticket App that leverages proof composition. Users can buy a ticket using a simple-token, and Hylé will verify multiple proofs in a single transaction.
Find the source code for all contracts here:
Traditional verification systems often require all proofs to be generated using the same proving system. Hylé removes this limitation, allowing:
- Interoperability: use different proof systems within a single transaction.
- Atomicity: either all proofs verify, or none do. This ensures fail-safe execution.
- Efficiency: parallel processing of proofs without requiring a single proving standard.
How this example works
In this example, Alice
and Bob
both want to buy a ticket from Ticket App for 15 simple-tokens
. Only Bob has enough tokens to complete the transaction.
Let’s walk through an example where Bob and Alice want to buy a ticket from Ticket App, which costs 15 simple-tokens
. Bob has enough balance, Alice does not.
Step 1: Create the blob transaction
The Ticket App backend creates and sends a blob transaction to Hylé, including three blobs:
- an identity blob (see our custom identity contract quickstart) confirming that Bob (
bob.id
) is initiating the transaction; - a simple-token blob performing a transfer of 15 simple-tokens taken from
bob.id
's balance; - a ticket-app blob sending
bob.id
a ticket if conditions are met.
For now, Hylé sequences this transaction, but it’s not processed yet. Read more about pipelined proving.
Step 2: Prove the blobs
The Ticket App backend now generates ZK proofs of each blob.
During this time, the code of the ticket-app
contract is executed. During execution, the ticket-app
smart contract checks that there is a simple-token
blob performing a transfer of 15 simple-tokens taken from bob.id
's balance to the ticket-app
contract.
At this step, it cannot yet confirm Bob has enough tokens, but that’s fine: if the token transfer fails in Step 3, the entire transaction fails.
Check out what the source code looks like.
Step 3: Settlement
Once TicketApp has sent the proofs for the previously sequenced blobs, Hylé verifies these proofs:
- identity blob: verifies that
bob.id
has initiated the transaction. - simple-token blob: verifies that
bob.id
paid the correct amount for his ticket. - ticket-app blob: verifies that
bob.id
has received the ticket.
If all proofs are valid, the simple-token balance and ticket-app ticket balance are updated simultaneously at transaction settlement: bob.id
sends 15 simple-tokens and gains one ticket.
If any proof fails, the entire transaction fails. Neither state is updated: bob.id
's token balance does not change and still has no ticket.
To see proof composition in action in a different setting, you can check out our Vibe Check demo, which mixes Cairo and Noir proofs.
Run the example
Warning
Our examples work on Hylé v0.7.2. Later versions introduce breaking changes which have not yet been reflected in our examples.
Prerequisites
- Install Rust (you'll need
rustup
and Cargo). - For our example, install RISC Zero.
- Start a single-node devnet.
This quickstart guide will take you through the following steps:
- Simple-identity preparation: register an identity contract & two identities.
- Simple-token preparation: register a token contract and faucet the users with this token.
- Register the ticket-app contract
- Buy a ticket on ticket-app
Simple-identity preparation
Let's start with registering an identity contract and two identities.
Go to the ./simple-identity
folder and run:
Now we have an identity contract called id
. We can use it to declare our users:
cargo run -- --contract-name id register-identity bob.id pass
cargo run -- --contract-name id register-identity alice.id pass
Let's verify it quickly with:
0 is a nonce: every time we verify successfully bob's identity, it increments. Now if we want to verify it again, we should use 1 as nonce. (We also use « pass » as our default password.)
We now do the same for alice:
bob.id
is bob's identity on the simple-identity contract. Check out our Identity management and custom identity contract pages to know more.
Simple-token preparation
Register simple-token
Go to ./simple-token
folder and run:
On the node's logs, you will see:
📝 Registering new contract simple_token
You just registered a token contract named simple-token with an initial supply of 1000.
Transfer tokens
Now let's transfer some tokens to our user bob
.
To send 50 tokens to bob
and 10 tokens to alice
, run:
cargo run -- -contract-name simple-token transfer faucet.simple-token bob.id 50
cargo run -- -contract-name simple-token transfer faucet.simple-token alice.id 10
The node's log will show:
INFO hyle::data_availability::node_state::verifiers: ✅ Risc0 proof verified.
INFO hyle::data_availability::node_state::verifiers: 🔎 Program outputs: Transferred 50 to bob.ticket_app INFO hyle::data_availability::node_state::verifiers: 🔎 Program outputs: Transferred 10 to alice.ticket_app
Check onchain balance
Check onchain balance:
cargo run -- --contract-name simple-token balance faucet.simple-token
cargo run -- --contract-name simple-token balance bob.id
cargo run -- --contract-name simple-token balance alice.id
You should see that bob
has a balance of 50 and alice
has a balance of 10.
Using ticket-app
Now that bob
has some tokens, let's buy him a ticket.
Register ticket-app
Register the ticket app by going to ./ticket-app
folder and running:
ticket-app sells bob a ticket for 15 simple-token.
Buy a ticket
Let's buy a ticket for bob
:
Let's try with alice
:
You will get an error while executing the TicketApp program: Execution failed ! Program output: Insufficient balance
. This is because Alice has a balance of 10 and the ticket costs 15.
Check ticket and token balance
Check that bob
has a ticket:
You can also check bob
's balance and see he now has 35 tokens.
With proof composition, Hylé empowers you to leverage multiple proving systems in a single transaction, making advanced functionality like the Ticket App easier than ever.