Sitemap

Jolt & Lasso

4 min readDec 16, 2024

--

Read the latest and complete one on my Notion: https://doutv.notion.site/Jolt-Lasso-1591aee049b480b7a44ad7d00e3e9265?pvs=4

Why zkVM?

zkVM VS specialized circuits

✅ Develop zk app without learning zk

✅ Exploit existing compiler infra and tooling

✅ A single circuit can run all programs up to a certain time bound

❌ Much larger Circuit

❌ Any bug in the compiler can render the system insecure

How VM/CPU works?

  • Repeatedly execute the fetch-decode-execute logic
  • Perform reads and writes to Random Access Memory (RAM)

Watch and understand the animation in RISC-V Simulator

How does Jolt zkVM prove VM execution?

Press enter or click to view image in full size

https://excalidraw.com/#json=o6Sc1hlZSN0ZlGQS9aeob,XQusaS02jGZRzzDN0aRAug

Example: Fibonacci

Note: Jolt code tested on 2024.06, some of them maybe outdated

  1. Rust developer only needs to write this program
#![cfg_attr(feature = "guest", no_std)]
#![no_main]
#[jolt::provable]
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
}
let mut program = host::Program::new("fib");
program.set_input(3);
  1. RISC-V Compiler
let (bytecode, memory_init) = program.decode();

Decode native RISC-V instructions from ELF file

Even for this simple Fibonacci program, it has 500 instructions

Thus, I use a simple one from an online RISC-V emulator

bytecode: native RISC-V instructions

memory_init:

Jolt Prover

let preprocessing: crate::jolt::vm::JoltPreprocessing<F, PCS> =
RV32IJoltVM::preprocess(bytecode.clone(), memory_init, 1 << 20, 1 << 20, 1 << 22);
let (io_device, trace, circuit_flags) = program.trace();
let (jolt_proof, jolt_commitments) = <RV32IJoltVM as Jolt<_, PCS, C, M>>::prove(
io_device,
trace,
circuit_flags,
preprocessing.clone(),
);

RV32IJoltVM::preprocess(bytecode, memory_init)

  • Commit to instructions and memory layout
  • Generate lookup tables

program.trace()

  • simulate execution in RISC-V VM -> get the native execution trace
  • Mapping each RISC-V instructions to Jolt instructions -> get the Jolt execution trace trace
  • io_device just like a hard drive

prove()

  • Prove the execution trace step-by-step

Jolt Verifier

RV32IJoltVM::verify(preprocessing, jolt_proof, jolt_commitments);

Some observations

  • Prover and Verifier agree on preprocessing, which is similar to verification key vkey
  • Start from bytecode and memory_init, Jolt doesn’t include a compiler. Typically, we don’t consider compiler bugs.

Visualize Lasso

Lasso Contribution: MLE-structured and Decomposable tables

Jolt Contribution: Design efficient Lasso Lookup tables for RISC-V

Learning Goal: understand Decomposable tables and Offline Memory Checking

https://www.youtube.com/watch?v=iDcXj9Vx3zY

excalidraw: Visualize Lasso

What is Lookup Argument?

Prove \{3, 1, 1\} \subseteq \{1, 2, 3, 4\}

Get Backdoor’s stories in your inbox

Join Medium for free to get updates from this writer.

lookups (possibly repeated) are all contained in the table (distinct values)

Decomposable Tables

Offline Memory Checking

  • Online: Merkle hashing that immediately confirm that a memory read was done correctly by insisting that each read includes an authentication path.
  • Offline: check the correctness of all read operations “all at once”, after the reads have all occurred

Read-only

Each memory access is conceptually decoupled into a “read” operation and a “write” operation, where the write simply increments the counter.

  1. Init memory: [5, 9]

$$ I = (address, value, counter)=\{(0,5,0), (1, 9, 0) \} $$

  1. Read memory[1]

$$ R = \{(1, 9, 0)\} $$

  1. Write 5 into memory[1], counter+=1

$$ W = \{(1, 5, 1)\} $$

$$ F = \{(0,5,0), (1,5,1)\} $$

$$ I \cup W = R \cup F $$

How about read-write memory checking?

Should we introduce extra constraints?

Read-write

The multiset equality check for read-only memory is not adequate for ensuring the accuracy of read values. It is essential to also verify that each read operation retrieves a value that was written in a previous step (not a future step).

To formalize this, we assert that the timestamp of each read operation, denoted as read_timestamp, must not exceed the global timestamp at that particular step. The global timestamp starts at 0 and is incremented once per step.

The verification of read_timestamp≤global_timestamp is equivalent to confirming that read_timestamp falls within the range [0,TRACE_LENGTH) and that the difference (global_timestamp−read_timestamp) is also within the same range.

MLE: Multi-Linear Extension

MLE: Multi-Linear Extension Motivation: convert Vector -> Polynomial

Before extension: a vector [8, 6, 7, 5, 3, 0, 9] After extension: a multilinear polynomial $q(x_1, x_2, x_3)$ can be evaluated on any points

Univariate index in binary representation -> hypercube index

Design Lookup Tables for RISC-V

Lasso Contribution: MLE-structured and Decomposable tables Jolt Contribution: Design efficient Lasso Lookup tables for RISC-V

Jolt Roadmap

“Jolt-with-curves is what one would want to use when proving statements about elliptic curves (at least, without major advances in proving non-native field arithmetic).”

Jolt-with-Binius-commitment will be much faster as a pure zkVM than alternatives, and will be what people use except when proving statements about curves or proving with very small space (in which case people would use Jolt-with-curves).

Jolt: Clarifications, critiques, reflections

On-chain Verifier

Implement on-chain verifier (Solidity, Move, etc.) · Issue #209 · a16z/jolt

  • Current verifier is slow and the proof size is huge.

https://github.com/flyq/jolt_verifier_canister

Recursion

  • No recursion for now
  • Today Jolt is a monolithic SNARK. RISC-V traces cannot be broken up, they must be proven monolithically or not at all.
  • Require huge memory for large program trace

Questions

  • How does Lasso lookup, R1CS, and offline memory checking work together? Why Jolt need R1CS?
  • Why Jolt-with-curves is fast in proving elliptic curve operations? How Jolt prove elliptic curve operations?
  • How Jolt combined with Binius?
  • I tried to verify Schnorr signature using Jolt, it requires 500GB+ memory. why does Jolt consume such a large memory?

Read More

Lasso + Jolt — YouTube

Binius: highly efficient proofs over binary fields

Jolt — JoltBook

Jolt R1CS — How + why we rewrote Circom in Rust 🦀 | Sam Ragsdale

A Technical Dive into Jolt: The RISC-V zkVM

--

--