mirror of https://github.com/zcash/orchard.git
Further fixes.
This commit is contained in:
parent
56225d603a
commit
96504e7162
|
@ -6,6 +6,3 @@ members = [
|
||||||
"halo2_poseidon",
|
"halo2_poseidon",
|
||||||
"sinsemilla",
|
"sinsemilla",
|
||||||
]
|
]
|
||||||
|
|
||||||
[patch.crates-io]
|
|
||||||
halo2 = { git = "https://github.com/zcash/halo2.git", rev = "27c4187673a9c6ade13fbdbd4f20955530c22d7f" }
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ arrayvec = "0.7.0"
|
||||||
bigint = "4"
|
bigint = "4"
|
||||||
ff = "0.11"
|
ff = "0.11"
|
||||||
group = "0.11"
|
group = "0.11"
|
||||||
halo2 = "0.0"
|
halo2 = "=0.1.0-beta.1"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
pasta_curves = "0.2.1"
|
pasta_curves = "0.2.1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl EccPoint {
|
||||||
self.y
|
self.y
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(feature = "testing")]
|
||||||
fn is_identity(&self) -> Option<bool> {
|
fn is_identity(&self) -> Option<bool> {
|
||||||
self.x.value().map(|x| x == pallas::Base::zero())
|
self.x.value().map(|x| x == pallas::Base::zero())
|
||||||
}
|
}
|
||||||
|
@ -103,17 +103,6 @@ pub struct NonIdentityEccPoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonIdentityEccPoint {
|
impl NonIdentityEccPoint {
|
||||||
/// Constructs a point from its coordinates, without checking they are on the curve.
|
|
||||||
///
|
|
||||||
/// This is an internal API that we only use where we know we have a valid non-identity
|
|
||||||
/// curve point (specifically inside Sinsemilla).
|
|
||||||
pub(in crate::circuit::gadget) fn from_coordinates_unchecked(
|
|
||||||
x: CellValue<pallas::Base>,
|
|
||||||
y: CellValue<pallas::Base>,
|
|
||||||
) -> Self {
|
|
||||||
NonIdentityEccPoint { x, y }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the value of this curve point, if known.
|
/// Returns the value of this curve point, if known.
|
||||||
pub fn point(&self) -> Option<pallas::Affine> {
|
pub fn point(&self) -> Option<pallas::Affine> {
|
||||||
match (self.x.value(), self.y.value()) {
|
match (self.x.value(), self.y.value()) {
|
||||||
|
@ -447,6 +436,81 @@ impl<Fixed: FixedPoints<pallas::Affine>> EccInstructions<pallas::Affine> for Ecc
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn copy_point(
|
||||||
|
&self,
|
||||||
|
layouter: &mut impl Layouter<pallas::Base>,
|
||||||
|
point: Self::Point,
|
||||||
|
) -> Result<Self::Point, Error> {
|
||||||
|
let config: witness_point::Config = self.config().into();
|
||||||
|
let (x, y) = layouter.assign_region(
|
||||||
|
|| "copy point",
|
||||||
|
|mut region| {
|
||||||
|
let x = {
|
||||||
|
let cell = region.assign_advice(
|
||||||
|
|| "copy x",
|
||||||
|
config.x,
|
||||||
|
0,
|
||||||
|
|| point.x().value().ok_or(Error::SynthesisError),
|
||||||
|
)?;
|
||||||
|
region.constrain_equal(cell, point.x().cell())?;
|
||||||
|
CellValue::new(cell, point.x().value())
|
||||||
|
};
|
||||||
|
let y = {
|
||||||
|
let cell = region.assign_advice(
|
||||||
|
|| "copy y",
|
||||||
|
config.y,
|
||||||
|
0,
|
||||||
|
|| point.y().value().ok_or(Error::SynthesisError),
|
||||||
|
)?;
|
||||||
|
region.constrain_equal(cell, point.y().cell())?;
|
||||||
|
CellValue::new(cell, point.y().value())
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((x, y))
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(EccPoint { x, y })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_point_non_id(
|
||||||
|
&self,
|
||||||
|
layouter: &mut impl Layouter<pallas::Base>,
|
||||||
|
x: Self::Var,
|
||||||
|
y: Self::Var,
|
||||||
|
) -> Result<Self::NonIdentityPoint, Error> {
|
||||||
|
let config: witness_point::Config = self.config().into();
|
||||||
|
let (x, y) = layouter.assign_region(
|
||||||
|
|| "copy point",
|
||||||
|
|mut region| {
|
||||||
|
let x = {
|
||||||
|
let cell = region.assign_advice(
|
||||||
|
|| "copy x",
|
||||||
|
config.x,
|
||||||
|
0,
|
||||||
|
|| x.value().ok_or(Error::SynthesisError),
|
||||||
|
)?;
|
||||||
|
region.constrain_equal(cell, x.cell())?;
|
||||||
|
CellValue::new(cell, x.value())
|
||||||
|
};
|
||||||
|
let y = {
|
||||||
|
let cell = region.assign_advice(
|
||||||
|
|| "copy y",
|
||||||
|
config.y,
|
||||||
|
0,
|
||||||
|
|| y.value().ok_or(Error::SynthesisError),
|
||||||
|
)?;
|
||||||
|
region.constrain_equal(cell, y.cell())?;
|
||||||
|
CellValue::new(cell, y.value())
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((x, y))
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(NonIdentityEccPoint { x, y })
|
||||||
|
}
|
||||||
|
|
||||||
fn extract_p<Point: Into<Self::Point> + Clone>(point: &Point) -> Self::X {
|
fn extract_p<Point: Into<Self::Point> + Clone>(point: &Point) -> Self::X {
|
||||||
let point: EccPoint = (point.clone()).into();
|
let point: EccPoint = (point.clone()).into();
|
||||||
point.x()
|
point.x()
|
||||||
|
|
|
@ -391,7 +391,10 @@ pub mod tests {
|
||||||
use halo2::{circuit::Layouter, plonk::Error};
|
use halo2::{circuit::Layouter, plonk::Error};
|
||||||
use pasta_curves::{arithmetic::CurveExt, pallas};
|
use pasta_curves::{arithmetic::CurveExt, pallas};
|
||||||
|
|
||||||
use crate::gadget::{EccInstructions, NonIdentityPoint};
|
use crate::{
|
||||||
|
chip::EccPoint,
|
||||||
|
gadget::{EccInstructions, NonIdentityPoint, Point},
|
||||||
|
};
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn test_add<
|
pub fn test_add<
|
||||||
|
|
|
@ -145,11 +145,13 @@ impl Config {
|
||||||
|
|
||||||
#[cfg(feature = "testing")]
|
#[cfg(feature = "testing")]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use group::{prime::PrimeCurveAffine, Curve, Group};
|
use group::{Curve, Group};
|
||||||
use halo2::{circuit::Layouter, plonk::Error};
|
use halo2::{circuit::Layouter, plonk::Error};
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
|
|
||||||
use crate::gadget::{EccInstructions, NonIdentityPoint};
|
use crate::{
|
||||||
|
gadget::{EccInstructions, NonIdentityPoint},
|
||||||
|
};
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn test_add_incomplete<
|
pub fn test_add_incomplete<
|
||||||
|
@ -171,15 +173,6 @@ pub mod tests {
|
||||||
// Make sure P and Q are not the same point.
|
// Make sure P and Q are not the same point.
|
||||||
assert_ne!(p_val, q_val);
|
assert_ne!(p_val, q_val);
|
||||||
|
|
||||||
// Generate a (0,0) point to be used in other tests.
|
|
||||||
let zero = {
|
|
||||||
Point::new(
|
|
||||||
chip.clone(),
|
|
||||||
layouter.namespace(|| "identity"),
|
|
||||||
Some(pallas::Affine::identity()),
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
// P + Q
|
// P + Q
|
||||||
{
|
{
|
||||||
let result = p.add_incomplete(layouter.namespace(|| "P + Q"), &q)?;
|
let result = p.add_incomplete(layouter.namespace(|| "P + Q"), &q)?;
|
||||||
|
|
|
@ -444,7 +444,7 @@ fn decompose_for_scalar_mul(scalar: Option<pallas::Base>) -> Vec<Option<bool>> {
|
||||||
|
|
||||||
#[cfg(feature = "testing")]
|
#[cfg(feature = "testing")]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use group::{prime::PrimeCurveAffine, Curve, Group};
|
use group::{Curve, Group};
|
||||||
use halo2::{
|
use halo2::{
|
||||||
circuit::{Chip, Layouter},
|
circuit::{Chip, Layouter},
|
||||||
plonk::Error,
|
plonk::Error,
|
||||||
|
@ -452,7 +452,7 @@ pub mod tests {
|
||||||
use pasta_curves::{arithmetic::FieldExt, pallas};
|
use pasta_curves::{arithmetic::FieldExt, pallas};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chip::EccChip,
|
chip::{EccChip, EccPoint},
|
||||||
gadget::{EccInstructions, FixedPoints, NonIdentityPoint, Point},
|
gadget::{EccInstructions, FixedPoints, NonIdentityPoint, Point},
|
||||||
};
|
};
|
||||||
use utilities::UtilitiesInstructions;
|
use utilities::UtilitiesInstructions;
|
||||||
|
@ -465,15 +465,6 @@ pub mod tests {
|
||||||
let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P
|
let p_val = pallas::Point::random(rand::rngs::OsRng).to_affine(); // P
|
||||||
let p = NonIdentityPoint::new(chip.clone(), layouter.namespace(|| "P"), Some(p_val))?;
|
let p = NonIdentityPoint::new(chip.clone(), layouter.namespace(|| "P"), Some(p_val))?;
|
||||||
|
|
||||||
// Generate a (0,0) point to be used in other tests.
|
|
||||||
let zero = {
|
|
||||||
Point::new(
|
|
||||||
chip.clone(),
|
|
||||||
layouter.namespace(|| "identity"),
|
|
||||||
Some(pallas::Affine::identity()),
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let column = chip.config().advices[0];
|
let column = chip.config().advices[0];
|
||||||
|
|
||||||
fn constrain_equal_non_id<
|
fn constrain_equal_non_id<
|
||||||
|
|
|
@ -364,7 +364,7 @@ pub mod tests {
|
||||||
*magnitude,
|
*magnitude,
|
||||||
*sign,
|
*sign,
|
||||||
)?;
|
)?;
|
||||||
value_commit_v.mul_short(layouter.namespace(|| *name), magnitude_sign)?
|
base.mul_short(layouter.namespace(|| *name), magnitude_sign)?
|
||||||
};
|
};
|
||||||
assert!(result.inner().is_identity().unwrap());
|
assert!(result.inner().is_identity().unwrap());
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ use halo2::{
|
||||||
poly::Rotation,
|
poly::Rotation,
|
||||||
};
|
};
|
||||||
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
use pasta_curves::{arithmetic::CurveAffine, pallas};
|
||||||
use utilities::copy;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
@ -147,20 +146,20 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(feature = "testing")]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use halo2::circuit::Layouter;
|
use halo2::circuit::Layouter;
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::circuit::gadget::ecc::{EccInstructions, NonIdentityPoint};
|
use crate::gadget::{EccInstructions, NonIdentityPoint};
|
||||||
|
|
||||||
pub fn test_witness_non_id<
|
pub fn test_witness_non_id<
|
||||||
EccChip: EccInstructions<pallas::Affine> + Clone + Eq + std::fmt::Debug,
|
EccChip: EccInstructions<pallas::Affine> + Clone + Eq + std::fmt::Debug,
|
||||||
>(
|
>(
|
||||||
chip: EccChip,
|
chip: EccChip,
|
||||||
mut layouter: impl Layouter<pallas::Base>,
|
mut layouter: impl Layouter<pallas::Base>,
|
||||||
) {
|
) -> Result<(), Error> {
|
||||||
// Witnessing the identity should return an error.
|
// Witnessing the identity should return an error.
|
||||||
NonIdentityPoint::new(
|
NonIdentityPoint::new(
|
||||||
chip,
|
chip,
|
||||||
|
@ -168,23 +167,7 @@ pub mod tests {
|
||||||
Some(pallas::Affine::identity()),
|
Some(pallas::Affine::identity()),
|
||||||
)
|
)
|
||||||
.expect_err("witnessing 𝒪 should return an error");
|
.expect_err("witnessing 𝒪 should return an error");
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn copy_point(
|
Ok(())
|
||||||
&self,
|
|
||||||
x: CellValue<pallas::Base>,
|
|
||||||
y: CellValue<pallas::Base>,
|
|
||||||
offset: usize,
|
|
||||||
region: &mut Region<'_, pallas::Base>,
|
|
||||||
) -> Result<EccPoint, Error> {
|
|
||||||
// Enable `q_point` selector
|
|
||||||
self.q_point.enable(region, offset)?;
|
|
||||||
|
|
||||||
// Copy `x` value
|
|
||||||
let x = copy(region, || "x", self.x, offset, &x)?;
|
|
||||||
// Copy `y` value
|
|
||||||
let y = copy(region, || "y", self.y, offset, &y)?;
|
|
||||||
|
|
||||||
Ok(EccPoint { x, y })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! Gadgets for elliptic curve operations.
|
//! Gadgets for elliptic curve operations.
|
||||||
|
|
||||||
|
use pasta_curves::arithmetic::CurveAffine;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use halo2::{
|
use halo2::{
|
||||||
arithmetic::CurveAffine,
|
|
||||||
circuit::{Chip, Layouter},
|
circuit::{Chip, Layouter},
|
||||||
plonk::Error,
|
plonk::Error,
|
||||||
};
|
};
|
||||||
|
@ -79,11 +79,19 @@ pub trait EccInstructions<C: CurveAffine>:
|
||||||
/// checking that the coordinates indeed belong to a valid point.
|
/// checking that the coordinates indeed belong to a valid point.
|
||||||
/// This maps the identity to (0, 0) in affine coordinates.
|
/// This maps the identity to (0, 0) in affine coordinates.
|
||||||
fn copy_point(
|
fn copy_point(
|
||||||
|
&self,
|
||||||
|
layouter: &mut impl Layouter<C::Base>,
|
||||||
|
point: Self::Point,
|
||||||
|
) -> Result<Self::Point, Error>;
|
||||||
|
|
||||||
|
/// Copies a point given existing x- and y-coordinate variables,
|
||||||
|
/// checking that the coordinates indeed belong to a valid point.
|
||||||
|
fn copy_point_non_id(
|
||||||
&self,
|
&self,
|
||||||
layouter: &mut impl Layouter<C::Base>,
|
layouter: &mut impl Layouter<C::Base>,
|
||||||
x: Self::Var,
|
x: Self::Var,
|
||||||
y: Self::Var,
|
y: Self::Var,
|
||||||
) -> Result<Self::Point, Error>;
|
) -> Result<Self::NonIdentityPoint, Error>;
|
||||||
|
|
||||||
/// Extracts the x-coordinate of a point.
|
/// Extracts the x-coordinate of a point.
|
||||||
fn extract_p<Point: Into<Self::Point> + Clone>(point: &Point) -> Self::X;
|
fn extract_p<Point: Into<Self::Point> + Clone>(point: &Point) -> Self::X;
|
||||||
|
@ -199,17 +207,6 @@ impl<C: CurveAffine, EccChip: EccInstructions<C>> NonIdentityPoint<C, EccChip> {
|
||||||
point.map(|inner| NonIdentityPoint { chip, inner })
|
point.map(|inner| NonIdentityPoint { chip, inner })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a new point by copying in its coordinates as `x`, `y` cells.
|
|
||||||
pub fn copy(
|
|
||||||
chip: EccChip,
|
|
||||||
mut layouter: impl Layouter<C::Base>,
|
|
||||||
x: EccChip::Var,
|
|
||||||
y: EccChip::Var,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let point = chip.copy_point(&mut layouter, x, y);
|
|
||||||
point.map(|inner| Point { chip, inner })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constrains this point to be equal in value to another point.
|
/// Constrains this point to be equal in value to another point.
|
||||||
pub fn constrain_equal<Other: Into<Point<C, EccChip>> + Clone>(
|
pub fn constrain_equal<Other: Into<Point<C, EccChip>> + Clone>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -224,6 +221,17 @@ impl<C: CurveAffine, EccChip: EccInstructions<C>> NonIdentityPoint<C, EccChip> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a new point by copying in its coordinates as `x`, `y` cells.
|
||||||
|
pub fn copy(
|
||||||
|
chip: EccChip,
|
||||||
|
mut layouter: impl Layouter<C::Base>,
|
||||||
|
x: EccChip::Var,
|
||||||
|
y: EccChip::Var,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let point = chip.copy_point_non_id(&mut layouter, x, y);
|
||||||
|
point.map(|inner| NonIdentityPoint { chip, inner })
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the inner point.
|
/// Returns the inner point.
|
||||||
pub fn inner(&self) -> &EccChip::NonIdentityPoint {
|
pub fn inner(&self) -> &EccChip::NonIdentityPoint {
|
||||||
&self.inner
|
&self.inner
|
||||||
|
@ -338,6 +346,16 @@ impl<C: CurveAffine, EccChip: EccInstructions<C> + Clone + Debug + Eq> Point<C,
|
||||||
.constrain_equal(&mut layouter, &self.inner, &other.inner)
|
.constrain_equal(&mut layouter, &self.inner, &other.inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a new point by copying in its coordinates as `x`, `y` cells.
|
||||||
|
pub fn copy(
|
||||||
|
chip: EccChip,
|
||||||
|
mut layouter: impl Layouter<C::Base>,
|
||||||
|
point: EccChip::Point,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let point = chip.copy_point(&mut layouter, point);
|
||||||
|
point.map(|inner| Point { chip, inner })
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the inner point.
|
/// Returns the inner point.
|
||||||
pub fn inner(&self) -> &EccChip::Point {
|
pub fn inner(&self) -> &EccChip::Point {
|
||||||
&self.inner
|
&self.inner
|
||||||
|
|
|
@ -21,7 +21,7 @@ pprof = { version = "0.4.2", features = ["criterion", "flamegraph"] }
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitvec = "0.22"
|
bitvec = "0.22"
|
||||||
ff = "0.11"
|
ff = "0.11"
|
||||||
halo2 = { version = "0.0", optional = true }
|
halo2 = { version = "=0.1.0-beta.1", optional = true }
|
||||||
pasta_curves = "0.2.1"
|
pasta_curves = "0.2.1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
utilities = { package = "halo2_utilities", version = "0.0", path = "../halo2_utilities" }
|
utilities = { package = "halo2_utilities", version = "0.0", path = "../halo2_utilities" }
|
||||||
|
|
|
@ -18,7 +18,7 @@ publish = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bigint = "4"
|
bigint = "4"
|
||||||
ff = "0.11"
|
ff = "0.11"
|
||||||
halo2 = "0.0"
|
halo2 = "=0.1.0-beta.1"
|
||||||
pasta_curves = "0.2.1"
|
pasta_curves = "0.2.1"
|
||||||
proptest = { version = "1.0.0", optional = true }
|
proptest = { version = "1.0.0", optional = true }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|
|
@ -22,7 +22,7 @@ pprof = { version = "0.4.2", features = ["criterion", "flamegraph"] }
|
||||||
ecc = { package = "halo2_ecc", version = "0.0", path = "../halo2_ecc" }
|
ecc = { package = "halo2_ecc", version = "0.0", path = "../halo2_ecc" }
|
||||||
ff = "0.11"
|
ff = "0.11"
|
||||||
group = "0.11"
|
group = "0.11"
|
||||||
halo2 = { version = "0.0", optional = true }
|
halo2 = { version = "=0.1.0-beta.1", optional = true }
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
pasta_curves = "0.2.1"
|
pasta_curves = "0.2.1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{
|
use super::{
|
||||||
gadget::{self, CommitDomains, HashDomains, SinsemillaInstructions},
|
gadget::{CommitDomains, HashDomains, SinsemillaInstructions, Point as PointTrait},
|
||||||
message::{Message, MessagePiece},
|
message::{Message, MessagePiece},
|
||||||
primitive as sinsemilla,
|
primitive as sinsemilla,
|
||||||
};
|
};
|
||||||
|
@ -26,12 +26,12 @@ mod hash_to_point;
|
||||||
|
|
||||||
/// A point output by hash_to_point
|
/// A point output by hash_to_point
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Point {
|
pub struct Point {
|
||||||
x: CellValue<pallas::Base>,
|
x: CellValue<pallas::Base>,
|
||||||
y: CellValue<pallas::Base>,
|
y: CellValue<pallas::Base>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl gadget::Point<pallas::Affine, CellValue<pallas::Base>> for Point {
|
impl PointTrait<pallas::Affine, CellValue<pallas::Base>> for Point {
|
||||||
fn x(&self) -> CellValue<pallas::Base> {
|
fn x(&self) -> CellValue<pallas::Base> {
|
||||||
self.x
|
self.x
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,7 +231,7 @@ pub struct HashDomain<
|
||||||
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
||||||
EccChip: EccInstructions<
|
EccChip: EccInstructions<
|
||||||
C,
|
C,
|
||||||
NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
// NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
||||||
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
||||||
Var = SinsemillaChip::Var,
|
Var = SinsemillaChip::Var,
|
||||||
> + Clone
|
> + Clone
|
||||||
|
@ -249,7 +249,7 @@ where
|
||||||
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
||||||
EccChip: EccInstructions<
|
EccChip: EccInstructions<
|
||||||
C,
|
C,
|
||||||
NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
// NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
||||||
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
||||||
Var = SinsemillaChip::Var,
|
Var = SinsemillaChip::Var,
|
||||||
> + Clone
|
> + Clone
|
||||||
|
@ -340,7 +340,7 @@ pub struct CommitDomain<
|
||||||
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
||||||
EccChip: EccInstructions<
|
EccChip: EccInstructions<
|
||||||
C,
|
C,
|
||||||
NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
// NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
||||||
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
||||||
Var = SinsemillaChip::Var,
|
Var = SinsemillaChip::Var,
|
||||||
> + Clone
|
> + Clone
|
||||||
|
@ -357,7 +357,7 @@ where
|
||||||
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
SinsemillaChip: SinsemillaInstructions<C, K, MAX_WORDS> + Clone + Debug + Eq,
|
||||||
EccChip: EccInstructions<
|
EccChip: EccInstructions<
|
||||||
C,
|
C,
|
||||||
NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
// NonIdentityPoint = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::NonIdentityPoint,
|
||||||
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
FixedPoints = <SinsemillaChip as SinsemillaInstructions<C, K, MAX_WORDS>>::FixedPoints,
|
||||||
Var = SinsemillaChip::Var,
|
Var = SinsemillaChip::Var,
|
||||||
> + Clone
|
> + Clone
|
||||||
|
@ -614,8 +614,8 @@ pub mod testing {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
NonIdentityPoint::new(
|
Point::new(
|
||||||
ecc_chip,
|
ecc_chip.clone(),
|
||||||
layouter.namespace(|| "Witness expected result"),
|
layouter.namespace(|| "Witness expected result"),
|
||||||
expected_result,
|
expected_result,
|
||||||
)?
|
)?
|
||||||
|
|
|
@ -164,26 +164,20 @@ where
|
||||||
pub mod testing {
|
pub mod testing {
|
||||||
use super::{
|
use super::{
|
||||||
chip::{MerkleChip, MerkleConfig},
|
chip::{MerkleChip, MerkleConfig},
|
||||||
i2lebsp, MerklePath, L_PALLAS_BASE, MERKLE_DEPTH,
|
MerklePath, MERKLE_DEPTH,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
chip::SinsemillaChip,
|
chip::SinsemillaChip,
|
||||||
gadget::{CommitDomains, HashDomains},
|
gadget::{CommitDomains, HashDomains},
|
||||||
primitive::HashDomain,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use ecc::gadget::FixedPoints;
|
use ecc::gadget::FixedPoints;
|
||||||
use utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions, Var};
|
use utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions, Var};
|
||||||
|
|
||||||
use ff::PrimeFieldBits;
|
|
||||||
use group::prime::PrimeCurveAffine;
|
|
||||||
use halo2::{
|
use halo2::{
|
||||||
circuit::{Layouter, SimpleFloorPlanner},
|
circuit::{Layouter, SimpleFloorPlanner},
|
||||||
dev::MockProver,
|
|
||||||
note::commitment::ExtractedNoteCommitment,
|
|
||||||
plonk::{Circuit, ConstraintSystem, Error},
|
plonk::{Circuit, ConstraintSystem, Error},
|
||||||
tree,
|
|
||||||
};
|
};
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
|
|
||||||
|
@ -313,25 +307,29 @@ pub mod testing {
|
||||||
path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?;
|
path.calculate_root(layouter.namespace(|| "calculate root"), leaf)?;
|
||||||
|
|
||||||
if let Some(leaf_pos) = self.leaf_pos {
|
if let Some(leaf_pos) = self.leaf_pos {
|
||||||
let domain = HashDomain {
|
|
||||||
Q: S::hash_domain().Q().to_curve(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// The expected final root
|
// The expected final root
|
||||||
let final_root = {
|
let final_root = S::root(
|
||||||
let path = tree::MerklePath::new(leaf_pos, self.merkle_path.unwrap());
|
self.merkle_path.unwrap(),
|
||||||
let leaf = ExtractedNoteCommitment::from_bytes(&self.leaf.unwrap().to_bytes())
|
leaf_pos,
|
||||||
.unwrap();
|
self.leaf.unwrap(),
|
||||||
path.root(leaf)
|
);
|
||||||
};
|
|
||||||
|
|
||||||
// Check the computed final root against the expected final root.
|
// Check the computed final root against the expected final root.
|
||||||
assert_eq!(computed_final_root.value().unwrap(), final_root.inner());
|
assert_eq!(computed_final_root.value().unwrap(), final_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait MerkleTest<Hash: HashDomains<pallas::Affine>> {
|
||||||
|
fn hash_domain() -> Hash;
|
||||||
|
fn root(
|
||||||
|
path: [pallas::Base; MERKLE_DEPTH],
|
||||||
|
leaf_pos: u32,
|
||||||
|
leaf: pallas::Base,
|
||||||
|
) -> pallas::Base;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "testing")]
|
#[cfg(feature = "testing")]
|
||||||
|
@ -344,9 +342,11 @@ pub mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gadget::{CommitDomains, HashDomains},
|
gadget::{CommitDomains, HashDomains},
|
||||||
|
merkle::{i2lebsp, L_PALLAS_BASE, MERKLE_DEPTH},
|
||||||
primitive::{CommitDomain, HashDomain},
|
primitive::{CommitDomain, HashDomain},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use ff::PrimeFieldBits;
|
||||||
use group::Curve;
|
use group::Curve;
|
||||||
use pasta_curves::pallas;
|
use pasta_curves::pallas;
|
||||||
|
|
||||||
|
@ -406,11 +406,50 @@ pub mod tests {
|
||||||
fn hash_domain() -> Hash {
|
fn hash_domain() -> Hash {
|
||||||
Hash
|
Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn root(path: [pallas::Base; MERKLE_DEPTH],
|
||||||
|
leaf_pos: u32,
|
||||||
|
leaf: pallas::Base,) -> pallas::Base {
|
||||||
|
use group::prime::PrimeCurveAffine;
|
||||||
|
let domain = HashDomain { Q: Self::hash_domain().Q().to_curve() };
|
||||||
|
let pos_bool = i2lebsp::<32>(leaf_pos as u64);
|
||||||
|
|
||||||
|
// Compute the root
|
||||||
|
let mut node = leaf;
|
||||||
|
for (l, (sibling, pos)) in path.iter().zip(pos_bool.iter()).enumerate() {
|
||||||
|
let (left, right) = if *pos {
|
||||||
|
(*sibling, node)
|
||||||
|
} else {
|
||||||
|
(node, *sibling)
|
||||||
|
};
|
||||||
|
|
||||||
|
let l_star = i2lebsp::<10>(l as u64);
|
||||||
|
let left: Vec<_> = left
|
||||||
|
.to_le_bits()
|
||||||
|
.iter()
|
||||||
|
.by_val()
|
||||||
|
.take(L_PALLAS_BASE)
|
||||||
|
.collect();
|
||||||
|
let right: Vec<_> = right
|
||||||
|
.to_le_bits()
|
||||||
|
.iter()
|
||||||
|
.by_val()
|
||||||
|
.take(L_PALLAS_BASE)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut message = l_star.to_vec();
|
||||||
|
message.extend_from_slice(&left);
|
||||||
|
message.extend_from_slice(&right);
|
||||||
|
|
||||||
|
node = domain.hash(message.into_iter()).unwrap();
|
||||||
|
}
|
||||||
|
node
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn merkle_chip() {
|
fn merkle_chip() {
|
||||||
use crate::merkle::{i2lebsp, MERKLE_DEPTH};
|
use crate::merkle::{MERKLE_DEPTH};
|
||||||
use halo2::dev::MockProver;
|
use halo2::dev::MockProver;
|
||||||
use pasta_curves::arithmetic::FieldExt;
|
use pasta_curves::arithmetic::FieldExt;
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
|
|
@ -15,8 +15,7 @@ use pasta_curves::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::{
|
constants::{
|
||||||
util::gen_const_array, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains,
|
OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, MERKLE_DEPTH_ORCHARD,
|
||||||
MERKLE_DEPTH_ORCHARD,
|
|
||||||
},
|
},
|
||||||
keys::{
|
keys::{
|
||||||
CommitIvkRandomness, DiversifiedTransmissionKey, NullifierDerivingKey, SpendValidatingKey,
|
CommitIvkRandomness, DiversifiedTransmissionKey, NullifierDerivingKey, SpendValidatingKey,
|
||||||
|
@ -48,7 +47,8 @@ use sinsemilla::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use utilities::{
|
use utilities::{
|
||||||
copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var,
|
copy, gen_const_array, lookup_range_check::LookupRangeCheckConfig, CellValue,
|
||||||
|
UtilitiesInstructions, Var,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
@ -411,7 +411,7 @@ impl plonk::Circuit<pallas::Base> for Circuit {
|
||||||
config.merkle_chip_2(),
|
config.merkle_chip_2(),
|
||||||
OrchardHashDomains::MerkleCrh,
|
OrchardHashDomains::MerkleCrh,
|
||||||
self.pos,
|
self.pos,
|
||||||
self.path,
|
path,
|
||||||
);
|
);
|
||||||
let leaf = *cm_old.extract_p().inner();
|
let leaf = *cm_old.extract_p().inner();
|
||||||
merkle_inputs.calculate_root(layouter.namespace(|| "MerkleCRH"), leaf)?
|
merkle_inputs.calculate_root(layouter.namespace(|| "MerkleCRH"), leaf)?
|
||||||
|
|
|
@ -303,6 +303,7 @@ fn test_orchard_domains() {
|
||||||
#[cfg(feature = "test-ecc")]
|
#[cfg(feature = "test-ecc")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merkle_crh() {
|
fn test_merkle_crh() {
|
||||||
|
use crate::constants::MERKLE_DEPTH_ORCHARD;
|
||||||
use halo2::dev::MockProver;
|
use halo2::dev::MockProver;
|
||||||
use rand::random;
|
use rand::random;
|
||||||
use sinsemilla::merkle::testing;
|
use sinsemilla::merkle::testing;
|
||||||
|
@ -313,6 +314,17 @@ fn test_merkle_crh() {
|
||||||
fn hash_domain() -> OrchardHashDomains {
|
fn hash_domain() -> OrchardHashDomains {
|
||||||
OrchardHashDomains::MerkleCrh
|
OrchardHashDomains::MerkleCrh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn root(
|
||||||
|
path: [pallas::Base; MERKLE_DEPTH_ORCHARD],
|
||||||
|
leaf_pos: u32,
|
||||||
|
leaf: pallas::Base,
|
||||||
|
) -> pallas::Base {
|
||||||
|
use crate::{note::ExtractedNoteCommitment, tree::MerklePath};
|
||||||
|
let path = MerklePath::new(leaf_pos, path);
|
||||||
|
let leaf = ExtractedNoteCommitment::from_bytes(&leaf.to_bytes()).unwrap();
|
||||||
|
path.root(leaf).inner()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose a random leaf and position
|
// Choose a random leaf and position
|
||||||
|
|
|
@ -7,10 +7,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
note::commitment::ExtractedNoteCommitment,
|
note::commitment::ExtractedNoteCommitment,
|
||||||
};
|
};
|
||||||
use halo2_utilities::utilities::gen_const_array_with_default;
|
|
||||||
use incrementalmerkletree::{Altitude, Hashable};
|
use incrementalmerkletree::{Altitude, Hashable};
|
||||||
use pasta_curves::{arithmetic::FieldExt, pallas};
|
use pasta_curves::{arithmetic::FieldExt, pallas};
|
||||||
use sinsemilla::primitive::HashDomain;
|
use sinsemilla::primitive::HashDomain;
|
||||||
|
use utilities::gen_const_array_with_default;
|
||||||
|
|
||||||
use ff::{Field, PrimeField, PrimeFieldBits};
|
use ff::{Field, PrimeField, PrimeFieldBits};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
Loading…
Reference in New Issue