> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/a16z/jolt/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Build your first zero-knowledge proof with Jolt in under 5 minutes

Get started with Jolt by creating a simple zkVM program that proves Fibonacci number computation.

## Prerequisites

Before you begin, make sure you have completed the [installation](/installation) steps.

## Create Your First Project

<Steps>
  <Step title="Create a new Jolt project">
    Use the Jolt CLI to scaffold a new project:

    ```bash theme={null}
    jolt new my-jolt-app
    cd my-jolt-app
    ```

    This creates a workspace with two parts:

    * `guest/` - Code that runs inside the zkVM (RISC-V)
    * `src/` (host) - Code that compiles, proves, and verifies guest execution
  </Step>

  <Step title="Understand the guest code">
    Open `guest/src/lib.rs` to see the guest program:

    ```rust guest/src/lib.rs theme={null}
    #![cfg_attr(feature = "guest", no_std)]

    #[jolt::provable(heap_size = 32768, max_trace_length = 65536)]
    fn fib(n: u32) -> u128 {
        let mut a: u128 = 0;
        let mut b: u128 = 1;
        let mut sum: u128;
        for _ in 1..n {
            sum = a + b;
            a = b;
            b = sum;
        }
        b
    }
    ```

    The `#[jolt::provable]` macro transforms this function into a zkVM program. It generates:

    * `compile_fib()` - Compiles the guest to RISC-V ELF
    * `prove_fib()` - Generates a zero-knowledge proof of execution
    * `verify_fib()` - Verifies the proof
    * Preprocessing functions for optimization
  </Step>

  <Step title="Understand the host code">
    The host code in `src/main.rs` orchestrates the proving and verification:

    ```rust src/main.rs theme={null}
    use tracing::info;

    pub fn main() {
        tracing_subscriber::fmt::init();

        let target_dir = "/tmp/jolt-guest-targets";
        let mut program = guest::compile_fib(target_dir);

        let shared_preprocessing = guest::preprocess_shared_fib(&mut program);

        let prover_preprocessing = guest::preprocess_prover_fib(shared_preprocessing.clone());
        let verifier_setup = prover_preprocessing.generators.to_verifier_setup();
        let verifier_preprocessing =
            guest::preprocess_verifier_fib(shared_preprocessing, verifier_setup);

        let prove_fib = guest::build_prover_fib(program, prover_preprocessing);
        let verify_fib = guest::build_verifier_fib(verifier_preprocessing);

        let (output, proof, io_device) = prove_fib(50);
        let is_valid = verify_fib(50, output, io_device.panic, proof);

        info!("output: {output}");
        info!("valid: {is_valid}");
    }
    ```

    This code:

    1. Compiles the guest program to RISC-V
    2. Preprocesses (generates proving/verifying keys - done once per program)
    3. Proves execution with input `50`
    4. Verifies the proof
  </Step>

  <Step title="Run your first proof">
    Build and run the program:

    ```bash theme={null}
    cargo run --release
    ```

    You should see output like:

    ```
    INFO output: 12586269025
    INFO valid: true
    ```

    <Note>
      The first run will be slow (\~1-5 minutes) as it compiles dependencies and the guest program. Subsequent runs are much faster.
    </Note>
  </Step>
</Steps>

## What Just Happened?

1. **Compilation**: The guest Fibonacci function was compiled to a RISC-V ELF binary
2. **Preprocessing**: Jolt generated proving and verifying keys for this specific program
3. **Proving**: Jolt executed the guest program, computed the 50th Fibonacci number, and generated a ZK proof
4. **Verification**: The verifier checked the proof without re-executing the program

The proof demonstrates that the computation was performed correctly, without revealing the intermediate steps.

## Understanding the Macro

The `#[jolt::provable]` macro accepts several parameters to configure the zkVM:

<ParamField path="heap_size" type="number" default="1048576">
  Size of the guest heap in bytes (default: 1MB)
</ParamField>

<ParamField path="max_trace_length" type="number" default="1048576">
  Maximum number of CPU cycles the program can execute
</ParamField>

<ParamField path="stack_size" type="number" default="4194304">
  Size of the guest stack in bytes (default: 4MB)
</ParamField>

Example with different parameters:

```rust theme={null}
#[jolt::provable(
    heap_size = 65536,           // 64KB heap
    max_trace_length = 1000000,  // 1M cycles max
    stack_size = 8388608         // 8MB stack
)]
fn my_function(input: u64) -> u64 {
    // Your computation here
    input * 2
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Core Concepts" icon="book" href="/concepts/guests-and-hosts">
    Learn about the guest/host architecture
  </Card>

  <Card title="Runtime Advice" icon="lightbulb" href="/concepts/runtime-advice">
    Provide non-deterministic hints to speed up proving
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/cli/overview">
    Explore all CLI commands
  </Card>

  <Card title="API Reference" icon="code" href="/api/macros/provable">
    Dive into the full API documentation
  </Card>
</CardGroup>

## Common Patterns

### Multiple Functions

You can mark multiple functions as provable in the same guest:

```rust theme={null}
#[jolt::provable]
fn add(a: u64, b: u64) -> u64 {
    a + b
}

#[jolt::provable]
fn multiply(a: u64, b: u64) -> u64 {
    a * b
}
```

### Working with Complex Types

Functions can accept and return complex types that implement `Serialize`:

```rust theme={null}
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Point {
    x: i32,
    y: i32,
}

#[jolt::provable]
fn distance_squared(p1: Point, p2: Point) -> i32 {
    let dx = p2.x - p1.x;
    let dy = p2.y - p1.y;
    dx * dx + dy * dy
}
```

### Cycle Tracking

Measure performance of specific code sections:

```rust theme={null}
use jolt::{start_cycle_tracking, end_cycle_tracking};

#[jolt::provable]
fn compute_with_tracking(n: u32) -> u128 {
    start_cycle_tracking("computation");
    
    // Your computation here
    let result = expensive_calculation(n);
    
    end_cycle_tracking("computation");
    result
}
```

The cycle counts will appear in the execution summary when you use `analyze_<function_name>()` instead of `prove_<function_name>()`.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Guest build fails">
    Make sure you have the RISC-V target installed:

    ```bash theme={null}
    rustup target add riscv64imac-unknown-none-elf
    ```

    If issues persist, try reinstalling the Jolt CLI:

    ```bash theme={null}
    cd jolt
    cargo install --path . --locked
    ```
  </Accordion>

  <Accordion title="Proving is very slow">
    For development, use `analyze_<function_name>()` instead of `prove_<function_name>()` to skip proof generation:

    ```rust theme={null}
    // Fast analysis without proof
    let summary = guest::analyze_fib(50);
    println!("Cycles: {}", summary.total_cycles());
    ```
  </Accordion>

  <Accordion title="Out of memory during proving">
    Reduce the trace length or use streaming mode (if available). Also ensure you have sufficient RAM (16GB+ recommended for complex proofs).
  </Accordion>
</AccordionGroup>

For more troubleshooting tips, see [Troubleshooting](/development/troubleshooting).
