Skip to content

Commit

Permalink
feat: pick changes from zcash#622
Browse files Browse the repository at this point in the history
  • Loading branch information
han0110 committed Sep 4, 2023
1 parent 9dd3a2d commit 115cbce
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 42 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## Minimum Supported Rust Version

Requires Rust **1.56.1** or higher.
Requires Rust **1.65.0** or higher.

Minimum supported Rust version can be changed in the future, but it will be done with a
minor version bump.
Expand Down
6 changes: 5 additions & 1 deletion halo2_proofs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## Minimum Supported Rust Version

Requires Rust **1.56.1** or higher.
Requires Rust **1.65.0** or higher.

Minimum supported Rust version can be changed in the future, but it will be done with a
minor version bump.
Expand All @@ -15,6 +15,10 @@ minor version bump.
computation. The `RAYON_NUM_THREADS` environment variable can be used to set the number of
threads.

You can disable `rayon` by disabling the `"multicore"` feature.
Warning! Halo2 will lose access to parallelism if you disable the `"multicore"` feature.
This will significantly degrade performance.

## License

Licensed under either of
Expand Down
147 changes: 110 additions & 37 deletions halo2_proofs/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ pub struct MockProver<F: Field> {
// The advice cells in the circuit, arranged as [column][row].
advice: Vec<Vec<CellValue<F>>>,
// The instance cells in the circuit, arranged as [column][row].
instance: Vec<Vec<F>>,
instance: Vec<Vec<InstanceValue<F>>>,

selectors: Vec<Vec<bool>>,

Expand All @@ -318,6 +318,21 @@ pub struct MockProver<F: Field> {
current_phase: sealed::Phase,
}

#[derive(Debug, Clone, PartialEq, Eq)]
enum InstanceValue<F: Field> {
Assigned(F),
Padding,
}

impl<F: Field> InstanceValue<F> {
fn value(&self) -> F {
match self {
InstanceValue::Assigned(v) => *v,
InstanceValue::Padding => F::ZERO,
}
}
}

impl<F: Field> MockProver<F> {
fn in_phase<P: Phase>(&self, phase: P) -> bool {
self.current_phase == phase.to_sealed()
Expand Down Expand Up @@ -418,7 +433,7 @@ impl<F: Field> Assignment<F> for MockProver<F> {
.instance
.get(column.index())
.and_then(|column| column.get(row))
.map(|v| circuit::Value::known(*v))
.map(|v| circuit::Value::known(v.value()))
.expect("bound failure"))
}

Expand Down Expand Up @@ -616,7 +631,7 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {

let instance = instance
.into_iter()
.map(|mut instance| {
.map(|instance| {
assert!(
instance.len() <= n - (cs.blinding_factors() + 1),
"instance.len={}, n={}, cs.blinding_factors={}",
Expand All @@ -625,8 +640,12 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
cs.blinding_factors()
);

instance.resize(n, F::ZERO);
instance
let mut instance_values = vec![InstanceValue::Padding; n];
for (idx, value) in instance.into_iter().enumerate() {
instance_values[idx] = InstanceValue::Assigned(value);
}

instance_values
})
.collect::<Vec<_>>();

Expand Down Expand Up @@ -768,17 +787,42 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
// Determine where this cell should have been assigned.
let cell_row = ((gate_row + n + cell.rotation.0) % n) as usize;

// Check that it was assigned!
if r.cells.get(&(cell.column, cell_row)).is_some() {
None
} else {
Some(VerifyFailure::CellNotAssigned {
gate: (gate_index, gate.name()).into(),
region: (r_i, r.name.clone(), r.annotations.clone()).into(),
gate_offset: *selector_row,
column: cell.column,
offset: cell_row as isize - r.rows.unwrap().0 as isize,
})
match cell.column.column_type() {
Any::Instance => {
// Handle instance cells, which are not in the region.
let instance_value =
&self.instance[cell.column.index()][cell_row];
match instance_value {
InstanceValue::Assigned(_) => None,
_ => Some(VerifyFailure::InstanceCellNotAssigned {
gate: (gate_index, gate.name()).into(),
region: (r_i, r.name.clone()).into(),
gate_offset: *selector_row,
column: cell.column.try_into().unwrap(),
row: cell_row,
}),
}
}
_ => {
// Check that it was assigned!
if r.cells.contains_key(&(cell.column, cell_row)) {
None
} else {
Some(VerifyFailure::CellNotAssigned {
gate: (gate_index, gate.name()).into(),
region: (
r_i,
r.name.clone(),
r.annotations.clone(),
)
.into(),
gate_offset: *selector_row,
column: cell.column,
offset: cell_row as isize
- r.rows.unwrap().0 as isize,
})
}
}
}
})
})
Expand Down Expand Up @@ -880,7 +924,8 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
let rotation = query.1 .0;
Value::Real(
self.instance[column_index]
[(row as i32 + n + rotation) as usize % n as usize],
[(row as i32 + n + rotation) as usize % n as usize]
.value(),
)
},
&|challenge| Value::Real(self.challenges[challenge.index()]),
Expand Down Expand Up @@ -1065,7 +1110,10 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
.map(|c: &Column<Any>| match c.column_type() {
Any::Advice(_) => self.advice[c.index()][row],
Any::Fixed => self.fixed[c.index()][row],
Any::Instance => CellValue::Assigned(self.instance[c.index()][row]),
Any::Instance => {
let cell: &InstanceValue<F> = &self.instance[c.index()][row];
CellValue::Assigned(cell.value())
}
})
.unwrap()
};
Expand Down Expand Up @@ -1184,23 +1232,44 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
let cell_row =
((gate_row + n + cell.rotation.0) % n) as usize;

