mirror of https://github.com/zcash/halo2.git
commit
cd5522496a
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -6,6 +6,17 @@ and this project adheres to Rust's notion of
|
||||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Changed
|
||||||
|
- `halo2::plonk::Error` has been overhauled:
|
||||||
|
- `Error` now implements `std::fmt::Display` and `std::error::Error`.
|
||||||
|
- `Error` no longer implements `PartialEq`. Tests can check for specific error
|
||||||
|
cases with `assert!(matches!(..))`.
|
||||||
|
- `Error::IncompatibleParams` is now `Error::InvalidInstances`.
|
||||||
|
- `Error::OpeningError` is now `Error::Opening`.
|
||||||
|
- `Error::SynthesisError` is now `Error::Synthesis`.
|
||||||
|
- `Error::TranscriptError` is now `Error::Transcript`, and stores the
|
||||||
|
underlying `io::Error`.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- `halo2::arithmetic::BatchInvert` (use `ff::BatchInvert` instead).
|
- `halo2::arithmetic::BatchInvert` (use `ff::BatchInvert` instead).
|
||||||
|
|
||||||
|
|
|
@ -90,20 +90,20 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
||||||
0,
|
0,
|
||||||
|| {
|
|| {
|
||||||
value = Some(f()?);
|
value = Some(f()?);
|
||||||
Ok(value.ok_or(Error::SynthesisError)?.0)
|
Ok(value.ok_or(Error::Synthesis)?.0)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
self.config.b,
|
self.config.b,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1),
|
|| Ok(value.ok_or(Error::Synthesis)?.1),
|
||||||
)?;
|
)?;
|
||||||
let out = region.assign_advice(
|
let out = region.assign_advice(
|
||||||
|| "out",
|
|| "out",
|
||||||
self.config.c,
|
self.config.c,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.2),
|
|| Ok(value.ok_or(Error::Synthesis)?.2),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::zero()))?;
|
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::zero()))?;
|
||||||
|
@ -132,20 +132,20 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
||||||
0,
|
0,
|
||||||
|| {
|
|| {
|
||||||
value = Some(f()?);
|
value = Some(f()?);
|
||||||
Ok(value.ok_or(Error::SynthesisError)?.0)
|
Ok(value.ok_or(Error::Synthesis)?.0)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
self.config.b,
|
self.config.b,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1),
|
|| Ok(value.ok_or(Error::Synthesis)?.1),
|
||||||
)?;
|
)?;
|
||||||
let out = region.assign_advice(
|
let out = region.assign_advice(
|
||||||
|| "out",
|
|| "out",
|
||||||
self.config.c,
|
self.config.c,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.2),
|
|| Ok(value.ok_or(Error::Synthesis)?.2),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::one()))?;
|
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::one()))?;
|
||||||
|
@ -226,17 +226,17 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
||||||
let (a0, _, c0) = cs.raw_multiply(&mut layouter, || {
|
let (a0, _, c0) = cs.raw_multiply(&mut layouter, || {
|
||||||
a_squared = self.a.map(|a| a.square());
|
a_squared = self.a.map(|a| a.square());
|
||||||
Ok((
|
Ok((
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
a_squared.ok_or(Error::SynthesisError)?,
|
a_squared.ok_or(Error::Synthesis)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let (a1, b1, _) = cs.raw_add(&mut layouter, || {
|
let (a1, b1, _) = cs.raw_add(&mut layouter, || {
|
||||||
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
||||||
Ok((
|
Ok((
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
a_squared.ok_or(Error::SynthesisError)?,
|
a_squared.ok_or(Error::Synthesis)?,
|
||||||
fin.ok_or(Error::SynthesisError)?,
|
fin.ok_or(Error::Synthesis)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
cs.copy(&mut layouter, a0, a1)?;
|
cs.copy(&mut layouter, a0, a1)?;
|
||||||
|
|
|
@ -16,6 +16,11 @@ granular error messages that indicate which specific constraint (if any) is not
|
||||||
The `dev-graph` feature flag exposes several helper methods for creating graphical
|
The `dev-graph` feature flag exposes several helper methods for creating graphical
|
||||||
representations of circuits.
|
representations of circuits.
|
||||||
|
|
||||||
|
On Debian systems, you will need the following additional packages:
|
||||||
|
```plaintext
|
||||||
|
sudo apt install cmake libexpat1-dev libfreetype6-dev
|
||||||
|
```
|
||||||
|
|
||||||
### Circuit layout
|
### Circuit layout
|
||||||
|
|
||||||
`halo2::dev::CircuitLayout` renders the circuit layout as a grid:
|
`halo2::dev::CircuitLayout` renders the circuit layout as a grid:
|
||||||
|
|
|
@ -72,32 +72,32 @@ impl<FF: FieldExt> StandardCs<FF> for StandardPlonk<FF> {
|
||||||
0,
|
0,
|
||||||
|| {
|
|| {
|
||||||
value = Some(f()?);
|
value = Some(f()?);
|
||||||
Ok(value.ok_or(Error::SynthesisError)?.0)
|
Ok(value.ok_or(Error::Synthesis)?.0)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "lhs^4",
|
|| "lhs^4",
|
||||||
self.config.d,
|
self.config.d,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.0.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.0.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
self.config.b,
|
self.config.b,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1),
|
|| Ok(value.ok_or(Error::Synthesis)?.1),
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "rhs^4",
|
|| "rhs^4",
|
||||||
self.config.e,
|
self.config.e,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.1.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let out = region.assign_advice(
|
let out = region.assign_advice(
|
||||||
|| "out",
|
|| "out",
|
||||||
self.config.c,
|
self.config.c,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.2),
|
|| Ok(value.ok_or(Error::Synthesis)?.2),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::zero()))?;
|
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::zero()))?;
|
||||||
|
@ -117,32 +117,32 @@ impl<FF: FieldExt> StandardCs<FF> for StandardPlonk<FF> {
|
||||||
0,
|
0,
|
||||||
|| {
|
|| {
|
||||||
value = Some(f()?);
|
value = Some(f()?);
|
||||||
Ok(value.ok_or(Error::SynthesisError)?.0)
|
Ok(value.ok_or(Error::Synthesis)?.0)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "lhs^4",
|
|| "lhs^4",
|
||||||
self.config.d,
|
self.config.d,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.0.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.0.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
self.config.b,
|
self.config.b,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1),
|
|| Ok(value.ok_or(Error::Synthesis)?.1),
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "rhs^4",
|
|| "rhs^4",
|
||||||
self.config.e,
|
self.config.e,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.1.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let out = region.assign_advice(
|
let out = region.assign_advice(
|
||||||
|| "out",
|
|| "out",
|
||||||
self.config.c,
|
self.config.c,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.2),
|
|| Ok(value.ok_or(Error::Synthesis)?.2),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::one()))?;
|
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::one()))?;
|
||||||
|
@ -259,17 +259,17 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
||||||
let (a0, _, c0) = cs.raw_multiply(&mut region, || {
|
let (a0, _, c0) = cs.raw_multiply(&mut region, || {
|
||||||
a_squared = self.a.map(|a| a.square());
|
a_squared = self.a.map(|a| a.square());
|
||||||
Ok((
|
Ok((
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
a_squared.ok_or(Error::SynthesisError)?,
|
a_squared.ok_or(Error::Synthesis)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let (a1, b1, _) = cs.raw_add(&mut region, || {
|
let (a1, b1, _) = cs.raw_add(&mut region, || {
|
||||||
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
||||||
Ok((
|
Ok((
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
a_squared.ok_or(Error::SynthesisError)?,
|
a_squared.ok_or(Error::Synthesis)?,
|
||||||
fin.ok_or(Error::SynthesisError)?,
|
fin.ok_or(Error::Synthesis)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
cs.copy(&mut region, a0, a1)?;
|
cs.copy(&mut region, a0, a1)?;
|
||||||
|
|
|
@ -172,7 +172,7 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
|
||||||
|| "private input",
|
|| "private input",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
0,
|
0,
|
||||||
|| value.ok_or(Error::SynthesisError),
|
|| value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
num = Some(Number { cell, value });
|
num = Some(Number { cell, value });
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -233,13 +233,13 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
|
||||||
|| "lhs",
|
|| "lhs",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
0,
|
0,
|
||||||
|| a.value.ok_or(Error::SynthesisError),
|
|| a.value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
config.advice[1],
|
config.advice[1],
|
||||||
0,
|
0,
|
||||||
|| b.value.ok_or(Error::SynthesisError),
|
|| b.value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
region.constrain_equal(a.cell, lhs)?;
|
region.constrain_equal(a.cell, lhs)?;
|
||||||
region.constrain_equal(b.cell, rhs)?;
|
region.constrain_equal(b.cell, rhs)?;
|
||||||
|
@ -250,7 +250,7 @@ impl<F: FieldExt> NumericInstructions<F> for FieldChip<F> {
|
||||||
|| "lhs * rhs",
|
|| "lhs * rhs",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
1,
|
1,
|
||||||
|| value.ok_or(Error::SynthesisError),
|
|| value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Finally, we return a variable representing the output,
|
// Finally, we return a variable representing the output,
|
||||||
|
|
|
@ -222,13 +222,13 @@ impl<F: FieldExt> AddInstructions<F> for AddChip<F> {
|
||||||
|| "lhs",
|
|| "lhs",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
0,
|
0,
|
||||||
|| a.value.ok_or(Error::SynthesisError),
|
|| a.value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
config.advice[1],
|
config.advice[1],
|
||||||
0,
|
0,
|
||||||
|| b.value.ok_or(Error::SynthesisError),
|
|| b.value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
region.constrain_equal(a.cell, lhs)?;
|
region.constrain_equal(a.cell, lhs)?;
|
||||||
region.constrain_equal(b.cell, rhs)?;
|
region.constrain_equal(b.cell, rhs)?;
|
||||||
|
@ -239,7 +239,7 @@ impl<F: FieldExt> AddInstructions<F> for AddChip<F> {
|
||||||
|| "lhs * rhs",
|
|| "lhs * rhs",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
1,
|
1,
|
||||||
|| value.ok_or(Error::SynthesisError),
|
|| value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Finally, we return a variable representing the output,
|
// Finally, we return a variable representing the output,
|
||||||
|
@ -362,13 +362,13 @@ impl<F: FieldExt> MulInstructions<F> for MulChip<F> {
|
||||||
|| "lhs",
|
|| "lhs",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
0,
|
0,
|
||||||
|| a.value.ok_or(Error::SynthesisError),
|
|| a.value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
config.advice[1],
|
config.advice[1],
|
||||||
0,
|
0,
|
||||||
|| b.value.ok_or(Error::SynthesisError),
|
|| b.value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
region.constrain_equal(a.cell, lhs)?;
|
region.constrain_equal(a.cell, lhs)?;
|
||||||
region.constrain_equal(b.cell, rhs)?;
|
region.constrain_equal(b.cell, rhs)?;
|
||||||
|
@ -379,7 +379,7 @@ impl<F: FieldExt> MulInstructions<F> for MulChip<F> {
|
||||||
|| "lhs * rhs",
|
|| "lhs * rhs",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
1,
|
1,
|
||||||
|| value.ok_or(Error::SynthesisError),
|
|| value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Finally, we return a variable representing the output,
|
// Finally, we return a variable representing the output,
|
||||||
|
@ -457,7 +457,7 @@ impl<F: FieldExt> FieldInstructions<F> for FieldChip<F> {
|
||||||
|| "private input",
|
|| "private input",
|
||||||
config.advice[0],
|
config.advice[0],
|
||||||
0,
|
0,
|
||||||
|| value.ok_or(Error::SynthesisError),
|
|| value.ok_or(Error::Synthesis),
|
||||||
)?;
|
)?;
|
||||||
num = Some(Number { cell, value });
|
num = Some(Number { cell, value });
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -180,7 +180,7 @@ impl<'a, F: Field, CS: Assignment<F> + 'a> Layouter<F> for SingleChipLayouter<'a
|
||||||
_ => None,
|
_ => None,
|
||||||
}) {
|
}) {
|
||||||
Some(Some(len)) => len,
|
Some(Some(len)) => len,
|
||||||
_ => return Err(Error::SynthesisError), // TODO better error
|
_ => return Err(Error::Synthesis), // TODO better error
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F>
|
||||||
let value = self.layouter.cs.query_instance(instance, row)?;
|
let value = self.layouter.cs.query_instance(instance, row)?;
|
||||||
|
|
||||||
let cell = self.assign_advice(annotation, advice, offset, &mut || {
|
let cell = self.assign_advice(annotation, advice, offset, &mut || {
|
||||||
value.ok_or(Error::SynthesisError).map(|v| v.into())
|
value.ok_or(Error::Synthesis).map(|v| v.into())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.layouter.cs.copy(
|
self.layouter.cs.copy(
|
||||||
|
@ -417,7 +417,7 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> TableLayouter<F>
|
||||||
to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
|
to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if self.used_columns.contains(&column) {
|
if self.used_columns.contains(&column) {
|
||||||
return Err(Error::SynthesisError); // TODO better error
|
return Err(Error::Synthesis); // TODO better error
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry = self.default_and_assigned.entry(column).or_default();
|
let entry = self.default_and_assigned.entry(column).or_default();
|
||||||
|
@ -439,7 +439,7 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> TableLayouter<F>
|
||||||
(true, 0) => entry.0 = Some(value),
|
(true, 0) => entry.0 = Some(value),
|
||||||
// Since there is already an existing default value for this table column,
|
// Since there is already an existing default value for this table column,
|
||||||
// the caller should not be attempting to assign another value at offset 0.
|
// the caller should not be attempting to assign another value at offset 0.
|
||||||
(false, 0) => return Err(Error::SynthesisError), // TODO better error
|
(false, 0) => return Err(Error::Synthesis), // TODO better error
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
if entry.1.len() <= offset {
|
if entry.1.len() <= offset {
|
||||||
|
@ -499,9 +499,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let circuit = MyCircuit {};
|
let circuit = MyCircuit {};
|
||||||
assert_eq!(
|
assert!(matches!(
|
||||||
MockProver::run(3, &circuit, vec![]).unwrap_err(),
|
MockProver::run(3, &circuit, vec![]).unwrap_err(),
|
||||||
Error::NotEnoughColumnsForConstants,
|
Error::NotEnoughColumnsForConstants,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,7 @@ impl<'p, 'a, F: Field, CS: Assignment<F> + 'a> AssignmentPass<'p, 'a, F, CS> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}) {
|
}) {
|
||||||
Some(Some(len)) => len,
|
Some(Some(len)) => len,
|
||||||
_ => return Err(Error::SynthesisError), // TODO better error
|
_ => return Err(Error::Synthesis), // TODO better error
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F> for V1Region<'r
|
||||||
let value = self.plan.cs.query_instance(instance, row)?;
|
let value = self.plan.cs.query_instance(instance, row)?;
|
||||||
|
|
||||||
let cell = self.assign_advice(annotation, advice, offset, &mut || {
|
let cell = self.assign_advice(annotation, advice, offset, &mut || {
|
||||||
value.ok_or(Error::SynthesisError).map(|v| v.into())
|
value.ok_or(Error::Synthesis).map(|v| v.into())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.plan.cs.copy(
|
self.plan.cs.copy(
|
||||||
|
@ -534,9 +534,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let circuit = MyCircuit {};
|
let circuit = MyCircuit {};
|
||||||
assert_eq!(
|
assert!(matches!(
|
||||||
MockProver::run(3, &circuit, vec![]).unwrap_err(),
|
MockProver::run(3, &circuit, vec![]).unwrap_err(),
|
||||||
Error::NotEnoughColumnsForConstants,
|
Error::NotEnoughColumnsForConstants,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,15 +292,15 @@ impl<F: Group + Field> Mul<F> for Value<F> {
|
||||||
/// layouter.assign_region(|| "Example region", |mut region| {
|
/// layouter.assign_region(|| "Example region", |mut region| {
|
||||||
/// config.s.enable(&mut region, 0)?;
|
/// config.s.enable(&mut region, 0)?;
|
||||||
/// region.assign_advice(|| "a", config.a, 0, || {
|
/// region.assign_advice(|| "a", config.a, 0, || {
|
||||||
/// self.a.map(|v| F::from(v)).ok_or(Error::SynthesisError)
|
/// self.a.map(|v| F::from(v)).ok_or(Error::Synthesis)
|
||||||
/// })?;
|
/// })?;
|
||||||
/// region.assign_advice(|| "b", config.b, 0, || {
|
/// region.assign_advice(|| "b", config.b, 0, || {
|
||||||
/// self.b.map(|v| F::from(v)).ok_or(Error::SynthesisError)
|
/// self.b.map(|v| F::from(v)).ok_or(Error::Synthesis)
|
||||||
/// })?;
|
/// })?;
|
||||||
/// region.assign_advice(|| "c", config.c, 0, || {
|
/// region.assign_advice(|| "c", config.c, 0, || {
|
||||||
/// self.a
|
/// self.a
|
||||||
/// .and_then(|a| self.b.map(|b| F::from(a * b)))
|
/// .and_then(|a| self.b.map(|b| F::from(a * b)))
|
||||||
/// .ok_or(Error::SynthesisError)
|
/// .ok_or(Error::Synthesis)
|
||||||
/// })?;
|
/// })?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// })
|
/// })
|
||||||
|
@ -528,7 +528,7 @@ impl<F: FieldExt> MockProver<F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if instance.len() != cs.num_instance_columns {
|
if instance.len() != cs.num_instance_columns {
|
||||||
return Err(Error::IncompatibleParams);
|
return Err(Error::InvalidInstances);
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance = instance
|
let instance = instance
|
||||||
|
|
29
src/plonk.rs
29
src/plonk.rs
|
@ -16,6 +16,7 @@ use crate::poly::{
|
||||||
use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript};
|
use crate::transcript::{ChallengeScalar, EncodedChallenge, Transcript};
|
||||||
|
|
||||||
mod circuit;
|
mod circuit;
|
||||||
|
mod error;
|
||||||
mod keygen;
|
mod keygen;
|
||||||
mod lookup;
|
mod lookup;
|
||||||
pub(crate) mod permutation;
|
pub(crate) mod permutation;
|
||||||
|
@ -25,6 +26,7 @@ mod prover;
|
||||||
mod verifier;
|
mod verifier;
|
||||||
|
|
||||||
pub use circuit::*;
|
pub use circuit::*;
|
||||||
|
pub use error::*;
|
||||||
pub use keygen::*;
|
pub use keygen::*;
|
||||||
pub use prover::*;
|
pub use prover::*;
|
||||||
pub use verifier::*;
|
pub use verifier::*;
|
||||||
|
@ -133,33 +135,6 @@ pub struct ProvingKey<C: CurveAffine> {
|
||||||
permutation: permutation::ProvingKey<C>,
|
permutation: permutation::ProvingKey<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is an error that could occur during proving or circuit synthesis.
|
|
||||||
// TODO: these errors need to be cleaned up
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum Error {
|
|
||||||
/// This is an error that can occur during synthesis of the circuit, for
|
|
||||||
/// example, when the witness is not present.
|
|
||||||
SynthesisError,
|
|
||||||
/// The structured reference string or the parameters are not compatible
|
|
||||||
/// with the circuit being synthesized.
|
|
||||||
IncompatibleParams,
|
|
||||||
/// The constraint system is not satisfied.
|
|
||||||
ConstraintSystemFailure,
|
|
||||||
/// Out of bounds index passed to a backend
|
|
||||||
BoundsFailure,
|
|
||||||
/// Opening error
|
|
||||||
OpeningError,
|
|
||||||
/// Transcript error
|
|
||||||
TranscriptError,
|
|
||||||
/// Instance provided has more rows than supported by circuit
|
|
||||||
NotEnoughRowsAvailable,
|
|
||||||
/// Instance provided exceeds number of available rows
|
|
||||||
InstanceTooLarge,
|
|
||||||
/// Circuit synthesis requires global constants, but circuit configuration did not
|
|
||||||
/// call [`ConstraintSystem::enable_constant`] on fixed columns with sufficient space.
|
|
||||||
NotEnoughColumnsForConstants,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C: CurveAffine> ProvingKey<C> {
|
impl<C: CurveAffine> ProvingKey<C> {
|
||||||
/// Get the underlying [`VerifyingKey`].
|
/// Get the underlying [`VerifyingKey`].
|
||||||
pub fn get_vk(&self) -> &VerifyingKey<C> {
|
pub fn get_vk(&self) -> &VerifyingKey<C> {
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
use std::error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
/// This is an error that could occur during proving or circuit synthesis.
|
||||||
|
// TODO: these errors need to be cleaned up
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// This is an error that can occur during synthesis of the circuit, for
|
||||||
|
/// example, when the witness is not present.
|
||||||
|
Synthesis,
|
||||||
|
/// The provided instances do not match the circuit parameters.
|
||||||
|
InvalidInstances,
|
||||||
|
/// The constraint system is not satisfied.
|
||||||
|
ConstraintSystemFailure,
|
||||||
|
/// Out of bounds index passed to a backend
|
||||||
|
BoundsFailure,
|
||||||
|
/// Opening error
|
||||||
|
Opening,
|
||||||
|
/// Transcript error
|
||||||
|
Transcript(io::Error),
|
||||||
|
/// Instance provided has more rows than supported by circuit
|
||||||
|
NotEnoughRowsAvailable,
|
||||||
|
/// Instance provided exceeds number of available rows
|
||||||
|
InstanceTooLarge,
|
||||||
|
/// Circuit synthesis requires global constants, but circuit configuration did not
|
||||||
|
/// call [`ConstraintSystem::enable_constant`] on fixed columns with sufficient space.
|
||||||
|
///
|
||||||
|
/// [`ConstraintSystem::enable_constant`]: crate::plonk::ConstraintSystem::enable_constant
|
||||||
|
NotEnoughColumnsForConstants,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(error: io::Error) -> Self {
|
||||||
|
// The only place we can get io::Error from is the transcript.
|
||||||
|
Error::Transcript(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::Synthesis => write!(f, "General synthesis error"),
|
||||||
|
Error::InvalidInstances => write!(f, "Provided instances do not match the circuit"),
|
||||||
|
Error::ConstraintSystemFailure => write!(f, "The constraint system is not satisfied"),
|
||||||
|
Error::BoundsFailure => write!(f, "An out-of-bounds index was passed to the backend"),
|
||||||
|
Error::Opening => write!(f, "Multi-opening proof was invalid"),
|
||||||
|
Error::Transcript(e) => write!(f, "Transcript error: {}", e),
|
||||||
|
Error::NotEnoughRowsAvailable => write!(f, "`k` is too small for the given circuit"),
|
||||||
|
Error::InstanceTooLarge => write!(f, "Instance vectors are larger than the circuit"),
|
||||||
|
Error::NotEnoughColumnsForConstants => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Too few fixed columns are enabled for global constants usage"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for Error {
|
||||||
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
Error::Transcript(e) => Some(e),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -160,7 +160,7 @@ impl<F: Field> Assignment<F> for Assembly<F> {
|
||||||
.ok_or(Error::BoundsFailure)?;
|
.ok_or(Error::BoundsFailure)?;
|
||||||
|
|
||||||
for row in self.usable_rows.clone().skip(from_row) {
|
for row in self.usable_rows.clone().skip(from_row) {
|
||||||
col[row] = to.ok_or(Error::SynthesisError)?;
|
col[row] = to.ok_or(Error::Synthesis)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -210,14 +210,10 @@ impl<F: FieldExt> Argument<F> {
|
||||||
commit_values(&permuted_table_expression);
|
commit_values(&permuted_table_expression);
|
||||||
|
|
||||||
// Hash permuted input commitment
|
// Hash permuted input commitment
|
||||||
transcript
|
transcript.write_point(permuted_input_commitment)?;
|
||||||
.write_point(permuted_input_commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
// Hash permuted table commitment
|
// Hash permuted table commitment
|
||||||
transcript
|
transcript.write_point(permuted_table_commitment)?;
|
||||||
.write_point(permuted_table_commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
let permuted_input_coset = pk.vk.domain.coeff_to_extended(permuted_input_poly.clone());
|
let permuted_input_coset = pk.vk.domain.coeff_to_extended(permuted_input_poly.clone());
|
||||||
let permuted_table_coset = pk.vk.domain.coeff_to_extended(permuted_table_poly.clone());
|
let permuted_table_coset = pk.vk.domain.coeff_to_extended(permuted_table_poly.clone());
|
||||||
|
@ -391,9 +387,7 @@ impl<C: CurveAffine> Permuted<C> {
|
||||||
let product_coset = pk.vk.domain.coeff_to_extended(z.clone());
|
let product_coset = pk.vk.domain.coeff_to_extended(z.clone());
|
||||||
|
|
||||||
// Hash product commitment
|
// Hash product commitment
|
||||||
transcript
|
transcript.write_point(product_commitment)?;
|
||||||
.write_point(product_commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(Committed::<C> {
|
Ok(Committed::<C> {
|
||||||
permuted: self,
|
permuted: self,
|
||||||
|
@ -541,9 +535,7 @@ impl<C: CurveAffine> Constructed<C> {
|
||||||
.chain(Some(permuted_input_inv_eval))
|
.chain(Some(permuted_input_inv_eval))
|
||||||
.chain(Some(permuted_table_eval))
|
.chain(Some(permuted_table_eval))
|
||||||
{
|
{
|
||||||
transcript
|
transcript.write_scalar(eval)?;
|
||||||
.write_scalar(eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Evaluated { constructed: self })
|
Ok(Evaluated { constructed: self })
|
||||||
|
|
|
@ -40,12 +40,8 @@ impl<F: FieldExt> Argument<F> {
|
||||||
&self,
|
&self,
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<PermutationCommitments<C>, Error> {
|
) -> Result<PermutationCommitments<C>, Error> {
|
||||||
let permuted_input_commitment = transcript
|
let permuted_input_commitment = transcript.read_point()?;
|
||||||
.read_point()
|
let permuted_table_commitment = transcript.read_point()?;
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
let permuted_table_commitment = transcript
|
|
||||||
.read_point()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(PermutationCommitments {
|
Ok(PermutationCommitments {
|
||||||
permuted_input_commitment,
|
permuted_input_commitment,
|
||||||
|
@ -62,9 +58,7 @@ impl<C: CurveAffine> PermutationCommitments<C> {
|
||||||
self,
|
self,
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<Committed<C>, Error> {
|
) -> Result<Committed<C>, Error> {
|
||||||
let product_commitment = transcript
|
let product_commitment = transcript.read_point()?;
|
||||||
.read_point()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(Committed {
|
Ok(Committed {
|
||||||
permuted: self,
|
permuted: self,
|
||||||
|
@ -78,21 +72,11 @@ impl<C: CurveAffine> Committed<C> {
|
||||||
self,
|
self,
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<Evaluated<C>, Error> {
|
) -> Result<Evaluated<C>, Error> {
|
||||||
let product_eval = transcript
|
let product_eval = transcript.read_scalar()?;
|
||||||
.read_scalar()
|
let product_next_eval = transcript.read_scalar()?;
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
let permuted_input_eval = transcript.read_scalar()?;
|
||||||
let product_next_eval = transcript
|
let permuted_input_inv_eval = transcript.read_scalar()?;
|
||||||
.read_scalar()
|
let permuted_table_eval = transcript.read_scalar()?;
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
let permuted_input_eval = transcript
|
|
||||||
.read_scalar()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
let permuted_input_inv_eval = transcript
|
|
||||||
.read_scalar()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
let permuted_table_eval = transcript
|
|
||||||
.read_scalar()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(Evaluated {
|
Ok(Evaluated {
|
||||||
committed: self,
|
committed: self,
|
||||||
|
|
|
@ -51,12 +51,12 @@ impl Assembly {
|
||||||
.columns
|
.columns
|
||||||
.iter()
|
.iter()
|
||||||
.position(|c| c == &left_column)
|
.position(|c| c == &left_column)
|
||||||
.ok_or(Error::SynthesisError)?;
|
.ok_or(Error::Synthesis)?;
|
||||||
let right_column = self
|
let right_column = self
|
||||||
.columns
|
.columns
|
||||||
.iter()
|
.iter()
|
||||||
.position(|c| c == &right_column)
|
.position(|c| c == &right_column)
|
||||||
.ok_or(Error::SynthesisError)?;
|
.ok_or(Error::Synthesis)?;
|
||||||
|
|
||||||
// Check bounds
|
// Check bounds
|
||||||
if left_row >= self.mapping[left_column].len()
|
if left_row >= self.mapping[left_column].len()
|
||||||
|
|
|
@ -173,9 +173,7 @@ impl Argument {
|
||||||
permutation_product_commitment_projective.to_affine();
|
permutation_product_commitment_projective.to_affine();
|
||||||
|
|
||||||
// Hash the permutation product commitment
|
// Hash the permutation product commitment
|
||||||
transcript
|
transcript.write_point(permutation_product_commitment)?;
|
||||||
.write_point(permutation_product_commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
sets.push(CommittedSet {
|
sets.push(CommittedSet {
|
||||||
permutation_product_poly,
|
permutation_product_poly,
|
||||||
|
@ -330,9 +328,7 @@ impl<C: CurveAffine> super::ProvingKey<C> {
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Hash permutation evals
|
// Hash permutation evals
|
||||||
for eval in self.polys.iter().map(|poly| eval_polynomial(poly, *x)) {
|
for eval in self.polys.iter().map(|poly| eval_polynomial(poly, *x)) {
|
||||||
transcript
|
transcript.write_scalar(eval)?;
|
||||||
.write_scalar(eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -365,9 +361,7 @@ impl<C: CurveAffine> Constructed<C> {
|
||||||
.chain(Some(&permutation_product_eval))
|
.chain(Some(&permutation_product_eval))
|
||||||
.chain(Some(&permutation_product_next_eval))
|
.chain(Some(&permutation_product_next_eval))
|
||||||
{
|
{
|
||||||
transcript
|
transcript.write_scalar(*eval)?;
|
||||||
.write_scalar(*eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have any remaining sets to process, evaluate this set at omega^u
|
// If we have any remaining sets to process, evaluate this set at omega^u
|
||||||
|
@ -379,9 +373,7 @@ impl<C: CurveAffine> Constructed<C> {
|
||||||
domain.rotate_omega(*x, Rotation(-((blinding_factors + 1) as i32))),
|
domain.rotate_omega(*x, Rotation(-((blinding_factors + 1) as i32))),
|
||||||
);
|
);
|
||||||
|
|
||||||
transcript
|
transcript.write_scalar(permutation_product_last_eval)?;
|
||||||
.write_scalar(permutation_product_last_eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ impl Argument {
|
||||||
let permutation_product_commitments = self
|
let permutation_product_commitments = self
|
||||||
.columns
|
.columns
|
||||||
.chunks(chunk_len)
|
.chunks(chunk_len)
|
||||||
.map(|_| transcript.read_point().map_err(|_| Error::TranscriptError))
|
.map(|_| transcript.read_point())
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(Committed {
|
Ok(Committed {
|
||||||
|
@ -61,7 +61,7 @@ impl<C: CurveAffine> VerifyingKey<C> {
|
||||||
let permutation_evals = self
|
let permutation_evals = self
|
||||||
.commitments
|
.commitments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|_| transcript.read_scalar().map_err(|_| Error::TranscriptError))
|
.map(|_| transcript.read_scalar())
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(CommonEvaluated { permutation_evals })
|
Ok(CommonEvaluated { permutation_evals })
|
||||||
|
@ -78,18 +78,10 @@ impl<C: CurveAffine> Committed<C> {
|
||||||
let mut iter = self.permutation_product_commitments.into_iter();
|
let mut iter = self.permutation_product_commitments.into_iter();
|
||||||
|
|
||||||
while let Some(permutation_product_commitment) = iter.next() {
|
while let Some(permutation_product_commitment) = iter.next() {
|
||||||
let permutation_product_eval = transcript
|
let permutation_product_eval = transcript.read_scalar()?;
|
||||||
.read_scalar()
|
let permutation_product_next_eval = transcript.read_scalar()?;
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
let permutation_product_next_eval = transcript
|
|
||||||
.read_scalar()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
let permutation_product_last_eval = if iter.len() > 0 {
|
let permutation_product_last_eval = if iter.len() > 0 {
|
||||||
Some(
|
Some(transcript.read_scalar()?)
|
||||||
transcript
|
|
||||||
.read_scalar()
|
|
||||||
.map_err(|_| Error::TranscriptError)?,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,14 +43,12 @@ pub fn create_proof<
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
for instance in instances.iter() {
|
for instance in instances.iter() {
|
||||||
if instance.len() != pk.vk.cs.num_instance_columns {
|
if instance.len() != pk.vk.cs.num_instance_columns {
|
||||||
return Err(Error::IncompatibleParams);
|
return Err(Error::InvalidInstances);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash verification key into transcript
|
// Hash verification key into transcript
|
||||||
pk.vk
|
pk.vk.hash_into(transcript)?;
|
||||||
.hash_into(transcript)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
let domain = &pk.vk.domain;
|
let domain = &pk.vk.domain;
|
||||||
let mut meta = ConstraintSystem::default();
|
let mut meta = ConstraintSystem::default();
|
||||||
|
@ -94,9 +92,7 @@ pub fn create_proof<
|
||||||
drop(instance_commitments_projective);
|
drop(instance_commitments_projective);
|
||||||
|
|
||||||
for commitment in &instance_commitments {
|
for commitment in &instance_commitments {
|
||||||
transcript
|
transcript.common_point(*commitment)?;
|
||||||
.common_point(*commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance_polys: Vec<_> = instance_values
|
let instance_polys: Vec<_> = instance_values
|
||||||
|
@ -303,9 +299,7 @@ pub fn create_proof<
|
||||||
drop(advice_commitments_projective);
|
drop(advice_commitments_projective);
|
||||||
|
|
||||||
for commitment in &advice_commitments {
|
for commitment in &advice_commitments {
|
||||||
transcript
|
transcript.write_point(*commitment)?;
|
||||||
.write_point(*commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let advice_polys: Vec<_> = advice
|
let advice_polys: Vec<_> = advice
|
||||||
|
@ -498,9 +492,7 @@ pub fn create_proof<
|
||||||
|
|
||||||
// Hash each instance column evaluation
|
// Hash each instance column evaluation
|
||||||
for eval in instance_evals.iter() {
|
for eval in instance_evals.iter() {
|
||||||
transcript
|
transcript.write_scalar(*eval)?;
|
||||||
.write_scalar(*eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,9 +512,7 @@ pub fn create_proof<
|
||||||
|
|
||||||
// Hash each advice column evaluation
|
// Hash each advice column evaluation
|
||||||
for eval in advice_evals.iter() {
|
for eval in advice_evals.iter() {
|
||||||
transcript
|
transcript.write_scalar(*eval)?;
|
||||||
.write_scalar(*eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,9 +527,7 @@ pub fn create_proof<
|
||||||
|
|
||||||
// Hash each fixed column evaluation
|
// Hash each fixed column evaluation
|
||||||
for eval in fixed_evals.iter() {
|
for eval in fixed_evals.iter() {
|
||||||
transcript
|
transcript.write_scalar(*eval)?;
|
||||||
.write_scalar(*eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let vanishing = vanishing.evaluate(x, xn, domain, transcript)?;
|
let vanishing = vanishing.evaluate(x, xn, domain, transcript)?;
|
||||||
|
@ -611,5 +599,5 @@ pub fn create_proof<
|
||||||
// We query the h(X) polynomial at x
|
// We query the h(X) polynomial at x
|
||||||
.chain(vanishing.open(x));
|
.chain(vanishing.open(x));
|
||||||
|
|
||||||
multiopen::create_proof(params, transcript, instances).map_err(|_| Error::OpeningError)
|
multiopen::create_proof(params, transcript, instances).map_err(|_| Error::Opening)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,7 @@ impl<C: CurveAffine> Argument<C> {
|
||||||
|
|
||||||
// Commit
|
// Commit
|
||||||
let c = params.commit(&random_poly, random_blind).to_affine();
|
let c = params.commit(&random_poly, random_blind).to_affine();
|
||||||
transcript
|
transcript.write_point(c)?;
|
||||||
.write_point(c)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(Committed {
|
Ok(Committed {
|
||||||
random_poly,
|
random_poly,
|
||||||
|
@ -97,9 +95,7 @@ impl<C: CurveAffine> Committed<C> {
|
||||||
|
|
||||||
// Hash each h(X) piece
|
// Hash each h(X) piece
|
||||||
for c in h_commitments.iter() {
|
for c in h_commitments.iter() {
|
||||||
transcript
|
transcript.write_point(*c)?;
|
||||||
.write_point(*c)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Constructed {
|
Ok(Constructed {
|
||||||
|
@ -133,9 +129,7 @@ impl<C: CurveAffine> Constructed<C> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let random_eval = eval_polynomial(&self.committed.random_poly, *x);
|
let random_eval = eval_polynomial(&self.committed.random_poly, *x);
|
||||||
transcript
|
transcript.write_scalar(random_eval)?;
|
||||||
.write_scalar(random_eval)
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(Evaluated {
|
Ok(Evaluated {
|
||||||
h_poly,
|
h_poly,
|
||||||
|
|
|
@ -44,9 +44,7 @@ impl<C: CurveAffine> Argument<C> {
|
||||||
>(
|
>(
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<Committed<C>, Error> {
|
) -> Result<Committed<C>, Error> {
|
||||||
let random_poly_commitment = transcript
|
let random_poly_commitment = transcript.read_point()?;
|
||||||
.read_point()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(Committed {
|
Ok(Committed {
|
||||||
random_poly_commitment,
|
random_poly_commitment,
|
||||||
|
@ -64,8 +62,7 @@ impl<C: CurveAffine> Committed<C> {
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<Constructed<C>, Error> {
|
) -> Result<Constructed<C>, Error> {
|
||||||
// Obtain a commitment to h(X) in the form of multiple pieces of degree n - 1
|
// Obtain a commitment to h(X) in the form of multiple pieces of degree n - 1
|
||||||
let h_commitments = read_n_points(transcript, vk.domain.get_quotient_poly_degree())
|
let h_commitments = read_n_points(transcript, vk.domain.get_quotient_poly_degree())?;
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(Constructed {
|
Ok(Constructed {
|
||||||
h_commitments,
|
h_commitments,
|
||||||
|
@ -79,9 +76,7 @@ impl<C: CurveAffine> Constructed<C> {
|
||||||
self,
|
self,
|
||||||
transcript: &mut T,
|
transcript: &mut T,
|
||||||
) -> Result<PartiallyEvaluated<C>, Error> {
|
) -> Result<PartiallyEvaluated<C>, Error> {
|
||||||
let random_eval = transcript
|
let random_eval = transcript.read_scalar()?;
|
||||||
.read_scalar()
|
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
Ok(PartiallyEvaluated {
|
Ok(PartiallyEvaluated {
|
||||||
h_commitments: self.h_commitments,
|
h_commitments: self.h_commitments,
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
|
||||||
// Check that instances matches the expected number of instance columns
|
// Check that instances matches the expected number of instance columns
|
||||||
for instances in instances.iter() {
|
for instances in instances.iter() {
|
||||||
if instances.len() != vk.cs.num_instance_columns {
|
if instances.len() != vk.cs.num_instance_columns {
|
||||||
return Err(Error::IncompatibleParams);
|
return Err(Error::InvalidInstances);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,22 +50,19 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
|
||||||
let num_proofs = instance_commitments.len();
|
let num_proofs = instance_commitments.len();
|
||||||
|
|
||||||
// Hash verification key into transcript
|
// Hash verification key into transcript
|
||||||
vk.hash_into(transcript)
|
vk.hash_into(transcript)?;
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
for instance_commitments in instance_commitments.iter() {
|
for instance_commitments in instance_commitments.iter() {
|
||||||
// Hash the instance (external) commitments into the transcript
|
// Hash the instance (external) commitments into the transcript
|
||||||
for commitment in instance_commitments {
|
for commitment in instance_commitments {
|
||||||
transcript
|
transcript.common_point(*commitment)?
|
||||||
.common_point(*commitment)
|
|
||||||
.map_err(|_| Error::TranscriptError)?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let advice_commitments = (0..num_proofs)
|
let advice_commitments = (0..num_proofs)
|
||||||
.map(|_| -> Result<Vec<_>, _> {
|
.map(|_| -> Result<Vec<_>, _> {
|
||||||
// Hash the prover's advice commitments into the transcript
|
// Hash the prover's advice commitments into the transcript
|
||||||
read_n_points(transcript, vk.cs.num_advice_columns).map_err(|_| Error::TranscriptError)
|
read_n_points(transcript, vk.cs.num_advice_columns)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
@ -118,21 +115,14 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
|
||||||
// satisfied with high probability.
|
// satisfied with high probability.
|
||||||
let x: ChallengeX<_> = transcript.squeeze_challenge_scalar();
|
let x: ChallengeX<_> = transcript.squeeze_challenge_scalar();
|
||||||
let instance_evals = (0..num_proofs)
|
let instance_evals = (0..num_proofs)
|
||||||
.map(|_| -> Result<Vec<_>, _> {
|
.map(|_| -> Result<Vec<_>, _> { read_n_scalars(transcript, vk.cs.instance_queries.len()) })
|
||||||
read_n_scalars(transcript, vk.cs.instance_queries.len())
|
|
||||||
.map_err(|_| Error::TranscriptError)
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let advice_evals = (0..num_proofs)
|
let advice_evals = (0..num_proofs)
|
||||||
.map(|_| -> Result<Vec<_>, _> {
|
.map(|_| -> Result<Vec<_>, _> { read_n_scalars(transcript, vk.cs.advice_queries.len()) })
|
||||||
read_n_scalars(transcript, vk.cs.advice_queries.len())
|
|
||||||
.map_err(|_| Error::TranscriptError)
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let fixed_evals = read_n_scalars(transcript, vk.cs.fixed_queries.len())
|
let fixed_evals = read_n_scalars(transcript, vk.cs.fixed_queries.len())?;
|
||||||
.map_err(|_| Error::TranscriptError)?;
|
|
||||||
|
|
||||||
let vanishing = vanishing.evaluate_after_x(transcript)?;
|
let vanishing = vanishing.evaluate_after_x(transcript)?;
|
||||||
|
|
||||||
|
@ -295,5 +285,5 @@ pub fn verify_proof<'params, C: CurveAffine, E: EncodedChallenge<C>, T: Transcri
|
||||||
|
|
||||||
// We are now convinced the circuit is satisfied so long as the
|
// We are now convinced the circuit is satisfied so long as the
|
||||||
// polynomial commitments open to the correct values.
|
// polynomial commitments open to the correct values.
|
||||||
multiopen::verify_proof(params, transcript, queries, msm).map_err(|_| Error::OpeningError)
|
multiopen::verify_proof(params, transcript, queries, msm).map_err(|_| Error::Opening)
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,32 +105,32 @@ fn plonk_api() {
|
||||||
0,
|
0,
|
||||||
|| {
|
|| {
|
||||||
value = Some(f()?);
|
value = Some(f()?);
|
||||||
Ok(value.ok_or(Error::SynthesisError)?.0)
|
Ok(value.ok_or(Error::Synthesis)?.0)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "lhs^4",
|
|| "lhs^4",
|
||||||
self.config.d,
|
self.config.d,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.0.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.0.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
self.config.b,
|
self.config.b,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1),
|
|| Ok(value.ok_or(Error::Synthesis)?.1),
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "rhs^4",
|
|| "rhs^4",
|
||||||
self.config.e,
|
self.config.e,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.1.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let out = region.assign_advice(
|
let out = region.assign_advice(
|
||||||
|| "out",
|
|| "out",
|
||||||
self.config.c,
|
self.config.c,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.2),
|
|| Ok(value.ok_or(Error::Synthesis)?.2),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::zero()))?;
|
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::zero()))?;
|
||||||
|
@ -159,32 +159,32 @@ fn plonk_api() {
|
||||||
0,
|
0,
|
||||||
|| {
|
|| {
|
||||||
value = Some(f()?);
|
value = Some(f()?);
|
||||||
Ok(value.ok_or(Error::SynthesisError)?.0)
|
Ok(value.ok_or(Error::Synthesis)?.0)
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "lhs^4",
|
|| "lhs^4",
|
||||||
self.config.d,
|
self.config.d,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.0.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.0.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let rhs = region.assign_advice(
|
let rhs = region.assign_advice(
|
||||||
|| "rhs",
|
|| "rhs",
|
||||||
self.config.b,
|
self.config.b,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1),
|
|| Ok(value.ok_or(Error::Synthesis)?.1),
|
||||||
)?;
|
)?;
|
||||||
region.assign_advice(
|
region.assign_advice(
|
||||||
|| "rhs^4",
|
|| "rhs^4",
|
||||||
self.config.e,
|
self.config.e,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.1.square().square()),
|
|| Ok(value.ok_or(Error::Synthesis)?.1.square().square()),
|
||||||
)?;
|
)?;
|
||||||
let out = region.assign_advice(
|
let out = region.assign_advice(
|
||||||
|| "out",
|
|| "out",
|
||||||
self.config.c,
|
self.config.c,
|
||||||
0,
|
0,
|
||||||
|| Ok(value.ok_or(Error::SynthesisError)?.2),
|
|| Ok(value.ok_or(Error::Synthesis)?.2),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::one()))?;
|
region.assign_fixed(|| "a", self.config.sa, 0, || Ok(FF::one()))?;
|
||||||
|
@ -356,17 +356,17 @@ fn plonk_api() {
|
||||||
let (a0, _, c0) = cs.raw_multiply(&mut layouter, || {
|
let (a0, _, c0) = cs.raw_multiply(&mut layouter, || {
|
||||||
a_squared = self.a.map(|a| a.square());
|
a_squared = self.a.map(|a| a.square());
|
||||||
Ok((
|
Ok((
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
a_squared.ok_or(Error::SynthesisError)?,
|
a_squared.ok_or(Error::Synthesis)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let (a1, b1, _) = cs.raw_add(&mut layouter, || {
|
let (a1, b1, _) = cs.raw_add(&mut layouter, || {
|
||||||
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
||||||
Ok((
|
Ok((
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::Synthesis)?,
|
||||||
a_squared.ok_or(Error::SynthesisError)?,
|
a_squared.ok_or(Error::Synthesis)?,
|
||||||
fin.ok_or(Error::SynthesisError)?,
|
fin.ok_or(Error::Synthesis)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
cs.copy(&mut layouter, a0, a1)?;
|
cs.copy(&mut layouter, a0, a1)?;
|
||||||
|
|
Loading…
Reference in New Issue