> ## 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.

# AdviceWriter

> Writer for sending advice data to the host during the compute_advice phase in Jolt zkVM

## Overview

`AdviceWriter` provides low-level access to write data to the advice tape during the `compute_advice` phase of a zkVM program. The advice tape allows the guest program to send non-deterministic inputs to the prover that can later be read during the proving phase.

## Type Definition

```rust theme={null}
pub struct AdviceWriter;
```

## Methods

### get

Returns a reference to the global advice writer.

```rust theme={null}
pub fn get() -> Self
```

**Returns:** An `AdviceWriter` instance

**Example:**

```rust theme={null}
use jolt_sdk::AdviceWriter;

let mut writer = AdviceWriter::get();
```

### write\_u8

Writes a single byte (u8) to the advice tape.

```rust theme={null}
pub fn write_u8(&mut self, value: u8)
```

<ParamField path="value" type="u8" required>
  The byte value to write
</ParamField>

**Example:**

```rust theme={null}
let mut writer = AdviceWriter::get();
writer.write_u8(42);
```

### write\_u16

Writes a halfword (2 bytes, u16) to the advice tape in little-endian format.

```rust theme={null}
pub fn write_u16(&mut self, value: u16)
```

<ParamField path="value" type="u16" required>
  The u16 value to write
</ParamField>

**Example:**

```rust theme={null}
let mut writer = AdviceWriter::get();
writer.write_u16(1234);
```

### write\_u32

Writes a word (4 bytes, u32) to the advice tape in little-endian format.

```rust theme={null}
pub fn write_u32(&mut self, value: u32)
```

<ParamField path="value" type="u32" required>
  The u32 value to write
</ParamField>

**Example:**

```rust theme={null}
let mut writer = AdviceWriter::get();
writer.write_u32(123456);
```

### write\_u64

Writes a doubleword (8 bytes, u64) to the advice tape in little-endian format.

```rust theme={null}
pub fn write_u64(&mut self, value: u64)
```

<ParamField path="value" type="u64" required>
  The u64 value to write
</ParamField>

**Example:**

```rust theme={null}
let mut writer = AdviceWriter::get();
writer.write_u64(9876543210);
```

## Usage Example

### Basic Writing

```rust theme={null}
use jolt_sdk::AdviceWriter;

#[jolt::advice]
fn write_advice_data() {
    let mut writer = AdviceWriter::get();
    
    writer.write_u8(255);
    writer.write_u16(65535);
    writer.write_u32(4294967295);
    writer.write_u64(18446744073709551615);
}
```

### Writing Complex Types

For writing complex types, use the `AdviceTapeIO` trait:

```rust theme={null}
use jolt_sdk::AdviceTapeIO;

#[jolt::advice]
fn write_complex_data() {
    // Automatically writes length, capacity, and data
    let vec_data = vec![1u32, 2, 3, 4, 5];
    vec_data.write_to_advice_tape();
    
    // Write a tuple
    let tuple_data = (42u64, 123u32, 456u16);
    tuple_data.write_to_advice_tape();
    
    // Write an array
    let array_data = [1u64, 2, 3, 4];
    array_data.write_to_advice_tape();
}
```

### Complete Advice Flow

```rust theme={null}
use jolt_sdk::{AdviceWriter, AdviceReader, AdviceTapeIO};

#[jolt::advice]
fn compute_advice() {
    let mut writer = AdviceWriter::get();
    
    // Write some computed values
    let result = expensive_computation();
    writer.write_u64(result);
}

#[jolt::provable]
fn use_advice() -> u64 {
    let mut reader = AdviceReader::get();
    
    // Read the precomputed value
    let result = reader.read_u64();
    
    // Verify it's correct
    check_advice_eq!(result, expensive_computation());
    
    result
}

fn expensive_computation() -> u64 {
    // Some expensive computation
    42
}
```

## Platform Support

The following table shows platform-specific behavior:

| Target    | Supported | Notes                           |
| --------- | --------- | ------------------------------- |
| `riscv32` | Yes       | Uses custom RISC-V instructions |
| `riscv64` | Yes       | Uses custom RISC-V instructions |
| Others    | No        | All methods panic               |

<Warning>
  Advice tape I/O is only supported on RISC-V targets. Attempting to use `AdviceWriter` on non-RISC-V platforms will result in a panic.
</Warning>

## Implementation Details

### RISC-V Custom Instructions

`AdviceWriter` uses the `VirtualHostIO` custom instruction (opcode `0x5B`, funct3 `2`) to write bytes to the advice tape. The internal `write_bytes` method handles the actual I/O:

```rust theme={null}
// See jolt-sdk/src/lib.rs:188
core::arch::asm!(
    ".insn i 0x5B, 2, x0, x0, 0",
    in("a0") JOLT_ADVICE_WRITE_CALL_ID,
    in("a1") src_ptr,
    in("a2") len,
    options(nostack, preserves_flags)
);
```

### Data Format

All multi-byte values are written in little-endian format:

* `write_u16(0x1234)` writes bytes `[0x34, 0x12]`
* `write_u32(0x12345678)` writes bytes `[0x78, 0x56, 0x34, 0x12]`
* `write_u64(0x0123456789ABCDEF)` writes bytes `[0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01]`

## Best Practices

<AccordionGroup>
  <Accordion title="Use AdviceTapeIO for complex types">
    Instead of manually writing each field of a struct or vector, use the `AdviceTapeIO` trait which handles serialization automatically:

    ```rust theme={null}
    // Good
    my_vec.write_to_advice_tape();

    // Avoid
    writer.write_u64(my_vec.len() as u64);
    for item in &my_vec {
        writer.write_u32(*item);
    }
    ```
  </Accordion>

  <Accordion title="Match reads with writes">
    Ensure that the order and types of writes in `compute_advice` match the reads in your provable function:

    ```rust theme={null}
    #[jolt::advice]
    fn compute() {
        writer.write_u32(42);
        writer.write_u64(1000);
    }

    #[jolt::provable]
    fn prove() {
        let a = reader.read_u32(); // Matches write_u32
        let b = reader.read_u64(); // Matches write_u64
    }
    ```
  </Accordion>

  <Accordion title="Verify untrusted advice">
    Always verify values read from the advice tape using `check_advice!` or `check_advice_eq!` to ensure correctness:

    ```rust theme={null}
    let hint = reader.read_u64();
    let actual = compute_expected_value();
    check_advice_eq!(hint, actual);
    ```
  </Accordion>
</AccordionGroup>

## See Also

* [AdviceReader](/api/types/advice-reader) - Reading advice data from the advice tape
* [TrustedAdvice\<T>](/api/types/trusted-advice) - Wrapper for trusted advice inputs
* [UntrustedAdvice\<T>](/api/types/untrusted-advice) - Wrapper for untrusted advice inputs
* [#\[jolt::advice\] macro](/api/macros/advice) - Macro for advice computation functions
* [check\_advice! macro](/api/macros/check-advice) - Macro for verifying advice