// Check that it was assigned!
if r.cells.contains_key(&(cell.column, cell_row)) {
None
} else {
Some(VerifyFailure::CellNotAssigned {
gate: (gate_index, gate.name()).into(),
region: (
r_i,
r.name.clone(),
r.annotations.clone(),
)
.into(),
gate_offset: *selector_row,
column: cell.column,
offset: cell_row as isize
- r.rows.unwrap().0 as isize,
})
match cell.column.column_type() {
Any::Instance => {
// Handle instance cells, which are not in the region.
let instance_value =
&self.instance[cell.column.index()][cell_row];
match instance_value {
InstanceValue::Assigned(_) => None,
_ => Some(
VerifyFailure::InstanceCellNotAssigned {
gate: (gate_index, gate.name()).into(),
region: (r_i, r.name.clone()).into(),
gate_offset: *selector_row,
column: cell.column.try_into().unwrap(),
row: cell_row,
},
),
}
}
_ => {
// Check that it was assigned!
if r.cells.contains_key(&(cell.column, cell_row)) {
None
} else {
Some(VerifyFailure::CellNotAssigned {
gate: (gate_index, gate.name()).into(),
region: (
r_i,
r.name.clone(),
r.annotations.clone(),
)
.into(),
gate_offset: *selector_row,
column: cell.column,
offset: cell_row as isize
- r.rows.unwrap().0 as isize,
})
}
}
}
})
.collect::<Vec<_>>()
Expand Down Expand Up @@ -1306,7 +1375,8 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
&|query| {
Value::Real(
self.instance[query.column_index]
[(row as i32 + n + query.rotation.0) as usize % n as usize],
[(row as i32 + n + query.rotation.0) as usize % n as usize]
.value(),
)
},
&|challenge| Value::Real(self.challenges[challenge.index()]),
Expand Down Expand Up @@ -1487,7 +1557,10 @@ impl<F: FromUniformBytes<64> + Ord> MockProver<F> {
.map(|c: &Column<Any>| match c.column_type() {
Any::Advice(_) => self.advice[c.index()][row],
Any::Fixed => self.fixed[c.index()][row],
Any::Instance => CellValue::Assigned(self.instance[c.index()][row]),
Any::Instance => {
let cell: &InstanceValue<F> = &self.instance[c.index()][row];
CellValue::Assigned(cell.value())
}
})
.unwrap()
};
Expand Down
27 changes: 27 additions & 0 deletions halo2_proofs/src/dev/failure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,20 @@ pub enum VerifyFailure {
/// offset 0, but the gate uses `Rotation::prev()`).
offset: isize,
},
/// An instance cell used in an active gate was not assigned to.
InstanceCellNotAssigned {
/// The index of the active gate.
gate: metadata::Gate,
/// The region in which this gate was activated.
region: metadata::Region,
/// The offset (relative to the start of the region) at which the active gate
/// queries this cell.
gate_offset: usize,
/// The column in which this cell should be assigned.
column: Column<Instance>,
/// The absolute row at which this cell should be assigned.
row: usize,
},
/// A constraint was not satisfied for a particular row.
ConstraintNotSatisfied {
/// The polynomial constraint that is not satisfied.
Expand Down Expand Up @@ -225,6 +239,19 @@ impl fmt::Display for VerifyFailure {
region, gate, gate_offset, column, offset, region.get_column_annotation((*column).into())
)
}
Self::InstanceCellNotAssigned {
gate,
region,
gate_offset,
column,
row,
} => {
write!(
f,
"{} uses {} at offset {}, which requires cell in instance column {:?} at row {} to be assigned.",
region, gate, gate_offset, column, row
)
}
Self::ConstraintNotSatisfied {
constraint,
location,
Expand Down
7 changes: 4 additions & 3 deletions halo2_proofs/src/dev/util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use group::ff::Field;
use std::collections::BTreeMap;

use super::{metadata, CellValue, Value};
use super::{metadata, CellValue, InstanceValue, Value};
use crate::{
plonk::{
Advice, AdviceQuery, Any, Column, ColumnType, Expression, FixedQuery, Gate, InstanceQuery,
Expand Down Expand Up @@ -88,12 +88,13 @@ pub(super) fn load_instance<'a, F: Field, T: ColumnType, Q: Into<AnyQuery> + Cop
n: i32,
row: i32,
queries: &'a [(Column<T>, Rotation)],
cells: &'a [Vec<F>],
cells: &'a [Vec<InstanceValue<F>>],
) -> impl Fn(Q) -> Value<F> + 'a {
move |query| {
let (column, at) = &queries[query.into().index.unwrap()];
let resolved_row = (row + at.0) % n;
Value::Real(cells[column.index()][resolved_row as usize])
let cell = &cells[column.index()][resolved_row as usize];
Value::Real(cell.value())
}
}

Expand Down

0 comments on commit 115cbce

Please sign in to comment.