Skip to content
Open
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
50 changes: 50 additions & 0 deletions prover/src/auto_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,18 @@ use crate::tables::commit::{bus_interactions as commit_buses, cols::NUM_COLUMNS
use crate::tables::cpu::{bus_interactions as cpu_buses, cols::NUM_COLUMNS as CPU_COLS};
use crate::tables::decode::{bus_interactions as decode_buses, cols::NUM_COLUMNS as DECODE_COLS};
use crate::tables::dvrm::{bus_interactions as dvrm_buses, cols::NUM_COLUMNS as DVRM_COLS};
use crate::tables::ecdas::{bus_interactions as ecdas_buses, cols::NUM_COLUMNS as ECDAS_COLS};
use crate::tables::ecsm::{bus_interactions as ecsm_buses, cols::NUM_COLUMNS as ECSM_COLS};
use crate::tables::halt::{bus_interactions as halt_buses, cols::NUM_COLUMNS as HALT_COLS};
use crate::tables::hint::{bus_interactions as hint_buses, cols::NUM_COLUMNS as HINT_COLS};
use crate::tables::keccak::{bus_interactions as keccak_buses, cols::NUM_COLUMNS as KECCAK_COLS};
use crate::tables::keccak_rc::{
NUM_ROWS as KECCAK_RC_ROWS, bus_interactions as keccak_rc_buses,
cols::NUM_COLUMNS as KECCAK_RC_COLS,
};
use crate::tables::keccak_rnd::{
bus_interactions as keccak_rnd_buses, cols::NUM_COLUMNS as KECCAK_RND_COLS,
};
use crate::tables::load::{bus_interactions as load_buses, cols::NUM_COLUMNS as LOAD_COLS};
use crate::tables::lt::{bus_interactions as lt_buses, cols::NUM_COLUMNS as LT_COLS};
use crate::tables::memw::{bus_interactions as memw_buses, cols::NUM_COLUMNS as MEMW_COLS};
Expand Down Expand Up @@ -109,6 +120,7 @@ fn table_specs(lengths: &TableLengths) -> Vec<TableSpec> {
let bitwise_rows = BITWISE_ROWS as u64;
let register_rows = NUM_REGISTER_ADDRESSES.next_power_of_two() as u64;
let halt_rows = 1u64;
let keccak_rc_rows = KECCAK_RC_ROWS as u64;
let page_rows = PAGE_SIZE as u64;

let mut specs = vec![
Expand Down Expand Up @@ -178,6 +190,44 @@ fn table_specs(lengths: &TableLengths) -> Vec<TableSpec> {
aux_cols(commit_buses().len()),
1,
),
// Accelerator chips. Wide and driven by guest data, so leaving them out
// under-projects any keccak- or ECSM-heavy program.
(
lengths.keccak_padded_rows,
KECCAK_COLS as u64,
aux_cols(keccak_buses().len()),
1,
),
(
lengths.keccak_rnd_padded_rows,
KECCAK_RND_COLS as u64,
aux_cols(keccak_rnd_buses().len()),
1,
),
(
keccak_rc_rows,
KECCAK_RC_COLS as u64,
aux_cols(keccak_rc_buses().len()),
2,
),
(
lengths.ecsm_padded_rows,
ECSM_COLS as u64,
aux_cols(ecsm_buses().len()),
1,
),
(
lengths.ecdas_padded_rows,
ECDAS_COLS as u64,
aux_cols(ecdas_buses().len()),
1,
),
(
lengths.hint_padded_rows,
HINT_COLS as u64,
aux_cols(hint_buses().len()),
1,
),
// BITWISE / DECODE / PAGE / REGISTER take the preprocessed-trace commit
// path: it extracts ALL columns into the LDE and builds two Merkle trees
// (precomputed_tree + mult_tree), so main_cols = full NUM_COLUMNS and
Expand Down
138 changes: 105 additions & 33 deletions prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ pub struct RuntimePageRange {
}

/// Number of tables that always contribute exactly one sub-proof, regardless
/// of `TableCounts`: bitwise, decode, halt, commit, keccak, keccak_rnd,
/// keccak_rc, register, ecsm, ecdas, hint.
pub const FIXED_TABLE_COUNT: usize = 11;
/// of `TableCounts`: bitwise, decode, halt, keccak_rc, register. Every other
/// table's height grows with the execution, so it is chunked and counted.
pub const FIXED_TABLE_COUNT: usize = 5;

/// Number of chunks for each split table.
/// The verifier needs this to reconstruct matching AIRs.
Expand All @@ -104,6 +104,13 @@ pub struct TableCounts {
pub bytewise: usize,
pub store: usize,
pub cpu32: usize,
// Accelerator chips
pub keccak: usize,
pub keccak_rnd: usize,
pub ecsm: usize,
pub ecdas: usize,
pub hint: usize,
pub commit: usize,
}

impl TableCounts {
Expand All @@ -123,6 +130,12 @@ impl TableCounts {
+ self.bytewise
+ self.store
+ self.cpu32
+ self.keccak
+ self.keccak_rnd
+ self.ecsm
+ self.ecdas
+ self.hint
+ self.commit
}

/// Validate that all required tables have at least one chunk.
Expand All @@ -145,6 +158,12 @@ impl TableCounts {
("bytewise", self.bytewise),
("store", self.store),
("cpu32", self.cpu32),
("keccak", self.keccak),
("keccak_rnd", self.keccak_rnd),
("ecsm", self.ecsm),
("ecdas", self.ecdas),
("hint", self.hint),
("commit", self.commit),
];
for (name, count) in checks {
if count == 0 {
Expand Down Expand Up @@ -516,13 +535,13 @@ pub(crate) struct VmAirs {
pub dvrms: Vec<VmAir>,
pub branches: Vec<VmAir>,
pub halt: VmAir,
pub commit: VmAir,
pub keccak: VmAir,
pub keccak_rnd: VmAir,
pub commits: Vec<VmAir>,
pub keccaks: Vec<VmAir>,
pub keccak_rnds: Vec<VmAir>,
pub keccak_rc: VmAir,
pub ecsm: VmAir,
pub ecdas: VmAir,
pub hint: VmAir,
pub ecsms: Vec<VmAir>,
pub ecdases: Vec<VmAir>,
pub hints: Vec<VmAir>,
pub register: VmAir,
pub pages: Vec<VmAir>,
pub memw_registers: Vec<VmAir>,
Expand All @@ -542,18 +561,30 @@ impl VmAirs {
let mut pairs: Vec<AirTracePair<'a>> = vec![
(self.bitwise.as_ref(), &mut traces.bitwise, &()),
(self.decode.as_ref(), &mut traces.decode, &()),
(self.commit.as_ref(), &mut traces.commit, &()),
(self.keccak.as_ref(), &mut traces.keccak, &()),
(self.keccak_rnd.as_ref(), &mut traces.keccak_rnd, &()),
(self.keccak_rc.as_ref(), &mut traces.keccak_rc, &()),
(self.ecsm.as_ref(), &mut traces.ecsm, &()),
(self.ecdas.as_ref(), &mut traces.ecdas, &()),
(self.hint.as_ref(), &mut traces.hint, &()),
(self.register.as_ref(), &mut traces.register, &()),
];
if self.include_halt {
pairs.push((self.halt.as_ref(), &mut traces.halt, &()));
}
for (air, trace) in self.commits.iter().zip(traces.commits.iter_mut()) {
pairs.push((air.as_ref(), trace, &()));
}
for (air, trace) in self.keccaks.iter().zip(traces.keccaks.iter_mut()) {
pairs.push((air.as_ref(), trace, &()));
}
for (air, trace) in self.keccak_rnds.iter().zip(traces.keccak_rnds.iter_mut()) {
pairs.push((air.as_ref(), trace, &()));
}
for (air, trace) in self.ecsms.iter().zip(traces.ecsms.iter_mut()) {
pairs.push((air.as_ref(), trace, &()));
}
for (air, trace) in self.ecdases.iter().zip(traces.ecdases.iter_mut()) {
pairs.push((air.as_ref(), trace, &()));
}
for (air, trace) in self.hints.iter().zip(traces.hints.iter_mut()) {
pairs.push((air.as_ref(), trace, &()));
}

for (air, trace) in self.cpus.iter().zip(traces.cpus.iter_mut()) {
pairs.push((air.as_ref(), trace, &()));
Expand Down Expand Up @@ -617,18 +648,30 @@ impl VmAirs {
let mut refs: Vec<&dyn AIR<Field = F, FieldExtension = E, PublicInputs = ()>> = vec![
self.bitwise.as_ref(),
self.decode.as_ref(),
self.commit.as_ref(),
self.keccak.as_ref(),
self.keccak_rnd.as_ref(),
self.keccak_rc.as_ref(),
self.ecsm.as_ref(),
self.ecdas.as_ref(),
self.hint.as_ref(),
self.register.as_ref(),
];
if self.include_halt {
refs.push(self.halt.as_ref());
}
for air in &self.commits {
refs.push(air.as_ref());
}
for air in &self.keccaks {
refs.push(air.as_ref());
}
for air in &self.keccak_rnds {
refs.push(air.as_ref());
}
for air in &self.ecsms {
refs.push(air.as_ref());
}
for air in &self.ecdases {
refs.push(air.as_ref());
}
for air in &self.hints {
refs.push(air.as_ref());
}

for air in &self.cpus {
refs.push(air.as_ref());
Expand Down Expand Up @@ -786,16 +829,45 @@ impl VmAirs {
})
.collect();
let halt: VmAir = Box::new(create_halt_air(proof_options));
let commit: VmAir = Box::new(create_commit_air(proof_options));
let keccak: VmAir = Box::new(create_keccak_air(proof_options));
let keccak_rnd: VmAir = Box::new(create_keccak_rnd_air(proof_options));
let commits: Vec<_> = (0..table_counts.commit)
.map(|i| {
Box::new(create_commit_air(proof_options).with_name(&format!("COMMIT[{}]", i)))
as VmAir
})
.collect();
let keccaks: Vec<_> = (0..table_counts.keccak)
.map(|i| {
Box::new(create_keccak_air(proof_options).with_name(&format!("KECCAK[{}]", i)))
as VmAir
})
.collect();
let keccak_rnds: Vec<_> = (0..table_counts.keccak_rnd)
.map(|i| {
Box::new(
create_keccak_rnd_air(proof_options).with_name(&format!("KECCAK_RND[{}]", i)),
) as VmAir
})
.collect();
let keccak_rc: VmAir = Box::new(create_keccak_rc_air(proof_options).with_preprocessed(
tables::keccak_rc::preprocessed_commitment(proof_options),
tables::keccak_rc::NUM_PRECOMPUTED_COLS,
));
let ecsm: VmAir = Box::new(create_ecsm_air(proof_options));
let ecdas: VmAir = Box::new(create_ecdas_air(proof_options));
let hint: VmAir = Box::new(create_hint_air(proof_options));
let ecsms: Vec<_> = (0..table_counts.ecsm)
.map(|i| {
Box::new(create_ecsm_air(proof_options).with_name(&format!("ECSM[{}]", i))) as VmAir
})
.collect();
let ecdases: Vec<_> = (0..table_counts.ecdas)
.map(|i| {
Box::new(create_ecdas_air(proof_options).with_name(&format!("ECDAS[{}]", i)))
as VmAir
})
.collect();
let hints: Vec<_> = (0..table_counts.hint)
.map(|i| {
Box::new(create_hint_air(proof_options).with_name(&format!("HINT[{}]", i))) as VmAir
})
.collect();
let register: VmAir =
if let Some((commitment, num_preprocessed_cols)) = register_preprocessed {
Box::new(
Expand Down Expand Up @@ -910,13 +982,13 @@ impl VmAirs {
dvrms,
branches,
halt,
commit,
keccak,
keccak_rnd,
commits,
keccaks,
keccak_rnds,
keccak_rc,
ecsm,
ecdas,
hint,
ecsms,
ecdases,
hints,
register,
pages,
memw_registers,
Expand Down
16 changes: 14 additions & 2 deletions prover/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::test_utils::E;
use crate::{RuntimePageRange, TableCounts};

/// Domain-separation tag. Bump the suffix (`_V2`, ...) on any encoding change.
const DOMAIN_TAG: &[u8] = b"LAMBDAVM_STARK_STATEMENT_V3";
const DOMAIN_TAG: &[u8] = b"LAMBDAVM_STARK_STATEMENT_V4";

/// Canonical full-ELF identity digest — exactly what [`absorb_statement`] binds
/// into the transcript. The recursion attestation folds the same digest into
Expand Down Expand Up @@ -111,6 +111,12 @@ pub(crate) fn absorb_statement_with_digest(
bytewise,
store,
cpu32,
keccak,
keccak_rnd,
ecsm,
ecdas,
hint,
commit,
} = table_counts;
for count in [
cpu,
Expand All @@ -127,6 +133,12 @@ pub(crate) fn absorb_statement_with_digest(
bytewise,
store,
cpu32,
keccak,
keccak_rnd,
ecsm,
ecdas,
hint,
commit,
] {
t.append_bytes(&(count as u64).to_le_bytes());
}
Expand Down Expand Up @@ -155,7 +167,7 @@ pub(crate) fn absorb_statement_with_digest(

/// Continuation domain tags. Distinct from the monolithic `DOMAIN_TAG` so a
/// monolithic proof and a continuation proof can never share a transcript prefix.
const CONTINUATION_EPOCH_TAG: &[u8] = b"LAMBDAVM_CONTINUATION_EPOCH_V2";
const CONTINUATION_EPOCH_TAG: &[u8] = b"LAMBDAVM_CONTINUATION_EPOCH_V3";
const CONTINUATION_GLOBAL_TAG: &[u8] = b"LAMBDAVM_CONTINUATION_GLOBAL_V2";

/// Statement bound into the cross-epoch **global** proof's transcript before
Expand Down
6 changes: 6 additions & 0 deletions prover/src/tables/ecdas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ pub mod cols {
// Operation struct
// =========================================================================

/// Rows one ECSM call can add here, at most: the double-and-add ladder runs at
/// most one double and one add per bit of a 256-bit scalar. Used to bound the
/// table's height when sizing storage, which is why it is an upper bound and
/// not the exact per-call count (that depends on the scalar).
pub const MAX_STEPS_PER_ECSM: usize = 2 * 256;

/// One ECDAS row: a double/add step witness plus its ECALL timestamp.
#[derive(Debug, Clone)]
pub struct EcdasOperation {
Expand Down
6 changes: 5 additions & 1 deletion prover/src/tables/keccak_rnd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ pub mod cols {
// Operation struct
// =========================================================================

/// Trace rows one [`KeccakRoundOperation`] expands into, one per keccak round.
/// Chunking splits on whole operations, so a chunk limit in rows divides by this.
pub const ROUNDS_PER_OP: usize = 24;

/// One keccak permutation call's worth of data (produces 24 rows).
#[derive(Debug, Clone)]
pub struct KeccakRoundOperation {
Expand Down Expand Up @@ -246,7 +250,7 @@ fn hwsl(halfword: u16, shift: u8) -> (u16, u16) {
pub fn generate_keccak_rnd_trace(
ops: &[KeccakRoundOperation],
) -> TraceTable<GoldilocksField, GoldilocksExtension> {
let n_rows = (ops.len() * 24).next_power_of_two().max(4);
let n_rows = (ops.len() * ROUNDS_PER_OP).next_power_of_two().max(4);
let mut trace = TraceTable::new_main(
crate::tables::types::zeroed_fe_vec(n_rows * cols::NUM_COLUMNS),
cols::NUM_COLUMNS,
Expand Down
Loading
Loading