1use primeorder::{
2 elliptic_curve::{
3 bigint::U64, generic_array::typenum, Curve, CurveArithmetic, FieldBytes, FieldBytesEncoding,
4 },
5 point_arithmetic::EquationAIsMinusThree,
6 AffinePoint, PrimeCurve, PrimeCurveParams, ProjectivePoint,
7};
8
9use crate::{
10 prime_field::FieldElement,
11 traits::{Modulus, PrimeFieldConstants},
12};
13
14const ORDER: u64 = 0xffff0f07;
15const FIELD_MODULUS: u64 = 0xffffff67;
16
17impl PrimeFieldConstants<u32> for Modulus<u32, FIELD_MODULUS> {
18 type Repr = FieldBytes<TinyCurve32>;
19 const MODULUS_STR: &'static str = "0xffffff67";
20 const MODULUS: u32 = FIELD_MODULUS as u32;
21 const NUM_BITS: u32 = 32;
22 const CAPACITY: u32 = 31;
23 const TWO_INV: u32 = 0x7fffffb4;
24 const MULTIPLICATIVE_GENERATOR: u32 = 3;
25 const S: u32 = 1;
26 const ROOT_OF_UNITY: u32 = 0xffffff66;
27 const ROOT_OF_UNITY_INV: u32 = 0xffffff66;
28 const DELTA: u32 = 9;
29}
30
31impl PrimeFieldConstants<u32> for Modulus<u32, ORDER> {
32 type Repr = FieldBytes<TinyCurve32>;
33 const MODULUS_STR: &'static str = "0xffff0f07";
34 const MODULUS: u32 = ORDER as u32;
35 const NUM_BITS: u32 = 32;
36 const CAPACITY: u32 = 31;
37 const TWO_INV: u32 = 0x7fff8784;
38 const MULTIPLICATIVE_GENERATOR: u32 = 3;
39 const S: u32 = 1;
40 const ROOT_OF_UNITY: u32 = 0xffff0f06;
41 const ROOT_OF_UNITY_INV: u32 = 0xffff0f06;
42 const DELTA: u32 = 9;
43}
44
45#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
47pub struct TinyCurve32;
48
49impl Curve for TinyCurve32 {
50 type FieldBytesSize = typenum::U8;
51 type Uint = U64;
52 const ORDER: Self::Uint = Self::Uint::from_u64(ORDER);
53}
54
55impl FieldBytesEncoding<TinyCurve32> for <TinyCurve32 as Curve>::Uint {}
56
57impl CurveArithmetic for TinyCurve32 {
58 type Scalar = FieldElement<u32, ORDER>;
59 type AffinePoint = AffinePoint<Self>;
60 type ProjectivePoint = ProjectivePoint<Self>;
61}
62
63impl PrimeCurve for TinyCurve32 {}
64
65impl PrimeCurveParams for TinyCurve32 {
66 type FieldElement = FieldElement<u32, FIELD_MODULUS>;
67 type PointArithmetic = EquationAIsMinusThree;
68
69 const EQUATION_A: Self::FieldElement = FieldElement::new_unchecked(FIELD_MODULUS as u32 - 3);
70 const EQUATION_B: Self::FieldElement = FieldElement::new_unchecked(8);
71 const GENERATOR: (Self::FieldElement, Self::FieldElement) = (
72 FieldElement::new_unchecked(4274000713),
73 FieldElement::new_unchecked(443355223),
74 );
75}
76
77#[cfg(test)]
78mod tests {
79 use super::TinyCurve32;
80 use primeorder::elliptic_curve::{
81 bigint::U64,
82 ops::{MulByGenerator, Reduce},
83 CurveArithmetic, ProjectivePoint,
84 };
85 use proptest::prelude::*;
86
87 type Scalar = <TinyCurve32 as CurveArithmetic>::Scalar;
88 type Point = ProjectivePoint<TinyCurve32>;
89
90 prop_compose! {
91 fn scalar()(n in any::<u64>()) -> Scalar {
93 Scalar::reduce(U64::from(n))
94 }
95 }
96
97 proptest! {
98 #[test]
99 fn mul_by_generator(x in scalar(), y in scalar()) {
100 let p1 = Point::mul_by_generator(&x) + Point::mul_by_generator(&y);
101 let p2 = Point::mul_by_generator(&(x + y));
102 assert_eq!(p1, p2);
103 }
104 }
105}
106
107#[cfg(test)]
108mod tests_scalar {
109 use primeorder::{elliptic_curve::CurveArithmetic, Field, PrimeField};
110
111 use super::TinyCurve32;
112
113 type F = <TinyCurve32 as CurveArithmetic>::Scalar;
114
115 primeorder::impl_field_identity_tests!(F);
116 primeorder::impl_field_invert_tests!(F);
117 primeorder::impl_field_sqrt_tests!(F);
118
119 const T: [u64; 1] = [(F::MODULUS - 1) as u64 >> F::S];
121 primeorder::impl_primefield_tests!(F, T);
122}
123
124#[cfg(test)]
125mod tests_field_element {
126 use primeorder::{Field, PrimeCurveParams, PrimeField};
127
128 use super::TinyCurve32;
129
130 type F = <TinyCurve32 as PrimeCurveParams>::FieldElement;
131
132 primeorder::impl_field_identity_tests!(F);
133 primeorder::impl_field_invert_tests!(F);
134 primeorder::impl_field_sqrt_tests!(F);
135
136 const T: [u64; 1] = [(F::MODULUS - 1) as u64 >> F::S];
138 primeorder::impl_primefield_tests!(F, T);
139}