Simulate incomplete addition

Sinsemilla will use incomplete addition inside the circuit for
efficiency, but the pasta_curves crate uses complete addition.
This commit is contained in:
Jack Grigg 2021-04-20 10:02:59 +12:00
parent 4b05c20a2d
commit 907ff46078
4 changed files with 64 additions and 7 deletions

View File

@ -30,11 +30,11 @@ subtle = "2.3"
[dependencies.halo2]
git = "https://github.com/zcash/halo2.git"
rev = "b079624ea78b4a07d44cb3c725dd734093577062"
rev = "6acacf1aca12f34fc311aa59056e40adc0e6d8bd"
[dependencies.pasta_curves]
git = "https://github.com/zcash/pasta_curves.git"
rev = "0a6b2f6eb5acbe1dabc9e77ed0bcb748cc640196"
rev = "b55a6960dfafd7f767e2820ddf1adaa499322f98"
[dependencies.reddsa]
git = "https://github.com/str4d/redjubjub.git"

View File

@ -6,6 +6,8 @@ use pasta_curves::pallas;
use crate::spec::extract_p;
mod addition;
mod constants;
pub use constants::*;

View File

@ -0,0 +1,55 @@
use std::ops::Add;
use group::Curve;
use pasta_curves::{arithmetic::CurveAffine, pallas};
use subtle::{ConstantTimeEq, CtOption};
/// P {⊥}
///
/// Simulated incomplete addition built over complete addition.
#[derive(Clone, Copy, Debug)]
pub(super) struct IncompletePoint(CtOption<pallas::Point>);
impl From<pallas::Point> for IncompletePoint {
fn from(p: pallas::Point) -> Self {
IncompletePoint(CtOption::new(p, 1.into()))
}
}
impl From<IncompletePoint> for CtOption<pallas::Point> {
fn from(p: IncompletePoint) -> Self {
p.0
}
}
impl Add for IncompletePoint {
type Output = IncompletePoint;
fn add(self, rhs: Self) -> Self::Output {
// ⊥ ⊹ ⊥ = ⊥
// ⊥ ⊹ P = ⊥
IncompletePoint(self.0.and_then(|p| {
// P ⊹ ⊥ = ⊥
rhs.0.and_then(|q| {
// 0 ⊹ 0 = ⊥
// 0 ⊹ P = ⊥
p.to_affine().coordinates().and_then(|c_p| {
// P ⊹ 0 = ⊥
q.to_affine().coordinates().and_then(|c_q| {
// (x, y) ⊹ (x', y') = ⊥ if x == x'
// (x, y) ⊹ (x', y') = (x, y) + (x', y') if x != x'
CtOption::new(p + q, !c_p.x().ct_eq(c_q.x()))
})
})
})
}))
}
}
impl Add<pallas::Point> for IncompletePoint {
type Output = IncompletePoint;
fn add(self, rhs: pallas::Point) -> Self::Output {
self + IncompletePoint(CtOption::new(rhs, 1.into()))
}
}

View File

@ -120,11 +120,11 @@ pub(crate) fn ka_orchard(sk: &pallas::Scalar, b: &pallas::Point) -> pallas::Poin
///
/// [concreteextractorpallas]: https://zips.z.cash/protocol/nu5.pdf#concreteextractorpallas
pub(crate) fn extract_p(point: &pallas::Point) -> pallas::Base {
if let Some((x, _)) = point.to_affine().get_xy().into() {
x
} else {
pallas::Base::zero()
}
point
.to_affine()
.coordinates()
.map(|c| *c.x())
.unwrap_or_else(pallas::Base::zero)
}
#[cfg(test)]