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

# AdviceReader

> Reader for receiving advice data from the host during the proving phase in Jolt zkVM

## Overview

`AdviceReader` provides low-level access to read data from the advice tape during the proving phase of a zkVM program. The advice tape is a mechanism for the prover to provide non-deterministic inputs to the guest program that can be verified within the zkVM.

<Warning>
  Reading beyond the end of the advice tape will result in a runtime error during proof generation.
</Warning>

## Type Definition

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

## Methods

### get

Returns a reference to the global advice reader.

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

**Returns:** An `AdviceReader` instance

**Example:**

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

let mut reader = AdviceReader::get();
```

### read\_u8

Reads a single byte (u8) from the advice tape.

```rust theme={null}
pub fn read_u8(&mut self) -> u8
```

**Returns:** The next byte from the advice tape

**Example:**

```rust theme={null}
let mut reader = AdviceReader::get();
let byte_value = reader.read_u8();
```

<Note>
  This method is only available on RISC-V targets (`riscv32` or `riscv64`). On other targets, it will panic.
</Note>

### read\_u16

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

```rust theme={null}
pub fn read_u16(&mut self) -> u16
```

**Returns:** The next 2 bytes from the advice tape as a u16

**Example:**

```rust theme={null}
let mut reader = AdviceReader::get();
let halfword_value = reader.read_u16();
```

### read\_u32

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

```rust theme={null}
pub fn read_u32(&mut self) -> u32
```

**Returns:** The next 4 bytes from the advice tape as a u32

**Example:**

```rust theme={null}
let mut reader = AdviceReader::get();
let word_value = reader.read_u32();
```

### read\_u64

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

```rust theme={null}
pub fn read_u64(&mut self) -> u64
```

**Returns:** The next 8 bytes from the advice tape as a u64

**Example:**

```rust theme={null}
let mut reader = AdviceReader::get();
let doubleword_value = reader.read_u64();
```

<Note>
  On 32-bit RISC-V targets (`riscv32`), this is performed via two 4-byte reads. On 64-bit targets (`riscv64`), it's a single 8-byte read.
</Note>

### bytes\_remaining

Returns the number of bytes remaining in the advice tape.

```rust theme={null}
pub fn bytes_remaining(&mut self) -> u64
```

**Returns:** The count of unread bytes in the advice tape

**Example:**

```rust theme={null}
let mut reader = AdviceReader::get();
let remaining = reader.bytes_remaining();
println!("Bytes left: {}", remaining);
```

## Usage Example

### Basic Reading

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

#[jolt::provable]
fn read_advice_data() -> (u8, u16, u32, u64) {
    let mut reader = AdviceReader::get();
    
    let byte = reader.read_u8();
    let halfword = reader.read_u16();
    let word = reader.read_u32();
    let doubleword = reader.read_u64();
    
    (byte, halfword, word, doubleword)
}
```

### Reading with Length Checking

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

#[jolt::provable]
fn safe_read_advice() -> Vec<u64> {
    let mut reader = AdviceReader::get();
    let mut result = Vec::new();
    
    while reader.bytes_remaining() >= 8 {
        result.push(reader.read_u64());
    }
    
    result
}
```

### Reading Complex Types

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

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

#[jolt::provable]
fn read_vec() -> Vec<u32> {
    // Automatically reads length, capacity, and data
    Vec::<u32>::new_from_advice_tape()
}

#[jolt::provable]
fn read_tuple() -> (u64, u32, u16) {
    <(u64, u32, u16)>::new_from_advice_tape()
}
```

## Platform Support

The following table shows platform-specific behavior:

| Target    | Supported | Notes                            |
| --------- | --------- | -------------------------------- |
| `riscv32` | Yes       | `read_u64` uses two 4-byte reads |
| `riscv64` | Yes       | Full native support              |
| Others    | No        | All methods panic                |

## Implementation Details

### RISC-V Custom Instructions

`AdviceReader` uses custom RISC-V instructions to read from the advice tape:

* `FUNCT3_ADVICE_LB` (0b011) - Load byte
* `FUNCT3_ADVICE_LH` (0b100) - Load halfword
* `FUNCT3_ADVICE_LW` (0b101) - Load word
* `FUNCT3_ADVICE_LD` (0b110) - Load doubleword
* `FUNCT3_ADVICE_LEN` (0b111) - Get remaining bytes

These are encoded using the custom opcode `0x5B`.

### Memory Alignment

When reading slices of data (via `AdviceTapeIO` trait implementations), `AdviceReader` optimizes for alignment:

1. Performs largest aligned reads possible until 8-byte boundary
2. Reads in aligned 8-byte chunks
3. Handles remaining bytes greedily with aligned reads/writes

See `jolt-sdk/src/lib.rs:344` for the internal `read_slice` implementation.

## See Also

* [AdviceWriter](/api/types/advice-writer) - Writing advice data to 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
