From e942d6dc99ed4d7afd6a0cc715c80b64d1ce671a Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Wed, 8 Nov 2023 19:14:26 +0000 Subject: [PATCH 1/9] fix: importing traces as native values --- src/column.rs | 6 +++--- src/compiler/types.rs | 12 +++++------- src/import.rs | 6 +++--- src/lib.rs | 1 + 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/column.rs b/src/column.rs index 3fc2360..02665d3 100644 --- a/src/column.rs +++ b/src/column.rs @@ -443,7 +443,7 @@ impl From for BigInt { impl Pretty for Value { fn pretty(&self) -> String { match self { - Value::BigInt(i) => format!("ε{}", i), + Value::BigInt(i) => format!("{}", i), Value::Native(f) => f.pretty(), Value::ExoNative(fs) => fs.iter().map(|f| f.pretty()).join("/"), } @@ -453,7 +453,7 @@ impl Pretty for Value { match self { Value::BigInt(i) => { format!( - "ε{}", + "{}", match base { Base::Dec => i.to_str_radix(10), Base::Hex => format!("0x{}", i.to_str_radix(16)), @@ -510,7 +510,7 @@ impl std::cmp::PartialEq for Value { impl std::fmt::Display for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self { - Value::BigInt(i) => write!(f, "ε{}", i), + Value::BigInt(i) => write!(f, "{}", i), Value::Native(fr) => write!(f, "{}", fr.pretty()), Value::ExoNative(fs) => { write!(f, "{:?}", fs.iter().map(|f| f.pretty()).collect::>()) diff --git a/src/compiler/types.rs b/src/compiler/types.rs index b090a69..33b66ca 100755 --- a/src/compiler/types.rs +++ b/src/compiler/types.rs @@ -2,7 +2,7 @@ use anyhow::*; use owo_colors::OwoColorize; use serde::{Deserialize, Serialize}; -use std::cmp::Ordering; +use std::{cmp::Ordering, sync::OnceLock}; use crate::{column::Value, errors::RuntimeError}; @@ -281,10 +281,8 @@ impl TryFrom<&str> for Conditioning { } } -lazy_static::lazy_static! { - static ref F_15: Value = Value::from(15); - static ref F_255: Value = Value::from(255); -} +static F_15: OnceLock = OnceLock::new(); +static F_255: OnceLock = OnceLock::new(); // TODO: implement PartialOrd #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, Ord, PartialOrd)] @@ -331,14 +329,14 @@ impl RawMagma { } } RawMagma::Nibble => { - if x.le(&F_15) { + if x.le(F_15.get_or_init(|| Value::from(15))) { Ok(x) } else { bail!(RuntimeError::InvalidValue("nibble", x)) } } RawMagma::Byte => { - if x.le(&F_255) { + if x.le(F_255.get_or_init(|| Value::from(255))) { Ok(x) } else { bail!(RuntimeError::InvalidValue("byte", x)) diff --git a/src/import.rs b/src/import.rs index 15b50f2..7d3af91 100644 --- a/src/import.rs +++ b/src/import.rs @@ -98,12 +98,12 @@ fn parse_column(xs: &[Value], h: &Handle, t: Magma) -> Result> { .map(|x| match x { Value::Number(n) => t.rm().validate( cache_num - .cache_get_or_set_with(n, || CValue::from_str(&n.to_string()).unwrap()) + .cache_get_or_set_with(n, || CValue::from(n.as_str())) .to_owned(), ), Value::String(s) => t.rm().validate( cache_str - .cache_get_or_set_with(s.clone(), || CValue::from_str(&s).unwrap()) + .cache_get_or_set_with(s.clone(), || CValue::from(s.as_str())) .to_owned(), ), _ => bail!("expected numeric value, found `{}`", x), @@ -137,7 +137,7 @@ fn parse_column(xs: &[Value], h: &Handle, t: Magma) -> Result> { }; t.rm().validate( cache - .cache_get_or_set_with(s.clone(), || CValue::from_str(&s).unwrap()) + .cache_get_or_set_with(s.clone(), || CValue::from(s.as_str())) .to_owned(), ) }) diff --git a/src/lib.rs b/src/lib.rs index 528bb94..cbebd75 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,6 +256,7 @@ fn reverse_fr_x86_64(v: &mut [u64; 4]) { fn make_corset(mut constraints: ConstraintSet) -> Result { transformer::expand_to(&mut constraints, ExpansionLevel::all().into(), &[])?; + transformer::concretize(&mut constraints); Ok(constraints) } From ac8679088247282b84c23bb57ed99dc38e639567 Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Wed, 8 Nov 2023 19:14:43 +0000 Subject: [PATCH 2/9] fix: conditioning of guards --- src/compiler/generator.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/compiler/generator.rs b/src/compiler/generator.rs index 2036561..3c2dd7d 100644 --- a/src/compiler/generator.rs +++ b/src/compiler/generator.rs @@ -19,7 +19,7 @@ use std::sync::atomic::AtomicUsize; use super::node::ColumnRef; use super::tables::{ComputationTable, Scope}; -use super::{common::*, CompileSettings, Expression, Magma, Node, Type}; +use super::{common::*, CompileSettings, Conditioning, Expression, Magma, Node, Type}; use crate::column::{Column, ColumnSet, Computation, RegisterID, Value, ValueBacking}; use crate::compiler::parser::*; use crate::dag::ComputationDag; @@ -1565,7 +1565,12 @@ fn reduce_toplevel( let body = if let Some(guard) = guard { let guard_expr = reduce(guard, &mut ctx, settings)? .with_context(|| anyhow!("guard `{:?}` is empty", guard))?; - Intrinsic::Mul.call(&[guard_expr, body])? + match guard_expr.t().c() { + Conditioning::Loobean => { + bail!("unexpected loobean guard in {}", handle.pretty()) + } + _ => Intrinsic::IfNotZero.call(&[guard_expr, body])?, + } } else { body }; From 35f70eef5f65697b1ebae4bf324e9750350db93d Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Wed, 8 Nov 2023 19:25:36 +0000 Subject: [PATCH 3/9] fix: concretize computations --- src/transformer/concretize.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/transformer/concretize.rs b/src/transformer/concretize.rs index 1d98f34..d8b3523 100644 --- a/src/transformer/concretize.rs +++ b/src/transformer/concretize.rs @@ -1,4 +1,7 @@ -use crate::compiler::{Constraint, ConstraintSet, Expression, Node}; +use crate::{ + column::Computation, + compiler::{Constraint, ConstraintSet, Expression, Node}, +}; use std::str::FromStr; impl Node { @@ -36,6 +39,15 @@ impl ConstraintSet { } } + fn concretize_computations(&mut self) { + for c in self.computations.iter_mut() { + match c { + Computation::Composite { exp, .. } => exp.concretize(), + _ => {} + } + } + } + fn concretize_registers(&mut self) { for r in self.columns.registers.iter_mut() { r.concretize(); @@ -47,4 +59,5 @@ pub fn concretize(cs: &mut ConstraintSet) { *crate::IS_NATIVE.write().unwrap() = true; cs.concretize_registers(); cs.concretize_constraints(); + cs.concretize_computations(); } From 162ec670ae7acf3618581a1970bbb13497c64c9b Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Thu, 9 Nov 2023 07:10:28 +0000 Subject: [PATCH 4/9] fix: escaping function --- src/utils.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index 208ba80..a7bc75c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -53,7 +53,7 @@ pub fn maybe_warn(t: Magma, xs: &[Value], h: &Handle) -> Result<()> { pub fn purify(s: &str) -> String { s.replace( [ - '(', ')', '{', '}', '[', ']', '<', '>', ':', '%', '.', '-', '#', + '(', ')', '{', '}', '[', ']', '<', '>', ':', '%', '.', '-', '#', ' ', ], "_", ) @@ -61,6 +61,7 @@ pub fn purify(s: &str) -> String { .replace('+', "add") .replace('/', "div") .replace('^', "pow") + .replace('~', "norm") .replace('α', "alpha") .replace('β', "beta") .replace('γ', "gamma") From a6eae91053e8ead0316d1e34701bd8dc18bbe6f1 Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Thu, 9 Nov 2023 08:44:22 +0000 Subject: [PATCH 5/9] fix: correctly mark used columns --- src/column.rs | 9 +++++++++ src/compiler/generator.rs | 37 +++++++++++++++++++++++++++++++++-- src/exporters/wizardiop.rs | 5 +---- src/main.rs | 1 - src/transformer/concretize.rs | 1 - src/transformer/inverses.rs | 4 ++-- src/transformer/nhood.rs | 14 ++++++++++--- src/transformer/selectors.rs | 2 +- src/transformer/sort.rs | 16 +++++++-------- src/transformer/splatter.rs | 6 +++--- 10 files changed, 70 insertions(+), 25 deletions(-) diff --git a/src/column.rs b/src/column.rs index 02665d3..8bdc345 100644 --- a/src/column.rs +++ b/src/column.rs @@ -964,6 +964,15 @@ impl ColumnSet { } } + pub(crate) fn mark_used(&mut self, h: &ColumnRef) -> Result<()> { + if let Some(ref mut column) = self.get_col_mut(h) { + column.used = true; + Ok(()) + } else { + bail!("{} can not be found", h.pretty()) + } + } + pub fn get_col_mut(&mut self, h: &ColumnRef) -> Option<&mut Column> { if h.is_id() { self._cols.get_mut(h.as_id()) diff --git a/src/compiler/generator.rs b/src/compiler/generator.rs index 3c2dd7d..8307c8a 100644 --- a/src/compiler/generator.rs +++ b/src/compiler/generator.rs @@ -55,7 +55,6 @@ pub enum Constraint { handle: Handle, from: Vec, to: Vec, - signs: Vec, }, InRange { handle: Handle, @@ -641,6 +640,41 @@ impl ConstraintSet { &self.columns.column(h).unwrap().handle } + pub(crate) fn insert_constraint(&mut self, c: Constraint) { + match &c { + Constraint::Vanishes { expr, .. } => { + for c in expr.dependencies().into_iter() { + self.columns.get_col_mut(&c).unwrap().used = true + } + } + Constraint::Lookup { + including, + included, + .. + } => { + for c in including + .iter() + .flat_map(Node::dependencies) + .chain(included.iter().flat_map(Node::dependencies)) + { + self.columns.mark_used(&c).unwrap(); + } + } + Constraint::Permutation { from, to, .. } => { + for c in from.iter().chain(to.iter()) { + self.columns.mark_used(&c).unwrap(); + } + } + Constraint::InRange { exp, .. } => { + for c in exp.dependencies().into_iter() { + self.columns.mark_used(&c).unwrap(); + } + } + Constraint::Normalization { .. } => {} + } + self.constraints.push(c); + } + pub(crate) fn insert_perspective( &mut self, module: &str, @@ -1744,7 +1778,6 @@ fn reduce_toplevel( ), from: froms, to: tos, - signs: signs.clone(), })) } Token::DefInterleaving { .. } => { diff --git a/src/exporters/wizardiop.rs b/src/exporters/wizardiop.rs index 5c7c38a..bee2d51 100644 --- a/src/exporters/wizardiop.rs +++ b/src/exporters/wizardiop.rs @@ -169,10 +169,7 @@ fn render_constraints(cs: &ConstraintSet) -> Vec { .join(", ") )], Constraint::Permutation { - handle, - from, - to, - signs: _, + handle, from, to, .. } => vec![format!( "build.Permutation(\"{}\", []zkevm.Handle{{{}}}, []zkevm.Handle{{{}}})", handle.mangle().to_case(Case::Snake), diff --git a/src/main.rs b/src/main.rs index d2840eb..d6ca88f 100755 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,6 @@ use compiler::{Ast, ConstraintSet}; use either::Either; use log::*; use owo_colors::OwoColorize; -use std::cell::OnceCell; use std::io::IsTerminal; use std::sync::RwLock; use std::{ diff --git a/src/transformer/concretize.rs b/src/transformer/concretize.rs index d8b3523..2d13f69 100644 --- a/src/transformer/concretize.rs +++ b/src/transformer/concretize.rs @@ -2,7 +2,6 @@ use crate::{ column::Computation, compiler::{Constraint, ConstraintSet, Expression, Node}, }; -use std::str::FromStr; impl Node { pub(crate) fn concretize(&mut self) { diff --git a/src/transformer/inverses.rs b/src/transformer/inverses.rs index 18b791b..1c2f13a 100644 --- a/src/transformer/inverses.rs +++ b/src/transformer/inverses.rs @@ -6,7 +6,7 @@ use crate::{ pretty::Base, structs::Handle, }; -use anyhow::{anyhow, Context, Result}; +use anyhow::*; use super::expression_to_name; @@ -117,7 +117,7 @@ impl ConstraintSet { // exp: invert_expr(&normalized_expr), // }, // )?; - // self.constraints.push(Constraint::Normalization { + // self.insert_constraint(Constraint::Normalization { // handle: normalized_handle.clone(), // reference: normalized_expr.to_owned(), // inverted: inverted_id, diff --git a/src/transformer/nhood.rs b/src/transformer/nhood.rs index 88237a6..83450d7 100644 --- a/src/transformer/nhood.rs +++ b/src/transformer/nhood.rs @@ -65,6 +65,14 @@ fn process_nhood( signs: vec![true], }, )?; + cs.insert_constraint(Constraint::Permutation { + handle: Handle::new( + module, + format!("{} perm. {}", _intrld_aux_xs_id, srt_intrld_aux_xs_id), + ), + from: vec![_intrld_aux_xs_id], + to: vec![srt_intrld_aux_xs_id.clone()], + }); let srt_intrld_aux_xs_node = Node::column() .handle(srt_intrld_aux_xs_id.clone()) @@ -73,13 +81,13 @@ fn process_nhood( .t(Magma::byte()) .build(); - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(module, format!("2^{n}-hood-start")), domain: Some(Domain::Set(vec![0])), expr: Box::new(srt_intrld_aux_xs_node.clone()), }); - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(module, format!("2^{n}-hood-end")), domain: Some(Domain::Set(vec![-1])), expr: Box::new( @@ -94,7 +102,7 @@ fn process_nhood( ), }); - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(module, format!("2^{n}-hood-middle")), domain: None, expr: Box::new(Intrinsic::Mul.call(&[ diff --git a/src/transformer/selectors.rs b/src/transformer/selectors.rs index 2708dbb..66a501e 100644 --- a/src/transformer/selectors.rs +++ b/src/transformer/selectors.rs @@ -89,7 +89,7 @@ pub fn expand_constraints(cs: &mut ConstraintSet) -> Result<()> { } } if !new_cs_exps.is_empty() { - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new("RESERVED", "EXPANSION_CONSTRAINTS"), domain: None, expr: Box::new(Expression::List(new_cs_exps).into()), diff --git a/src/transformer/sort.rs b/src/transformer/sort.rs index fc955db..49654d7 100644 --- a/src/transformer/sort.rs +++ b/src/transformer/sort.rs @@ -99,7 +99,7 @@ fn create_sort_constraint( .collect::>>()?; // Create the binarity constraints - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(&module, format!("{}-is-binary", cs.handle(&eq).name)), domain: None, expr: Box::new(Intrinsic::Mul.call(&[ @@ -111,7 +111,7 @@ fn create_sort_constraint( ])?), }); for at in ats.iter() { - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(&module, format!("{}-is-binary", cs.handle(at).name)), domain: None, expr: Box::new(Intrinsic::Mul.call(&[ @@ -125,7 +125,7 @@ fn create_sort_constraint( } // Create the byte decomposition constraint - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(&module, format!("{}-is-binary", cs.handle(&delta).name)), domain: None, expr: Box::new( @@ -152,7 +152,7 @@ fn create_sort_constraint( // Create the bytehood constraints for delta_byte in delta_bytes.iter() { - cs.constraints.push(Constraint::InRange { + cs.insert_constraint(Constraint::InRange { handle: Handle::new(&module, format!("{}-is-byte", cs.handle(delta_byte).name)), exp: Node::column() .handle(delta_byte.clone()) @@ -185,7 +185,7 @@ fn create_sort_constraint( }; let sorted_t = cs.columns.column(&sorted[i])?.t; - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(&module, format!("{at}-0")), domain: None, expr: Box::new( @@ -209,7 +209,7 @@ fn create_sort_constraint( ])?, ), }); - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(&module, format!("{at}-1")), domain: None, expr: Box::new(Intrinsic::Mul.call(&[ @@ -235,7 +235,7 @@ fn create_sort_constraint( } // // Create the Eq + ∑@ = 1 (i.e. Eq = 1 XOR ∑@ = 1) - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(&module, format!("Eq_@_{suffix}")), domain: None, expr: Box::new( @@ -255,7 +255,7 @@ fn create_sort_constraint( }); // // Create the Eq[i] = 0 constraint - cs.constraints.push(Constraint::Vanishes { + cs.insert_constraint(Constraint::Vanishes { handle: Handle::new(&module, format!("__SRT__Eq_i_{suffix}")), domain: None, expr: Box::new( diff --git a/src/transformer/splatter.rs b/src/transformer/splatter.rs index bf25dbf..f65a9b1 100644 --- a/src/transformer/splatter.rs +++ b/src/transformer/splatter.rs @@ -260,7 +260,7 @@ impl ConstraintSet { } } - self.make_ancillaries(ancillaries); + // self.make_ancillaries(ancillaries); for (new_column, new_computation) in new_constants { let id = self.columns.insert_column_and_register(new_column).unwrap(); @@ -296,7 +296,7 @@ impl ConstraintSet { match func { ExoOperation::Add | ExoOperation::Sub => { let module = ADDER_MODULE; - self.constraints.push(Constraint::Lookup { + self.insert_constraint(Constraint::Lookup { handle: Handle::new(module, &new_handle.name), including: vec![ Node::column() @@ -331,7 +331,7 @@ impl ConstraintSet { } ExoOperation::Mul => { let module = MULER_MODULE; - self.constraints.push(Constraint::Lookup { + self.insert_constraint(Constraint::Lookup { handle: Handle::new(module, &new_handle.name), including: vec![ Node::column() From 8b0b7304f77dc74d59f0d9c765566f3ee1a4aa4b Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Thu, 9 Nov 2023 08:44:50 +0000 Subject: [PATCH 6/9] fix[debug]: render permutations & domains --- src/exporters/debugger.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/exporters/debugger.rs b/src/exporters/debugger.rs index 0cd9200..3bce797 100644 --- a/src/exporters/debugger.rs +++ b/src/exporters/debugger.rs @@ -195,11 +195,19 @@ fn render_constraints( match c { Constraint::Vanishes { handle, - domain: _, + domain, expr, } => { let mut tty = Tty::new().with_guides(); - println!("\n{} :=", handle.pretty()); + println!( + "\n{}{} :=", + handle.pretty(), + if let Some(domain) = domain { + domain.to_string() + } else { + String::new() + } + ); pretty_expr(expr, None, &mut tty, show_types); println!("{}", tty.page_feed()); } @@ -223,7 +231,16 @@ fn render_constraints( .join(", "), ) } - Constraint::Permutation { .. } => (), + Constraint::Permutation { + handle, from, to, .. + } => { + println!("\n{}", handle.pretty()); + println!( + "[{}] perm. [{}]", + to.iter().map(|c| c.pretty()).join(", "), + from.iter().map(|c| c.pretty()).join(", ") + ) + } Constraint::InRange { handle, exp, max } => { let mut tty = Tty::new().with_guides(); pretty_expr(exp, None, &mut tty, false); From 88c54c1012e84cbd38e593040a8787b2e865f60a Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Thu, 9 Nov 2023 08:53:55 +0000 Subject: [PATCH 7/9] fix[lib]: apply all auto-constraints --- src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cbebd75..cec09e8 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ use std::{ ffi::{c_uint, CStr, CString}, sync::RwLock, }; -use transformer::ExpansionLevel; +use transformer::{AutoConstraint, ExpansionLevel}; use crate::{ column::{Computation, Value, ValueBacking}, @@ -255,7 +255,11 @@ fn reverse_fr_x86_64(v: &mut [u64; 4]) { } fn make_corset(mut constraints: ConstraintSet) -> Result { - transformer::expand_to(&mut constraints, ExpansionLevel::all().into(), &[])?; + transformer::expand_to( + &mut constraints, + ExpansionLevel::all().into(), + AutoConstraint::all(), + )?; transformer::concretize(&mut constraints); Ok(constraints) } From a55d2400aed8b5437717ce72219d9382aedb140a Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Thu, 9 Nov 2023 09:39:26 +0000 Subject: [PATCH 8/9] fix: adapt default Value to native/non-native --- src/column.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/column.rs b/src/column.rs index 8bdc345..5ed464e 100644 --- a/src/column.rs +++ b/src/column.rs @@ -376,7 +376,7 @@ impl Value { // } impl std::default::Default for Value { fn default() -> Value { - Value::BigInt(BigInt::zero()) + Value::zero() } } impl From for Value { From 8bd7937c78761c27cbffa94da8005bd56b82ab70 Mon Sep 17 00:00:00 2001 From: Franklin Delehelle Date: Thu, 9 Nov 2023 16:01:11 +0000 Subject: [PATCH 9/9] fix: columns import/export for BLS --- src/column.rs | 40 +++++++------- src/compiler/generator.rs | 3 +- src/compiler/node.rs | 16 +++++- src/import.rs | 35 +++++++------ src/lib.rs | 106 ++++++++------------------------------ src/pretty/mod.rs | 6 ++- src/utils.rs | 13 +++++ 7 files changed, 94 insertions(+), 125 deletions(-) diff --git a/src/column.rs b/src/column.rs index 5ed464e..457e939 100644 --- a/src/column.rs +++ b/src/column.rs @@ -220,23 +220,11 @@ impl Value { } } - pub(crate) fn to_repr(&self) -> impl Iterator { - let us = match &self { - Value::Native(f) => f.0 .0.to_vec(), - Value::ExoNative(fs) => fs.iter().flat_map(|f| f.0 .0.iter()).cloned().collect(), - Value::BigInt(_) => todo!(), - }; - us.into_iter() - } - pub(crate) fn to_bytes(&self) -> Vec { match &self { - Value::Native(f) => f.0 .0.iter().flat_map(|u| u.to_be_bytes()).collect(), - Value::ExoNative(fs) => fs - .iter() - .flat_map(|f| f.0 .0.iter().flat_map(|u| u.to_be_bytes())) - .collect(), Value::BigInt(bi) => bi.to_bytes_be().1, + Value::Native(f) => f.into_bigint().to_bytes_be(), + Value::ExoNative(_) => todo!(), } } @@ -649,8 +637,8 @@ impl ValueBacking { } } .cloned(), - ValueBacking::Expression { e, spilling } => e.eval( - i + spilling, + ValueBacking::Expression { e, .. } => e.eval( + i, |handle, j, _| { cs.get(handle, j, false) .or_else(|| cs.column(handle).unwrap().padding_value.as_ref().cloned()) @@ -658,7 +646,7 @@ impl ValueBacking { &mut None, &EvalSettings { wrap: false }, ), - ValueBacking::Function { f, spilling } => f(i + spilling, cs), + ValueBacking::Function { f, .. } => f(i, cs), } } @@ -689,10 +677,11 @@ impl ValueBacking { } } - pub fn iter<'a>(&'a self, columns: &'a ColumnSet) -> ValueBackingIter<'a> { + pub fn iter<'a>(&'a self, columns: &'a ColumnSet, len: isize) -> ValueBackingIter<'a> { ValueBackingIter { value: self, i: 0, + len, columns, } } @@ -724,6 +713,7 @@ impl ValueBacking { pub struct ValueBackingIter<'a> { value: &'a ValueBacking, columns: &'a ColumnSet, + len: isize, i: isize, } @@ -741,9 +731,17 @@ impl<'a> Iterator for ValueBackingIter<'a> { v.get(self.i as usize).cloned() } } - ValueBacking::Expression { .. } => { - self.i += 1; - self.value.get_raw(self.i - 1, false, self.columns) + ValueBacking::Expression { spilling, .. } => { + if self.i >= self.len { + None + } else { + self.i += 1; + Some( + self.value + .get(self.i - 1, false, self.columns) + .unwrap_or_default(), + ) + } } ValueBacking::Function { f, .. } => { self.i += 1; diff --git a/src/compiler/generator.rs b/src/compiler/generator.rs index 8307c8a..6216a1d 100644 --- a/src/compiler/generator.rs +++ b/src/compiler/generator.rs @@ -873,6 +873,7 @@ impl ConstraintSet { let empty_backing: ValueBacking = ValueBacking::default(); while let Some((r, column)) = current_col.next() { let handle = &column.handle; + let module_size = self.effective_len_for(&handle.module).unwrap(); trace!("Writing {}", handle); let backing = self.columns.backing(&r).unwrap_or_else(|| &empty_backing); let padding: Value = if let Some(v) = column.padding_value.as_ref() { @@ -904,7 +905,7 @@ impl ConstraintSet { out.write_all(format!("\"{}\":{{\n", handle).as_bytes())?; out.write_all("\"values\":[".as_bytes())?; - let mut value = backing.iter(&self.columns).peekable(); + let mut value = backing.iter(&self.columns, module_size).peekable(); while let Some(x) = value.next() { out.write_all( cache diff --git a/src/compiler/node.rs b/src/compiler/node.rs index 609ed19..0fc7d0d 100644 --- a/src/compiler/node.rs +++ b/src/compiler/node.rs @@ -995,8 +995,20 @@ impl Display for Node { match self.e() { Expression::Const(x) => write!(f, "{}", x), - Expression::Column { handle, .. } | Expression::ExoColumn { handle, .. } => { - write!(f, "{}", handle.to_string_short()) + Expression::Column { handle, shift, .. } + | Expression::ExoColumn { handle, shift, .. } => { + write!( + f, + "{}{}", + handle.to_string_short(), + if *shift > 0 { + format!("₊{}", crate::pretty::subscript(&shift.to_string())) + } else if *shift < 0 { + crate::pretty::subscript(&shift.to_string()) + } else { + Default::default() + } + ) } Expression::ArrayColumn { handle, domain, .. } => { write!(f, "{}{}", handle.to_string_short(), domain) diff --git a/src/import.rs b/src/import.rs index 7d3af91..51a76d1 100644 --- a/src/import.rs +++ b/src/import.rs @@ -175,8 +175,6 @@ pub fn fill_traces( if path.len() >= 2 { let module = path[path.len() - 2].to_string(); let handle: ColumnRef = Handle::new(&module, &path[path.len() - 1]).into(); - // The first column sets the size of its module - let module_raw_size = cs.effective_len_or_set(&module, xs.len() as isize); // The min length can be set if the module contains range // proofs, that require a minimal length of a certain power of 2 @@ -197,16 +195,6 @@ pub fn fill_traces( let module_spilling = module_spilling .ok_or_else(|| anyhow!("no spilling found for {}", handle.pretty()))?; - if xs.len() as isize != module_raw_size { - bail!( - "{} has an incorrect length: expected {} (from {}), found {}", - handle.to_string().blue(), - module_raw_size.to_string().red().bold(), - initiator.as_ref().unwrap(), - xs.len().to_string().yellow().bold(), - ); - } - let mut xs = parse_column(xs, handle.as_handle(), *t) .with_context(|| anyhow!("while importing {}", handle))?; @@ -222,11 +210,9 @@ pub fn fill_traces( }); xs.reverse(); } - cs.columns.set_column_value(&handle, xs, module_spilling)? - } else if let Some(Register { magma, .. }) = cs.columns.register(&handle) { - let module_spilling = module_spilling - .ok_or_else(|| anyhow!("no spilling found for {}", handle.pretty()))?; + // The first column sets the size of its module + let module_raw_size = cs.effective_len_or_set(&module, xs.len() as isize); if xs.len() as isize != module_raw_size { bail!( "{} has an incorrect length: expected {} (from {}), found {}", @@ -237,6 +223,11 @@ pub fn fill_traces( ); } + cs.columns.set_column_value(&handle, xs, module_spilling)? + } else if let Some(Register { magma, .. }) = cs.columns.register(&handle) { + let module_spilling = module_spilling + .ok_or_else(|| anyhow!("no spilling found for {}", handle.pretty()))?; + let mut xs = parse_column(xs, handle.as_handle(), *magma) .with_context(|| anyhow!("while importing {}", handle))?; @@ -250,6 +241,18 @@ pub fn fill_traces( xs.resize(module_min_len, CValue::zero()); // TODO: register padding values xs.reverse(); } + + let module_raw_size = cs.effective_len_or_set(&module, xs.len() as isize); + if xs.len() as isize != module_raw_size { + bail!( + "{} has an incorrect length: expected {} (from {}), found {}", + handle.to_string().blue(), + module_raw_size.to_string().red().bold(), + initiator.as_ref().unwrap(), + xs.len().to_string().yellow().bold(), + ); + } + cs.columns .set_register_value(&handle, xs, module_spilling)? } else { diff --git a/src/lib.rs b/src/lib.rs index cec09e8..47db7b7 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,10 +94,13 @@ fn cstr_to_string<'a>(s: *const c_char) -> &'a str { name.to_str().unwrap() } -const EMPTY_MARKER: [u64; 4] = [0, u64::MAX, 0, u64::MAX]; +const EMPTY_MARKER: [u8; 32] = [ + 2, 4, 8, 16, 32, 64, 128, 255, 255, 128, 64, 32, 16, 8, 4, 2, 2, 4, 8, 16, 32, 64, 128, 255, + 255, 128, 64, 32, 16, 8, 4, 2, +]; struct ComputedColumn { - padding_value: [u64; 4], - values: Vec<[u64; 4]>, + padding_value: [u8; 32], + values: Vec<[u8; 32]>, } impl ComputedColumn { fn empty() -> Self { @@ -118,7 +121,7 @@ pub struct Trace { ids: Vec, } impl Trace { - fn from_constraints(c: &Corset, convert_to_be: bool) -> Self { + fn from_constraints(c: &Corset) -> Self { let mut r = Trace { ..Default::default() }; @@ -132,6 +135,11 @@ impl Trace { let column = c.columns.column(cref).unwrap(); let handle = &column.handle; + let module_size = c + .effective_len_for(&handle.module) + // If the module is empty, use its spilling + .or_else(|| c.spilling_of(&handle.module)) + .unwrap(); trace!("Writing {}", handle); let backing = c.columns.backing(cref).unwrap_or(&empty_backing); let padding: Value = if let Some(v) = column.padding_value.as_ref() { @@ -162,23 +170,10 @@ impl Trace { ( ComputedColumn { values: backing - .iter(&c.columns) - .map(|x| { - let mut v = x.to_repr().collect::>().try_into().unwrap(); - if convert_to_be { - reverse_fr(&mut v); - } - v - }) + .iter(&c.columns, module_size) + .map(|x| x.to_bytes().try_into().unwrap()) .collect(), - padding_value: { - let mut padding = - padding.to_repr().collect::>().try_into().unwrap(); - if convert_to_be { - reverse_fr(&mut padding); - } - padding - }, + padding_value: { padding.to_bytes().try_into().unwrap() }, }, c.handle(cref).to_string(), ) @@ -204,56 +199,6 @@ impl Trace { } } -fn reverse_fr(v: &mut [u64; 4]) { - #[cfg(target_arch = "aarch64")] - reverse_fr_aarch64(v); - #[cfg(target_arch = "x86_64")] - reverse_fr_x86_64(v); - #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))] - reverse_fr_fallback(v); -} - -fn reverse_fr_fallback(v: &mut [u64; 4]) { - for vi in v.iter_mut() { - *vi = vi.swap_bytes(); - } - v.swap(0, 3); - v.swap(1, 2); -} - -#[cfg(target_arch = "aarch64")] -fn reverse_fr_aarch64(v: &mut [u64; 4]) { - for vi in v.iter_mut() { - *vi = vi.swap_bytes(); - } - v.swap(0, 3); - v.swap(1, 2); -} - -#[cfg(target_arch = "x86_64")] -fn reverse_fr_x86_64(v: &mut [u64; 4]) { - if is_x86_feature_detected!("avx2") { - unsafe { - use std::arch::x86_64::*; - let inverter = _mm256_set_epi64x( - 0x0001020304050607, - 0x08090a0b0c0d0e0f, - 0x0001020304050607, - 0x08090a0b0c0d0e0f, - ); - let value = _mm256_loadu_si256(v.as_ptr() as *const __m256i); - let x = _mm256_shuffle_epi8(value, inverter); - *v = std::mem::transmute(_mm256_permute2f128_si256(x, x, 0x01)); - } - } else { - for vi in v.iter_mut() { - *vi = vi.swap_bytes(); - } - v.swap(0, 3); - v.swap(1, 2); - } -} - fn make_corset(mut constraints: ConstraintSet) -> Result { transformer::expand_to( &mut constraints, @@ -284,23 +229,21 @@ fn _corset_from_str(zkevmstr: &str) -> Result { fn _compute_trace_from_file( constraints: &mut Corset, tracefile: &str, - convert_to_be: bool, fail_on_missing: bool, ) -> Result { compute::compute_trace(tracefile, constraints, fail_on_missing) .with_context(|| format!("while computing from file `{}`", tracefile))?; - Ok(Trace::from_constraints(constraints, convert_to_be)) + Ok(Trace::from_constraints(constraints)) } fn _compute_trace_from_str( constraints: &mut Corset, tracestr: &str, - convert_to_be: bool, fail_on_missing: bool, ) -> Result { compute::compute_trace_str(tracestr.as_bytes(), constraints, fail_on_missing) .with_context(|| format!("while computing from string `{}`", tracestr))?; - Ok(Trace::from_constraints(constraints, convert_to_be)) + Ok(Trace::from_constraints(constraints)) } #[no_mangle] @@ -415,16 +358,14 @@ pub extern "C" fn trace_compute_from_file( corset: *mut Corset, tracefile: *const c_char, threads: c_uint, - convert_to_be: bool, fail_on_missing: bool, ) -> *mut Trace { match init_rayon(threads) { Result::Ok(tp) => { let tracefile = cstr_to_string(tracefile); let constraints = Corset::mut_from_ptr(corset); - let r = tp.install(|| { - _compute_trace_from_file(constraints, tracefile, convert_to_be, fail_on_missing) - }); + let r = + tp.install(|| _compute_trace_from_file(constraints, tracefile, fail_on_missing)); match r { Err(e) => { eprintln!("{:?}", e); @@ -446,7 +387,6 @@ pub extern "C" fn trace_compute_from_string( corset: *mut Corset, tracestr: *const c_char, threads: c_uint, - convert_to_be: bool, fail_on_missing: bool, ) -> *mut Trace { match init_rayon(threads) { @@ -458,9 +398,7 @@ pub extern "C" fn trace_compute_from_string( } let constraints = Corset::mut_from_ptr(corset); - let r = tp.install(|| { - _compute_trace_from_str(constraints, tracestr, convert_to_be, fail_on_missing) - }); + let r = tp.install(|| _compute_trace_from_str(constraints, tracestr, fail_on_missing)); match r { Err(e) => { eprintln!("{:?}", e); @@ -510,8 +448,8 @@ pub extern "C" fn trace_column_names(trace: *const Trace) -> *const *mut c_char #[repr(C)] pub struct ColumnData { - padding_value: [u64; 4], - values: *const [u64; 4], + padding_value: [u8; 32], + values: *const [u8; 32], values_len: u64, } impl Default for ColumnData { diff --git a/src/pretty/mod.rs b/src/pretty/mod.rs index 0738b40..ccb0119 100644 --- a/src/pretty/mod.rs +++ b/src/pretty/mod.rs @@ -87,7 +87,11 @@ fn to_byte(f: &Fr) -> Option { impl Pretty for Fr { fn pretty(&self) -> String { - format!("{}", self) + if self.is_zero() { + "0".into() + } else { + format!("{}", self) + } } fn pretty_with_base(&self, base: Base) -> String { diff --git a/src/utils.rs b/src/utils.rs index a7bc75c..3acc696 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -72,5 +72,18 @@ pub fn purify(s: &str) -> String { .replace('μ', "mu") .replace('ν', "nu") .replace('∅', "empty") + .replace('ₐ', "a") + .replace('ₑ', "e") + .replace('ₓ', "x") + .replace('₀', "0") + .replace('₁', "1") + .replace('₂', "2") + .replace('₃', "3") + .replace('₄', "4") + .replace('₅', "5") + .replace('₆', "6") + .replace('₇', "7") + .replace('₈', "8") + .replace('₉', "9") .replace(|c: char| !c.is_ascii(), "_") }