Add Point::new_from_constant method (#17)

It is now possible to create a Point from a constant.
This functionality is required to evaluate the old nullifier.
- for non split_notes, nf_old = Extract_P([PRF^{nfOrchard}_{nk}(rho_old) + psi_nf) mod q_P] NullifierK + cm_old)
- for split notes, nf_old = Extract_P([PRF^{nfOrchard}_{nk}(rho_old) + psi_nf) mod q_P] NullifierK + cm_old + NullifierL)
This commit is contained in:
Constance Beguier 2023-06-23 10:31:10 +02:00 committed by Constance
parent 4ce262d8e7
commit 475f54daa4
3 changed files with 68 additions and 0 deletions

View File

@ -60,6 +60,15 @@ pub trait EccInstructions<C: CurveAffine>:
value: Value<C>,
) -> Result<Self::Point, Error>;
/// Witnesses the given constant point as a private input to the circuit.
/// This allows the point to be the identity, mapped to (0, 0) in
/// affine coordinates.
fn witness_point_from_constant(
&self,
layouter: &mut impl Layouter<C::Base>,
value: C,
) -> Result<Self::Point, Error>;
/// Witnesses the given point as a private input to the circuit.
/// This returns an error if the point is the identity.
fn witness_point_non_id(
@ -399,6 +408,16 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> Point<C,
point.map(|inner| Point { chip, inner })
}
/// Constructs a new point with the given fixed value.
pub fn new_from_constant(
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
value: C,
) -> Result<Self, Error> {
let point = chip.witness_point_from_constant(&mut layouter, value);
point.map(|inner| Point { chip, inner })
}
/// Constrains this point to be equal in value to another point.
pub fn constrain_equal<Other: Into<Point<C, EccChip>> + Clone>(
&self,

View File

@ -453,6 +453,18 @@ where
)
}
fn witness_point_from_constant(
&self,
layouter: &mut impl Layouter<pallas::Base>,
value: pallas::Affine,
) -> Result<Self::Point, Error> {
let config = self.config().witness_point;
layouter.assign_region(
|| "witness point (constant)",
|mut region| config.constant_point(value, 0, &mut region),
)
}
fn witness_point_non_id(
&self,
layouter: &mut impl Layouter<pallas::Base>,

View File

@ -102,6 +102,21 @@ impl Config {
Ok((x_var, y_var))
}
fn assign_xy_constant(
&self,
value: (Assigned<pallas::Base>, Assigned<pallas::Base>),
offset: usize,
region: &mut Region<'_, pallas::Base>,
) -> Result<Coordinates, Error> {
// Assign `x` value
let x_var = region.assign_advice_from_constant(|| "x", self.x, offset, value.0)?;
// Assign `y` value
let y_var = region.assign_advice_from_constant(|| "y", self.y, offset, value.1)?;
Ok((x_var, y_var))
}
/// Assigns a point that can be the identity.
pub(super) fn point(
&self,
@ -126,6 +141,28 @@ impl Config {
.map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y))
}
/// Assigns a constant point that can be the identity.
pub(super) fn constant_point(
&self,
value: pallas::Affine,
offset: usize,
region: &mut Region<'_, pallas::Base>,
) -> Result<EccPoint, Error> {
// Enable `q_point` selector
self.q_point.enable(region, offset)?;
let value = if value == pallas::Affine::identity() {
// Map the identity to (0, 0).
(Assigned::Zero, Assigned::Zero)
} else {
let value = value.coordinates().unwrap();
(value.x().into(), value.y().into())
};
self.assign_xy_constant(value, offset, region)
.map(|(x, y)| EccPoint::from_coordinates_unchecked(x, y))
}
/// Assigns a non-identity point.
pub(super) fn point_non_id(
&self,