Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion halo2_gadgets/src/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ pub trait EccInstructions<C: CurveAffine>:
value: Value<C>,
) -> Result<Self::NonIdentityPoint, Error>;

/// Witnesses the given constant point with both coordinates pinned via fixed columns.
/// Returns an error if the point is the identity.
fn witness_point_non_id_from_constant(
&self,
layouter: &mut impl Layouter<C::Base>,
value: C,
) -> Result<Self::NonIdentityPoint, Error>;

/// Witnesses a full-width scalar to be used in variable-base multiplication.
fn witness_scalar_var(
&self,
Expand Down Expand Up @@ -280,7 +288,8 @@ pub struct NonIdentityPoint<C: CurveAffine, EccChip: EccInstructions<C>> {
}

impl<C: CurveAffine, EccChip: EccInstructions<C>> NonIdentityPoint<C, EccChip> {
/// Constructs a new point with the given value.
/// Witnesses the given point with only on-curve / non-identity constraints.
/// For known-constant points use [`NonIdentityPoint::new_from_constant`].
pub fn new(
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
Expand All @@ -290,6 +299,16 @@ impl<C: CurveAffine, EccChip: EccInstructions<C>> NonIdentityPoint<C, EccChip> {
point.map(|inner| NonIdentityPoint { chip, inner })
}

/// Witnesses the given constant point with both coordinates pinned via fixed columns.
pub fn new_from_constant(
chip: EccChip,
mut layouter: impl Layouter<C::Base>,
value: C,
) -> Result<Self, Error> {
let point = chip.witness_point_non_id_from_constant(&mut layouter, value);
point.map(|inner| NonIdentityPoint { chip, inner })
}

/// Constrains this point to be equal in value to another point.
pub fn constrain_equal<Other: Into<Point<C, EccChip>> + Clone>(
&self,
Expand Down
12 changes: 12 additions & 0 deletions halo2_gadgets/src/ecc/chip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,18 @@ where
)
}

fn witness_point_non_id_from_constant(
&self,
layouter: &mut impl Layouter<pallas::Base>,
value: pallas::Affine,
) -> Result<Self::NonIdentityPoint, Error> {
let config = self.config().witness_point;
layouter.assign_region(
|| "witness constant non-identity point",
|mut region| config.constant_point_non_id(value, 0, &mut region),
)
}

fn witness_scalar_var(
&self,
_layouter: &mut impl Layouter<pallas::Base>,
Expand Down
34 changes: 33 additions & 1 deletion halo2_gadgets/src/ecc/chip/witness_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,30 @@ impl Config {
self.assign_xy(value, offset, region)
.map(|(x, y)| NonIdentityEccPoint::from_coordinates_unchecked(x, y))
}

/// Assigns a constant non-identity point with both coordinates pinned via fixed columns.
pub(super) fn constant_point_non_id(
&self,
value: pallas::Affine,
offset: usize,
region: &mut Region<'_, pallas::Base>,
) -> Result<NonIdentityEccPoint, Error> {
// Enable `q_point_non_id` selector
self.q_point_non_id.enable(region, offset)?;

// Return an error if the point is the identity.
if value == pallas::Affine::identity() {
return Err(Error::Synthesis);
}

let value = {
let value = value.coordinates().unwrap();
(value.x().into(), value.y().into())
};

self.assign_xy_from_constant(value, offset, region)
.map(|(x, y)| NonIdentityEccPoint::from_coordinates_unchecked(x, y))
}
}

#[cfg(test)]
Expand All @@ -202,10 +226,18 @@ pub mod tests {
) {
// Witnessing the identity should return an error.
NonIdentityPoint::new(
chip,
chip.clone(),
layouter.namespace(|| "witness identity"),
Value::known(pallas::Affine::identity()),
)
.expect_err("witnessing 𝒪 should return an error");

// Witnessing the identity from a constant should return an error.
NonIdentityPoint::new_from_constant(
chip,
layouter.namespace(|| "witness identity"),
pallas::Affine::identity(),
)
.expect_err("witnessing 𝒪 should return an error");
}
}
Loading