Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/private-input: Unconstrained memory init #617

Merged
merged 4 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ceno_zkvm/src/instructions/riscv/memory/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl<E: ExtensionField, I: RIVInstruction> Instruction<E> for LoadInstruction<E,
) -> Result<Self::InstructionConfig, ZKVMError> {
let rs1_read = UInt::new_unchecked(|| "rs1_read", circuit_builder)?; // unsigned 32-bit value
let imm = circuit_builder.create_witin(|| "imm"); // signed 12-bit value
// Memory initialization is not guaranteed to contain u32. Range-check it here.
let memory_read = UInt::new(|| "memory_read", circuit_builder)?;

let memory_addr = match I::INST_KIND {
Expand Down
1 change: 1 addition & 0 deletions ceno_zkvm/src/instructions/riscv/memory/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl<E: ExtensionField, I: RIVInstruction, const N_ZEROS: usize> Instruction<E>
) -> Result<Self::InstructionConfig, ZKVMError> {
let rs1_read = UInt::new_unchecked(|| "rs1_read", circuit_builder)?; // unsigned 32-bit value
let rs2_read = UInt::new_unchecked(|| "rs2_read", circuit_builder)?;
// Memory initialization is not guaranteed to contain u32. Range-check it here.
let prev_memory_value = UInt::new(|| "prev_memory_value", circuit_builder)?;
let imm = circuit_builder.create_witin(|| "imm"); // signed 12-bit value

Expand Down
36 changes: 26 additions & 10 deletions ceno_zkvm/src/tables/ram.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use ceno_emul::{Addr, VMState, WORD_SIZE};
use ceno_emul::{Addr, VMState};
use ram_circuit::{DynVolatileRamCircuit, NonVolatileRamCircuit, PubIORamCircuit};

use crate::{
Expand All @@ -11,11 +11,12 @@ mod ram_impl;
pub use ram_circuit::{DynVolatileRamTable, MemFinalRecord, MemInitRecord, NonVolatileTable};

#[derive(Clone)]
pub struct MemTable;
pub struct DynMemTable;

impl DynVolatileRamTable for MemTable {
impl DynVolatileRamTable for DynMemTable {
const RAM_TYPE: RAMType = RAMType::Memory;
const V_LIMBS: usize = 1; // See `MemoryExpr`.
const ZERO_INIT: bool = true;

fn offset_addr(params: &ProgramParams) -> Addr {
params.platform.ram_start()
Expand All @@ -26,17 +27,32 @@ impl DynVolatileRamTable for MemTable {
}

fn name() -> &'static str {
"MemTable"
"DynMemTable"
}
}

pub type DynMemCircuit<E> = DynVolatileRamCircuit<E, DynMemTable>;

#[derive(Clone)]
pub struct PrivateMemTable;
impl DynVolatileRamTable for PrivateMemTable {
const RAM_TYPE: RAMType = RAMType::Memory;
const V_LIMBS: usize = 1; // See `MemoryExpr`.
const ZERO_INIT: bool = false;

fn offset_addr(params: &ProgramParams) -> Addr {
params.platform.ram_start()
}

fn end_addr(params: &ProgramParams) -> Addr {
params.platform.ram_end()
}

fn max_len(params: &ProgramParams) -> usize {
let max_size =
(Self::end_addr(params) - Self::offset_addr(params)).div_ceil(WORD_SIZE as u32) as Addr;
1 << (u32::BITS - 1 - max_size.leading_zeros()) // prev_power_of_2
fn name() -> &'static str {
"PrivateMemTable"
}
}

pub type MemCircuit<E> = DynVolatileRamCircuit<E, MemTable>;
pub type PrivateMemCircuit<E> = DynVolatileRamCircuit<E, PrivateMemTable>;

/// RegTable, fix size without offset
#[derive(Clone)]
Expand Down
13 changes: 11 additions & 2 deletions ceno_zkvm/src/tables/ram/ram_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,18 @@ impl<E: ExtensionField, NVRAM: NonVolatileTable + Send + Sync + Clone> TableCirc
pub trait DynVolatileRamTable {
const RAM_TYPE: RAMType;
const V_LIMBS: usize;
const ZERO_INIT: bool;

fn offset_addr(params: &ProgramParams) -> Addr;
fn end_addr(params: &ProgramParams) -> Addr;

fn name() -> &'static str;

fn max_len(params: &ProgramParams) -> usize;
fn max_len(params: &ProgramParams) -> usize {
let max_size =
(Self::end_addr(params) - Self::offset_addr(params)).div_ceil(WORD_SIZE as u32) as Addr;
1 << (u32::BITS - 1 - max_size.leading_zeros()) // prev_power_of_2
}

fn addr(params: &ProgramParams, entry_index: usize) -> Addr {
Self::offset_addr(params) + (entry_index * WORD_SIZE) as Addr
Expand All @@ -156,8 +161,12 @@ pub trait DynVolatileRamTable {

/// DynVolatileRamCircuit initializes and finalizes memory
/// - at witnessed addresses, in a contiguous range chosen by the prover,
/// - with zeros as initial content,
/// - with zeros as initial content if ZERO_INIT,
/// - with witnessed final content that the program wrote.
///
/// If not ZERO_INIT:
/// - The initial content is an unconstrained prover hint.
/// - The final content is equal to this initial content.
pub struct DynVolatileRamCircuit<E, R>(PhantomData<(E, R)>);

impl<E: ExtensionField, DVRAM: DynVolatileRamTable + Send + Sync + Clone> TableCircuit<E>
Expand Down
28 changes: 9 additions & 19 deletions ceno_zkvm/src/tables/ram/ram_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,17 @@ impl<DVRAM: DynVolatileRamTable + Send + Sync + Clone> DynVolatileRamTableConfig
.collect::<Vec<WitIn>>();
let final_cycle = cb.create_witin(|| "final_cycle");

let final_expr = final_v.iter().map(|v| v.expr()).collect_vec();
let init_expr = if DVRAM::ZERO_INIT {
vec![Expression::ZERO; DVRAM::V_LIMBS]
} else {
final_expr.clone()
};

let init_table = [
vec![(DVRAM::RAM_TYPE as usize).into()],
vec![addr.expr()],
vec![Expression::ZERO],
init_expr,
vec![Expression::ZERO], // Initial cycle.
]
.concat();
Expand All @@ -315,7 +322,7 @@ impl<DVRAM: DynVolatileRamTable + Send + Sync + Clone> DynVolatileRamTableConfig
// a v t
vec![(DVRAM::RAM_TYPE as usize).into()],
vec![addr.expr()],
final_v.iter().map(|v| v.expr()).collect_vec(),
final_expr,
vec![final_cycle.expr()],
]
.concat();
Expand Down Expand Up @@ -409,20 +416,3 @@ impl<DVRAM: DynVolatileRamTable + Send + Sync + Clone> DynVolatileRamTableConfig
Ok(final_table)
}
}

#[allow(dead_code)]
/// DynUnConstrainRamTableConfig with unconstrain init value and final value
/// dynamic address as witin, relied on augment of knowledge to prove address form
/// do not check init_value
/// TODO implement DynUnConstrainRamTableConfig
#[derive(Clone, Debug)]
pub struct DynUnConstrainRamTableConfig<RAM: DynVolatileRamTable + Send + Sync + Clone> {
addr: WitIn,

init_v: Vec<WitIn>,

final_v: Vec<WitIn>,
final_cycle: WitIn,

phantom: PhantomData<RAM>,
}