note_commit: Decompose q_canon into two binary selectors.

Previously, q_canon was a non-binary fixed column that was set to
either {1, 2}. It has been decomposed into two binary selectors.
This commit is contained in:
therealyingtong 2021-07-24 00:46:12 +08:00
parent 76c73531c8
commit 7af1ae5b52
1 changed files with 35 additions and 63 deletions

View File

@ -1,7 +1,7 @@
use group::GroupEncoding;
use halo2::{
circuit::Layouter,
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed},
plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector},
poly::Rotation,
};
use pasta_curves::{
@ -36,27 +36,13 @@ use super::{
- v is a 64-bit value;
- rho is a base field element (255 bits); and
- psi is a base field element (255 bits).
All bit ranges are inclusive.
a (250 bits) = bits 0..=249 of x(g_d)
b (10 bits) = b_0 || b_1 || b_2 || b_3
= (bits 250..=253 of x(g_d)) || (bit 254 of x(g_d)) || ( bit of g_d) || (bits 0..=3 of pk_d)
c (250 bits) = bits 4..=253 of pk_d
d (60 bits) = d_0 || d_1 || d_2 || d_3
= (bit 254 of x(pk_d)) || ( bit of pk_d) || (0..=7 of v) || (8..=57 of v)
e (10 bits) = e_0 || e_1
= (bits 58..=63 of v) || (bits 0..=3 of rho)
f (250 bits) = bits 4..=253 inclusive of rho
g (250 bits) = g_0 || g_1 || g_2
= (bit 254 of rho) || (bits 0..=8 of psi) || (bits 9..=248 of psi)
h (10 bits) = h_0 || h_1 || h_2
= (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits
*/
#[allow(non_snake_case)]
#[derive(Clone, Debug)]
pub struct NoteCommitConfig {
q_canon: Column<Fixed>,
q_canon_1: Selector,
q_canon_2: Selector,
advices: [Column<Advice>; 10],
sinsemilla_config: SinsemillaConfig,
}
@ -69,10 +55,12 @@ impl NoteCommitConfig {
advices: [Column<Advice>; 10],
sinsemilla_config: SinsemillaConfig,
) -> Self {
let q_canon = meta.fixed_column();
let q_canon_1 = meta.selector();
let q_canon_2 = meta.selector();
let config = Self {
q_canon,
q_canon_1,
q_canon_2,
advices,
sinsemilla_config,
};
@ -93,6 +81,8 @@ impl NoteCommitConfig {
meta.create_gate("NoteCommit decomposition check", |meta| {
/*
All bit ranges are inclusive.
a (250 bits) = bits 0..=249 of x(g_d)
b (10 bits) = b_0 || b_1 || b_2 || b_3
= (bits 250..=253 of x(g_d)) || (bit 254 of x(g_d)) || ( bit of g_d) || (bits 0..=3 of pk_d)
@ -107,14 +97,14 @@ impl NoteCommitConfig {
h (10 bits) = h_0 || h_1 || h_2
= (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits
| A_0 | A_1 | A_2 | A_3 | A_4 | A_5 | A_6 | A_7 | A_8 | A_9 | q_canon |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
| a_prime | b3_c_prime | e1_f_prime | g1_g2_prime | a | b | b_2 | b_3 | c | d | |
| d_1 | d_2 | z1_d | e | e_0 | e_1 | f | g | g_1 | h | 1 |
| h_0 | h_1 | x(g_d) | x(pk_d) | value | b_0 | b_1 | d_0 | g_0 | z1_g | 2 |
|a_prime_decomposition|b3_c_prime_decomposition|e1_f_prime_decomposition|g1_g2_prime_decomposition| z13_a | z13_c | z13_f | z13_g | psi | rho | |
| A_0 | A_1 | A_2 | A_3 | A_4 | A_5 | A_6 | A_7 | A_8 | A_9 | q_canon_1 | q_canon_2 |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| a_prime | b3_c_prime | e1_f_prime | g1_g2_prime | a | b | b_2 | b_3 | c | d | 0 | 0 |
| d_1 | d_2 | z1_d | e | e_0 | e_1 | f | g | g_1 | h | 1 | 0 |
| h_0 | h_1 | x(g_d) | x(pk_d) | value | b_0 | b_1 | d_0 | g_0 | z1_g | 0 | 1 |
|a_prime_decomposition|b3_c_prime_decomposition|e1_f_prime_decomposition|g1_g2_prime_decomposition| z13_a | z13_c | z13_f | z13_g | psi | rho | 0 | 0 |
q_canon_is_one checks that:
q_canon_1 checks that:
- piece decomposition:
- b = b_0 + (2^4) b_1 + (2^5) b_2 + (2^6) b_3
- b_1 is boolean
@ -137,11 +127,7 @@ impl NoteCommitConfig {
- e1_f_prime = e_1 + (2^4)g + 2^140 - t_P
- g1_g2_prime = g_1 + (2^9) g_2 + 2^140 - t_P
*/
let q_canon_is_one = {
let two = Expression::Constant(pallas::Base::from_u64(2));
let q_canon = meta.query_fixed(config.q_canon, Rotation::cur());
q_canon.clone() * (two - q_canon)
};
let q_canon_1 = meta.query_selector(config.q_canon_1);
// Offset prev
let a_prime = meta.query_advice(config.advices[0], Rotation::prev());
@ -282,7 +268,7 @@ impl NoteCommitConfig {
.chain(Some(("gd_x_check", gd_x_check)))
.chain(Some(("pkd_x_check", pkd_x_check)))
.chain(Some(("value_check", value_check)))
.map(move |(name, poly)| (name, q_canon_is_one.clone() * poly))
.map(move |(name, poly)| (name, q_canon_1.clone() * poly))
});
meta.create_gate("Canonicity checks", |meta| {
@ -301,15 +287,15 @@ impl NoteCommitConfig {
h (10 bits) = h_0 || h_1 || h_2
= (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits
| A_0 | A_1 | A_2 | A_3 | A_4 | A_5 | A_6 | A_7 | A_8 | A_9 | q_canon |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
| a_prime | b3_c_prime | e1_f_prime | g1_g2_prime | a | b | b_2 | b_3 | c | d | |
| d_1 | d_2 | z1_d | e | e_0 | e_1 | f | g | g_1 | h | 1 |
| h_0 | h_1 | x(g_d) | x(pk_d) | value | b_0 | b_1 | d_0 | g_0 | z1_g | 2 |
|a_prime_decomposition|b3_c_prime_decomposition|e1_f_prime_decomposition|g1_g2_prime_decomposition| z13_a | z13_c | z13_f | z13_g | psi | rho | |
| A_0 | A_1 | A_2 | A_3 | A_4 | A_5 | A_6 | A_7 | A_8 | A_9 | q_canon_1 | q_canon_2 |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| a_prime | b3_c_prime | e1_f_prime | g1_g2_prime | a | b | b_2 | b_3 | c | d | 0 | 0 |
| d_1 | d_2 | z1_d | e | e_0 | e_1 | f | g | g_1 | h | 1 | 0 |
| h_0 | h_1 | x(g_d) | x(pk_d) | value | b_0 | b_1 | d_0 | g_0 | z1_g | 0 | 1 |
|a_prime_decomposition|b3_c_prime_decomposition|e1_f_prime_decomposition|g1_g2_prime_decomposition| z13_a | z13_c | z13_f | z13_g | psi | rho | 0 | 0 |
*/
// q_canon_is_two checks that:
// q_canon_2 checks that:
// - field element decomposition:
// - rho = e_1 + (2^4) g + (2^254) h_0
// - psi = h_1 + (2^9) i + (2^249) j_0 + (2^254) j_1
@ -324,11 +310,7 @@ impl NoteCommitConfig {
// - j_1 = 0 => j_0 = 0
// && g1_g2_prime_decomposition = 0
let q_canon_is_two = {
let one = Expression::Constant(pallas::Base::one());
let q_canon = meta.query_fixed(config.q_canon, Rotation::cur());
q_canon.clone() * (one - q_canon)
};
let q_canon_2 = meta.query_selector(config.q_canon_2);
// Offset prev
let e_1 = meta.query_advice(config.advices[5], Rotation::prev());
@ -411,7 +393,7 @@ impl NoteCommitConfig {
.chain(pkd_x_canonicity_checks)
.chain(rho_canonicity_checks)
.chain(psi_canonicity_checks)
.map(move |poly| q_canon_is_two.clone() * poly)
.map(move |poly| q_canon_2.clone() * poly)
});
config
@ -861,30 +843,20 @@ impl NoteCommitConfig {
The pieces are witnessed in the below configuration, such that no gate has to query an
offset greater than +/- 1 from its relative row.
| A_0 | A_1 | A_2 | A_3 | A_4 | A_5 | A_6 | A_7 | A_8 | A_9 | q_canon |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
| a_prime | b3_c_prime | e1_f_prime | g1_g2_prime | a | b | b_2 | b_3 | c | d | |
| d_1 | d_2 | z1_d | e | e_0 | e_1 | f | g | g_1 | h | 1 |
| h_0 | h_1 | x(g_d) | x(pk_d) | value | b_0 | b_1 | d_0 | g_0 | z1_g | 2 |
|a_prime_decomposition|b3_c_prime_decomposition|e1_f_prime_decomposition|g1_g2_prime_decomposition| z13_a | z13_c | z13_f | z13_g | psi | rho | |
| A_0 | A_1 | A_2 | A_3 | A_4 | A_5 | A_6 | A_7 | A_8 | A_9 | q_canon_1 | q_canon_2 |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| a_prime | b3_c_prime | e1_f_prime | g1_g2_prime | a | b | b_2 | b_3 | c | d | 0 | 0 |
| d_1 | d_2 | z1_d | e | e_0 | e_1 | f | g | g_1 | h | 1 | 0 |
| h_0 | h_1 | x(g_d) | x(pk_d) | value | b_0 | b_1 | d_0 | g_0 | z1_g | 0 | 1 |
|a_prime_decomposition|b3_c_prime_decomposition|e1_f_prime_decomposition|g1_g2_prime_decomposition| z13_a | z13_c | z13_f | z13_g | psi | rho | 0 | 0 |
*/
layouter.assign_region(
|| "Assign gate cells",
|mut region| {
// Assign fixed column the correct values
region.assign_fixed(
|| "q_canon = 1",
self.q_canon,
1,
|| Ok(pallas::Base::one()),
)?;
region.assign_fixed(
|| "q_canon = 2",
self.q_canon,
2,
|| Ok(pallas::Base::from_u64(2)),
)?;
self.q_canon_1.enable(&mut region, 1)?;
self.q_canon_2.enable(&mut region, 2)?;
// Offset 0
{