Allow halo2 constraint names to have non static names (#156)

* static ref to String type in Gates, Constraints, VirtualCell, Argument

* 'lookup'.to_string()

* return &str for gate name and constriant_name, also run fmt

* Update halo2_gadgets/Cargo.toml

Co-authored-by: Han <tinghan0110@gmail.com>

* upgrade rust-toochain

---------

Co-authored-by: Carlos Pérez <37264926+CPerezz@users.noreply.github.com>
Co-authored-by: Han <tinghan0110@gmail.com>
This commit is contained in:
CeciliaZ030 2023-04-20 23:26:34 +09:00 committed by GitHub
parent 0d56c57a07
commit b739b543d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 79 additions and 61 deletions

View File

@ -586,13 +586,13 @@ mod tests {
assert_eq!(
prover.verify(),
Err(vec![VerifyFailure::Lookup {
name: "lookup",
name: "lookup".to_string(),
lookup_index: 0,
location: FailureLocation::InRegion {
region: (1, "Range check 6 bits").into(),
offset: 1,
},
}])
}]),
);
}
@ -607,7 +607,7 @@ mod tests {
prover.verify(),
Err(vec![
VerifyFailure::Lookup {
name: "lookup",
name: "lookup".to_string(),
lookup_index: 0,
location: FailureLocation::InRegion {
region: (1, "Range check 6 bits").into(),
@ -615,7 +615,7 @@ mod tests {
},
},
VerifyFailure::Lookup {
name: "lookup",
name: "lookup".to_string(),
lookup_index: 0,
location: FailureLocation::InRegion {
region: (1, "Range check 6 bits").into(),
@ -645,7 +645,7 @@ mod tests {
assert_eq!(
prover.verify(),
Err(vec![VerifyFailure::Lookup {
name: "lookup",
name: "lookup".to_string(),
lookup_index: 0,
location: FailureLocation::InRegion {
region: (1, "Range check 6 bits").into(),

View File

@ -986,7 +986,7 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
assert!(table.binary_search(input).is_err());
Some(VerifyFailure::Lookup {
name: lookup.name,
name: lookup.name.clone(),
lookup_index,
location: FailureLocation::find_expressions(
&self.cs,
@ -1347,7 +1347,7 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
.filter_map(move |(input, input_row)| {
if table.binary_search(input).is_err() {
Some(VerifyFailure::Lookup {
name: lookup.name,
name: lookup.name.clone(),
lookup_index,
location: FailureLocation::find_expressions(
&self.cs,
@ -1774,7 +1774,7 @@ mod tests {
assert_eq!(
prover.verify(),
Err(vec![VerifyFailure::Lookup {
name: "lookup",
name: "lookup".to_string(),
lookup_index: 0,
location: FailureLocation::InRegion {
region: (1, "Faulty synthesis").into(),
@ -1908,7 +1908,7 @@ mod tests {
assert_eq!(
prover.verify(),
Err(vec![VerifyFailure::Lookup {
name: "lookup",
name: "lookup".to_string(),
lookup_index: 0,
location: FailureLocation::InRegion {
region: (2, "Faulty synthesis").into(),

View File

@ -159,7 +159,7 @@ pub enum VerifyFailure {
/// A lookup input did not exist in its corresponding table.
Lookup {
/// The name of the lookup that is not satisfied.
name: &'static str,
name: String,
/// The index of the lookup that is not satisfied. These indices are assigned in
/// the order in which `ConstraintSystem::lookup` is called during
/// `Circuit::configure`.
@ -277,7 +277,7 @@ impl Debug for VerifyFailure {
};
let debug = ConstraintCaseDebug {
constraint: *constraint,
constraint: constraint.clone(),
location: location.clone(),
cell_values: cell_values
.iter()

View File

@ -15,14 +15,14 @@ use crate::{
#[derive(Debug)]
struct Constraint {
name: &'static str,
name: String,
expression: String,
queries: BTreeSet<String>,
}
#[derive(Debug)]
struct Gate {
name: &'static str,
name: String,
constraints: Vec<Constraint>,
}
@ -122,13 +122,13 @@ impl CircuitGates {
.gates
.iter()
.map(|gate| Gate {
name: gate.name(),
name: gate.name().to_string(),
constraints: gate
.polynomials()
.iter()
.enumerate()
.map(|(i, constraint)| Constraint {
name: gate.constraint_name(i),
name: gate.constraint_name(i).to_string(),
expression: constraint.evaluate(
&util::format_value,
&|selector| format!("S{}", selector.0),

View File

@ -75,7 +75,7 @@ impl fmt::Display for DebugColumn {
/// within a custom gate.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct VirtualCell {
name: &'static str,
name: String,
pub(super) column: Column,
pub(super) rotation: i32,
}
@ -83,17 +83,17 @@ pub struct VirtualCell {
impl From<(Column, i32)> for VirtualCell {
fn from((column, rotation): (Column, i32)) -> Self {
VirtualCell {
name: "",
name: "".to_string(),
column,
rotation,
}
}
}
impl From<(&'static str, Column, i32)> for VirtualCell {
fn from((name, column, rotation): (&'static str, Column, i32)) -> Self {
impl<S: AsRef<str>> From<(S, Column, i32)> for VirtualCell {
fn from((name, column, rotation): (S, Column, i32)) -> Self {
VirtualCell {
name,
name: name.as_ref().to_string(),
column,
rotation,
}
@ -103,7 +103,7 @@ impl From<(&'static str, Column, i32)> for VirtualCell {
impl From<plonk::VirtualCell> for VirtualCell {
fn from(c: plonk::VirtualCell) -> Self {
VirtualCell {
name: "",
name: "".to_string(),
column: c.column.into(),
rotation: c.rotation.0,
}
@ -114,7 +114,7 @@ impl fmt::Display for VirtualCell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}@{}", self.column, self.rotation)?;
if !self.name.is_empty() {
write!(f, "({})", self.name)?;
write!(f, "({})", self.name.as_str())?;
}
Ok(())
}
@ -123,7 +123,7 @@ impl fmt::Display for VirtualCell {
/// Helper structure used to be able to inject Column annotations inside a `Display` or `Debug` call.
#[derive(Clone, Debug)]
pub(super) struct DebugVirtualCell {
name: &'static str,
name: String,
column: DebugColumn,
rotation: i32,
}
@ -131,7 +131,7 @@ pub(super) struct DebugVirtualCell {
impl From<(&VirtualCell, Option<&HashMap<Column, String>>)> for DebugVirtualCell {
fn from(info: (&VirtualCell, Option<&HashMap<Column, String>>)) -> Self {
DebugVirtualCell {
name: info.0.name,
name: info.0.name.clone(),
column: DebugColumn::from((info.0.column, info.1)),
rotation: info.0.rotation,
}
@ -149,30 +149,33 @@ impl fmt::Display for DebugVirtualCell {
}
/// Metadata about a configured gate within a circuit.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Gate {
/// The index of the active gate. These indices are assigned in the order in which
/// `ConstraintSystem::create_gate` is called during `Circuit::configure`.
pub(super) index: usize,
/// The name of the active gate. These are specified by the gate creator (such as
/// a chip implementation), and is not enforced to be unique.
pub(super) name: &'static str,
pub(super) name: String,
}
impl fmt::Display for Gate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Gate {} ('{}')", self.index, self.name)
write!(f, "Gate {} ('{}')", self.index, self.name.as_str())
}
}
impl From<(usize, &'static str)> for Gate {
fn from((index, name): (usize, &'static str)) -> Self {
Gate { index, name }
impl<S: AsRef<str>> From<(usize, S)> for Gate {
fn from((index, name): (usize, S)) -> Self {
Gate {
index,
name: name.as_ref().to_string(),
}
}
}
/// Metadata about a configured constraint within a circuit.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Constraint {
/// The gate containing the constraint.
pub(super) gate: Gate,
@ -182,7 +185,7 @@ pub struct Constraint {
pub(super) index: usize,
/// The name of the constraint. This is specified by the gate creator (such as a chip
/// implementation), and is not enforced to be unique.
pub(super) name: &'static str,
pub(super) name: String,
}
impl fmt::Display for Constraint {
@ -194,7 +197,7 @@ impl fmt::Display for Constraint {
if self.name.is_empty() {
String::new()
} else {
format!(" ('{}')", self.name)
format!(" ('{}')", self.name.as_str())
},
self.gate.index,
self.gate.name,
@ -202,9 +205,13 @@ impl fmt::Display for Constraint {
}
}
impl From<(Gate, usize, &'static str)> for Constraint {
fn from((gate, index, name): (Gate, usize, &'static str)) -> Self {
Constraint { gate, index, name }
impl<S: AsRef<str>> From<(Gate, usize, S)> for Constraint {
fn from((gate, index, name): (Gate, usize, S)) -> Self {
Constraint {
gate,
index,
name: name.as_ref().to_string(),
}
}
}
@ -250,7 +257,7 @@ impl Debug for Region {
impl fmt::Display for Region {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Region {} ('{}')", self.index, self.name)
write!(f, "Region {} ('{}')", self.index, self.name.as_str())
}
}

View File

@ -1234,25 +1234,34 @@ impl<Col: Into<Column<Any>>> From<(Col, Rotation)> for VirtualCell {
/// These are returned by the closures passed to `ConstraintSystem::create_gate`.
#[derive(Debug)]
pub struct Constraint<F: Field> {
name: &'static str,
name: String,
poly: Expression<F>,
}
impl<F: Field> From<Expression<F>> for Constraint<F> {
fn from(poly: Expression<F>) -> Self {
Constraint { name: "", poly }
Constraint {
name: "".to_string(),
poly,
}
}
}
impl<F: Field> From<(&'static str, Expression<F>)> for Constraint<F> {
fn from((name, poly): (&'static str, Expression<F>)) -> Self {
Constraint { name, poly }
impl<F: Field, S: AsRef<str>> From<(S, Expression<F>)> for Constraint<F> {
fn from((name, poly): (S, Expression<F>)) -> Self {
Constraint {
name: name.as_ref().to_string(),
poly,
}
}
}
impl<F: Field> From<Expression<F>> for Vec<Constraint<F>> {
fn from(poly: Expression<F>) -> Self {
vec![Constraint { name: "", poly }]
vec![Constraint {
name: "".to_string(),
poly,
}]
}
}
@ -1342,8 +1351,8 @@ impl<F: Field, C: Into<Constraint<F>>, Iter: IntoIterator<Item = C>> IntoIterato
/// Gate
#[derive(Clone, Debug)]
pub struct Gate<F: Field> {
name: &'static str,
constraint_names: Vec<&'static str>,
name: String,
constraint_names: Vec<String>,
polys: Vec<Expression<F>>,
/// We track queried selectors separately from other cells, so that we can use them to
/// trigger debug checks on gates.
@ -1352,12 +1361,12 @@ pub struct Gate<F: Field> {
}
impl<F: Field> Gate<F> {
pub(crate) fn name(&self) -> &'static str {
self.name
pub(crate) fn name(&self) -> &str {
self.name.as_str()
}
pub(crate) fn constraint_name(&self, constraint_index: usize) -> &'static str {
self.constraint_names[constraint_index]
pub(crate) fn constraint_name(&self, constraint_index: usize) -> &str {
self.constraint_names[constraint_index].as_str()
}
/// Returns constraints of this gate
@ -1550,9 +1559,9 @@ impl<F: Field> ConstraintSystem<F> {
///
/// `table_map` returns a map between input expressions and the table columns
/// they need to match.
pub fn lookup(
pub fn lookup<S: AsRef<str>>(
&mut self,
name: &'static str,
name: S,
table_map: impl FnOnce(&mut VirtualCells<'_, F>) -> Vec<(Expression<F>, TableColumn)>,
) -> usize {
let mut cells = VirtualCells::new(self);
@ -1571,7 +1580,8 @@ impl<F: Field> ConstraintSystem<F> {
let index = self.lookups.len();
self.lookups.push(lookup::Argument::new(name, table_map));
self.lookups
.push(lookup::Argument::new(name.as_ref(), table_map));
index
}
@ -1580,9 +1590,9 @@ impl<F: Field> ConstraintSystem<F> {
///
/// `table_map` returns a map between input expressions and the table expressions
/// they need to match.
pub fn lookup_any(
pub fn lookup_any<S: AsRef<str>>(
&mut self,
name: &'static str,
name: S,
table_map: impl FnOnce(&mut VirtualCells<'_, F>) -> Vec<(Expression<F>, Expression<F>)>,
) -> usize {
let mut cells = VirtualCells::new(self);
@ -1590,7 +1600,8 @@ impl<F: Field> ConstraintSystem<F> {
let index = self.lookups.len();
self.lookups.push(lookup::Argument::new(name, table_map));
self.lookups
.push(lookup::Argument::new(name.as_ref(), table_map));
index
}
@ -1710,9 +1721,9 @@ impl<F: Field> ConstraintSystem<F> {
///
/// A gate is required to contain polynomial constraints. This method will panic if
/// `constraints` returns an empty iterator.
pub fn create_gate<C: Into<Constraint<F>>, Iter: IntoIterator<Item = C>>(
pub fn create_gate<C: Into<Constraint<F>>, Iter: IntoIterator<Item = C>, S: AsRef<str>>(
&mut self,
name: &'static str,
name: S,
constraints: impl FnOnce(&mut VirtualCells<'_, F>) -> Iter,
) {
let mut cells = VirtualCells::new(self);
@ -1732,7 +1743,7 @@ impl<F: Field> ConstraintSystem<F> {
);
self.gates.push(Gate {
name,
name: name.as_ref().to_string(),
constraint_names,
polys,
queried_selectors,

View File

@ -7,7 +7,7 @@ pub(crate) mod verifier;
#[derive(Clone)]
pub struct Argument<F: Field> {
pub(crate) name: &'static str,
pub(crate) name: String,
pub(crate) input_expressions: Vec<Expression<F>>,
pub(crate) table_expressions: Vec<Expression<F>>,
}
@ -25,10 +25,10 @@ impl<F: Field> Argument<F> {
/// Constructs a new lookup argument.
///
/// `table_map` is a sequence of `(input, table)` tuples.
pub fn new(name: &'static str, table_map: Vec<(Expression<F>, Expression<F>)>) -> Self {
pub fn new<S: AsRef<str>>(name: S, table_map: Vec<(Expression<F>, Expression<F>)>) -> Self {
let (input_expressions, table_expressions) = table_map.into_iter().unzip();
Argument {
name,
name: name.as_ref().to_string(),
input_expressions,
table_expressions,
}