From 325736ce481b709a3d5ed7f3b1f9f66023ba4d5f Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Mon, 6 Jan 2025 20:52:33 +0800 Subject: [PATCH 01/12] Heap and stack sizes in kiB and MiB Allow specification of guest heap and stack sizes on the command line in more convenient units than just raw bytes. --- Cargo.lock | 7 +++++++ ceno_zkvm/Cargo.toml | 1 + ceno_zkvm/src/bin/e2e.rs | 11 +++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d9cc9427..ef8dbb072 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -339,6 +339,7 @@ dependencies = [ "mpcs", "multilinear_extensions", "num-traits", + "parse-size", "paste", "pprof2", "prettytable-rs", @@ -1364,6 +1365,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "parse-size" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b" + [[package]] name = "pasta_curves" version = "0.5.1" diff --git a/ceno_zkvm/Cargo.toml b/ceno_zkvm/Cargo.toml index 0f8241f57..97a7c9364 100644 --- a/ceno_zkvm/Cargo.toml +++ b/ceno_zkvm/Cargo.toml @@ -40,6 +40,7 @@ tracing-subscriber.workspace = true bincode = "1" clap = { version = "4.5", features = ["derive"] } generic_static = "0.2" +parse-size = "1.1" rand.workspace = true tempfile = "3.14" thread_local = "1.1" diff --git a/ceno_zkvm/src/bin/e2e.rs b/ceno_zkvm/src/bin/e2e.rs index 47f268b36..5de9b3fab 100644 --- a/ceno_zkvm/src/bin/e2e.rs +++ b/ceno_zkvm/src/bin/e2e.rs @@ -18,6 +18,13 @@ use transcript::{ BasicTranscript as Transcript, BasicTranscriptWithStat as TranscriptWithStat, StatisticRecorder, }; +fn parse_size(s: &str) -> Result { + parse_size::Config::new() + .with_binary() + .parse_size(s) + .map(|size| size as u32) +} + /// Prove the execution of a fixed RISC-V program. #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -45,11 +52,11 @@ struct Args { hints: Option, /// Stack size in bytes. - #[arg(long, default_value = "32768")] + #[arg(long, default_value = "32k", value_parser = parse_size)] stack_size: u32, /// Heap size in bytes. - #[arg(long, default_value = "2097152")] + #[arg(long, default_value = "2M", value_parser = parse_size)] heap_size: u32, } From 5bc10b26cb86347ca490f22f10c561fc17e4caa6 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Mon, 6 Jan 2025 21:04:11 +0800 Subject: [PATCH 02/12] Support sproll proving --- ceno_zkvm/Cargo.toml | 1 - ceno_zkvm/src/e2e.rs | 15 +++++++++++++-- ceno_zkvm/src/scheme/constants.rs | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ceno_zkvm/Cargo.toml b/ceno_zkvm/Cargo.toml index 97a7c9364..941fad358 100644 --- a/ceno_zkvm/Cargo.toml +++ b/ceno_zkvm/Cargo.toml @@ -36,7 +36,6 @@ tracing.workspace = true tracing-forest.workspace = true tracing-subscriber.workspace = true - bincode = "1" clap = { version = "4.5", features = ["derive"] } generic_static = "0.2" diff --git a/ceno_zkvm/src/e2e.rs b/ceno_zkvm/src/e2e.rs index 31cf9d55c..15ba73fab 100644 --- a/ceno_zkvm/src/e2e.rs +++ b/ceno_zkvm/src/e2e.rs @@ -45,6 +45,7 @@ pub struct EmulationResult { pi: PublicValues, } +// TODO(Matthias): handle hints properly. fn emulate_program( program: Arc, max_steps: usize, @@ -574,8 +575,18 @@ fn debug_memory_ranges(vm: &VMState, mem_final: &[MemFinalRecord]) { format_segments(vm.platform(), handled_addrs.iter().copied()) ); - for addr in &accessed_addrs { - assert!(handled_addrs.contains(addr), "unhandled addr: {:?}", addr); + let unhandled: BTreeSet<_> = accessed_addrs + .iter() + .filter(|addr| !handled_addrs.contains(addr)) + .collect(); + + // TODO(Matthias): this should be an assert, but it's currently broken, because our caller doesn't handle hints. + if !unhandled.is_empty() { + tracing::warn!( + "unhandled addr: {:?} to {:?}", + unhandled.first(), + unhandled.last() + ); } } diff --git a/ceno_zkvm/src/scheme/constants.rs b/ceno_zkvm/src/scheme/constants.rs index 4ad5ed0ba..a7f059f54 100644 --- a/ceno_zkvm/src/scheme/constants.rs +++ b/ceno_zkvm/src/scheme/constants.rs @@ -5,4 +5,5 @@ pub(crate) const SEL_DEGREE: usize = 2; pub const NUM_FANIN: usize = 2; pub const NUM_FANIN_LOGUP: usize = 2; -pub const MAX_NUM_VARIABLES: usize = 24; +// TODO(Matthias): what are the trade-offs for this value? +pub const MAX_NUM_VARIABLES: usize = 27; From ca37daef3807f40e5a6ee78832440a6c8fadbb35 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Tue, 7 Jan 2025 11:06:17 +0800 Subject: [PATCH 03/12] Minimise diff --- ceno_zkvm/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/ceno_zkvm/Cargo.toml b/ceno_zkvm/Cargo.toml index 941fad358..97a7c9364 100644 --- a/ceno_zkvm/Cargo.toml +++ b/ceno_zkvm/Cargo.toml @@ -36,6 +36,7 @@ tracing.workspace = true tracing-forest.workspace = true tracing-subscriber.workspace = true + bincode = "1" clap = { version = "4.5", features = ["derive"] } generic_static = "0.2" From 5eda52c34e0264f3b25aac5340940f7572875e81 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 12:42:05 +0800 Subject: [PATCH 04/12] Less spam when running `e2e` This avoids spam like the following going on for thousands of lines: ``` INFO e2e: Running on platform Ceno Platform { rom: 536870912..538373056, prog_data: {536870912, [...] ``` --- ceno_emul/src/platform.rs | 23 ++++++++++++++++++++++- ceno_zkvm/src/bin/e2e.rs | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/ceno_emul/src/platform.rs b/ceno_emul/src/platform.rs index e8b06721c..034340c54 100644 --- a/ceno_emul/src/platform.rs +++ b/ceno_emul/src/platform.rs @@ -1,4 +1,5 @@ -use std::{collections::BTreeSet, ops::Range}; +use core::fmt::{self, Formatter}; +use std::{collections::BTreeSet, fmt::Display, ops::Range}; use crate::addr::{Addr, RegIdx}; @@ -19,6 +20,26 @@ pub struct Platform { pub unsafe_ecall_nop: bool, } +impl Display for Platform { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let prog_data: Option> = match (self.prog_data.first(), self.prog_data.last()) { + (Some(first), Some(last)) => Some(*first..*last), + _ => None, + }; + write!( + f, + "Platform {{ rom: {:?}, prog_data: {:?}, stack: {:?}, heap: {:?}, public_io: {:?}, hints: {:?}, unsafe_ecall_nop: {} }}", + self.rom, + prog_data, + self.stack, + self.heap, + self.public_io, + self.hints, + self.unsafe_ecall_nop + ) + } +} + pub const CENO_PLATFORM: Platform = Platform { rom: 0x2000_0000..0x3000_0000, prog_data: BTreeSet::new(), diff --git a/ceno_zkvm/src/bin/e2e.rs b/ceno_zkvm/src/bin/e2e.rs index 5de9b3fab..f1da01d51 100644 --- a/ceno_zkvm/src/bin/e2e.rs +++ b/ceno_zkvm/src/bin/e2e.rs @@ -113,7 +113,7 @@ fn main() { args.heap_size, pub_io_size, ); - tracing::info!("Running on platform {:?} {:?}", args.platform, platform); + tracing::info!("Running on platform {:?} {}", args.platform, platform); tracing::info!( "Stack: {} bytes. Heap: {} bytes.", args.stack_size, From 558bee066680bf800bc0fbf4678c72f28df1334d Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 13:28:35 +0800 Subject: [PATCH 05/12] Only log once --- multilinear_extensions/src/util.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/multilinear_extensions/src/util.rs b/multilinear_extensions/src/util.rs index a0a8e56a2..9bbadc25a 100644 --- a/multilinear_extensions/src/util.rs +++ b/multilinear_extensions/src/util.rs @@ -37,14 +37,13 @@ fn prev_power_of_two(n: usize) -> usize { /// Largest power of two that fits the available rayon threads pub fn max_usable_threads() -> usize { - if cfg!(test) { - 1 - } else { + static MAX_USABLE_THREADS: std::sync::OnceLock = std::sync::OnceLock::new(); + *MAX_USABLE_THREADS.get_or_init(|| { let n = rayon::current_num_threads(); let threads = prev_power_of_two(n); if n != threads { tracing::warn!("thread size {n} is not power of 2, using {threads} threads instead."); } threads - } + }) } From d1d447b8b16d79a4d795380c5c8479bbb1b9036e Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 13:28:35 +0800 Subject: [PATCH 06/12] Only complain about threads once This cuts down on logging spam. --- multilinear_extensions/src/util.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/multilinear_extensions/src/util.rs b/multilinear_extensions/src/util.rs index a0a8e56a2..9bbadc25a 100644 --- a/multilinear_extensions/src/util.rs +++ b/multilinear_extensions/src/util.rs @@ -37,14 +37,13 @@ fn prev_power_of_two(n: usize) -> usize { /// Largest power of two that fits the available rayon threads pub fn max_usable_threads() -> usize { - if cfg!(test) { - 1 - } else { + static MAX_USABLE_THREADS: std::sync::OnceLock = std::sync::OnceLock::new(); + *MAX_USABLE_THREADS.get_or_init(|| { let n = rayon::current_num_threads(); let threads = prev_power_of_two(n); if n != threads { tracing::warn!("thread size {n} is not power of 2, using {threads} threads instead."); } threads - } + }) } From 2f08224111d6ce70ebf82833a10c1f10e9732357 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 13:37:45 +0800 Subject: [PATCH 07/12] Show unused operations, too --- ceno_emul/src/platform.rs | 2 +- ceno_zkvm/src/instructions/riscv/rv32im.rs | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ceno_emul/src/platform.rs b/ceno_emul/src/platform.rs index 034340c54..d69b3d7ed 100644 --- a/ceno_emul/src/platform.rs +++ b/ceno_emul/src/platform.rs @@ -28,7 +28,7 @@ impl Display for Platform { }; write!( f, - "Platform {{ rom: {:?}, prog_data: {:?}, stack: {:?}, heap: {:?}, public_io: {:?}, hints: {:?}, unsafe_ecall_nop: {} }}", + "Platform {{ rom: {:?}, prog_data: {:x?}, stack: {:?}, heap: {:?}, public_io: {:?}, hints: {:?}, unsafe_ecall_nop: {} }}", self.rom, prog_data, self.stack, diff --git a/ceno_zkvm/src/instructions/riscv/rv32im.rs b/ceno_zkvm/src/instructions/riscv/rv32im.rs index 5d19255d7..fefb18ba5 100644 --- a/ceno_zkvm/src/instructions/riscv/rv32im.rs +++ b/ceno_zkvm/src/instructions/riscv/rv32im.rs @@ -29,12 +29,15 @@ use ceno_emul::{ }; use ecall::EcallDummy; use ff_ext::ExtensionField; -use itertools::Itertools; +use itertools::{Itertools, izip}; use mul::{MulInstruction, MulhInstruction, MulhsuInstruction}; use shift::SraInstruction; use slt::{SltInstruction, SltuInstruction}; use slti::SltiuInstruction; -use std::collections::{BTreeMap, BTreeSet}; +use std::{ + cmp::Reverse, + collections::{BTreeMap, BTreeSet}, +}; use strum::IntoEnumIterator; use super::{ @@ -337,14 +340,10 @@ impl Rv32imConfig { } }); - for (insn_kind, (_, records)) in InsnKind::iter() - .zip(all_records.iter()) - .sorted_by(|a, b| Ord::cmp(&a.1.1.len(), &b.1.1.len())) - .rev() + for (insn_kind, (_, records)) in + izip!(InsnKind::iter(), &all_records).sorted_by_key(|(_, (_, a))| Reverse(a.len())) { - if !records.is_empty() { - tracing::info!("tracer generated {:?} {} records", insn_kind, records.len()); - } + tracing::info!("tracer generated {:?} {} records", insn_kind, records.len()); } macro_rules! assign_opcode { From 172d2fdff23b85ab5fc465985223019a0535be85 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 15:22:31 +0800 Subject: [PATCH 08/12] All in Hex --- ceno_emul/src/platform.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ceno_emul/src/platform.rs b/ceno_emul/src/platform.rs index d69b3d7ed..c7bea8c4c 100644 --- a/ceno_emul/src/platform.rs +++ b/ceno_emul/src/platform.rs @@ -28,7 +28,7 @@ impl Display for Platform { }; write!( f, - "Platform {{ rom: {:?}, prog_data: {:x?}, stack: {:?}, heap: {:?}, public_io: {:?}, hints: {:?}, unsafe_ecall_nop: {} }}", + "Platform {{ rom: {:x?}, prog_data: {:x?}, stack: {:?}, heap: {:x?}, public_io: {:x?}, hints: {:x?}, unsafe_ecall_nop: {} }}", self.rom, prog_data, self.stack, From 10140498ccb42af0af0b84df173c4889121505b2 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 15:24:51 +0800 Subject: [PATCH 09/12] Display in hex --- ceno_emul/src/platform.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ceno_emul/src/platform.rs b/ceno_emul/src/platform.rs index c7bea8c4c..dfde42ed2 100644 --- a/ceno_emul/src/platform.rs +++ b/ceno_emul/src/platform.rs @@ -28,7 +28,7 @@ impl Display for Platform { }; write!( f, - "Platform {{ rom: {:x?}, prog_data: {:x?}, stack: {:?}, heap: {:x?}, public_io: {:x?}, hints: {:x?}, unsafe_ecall_nop: {} }}", + "Platform {{ rom: {:#x?}, prog_data: {:#x?}, stack: {:#x?}, heap: {:x?}, public_io: {:#x?}, hints: {:#x?}, unsafe_ecall_nop: {} }}", self.rom, prog_data, self.stack, From b27f10761d7bb21bf5f46aeef1d9efca1c79f6e4 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 15:27:19 +0800 Subject: [PATCH 10/12] Simpler --- ceno_emul/src/platform.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/ceno_emul/src/platform.rs b/ceno_emul/src/platform.rs index dfde42ed2..3bb3cf805 100644 --- a/ceno_emul/src/platform.rs +++ b/ceno_emul/src/platform.rs @@ -22,20 +22,14 @@ pub struct Platform { impl Display for Platform { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let prog_data: Option> = match (self.prog_data.first(), self.prog_data.last()) { - (Some(first), Some(last)) => Some(*first..*last), - _ => None, + let prog_data = match (self.prog_data.first(), self.prog_data.last()) { + (Some(first), Some(last)) => format!("{:#x?}", *first..*last), + _ => "-".to_string(), }; write!( f, - "Platform {{ rom: {:#x?}, prog_data: {:#x?}, stack: {:#x?}, heap: {:x?}, public_io: {:#x?}, hints: {:#x?}, unsafe_ecall_nop: {} }}", - self.rom, - prog_data, - self.stack, - self.heap, - self.public_io, - self.hints, - self.unsafe_ecall_nop + "Platform {{ rom: {:#x?}, prog_data: {prog_data}, stack: {:#x?}, heap: {:x?}, public_io: {:#x?}, hints: {:#x?}, unsafe_ecall_nop: {} }}", + self.rom, self.stack, self.heap, self.public_io, self.hints, self.unsafe_ecall_nop ) } } From ec4d2312c2c6fa0c390392b11991b9ab7bf11d01 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Wed, 8 Jan 2025 15:28:26 +0800 Subject: [PATCH 11/12] More hex --- ceno_zkvm/src/bin/e2e.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ceno_zkvm/src/bin/e2e.rs b/ceno_zkvm/src/bin/e2e.rs index f1da01d51..7a01a3286 100644 --- a/ceno_zkvm/src/bin/e2e.rs +++ b/ceno_zkvm/src/bin/e2e.rs @@ -115,7 +115,7 @@ fn main() { ); tracing::info!("Running on platform {:?} {}", args.platform, platform); tracing::info!( - "Stack: {} bytes. Heap: {} bytes.", + "Stack: {:#x?} bytes. Heap: {:#x?} bytes.", args.stack_size, args.heap_size ); From be7f34f43c02cb68f0ef22a5cec84076b0aa2772 Mon Sep 17 00:00:00 2001 From: Matthias Goergens Date: Tue, 14 Jan 2025 14:10:50 +0800 Subject: [PATCH 12/12] Minimise diff --- ceno_zkvm/src/scheme/constants.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ceno_zkvm/src/scheme/constants.rs b/ceno_zkvm/src/scheme/constants.rs index a7f059f54..4ad5ed0ba 100644 --- a/ceno_zkvm/src/scheme/constants.rs +++ b/ceno_zkvm/src/scheme/constants.rs @@ -5,5 +5,4 @@ pub(crate) const SEL_DEGREE: usize = 2; pub const NUM_FANIN: usize = 2; pub const NUM_FANIN_LOGUP: usize = 2; -// TODO(Matthias): what are the trade-offs for this value? -pub const MAX_NUM_VARIABLES: usize = 27; +pub const MAX_NUM_VARIABLES: usize = 24;