Skip to content

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

This quickstart guide will take you through the following steps:

Simple-identity preparation

Let's start with registering an identity contract and two identities.

Go to the ./simple-identity folder and run:

cargo run -- --contract-name id register-contract

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:

cargo run -- --contract-name id verify bob.id pass 0

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:

cargo run -- --contract-name id verify alice.id pass 0

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:

cargo run -- --contract-name simple-token register 1000

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:

cargo run -- --contract-name ticket-app register simple-token 15

ticket-app sells bob a ticket for 15 simple-token.

Buy a ticket

Let's buy a ticket for bob:

cargo run -- --contract-name ticket-app --user bob.id buy-ticket

Let's try with alice:

cargo run -- --contract-name ticket-app --user alice.id buy-ticket

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:

cargo run -- --contract-name ticket-app --user bob.id has-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.