mirror of https://github.com/zcash/halo2.git
Merge pull request #178 from zcash/simple-example-comments
Reflow simple-example.rs comments
This commit is contained in:
commit
13ac4e7573
|
@ -34,21 +34,22 @@ trait NumericInstructions: Chip {
|
|||
// ANCHOR_END: instructions
|
||||
|
||||
// ANCHOR: chip
|
||||
/// The chip that will implement our instructions! Chips do not store any persistent state
|
||||
/// themselves, and usually only contain type markers if necessary.
|
||||
/// The chip that will implement our instructions! Chips do not store any persistent
|
||||
/// state themselves, and usually only contain type markers if necessary.
|
||||
struct FieldChip<F: FieldExt> {
|
||||
_marker: PhantomData<F>,
|
||||
}
|
||||
// ANCHOR_END: chip
|
||||
|
||||
// ANCHOR: chip-config
|
||||
/// Chip state is stored in a separate config struct. This is generated by the chip during
|
||||
/// configuration, and then handed to the `Layouter`, which makes it available to the chip
|
||||
/// when it needs to implement its instructions.
|
||||
/// Chip state is stored in a separate config struct. This is generated by the chip
|
||||
/// during configuration, and then handed to the `Layouter`, which makes it available
|
||||
/// to the chip when it needs to implement its instructions.
|
||||
#[derive(Clone, Debug)]
|
||||
struct FieldConfig {
|
||||
/// For this chip, we will use two advice columns to implement our instructions. These
|
||||
/// are also the columns through which we communicate with other parts of the circuit.
|
||||
/// For this chip, we will use two advice columns to implement our instructions.
|
||||
/// These are also the columns through which we communicate with other parts of
|
||||
/// the circuit.
|
||||
advice: [Column<Advice>; 2],
|
||||
|
||||
// We need to create a permutation between our advice columns. This allows us to
|
||||
|
@ -86,18 +87,18 @@ impl<F: FieldExt> FieldChip<F> {
|
|||
// | lhs | rhs | s_mul |
|
||||
// | out | | |
|
||||
//
|
||||
// Gates may refer to any relative offsets we want, but each distinct offset
|
||||
// adds a cost to the proof. The most common offsets are 0 (the current row),
|
||||
// 1 (the next row), and -1 (the previous row), for which `Rotation` has
|
||||
// specific constructors.
|
||||
// Gates may refer to any relative offsets we want, but each distinct
|
||||
// offset adds a cost to the proof. The most common offsets are 0 (the
|
||||
// current row), 1 (the next row), and -1 (the previous row), for which
|
||||
// `Rotation` has specific constructors.
|
||||
let lhs = meta.query_advice(advice[0], Rotation::cur());
|
||||
let rhs = meta.query_advice(advice[1], Rotation::cur());
|
||||
let out = meta.query_advice(advice[0], Rotation::next());
|
||||
let s_mul = meta.query_fixed(s_mul, Rotation::cur());
|
||||
|
||||
// The polynomial expression returned from `create_gate` will be constrained
|
||||
// by the proving system to equal zero. Our expression has the following
|
||||
// properties:
|
||||
// The polynomial expression returned from `create_gate` will be
|
||||
// constrained by the proving system to equal zero. Our expression
|
||||
// has the following properties:
|
||||
// - When s_mul = 0, any value is allowed in lhs, rhs, and out.
|
||||
// - When s_mul != 0, this constrains lhs * rhs = out.
|
||||
s_mul * (lhs * rhs + out * -F::one())
|
||||
|
@ -105,14 +106,14 @@ impl<F: FieldExt> FieldChip<F> {
|
|||
|
||||
// Define our public-input gate!
|
||||
meta.create_gate("public input", |meta| {
|
||||
// We choose somewhat-arbitrarily that we will use the second advice column
|
||||
// for exposing numbers as public inputs.
|
||||
// We choose somewhat-arbitrarily that we will use the second advice
|
||||
// column for exposing numbers as public inputs.
|
||||
let a = meta.query_advice(advice[1], Rotation::cur());
|
||||
let p = meta.query_aux(aux, Rotation::cur());
|
||||
let s = meta.query_fixed(s_pub, Rotation::cur());
|
||||
|
||||
// We simply constrain the advice cell to be equal to the aux cell, when the
|
||||
// selector is enabled.
|
||||
// We simply constrain the advice cell to be equal to the aux cell,
|
||||
// when the selector is enabled.
|
||||
s * (p + a * -F::one())
|
||||
});
|
||||
|
||||
|
@ -132,8 +133,8 @@ impl<F: FieldExt> Chip for FieldChip<F> {
|
|||
type Field = F;
|
||||
|
||||
fn load(_layouter: &mut impl Layouter<Self>) -> Result<(), halo2::plonk::Error> {
|
||||
// None of the instructions implemented by this chip have any fixed state. But if
|
||||
// we required e.g. a lookup table, this is where we would load it.
|
||||
// None of the instructions implemented by this chip have any fixed state.
|
||||
// But if we required e.g. a lookup table, this is where we would load it.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -182,15 +183,15 @@ impl<F: FieldExt> NumericInstructions for FieldChip<F> {
|
|||
layouter.assign_region(
|
||||
|| "mul",
|
||||
|mut region| {
|
||||
// We only want to use a single multiplication gate in this region, so we
|
||||
// enable it at region offset 0; this means it will constrain cells at
|
||||
// offsets 0 and 1.
|
||||
// We only want to use a single multiplication gate in this region,
|
||||
// so we enable it at region offset 0; this means it will constrain
|
||||
// cells at offsets 0 and 1.
|
||||
region.assign_fixed(|| "example mul", config.s_mul, 0, || Ok(F::one()))?;
|
||||
|
||||
// The inputs we've been given could be located anywhere in the circuit,
|
||||
// but we can only rely on relative offsets inside this region. So we
|
||||
// assign new cells inside the region and constrain them to have the same
|
||||
// values as the inputs.
|
||||
// assign new cells inside the region and constrain them to have the
|
||||
// same values as the inputs.
|
||||
let lhs = region.assign_advice(
|
||||
|| "lhs",
|
||||
config.advice[0],
|
||||
|
@ -215,8 +216,8 @@ impl<F: FieldExt> NumericInstructions for FieldChip<F> {
|
|||
|| value.ok_or(Error::SynthesisError),
|
||||
)?;
|
||||
|
||||
// Finally, we return a variable representing the output, to be used in
|
||||
// another part of the circuit.
|
||||
// Finally, we return a variable representing the output,
|
||||
// to be used in another part of the circuit.
|
||||
out = Some(Number { cell, value });
|
||||
Ok(())
|
||||
},
|
||||
|
@ -242,8 +243,8 @@ impl<F: FieldExt> NumericInstructions for FieldChip<F> {
|
|||
)?;
|
||||
region.constrain_equal(&config.perm, num.cell, out)?;
|
||||
|
||||
// We don't assign to the auxiliary column inside the circuit; the mapping
|
||||
// of public inputs to cells is provided to the prover.
|
||||
// We don't assign to the auxiliary column inside the circuit;
|
||||
// the mapping of public inputs to cells is provided to the prover.
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
|
@ -254,9 +255,9 @@ impl<F: FieldExt> NumericInstructions for FieldChip<F> {
|
|||
// ANCHOR: circuit
|
||||
/// The full circuit implementation.
|
||||
///
|
||||
/// In this struct we store the private input variables. We use `Option<F>` because they
|
||||
/// won't have any value during key generation. During proving, if any of these were
|
||||
/// `None` we would get an error.
|
||||
/// In this struct we store the private input variables. We use `Option<F>` because
|
||||
/// they won't have any value during key generation. During proving, if any of these
|
||||
/// were `None` we would get an error.
|
||||
struct MyCircuit<F: FieldExt> {
|
||||
a: Option<F>,
|
||||
b: Option<F>,
|
||||
|
@ -283,7 +284,8 @@ impl<F: FieldExt> Circuit<F> for MyCircuit<F> {
|
|||
let a = FieldChip::load_private(&mut layouter, self.a)?;
|
||||
let b = FieldChip::load_private(&mut layouter, self.b)?;
|
||||
|
||||
// We only have access to plain multiplication. We could implement our circuit as:
|
||||
// We only have access to plain multiplication.
|
||||
// We could implement our circuit as:
|
||||
// asq = a*a
|
||||
// bsq = b*b
|
||||
// c = asq*bsq
|
||||
|
@ -304,8 +306,8 @@ fn main() {
|
|||
use halo2::{dev::MockProver, pasta::Fp};
|
||||
|
||||
// ANCHOR: test-circuit
|
||||
// The number of rows in our circuit cannot exceed 2^k. Since our example circuit is
|
||||
// very small, we can pick a very small value here.
|
||||
// The number of rows in our circuit cannot exceed 2^k. Since our example
|
||||
// circuit is very small, we can pick a very small value here.
|
||||
let k = 3;
|
||||
|
||||
// Prepare the private and public inputs to the circuit!
|
||||
|
@ -319,8 +321,8 @@ fn main() {
|
|||
b: Some(b),
|
||||
};
|
||||
|
||||
// Arrange the public input. We expose the multiplication result in row 4 of the aux
|
||||
// column, so we position it there in our public inputs.
|
||||
// Arrange the public input. We expose the multiplication result in row 6
|
||||
// of the aux column, so we position it there in our public inputs.
|
||||
let mut public_inputs = vec![Fp::zero(); 1 << k];
|
||||
public_inputs[6] = c;
|
||||
|
||||
|
|
Loading…
Reference in New Issue