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

# Cryptographic Inlines

> Replace expensive RISC-V execution with constraint-native cryptographic primitives

Cryptographic inlines are **custom instructions** that replace computationally expensive RISC-V implementations of cryptographic primitives with efficient, constraint-native implementations. This optimization can provide **2-5x throughput improvements** for cryptography-heavy programs.

## Problem: Expensive RISC-V Execution

Proving RISC-V execution of cryptographic operations is inefficient:

```rust theme={null}
// SHA-256 in pure RISC-V requires:
// - ~1000 instructions per block
// - Proving 1000 instruction lookups
// - Proving 1000 memory operations
// - Committing to ~1000 witness rows

fn sha256_block_naive(state: &mut [u32; 8], block: &[u8; 64]) {
    // Each of these operations becomes multiple RISC-V instructions:
    // - Bitwise rotations (RISC-V has no native rotate)
    // - Array indexing (load/store with bounds checking)
    // - 64 rounds of compression function
    // Total: ~1000 instructions → ~1000 witness rows
}
```

## Solution: Constraint-Native Primitives

Inlines replace the RISC-V trace with a **pre-computed sequence** of constraint-native operations:

```rust theme={null}
// SHA-256 inline:
// - Single "virtual instruction" in the trace
// - Pre-computed sequence of ~80 optimized operations
// - Each operation is already expressed in constraint-friendly form
// - Witness size: ~80 rows instead of ~1000

#[cfg(not(feature = "host"))]
pub unsafe fn sha256_compression(input: *const u32, state: *mut u32) {
    // Guest: Emit custom instruction opcode
    core::arch::asm!(
        ".insn i {OPCODE}, {FUNCT3}, x0, {input}, {FUNCT7}",
        input = in(reg) input as usize,
        // Custom instruction encoding
    );
}

#[cfg(feature = "host")]
pub unsafe fn sha256_compression(input: *const u32, state: *mut u32) {
    // Host: Execute native Rust implementation
    let result = exec::execute_sha256_compression(state_array, input_array);
}
```

## Available Inlines

Jolt provides optimized inlines for common cryptographic primitives:

### Hash Functions

<CardGroup cols={2}>
  <Card title="SHA-256" icon="fingerprint">
    * **Module**: `jolt-inlines/sha2`
    * **Operations**: Block compression, initial compression
    * **Speedup**: \~10-15x vs. RISC-V
  </Card>

  <Card title="Keccak-256" icon="fingerprint">
    * **Module**: `jolt-inlines/keccak256`
    * **Operations**: Permutation function
    * **Speedup**: \~20-30x vs. RISC-V
  </Card>

  <Card title="BLAKE2b" icon="fingerprint">
    * **Module**: `jolt-inlines/blake2`
    * **Operations**: Compression function
    * **Speedup**: \~12-18x vs. RISC-V
  </Card>

  <Card title="BLAKE3" icon="fingerprint">
    * **Module**: `jolt-inlines/blake3`
    * **Operations**: Compression function
    * **Speedup**: \~12-18x vs. RISC-V
  </Card>
</CardGroup>

### Elliptic Curve Operations

<CardGroup cols={2}>
  <Card title="secp256k1" icon="chart-line">
    * **Module**: `jolt-inlines/secp256k1`
    * **Operations**: Point multiplication, ECDSA
    * **Speedup**: \~50-100x vs. RISC-V
  </Card>

  <Card title="Grumpkin" icon="chart-line">
    * **Module**: `jolt-inlines/grumpkin`
    * **Operations**: Curve arithmetic
    * **Speedup**: \~50-100x vs. RISC-V
  </Card>
</CardGroup>

### Big Integer Arithmetic

<Card title="BigInt Multiplication" icon="calculator">
  * **Module**: `jolt-inlines/bigint`
  * **Operations**: 256-bit multiplication
  * **Speedup**: \~5-10x vs. RISC-V
</Card>

## How Inlines Work

### 1. Custom Instruction Encoding

Inlines use RISC-V's custom instruction extension space:

```rust theme={null}
// Constants defining the custom instruction
pub const INLINE_OPCODE: u32 = 0x0B;  // Custom-0 opcode
pub const SHA256_FUNCT3: u32 = 0x00;   // Function identifier
pub const SHA256_FUNCT7: u32 = 0x00;   // Variant identifier
```

### 2. Sequence Builder

Each inline defines a **sequence builder** that generates the constraint-native operation sequence:

```rust theme={null}
// Location: jolt-inlines/sha2/src/sequence_builder.rs
pub fn sha2_inline_sequence_builder(
    input: SequenceInputs,
    state: SequenceInputs,
) -> Vec<Instruction> {
    let mut builder = Sha256CompressionSequenceBuilder::new(false);
    
    // Generate optimized instruction sequence:
    // - Load input words
    // - Expand message schedule
    // - 64 compression rounds (optimized)
    // - Store result
    
    builder.build()
}
```

### 3. Tracer Integration

The tracer replaces custom instructions with the pre-computed sequence:

```rust theme={null}
// During trace generation:
// 1. Encounter custom instruction
// 2. Look up registered sequence builder
// 3. Execute sequence builder with current state
// 4. Emit sequence of operations instead of RISC-V instructions

register_inline(
    INLINE_OPCODE,
    SHA256_FUNCT3,
    SHA256_FUNCT7,
    "SHA256_INLINE",
    Box::new(sha2_inline_sequence_builder),
    None,  // Optional validator
)?;
```

