From bcec21020d4302c2c4f921b8560feffc5e3bb480 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 1 Apr 2021 12:07:17 +0800 Subject: [PATCH] [WIP] Configure Sinsemilla chip --- src/circuit/gadget/ecc/chip.rs | 88 +++++++++++++-------------- src/circuit/gadget/sinsemilla/chip.rs | 83 ++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 45 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 586218059..037934e75 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -47,49 +47,49 @@ impl CellValue { #[derive(Clone, Debug)] #[allow(non_snake_case)] pub struct EccConfig { - // Advice column for scalar decomposition into bits - bits: Column, - // Witness u = (y + z).sqrt(), used in fixed-base scalar multiplication - u: Column, - // Holds a point (x_a, y_a) that is usually the result of an addition - A: (Column, Column), - // Holds a point (x_p, y_p) - P: (Column, Column), - // A pair (lambda1, lambda2) representing gradients - lambda: (Column, Column), - // [A, B, C, D] boolean flags used in complete addition - add_complete_bool: [Column; 4], - // [alpha, beta, gamma, delta] inverses used in complete addition - add_complete_inv: [Column; 4], - // Coefficients of interpolation polynomials for x-coordinates (used in fixed-base scalar multiplication) - lagrange_coeffs: [Column; constants::H], - // Fixed z such that y + z = u^2 some square, and -y + z is a non-square. (Used in fixed-base scalar multiplication) - fixed_z: Column, - - // Incomplete addition - q_add: Selector, - // Complete addition - q_add_complete: Selector, - // Point doubling - q_double: Selector, - // Variable-base scalar multiplication - q_mul: Selector, - // Fixed-base full-width scalar multiplication - q_mul_fixed: Selector, - // Fixed-base signed short scalar multiplication - q_mul_fixed_short: Selector, - // Witness point - q_point: Selector, - // Witness scalar for variable-base scalar mul - q_scalar_var: Selector, - // Witness full-width scalar for fixed-base scalar mul - q_scalar_fixed: Selector, - // Witness signed short scalar for full-width fixed-base scalar mul - q_scalar_fixed_short: Selector, - // Copy bits of decomposed scalars - perm_scalar: Permutation, - // Copy between (x_p, y_p) and (x_a, y_a) - perm_sum: Permutation, + /// Advice column for scalar decomposition into bits + pub bits: Column, + /// Witness u = (y + z).sqrt(), used in fixed-base scalar multiplication + pub u: Column, + /// Holds a point (x_a, y_a) that is usually the result of an addition + pub A: (Column, Column), + /// Holds a point (x_p, y_p) + pub P: (Column, Column), + /// A pair (lambda1, lambda2) representing gradients + pub lambda: (Column, Column), + /// [A, B, C, D] boolean flags used in complete addition + pub add_complete_bool: [Column; 4], + /// [alpha, beta, gamma, delta] inverses used in complete addition + pub add_complete_inv: [Column; 4], + /// Coefficients of interpolation polynomials for x-coordinates (used in fixed-base scalar multiplication) + pub lagrange_coeffs: [Column; constants::H], + /// Fixed z such that y + z = u^2 some square, and -y + z is a non-square. (Used in fixed-base scalar multiplication) + pub fixed_z: Column, + + /// Incomplete addition + pub q_add: Selector, + /// Complete addition + pub q_add_complete: Selector, + /// Point doubling + pub q_double: Selector, + /// Variable-base scalar multiplication + pub q_mul: Selector, + /// Fixed-base full-width scalar multiplication + pub q_mul_fixed: Selector, + /// Fixed-base signed short scalar multiplication + pub q_mul_fixed_short: Selector, + /// Witness point + pub q_point: Selector, + /// Witness scalar for variable-base scalar mul + pub q_scalar_var: Selector, + /// Witness full-width scalar for fixed-base scalar mul + pub q_scalar_fixed: Selector, + /// Witness signed short scalar for full-width fixed-base scalar mul + pub q_scalar_fixed_short: Selector, + /// Copy bits of decomposed scalars + pub perm_scalar: Permutation, + /// Copy between (x_p, y_p) and (x_a, y_a) + pub perm_sum: Permutation, } /// A chip implementing EccInstructions @@ -100,7 +100,7 @@ pub struct EccChip { #[allow(non_snake_case)] impl EccChip { - fn configure( + pub fn configure( meta: &mut ConstraintSystem, bits: Column, u: Column, diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index 876c7dcbb..3582e2859 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -2,10 +2,15 @@ use super::super::ecc::chip::{EccChip, EccConfig}; use super::{CommitDomains, HashDomains, SinsemillaInstructions}; use crate::constants::OrchardFixedBases; +use crate::primitives::sinsemilla::K; + +use ff::Field; +use group::Curve; use halo2::{ arithmetic::{CurveAffine, FieldExt}, circuit::{Cell, Layouter}, - plonk::{Error, Selector}, + plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, + poly::Rotation, }; mod generator_table; @@ -92,6 +97,82 @@ impl CommitDomains, OrchardHashDomains EccChip { + fn configure_sinsemilla( + meta: &mut ConstraintSystem, + q_sinsemilla: Selector, + bits: Column, + u: Column, + A: (Column, Column), + P: (Column, Column), + lambda: (Column, Column), + add_complete_bool: [Column; 4], + add_complete_inv: [Column; 4], + ) -> SinsemillaConfig { + let ecc_config = EccChip::::configure( + meta, + bits, + u, + A, + P, + lambda, + add_complete_bool, + add_complete_inv, + ); + + // Fixed column for Sinsemilla selector + let sinsemilla_cur = meta.query_selector(q_sinsemilla, Rotation::cur()); + + // m_i = z_{i + 1} - (z_i * 2^k) + let z_cur = meta.query_advice(ecc_config.bits, Rotation::cur()); + let z_next = meta.query_advice(ecc_config.bits, Rotation::next()); + let m = z_next - z_cur * C::Base::from_u64((1 << K) as u64); + + // y_a = (1/2) ⋅ (lambda1 + lambda2) ⋅ (x_a - (lambda1^2 - x_a - x_p)) + let lambda1_cur = meta.query_advice(ecc_config.lambda.0, Rotation::cur()); + let lambda2_cur = meta.query_advice(ecc_config.lambda.1, Rotation::cur()); + let x_a_cur = meta.query_advice(ecc_config.A.0, Rotation::cur()); + let x_p_cur = meta.query_advice(ecc_config.P.0, Rotation::cur()); + let y_a_cur = (lambda1_cur.clone() + lambda2_cur.clone()) + * (x_a_cur.clone() + - (lambda1_cur.clone() * lambda1_cur.clone() - x_a_cur.clone() - x_p_cur.clone())) + * C::Base::TWO_INV; + + // y_p = y_a - lambda1 ⋅ (x_a - x_p) + let y_p = y_a_cur.clone() - lambda1_cur.clone() * (x_a_cur.clone() - x_p_cur.clone()); + + let (x_p_init, y_p_init) = get_s_by_idx::(0).to_affine().get_xy().unwrap(); + + let generator_table = GeneratorTable::configure::( + meta, + sinsemilla_cur.clone() * m + + (Expression::Constant(C::Base::one()) - sinsemilla_cur.clone()) * C::Base::zero(), + sinsemilla_cur.clone() * x_p_cur.clone() + + (Expression::Constant(C::Base::one()) - sinsemilla_cur.clone()) * x_p_init, + sinsemilla_cur.clone() * y_p + + (Expression::Constant(C::Base::one()) - sinsemilla_cur.clone()) * y_p_init, + ); + + // TODO: create gates + + SinsemillaConfig { + ecc_config, + generator_table, + q_sinsemilla, + } + } +} + impl SinsemillaInstructions for EccChip { type Message = Message; type CommitDomains = OrchardCommitDomains;