Zero Knowledge Proof — Error Explanation when developing Custom Gate

+----------+----------+
| Column A | Column B |
+----------+----------+
| a_prev | b_prev |
| a_cur | b_cur |
| ... | ... |
+----------+----------+
let a_p = meta.query_advice(advice[0], Rotation::prev());
let b_p = meta.query_advice(advice[1], Rotation::prev());
let a = meta.query_advice(advice[0], Rotation::cur());
let b = meta.query_advice(advice[1], Rotation::cur());

vec![a - (a_p*b_p)]
region.assign_advice( || "a", config.advice[0], 0, || Ok(F::from(1)), )?;
region.assign_advice( || "b", config.advice[1], 0, || Ok(F::from(2)), )?;
region.assign_advice( || "a", config.advice[0], 1, || Ok(F::from(2)), )?;
region.assign_advice( || "b", config.advice[1], 1, || Ok(F::from(3)), )?;
region.assign_advice( || "a", config.advice[0], 2, || Ok(F::from(6)), )?;
region.assign_advice( || "b", config.advice[1], 2, || Ok(F::from(7)), )?;

ConstraintPoisoned

Before moving on to the Constraint Poisoned, we must understand usable rows. The rows within the largest rows the program actively assigns are called usable rows. When the circuit rows need to be expanded, the expanded rows are not considered usable rows. The cells in the advice column of these rows are initialized to “Poisoned”.

let mut column = vec![CellValue::Unassigned; n];
// Poison unusable rows.
for (i, cell) in column.iter_mut().enumerate().skip(usable_rows) {
*cell = CellValue::Poison(i);
}
column
ConstraintPoisoned { constraint: Constraint { gate: Gate { index: 0, name: "mul" }, index: 0, name: "" } },
+----------+----------+----------+
| Selector | Column A | Column B |
+----------+----------+----------+
| 1 | a_prev | b_prev |
| 1 | a_cur | b_cur |
| ... | ... | ... |
+----------+----------+----------+
let a_p = meta.query_advice(advice[0], Rotation::prev());
let b_p = meta.query_advice(advice[1], Rotation::prev());
let a = meta.query_advice(advice[0], Rotation::cur());
let b = meta.query_advice(advice[1], Rotation::cur());

let enable = meta.query_selector(enable);

vec![enable*(a - (a_p*b_p))]
config.enable.enable(&mut region, 0);
region.assign_advice( || "a", config.advice[0], 0, || Ok(F::from(1)), )?;
region.assign_advice( || "b", config.advice[1], 0, || Ok(F::from(2)), )?;
config.enable.enable(&mut region, 1);
region.assign_advice( || "a", config.advice[0], 1, || Ok(F::from(2)), )?;
region.assign_advice( || "b", config.advice[1], 1, || Ok(F::from(3)), )?;
config.enable.enable(&mut region, 2);
region.assign_advice( || "a", config.advice[0], 2, || Ok(F::from(6)), )?;
region.assign_advice( || "b", config.advice[1], 2, || Ok(F::from(7)), )?;

CellNotAssigned

With the previous circuit adjustment, there’s a new error: CellNotAssigned.

CellNotAssigned { gate: Gate { index: 0, name: "mul" }, region: Region { index: 0, name: "mul" }, column: Column { index: 0, column_type: Advice }, offset: 15 },
CellNotAssigned { gate: Gate { index: 0, name: "mul" }, region: Region { index: 0, name: "mul" }, column: Column { index: 1, column_type: Advice }, offset: 15 },
gate.queried_cells().iter().filter_map(move |cell| {
// 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.contains(&(cell.column, cell_row)) {
None
} else {
Some(VerifyFailure::CellNotAssigned {
gate: (gate_index, gate.name()).into(),
region: (r_i, r.name.clone()).into(),
column: cell.column,
offset: cell_row as isize - r.rows.unwrap().0 as isize,
})
}
})

ConstraintNotSatisfied

This error is most commonly seen and easiest to understand: the constraints of the circuit are not satisfied. For a custom gate, the result of its Expression is not 0. This error is easy to solve, the developer only needs to carefully check the value assigned to each cell. For the example circuit, the constraint for the first line in the custom gate is not satisfied — there’s no value assigned for the offset of 15.

//config.enable.enable(&mut region, 0);
region.assign_advice( || "a", config.advice[0], 0, || Ok(F::from(1)), )?;
region.assign_advice( || "b", config.advice[1], 0, || Ok(F::from(2)), )?;
config.enable.enable(&mut region, 1);
region.assign_advice( || "a", config.advice[0], 1, || Ok(F::from(2)), )?;
region.assign_advice( || "b", config.advice[1], 1, || Ok(F::from(3)), )?;
config.enable.enable(&mut region, 2);
region.assign_advice( || "a", config.advice[0], 2, || Ok(F::from(6)), )?;
region.assign_advice( || "b", config.advice[1], 2, || Ok(F::from(7)), )?;

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Trapdoor-Tech

Trapdoor-Tech

Trapdoor-Tech tries to connect the world with zero-knowledge proof technologies. zk-SNARK/STARK solution and proving acceleration are our first small steps :)