### 4. Witness Generation

The inline sequence generates compact witness data:

```rust theme={null}
// Instead of proving 1000 RISC-V instructions:
// - 1000 instruction lookups
// - 1000 memory operations  
// - 1000 register operations

// Inline proves ~80 optimized operations:
// - Pre-computed instruction sequence (no lookup needed)
// - Minimal memory operations (optimized layout)
// - Direct constraint evaluation
```

## Performance Impact

### SHA-256 Example

| Metric                 | RISC-V | Inline | Improvement |
| ---------------------- | ------ | ------ | ----------- |
| **Instructions/block** | \~1000 | \~80   | 12.5x       |
| **Witness rows**       | \~1000 | \~80   | 12.5x       |
| **Prover time**        | 100ms  | \~7ms  | 14x         |
| **Memory usage**       | High   | Low    | \~10x       |

### secp256k1 Example

| Metric              | RISC-V   | Inline | Improvement |
| ------------------- | -------- | ------ | ----------- |
| **Instructions/op** | \~50,000 | \~500  | 100x        |
| **Witness rows**    | \~50,000 | \~500  | 100x        |
| **Prover time**     | 5s       | \~50ms | 100x        |

### End-to-End Impact

For a program that performs:

* 100 SHA-256 blocks
* 10 secp256k1 signatures

**Without inlines:**

* SHA-256: 100,000 instructions
* secp256k1: 500,000 instructions
* Total: \~600,000 instructions
* Proving time: \~60s

**With inlines:**

* SHA-256: 8,000 instructions (inline sequences)
* secp256k1: 5,000 instructions (inline sequences)
* Other logic: \~10,000 instructions
* Total: \~23,000 instructions
* Proving time: \~12s

**Result: \~5x end-to-end speedup**

## Creating Custom Inlines

To create a new inline for your application:

### 1. Define the Inline Module

```rust theme={null}
// my-inline/src/lib.rs
pub const INLINE_OPCODE: u32 = 0x0B;
pub const MY_OP_FUNCT3: u32 = 0x05;  // Choose unused funct3
pub const MY_OP_FUNCT7: u32 = 0x00;
pub const MY_OP_NAME: &str = "MY_CUSTOM_OP";

pub mod sdk;          // Guest API
pub mod exec;         // Host execution
pub mod sequence_builder;  // Constraint sequence
```

### 2. Implement Sequence Builder

```rust theme={null}
// my-inline/src/sequence_builder.rs
pub fn my_op_sequence_builder(
    input: SequenceInputs,
) -> Vec<Instruction> {
    let mut instructions = Vec::new();
    
    // Generate optimized instruction sequence
    // Use constraint-friendly operations
    
    instructions
}
```

### 3. Register the Inline

```rust theme={null}
// my-inline/src/lib.rs
#[cfg(feature = "host")]
pub fn init_inlines() -> Result<(), String> {
    register_inline(
        INLINE_OPCODE,
        MY_OP_FUNCT3,
        MY_OP_FUNCT7,
        MY_OP_NAME,
        Box::new(my_op_sequence_builder),
        None,
    )
}

#[cfg(not(target_arch = "wasm32"))]
#[ctor::ctor]
fn auto_register() {
    if let Err(e) = init_inlines() {
        tracing::error!("Failed to register inline: {e}");
    }
}
```

### 4. Provide Guest API

```rust theme={null}
// my-inline/src/sdk.rs
#[cfg(not(feature = "host"))]
pub unsafe fn my_custom_op(input: *const u64, output: *mut u64) {
    core::arch::asm!(
        ".insn i {OPCODE}, {FUNCT3}, x0, {input}, {FUNCT7}",
        input = in(reg) input as usize,
        OPCODE = const INLINE_OPCODE,
        FUNCT3 = const MY_OP_FUNCT3,
        FUNCT7 = const MY_OP_FUNCT7,
    );
}

#[cfg(feature = "host")]
pub unsafe fn my_custom_op(input: *const u64, output: *mut u64) {
    let result = exec::execute_my_op(input_array);
    // Write result to output
}
```

## Best Practices

### When to Use Inlines

✅ **Good candidates:**

* Cryptographic primitives (hash, signatures, encryption)
* Fixed computation patterns (no data-dependent branching)
* High instruction count in RISC-V (>100 instructions)
* Performance-critical operations

❌ **Poor candidates:**

* Simple operations (less than 10 instructions)
* Data-dependent control flow
* Operations that vary significantly based on input

### Optimization Guidelines

1. **Minimize witness size**: Each operation in the sequence adds to witness
2. **Use constraint-friendly operations**: Prefer operations that map cleanly to R1CS constraints
3. **Avoid branches**: Keep the sequence deterministic and fixed-length
4. **Test thoroughly**: Verify correctness in both host and guest modes

## Related Optimizations

* [CompactPolynomial](/architecture/optimizations/small-value): Efficient witness storage
* [Batched Sumcheck](/architecture/optimizations/batched-sumcheck): Protocol-level batching

## References

* Source: `jolt-inlines/` directory in Jolt repository
* RISC-V Custom Instruction Extension: [RISC-V ISA Specification](https://riscv.org/technical/specifications/)
