Nova/src/pasta.rs
src/pasta.rsRaw
1//! This module implements the Nova traits for pallas::Point and pallas::Scalar.
2use crate::traits::{ChallengeTrait, CompressedGroup, Group, PrimeField};
3use merlin::Transcript;
4use pasta_curves::arithmetic::{CurveExt, FieldExt, Group as Grp};
5use pasta_curves::group::GroupEncoding;
6use pasta_curves::{self, pallas, Ep, Fq};
7use rand::{CryptoRng, RngCore};
8use std::borrow::Borrow;
9use std::ops::Mul;
10
11impl Group for pallas::Point {
12 type Scalar = pallas::Scalar;
13 type CompressedGroupElement = <pallas::Point as GroupEncoding>::Repr;
14
15 fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self
16 where
17 I: IntoIterator,
18 I::Item: Borrow<Self::Scalar>,
19 J: IntoIterator,
20 J::Item: Borrow<Self>,
21 Self: Clone,
22 {
23 // Unoptimized.
24 scalars
25 .into_iter()
26 .zip(points)
27 .map(|(scalar, point)| (*point.borrow()).mul(*scalar.borrow()))
28 .fold(Ep::group_zero(), |acc, x| acc + x)
29 }
30
31 fn compress(&self) -> Self::CompressedGroupElement {
32 self.to_bytes()
33 }
34
35 fn from_uniform_bytes(bytes: &[u8]) -> Option<Self> {
36 if bytes.len() != 64 {
37 None
38 } else {
39 let mut arr = [0; 32];
40 arr.copy_from_slice(&bytes[0..32]);
41
42 let hash = Ep::hash_to_curve("from_uniform_bytes");
43 Some(hash(&arr))
44 }
45 }
46}
47
48impl PrimeField for pallas::Scalar {
49 fn zero() -> Self {
50 Fq::zero()
51 }
52 fn one() -> Self {
53 Fq::one()
54 }
55 fn from_bytes_mod_order_wide(bytes: &[u8]) -> Option<Self> {
56 if bytes.len() != 64 {
57 None
58 } else {
59 let mut arr = [0; 64];
60 arr.copy_from_slice(&bytes[0..64]);
61 Some(Fq::from_bytes_wide(&arr))
62 }
63 }
64
65 fn random(rng: &mut (impl RngCore + CryptoRng)) -> Self {
66 <Fq as ff::Field>::random(rng)
67 }
68}
69
70impl ChallengeTrait for pallas::Scalar {
71 fn challenge(label: &'static [u8], transcript: &mut Transcript) -> Self {
72 let mut buf = [0u8; 64];
73 transcript.challenge_bytes(label, &mut buf);
74 pallas::Scalar::from_bytes_mod_order_wide(&buf).unwrap()
75 }
76}
77
78impl CompressedGroup for <pallas::Point as GroupEncoding>::Repr {
79 type GroupElement = pallas::Point;
80 fn decompress(&self) -> Option<<Self as CompressedGroup>::GroupElement> {
81 Some(Ep::from_bytes(self).unwrap())
82 }
83 fn as_bytes(&self) -> &[u8] {
84 self
85 }
86}