mirror of https://github.com/zcash/orchard.git
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:
parent
4b05c20a2d
commit
907ff46078
|
@ -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"
|
||||
|
|
|
@ -6,6 +6,8 @@ use pasta_curves::pallas;
|
|||
|
||||
use crate::spec::extract_p;
|
||||
|
||||
mod addition;
|
||||
|
||||
mod constants;
|
||||
pub use constants::*;
|
||||
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
10
src/spec.rs
10
src/spec.rs
|
@ -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)]
|
||||
|
|
Loading…
Reference in New Issue