Skip to content

Commit d580c83

Browse files
authored
feat: (mostly) generic fields (#63)
* feat: gf17 * feat: rework of prime fields * chore: cleanup `prime` module * feat: big field rework * fix + fmt * remove ICE files we don't need to listen to the compiler whine * cleanup + clippy * add: type aliases and their docs * rename to `curve` * clean up * add: notes on `find_generator` function * feat: readme + cleanup * merge + fix one test
1 parent 899f19c commit d580c83

19 files changed

Lines changed: 1743 additions & 1294 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ repository ="https://github.com/thor314/ronkathon"
88
version ="0.1.0"
99

1010
[dependencies]
11-
rand ="0.8"
12-
serde ={ version="1.0", default-features=false, features=["derive"] }
13-
num-bigint={ version="0.4.5", default-features=false }
11+
rand ="0.8.5"
12+
num-bigint={ version="0.4.3", default-features=false }
1413
ark-std ={ version="0.4.0", default-features=false }
1514
ark-bn254 ="0.4.0"
1615
ark-poly ="0.4.0"
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ pub trait EllipticCurve: Copy {
1414
type BaseField: FiniteField;
1515

1616
/// Order of this elliptic curve, i.e. number of elements in the scalar field.
17-
const ORDER: u32;
17+
type ScalarField: FiniteField;
18+
19+
/// Order of this elliptic curve, i.e. number of elements in the scalar field.
20+
const ORDER: usize = Self::ScalarField::ORDER;
1821

1922
/// Coefficient `a` in the Weierstrass equation of this elliptic curve.
2023
const EQUATION_A: Self::Coefficient;
@@ -127,8 +130,8 @@ impl<C: EllipticCurve> Add for AffinePoint<C> {
127130
// compute new point using elliptic curve point group law
128131
// https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication
129132
let lambda = if x1 == x2 && y1 == y2 {
130-
((C::BaseField::TWO + C::BaseField::ONE) * x1 * x1 + C::EQUATION_A.into())
131-
/ (C::BaseField::TWO * y1)
133+
((C::BaseField::ONE + C::BaseField::ONE + C::BaseField::ONE) * x1 * x1 + C::EQUATION_A.into())
134+
/ ((C::BaseField::ONE + C::BaseField::ONE) * y1)
132135
} else {
133136
(y2 - y1) / (x2 - x1)
134137
};
@@ -146,12 +149,13 @@ impl<C: EllipticCurve> AffinePoint<C> {
146149
AffinePoint::PointOnCurve(x, y) => (x, y),
147150
AffinePoint::Infinity => panic!("Cannot double point at infinity"),
148151
};
149-
// m = (3x^2) + a / (2y) (a = 0 on our curve)
150-
let m = ((C::BaseField::TWO + C::BaseField::ONE) * x * x) / (C::BaseField::TWO * y);
152+
// m = (3x^2) / (2y)
153+
let m = (((C::BaseField::ONE + C::BaseField::ONE) + C::BaseField::ONE) * x * x)
154+
/ ((C::BaseField::ONE + C::BaseField::ONE) * y);
151155

152156
// 2P = (m^2 - 2x, m(3x - m^2)- y)
153-
let x_new = m * m - C::BaseField::TWO * x;
154-
let y_new = m * ((C::BaseField::TWO + C::BaseField::ONE) * x - m * m) - y;
157+
let x_new = m * m - (C::BaseField::ONE + C::BaseField::ONE) * x;
158+
let y_new = m * ((C::BaseField::ONE + C::BaseField::ONE + C::BaseField::ONE) * x - m * m) - y;
155159
AffinePoint::new(x_new, y_new)
156160
}
157161

src/curve/pluto_curve.rs

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
//! This module contains the constants and methods for the Pluto curve over the prime field `GF101`
2+
//! and its extensions.
3+
//!
4+
//! The basic idea here is that we have a curve that fixes `EQUATION_A` to 0 and `EQUATION_B` to 3.
5+
//! The rest of the properties of the curve depend solely on the field for which we define it over.
6+
//! This interface allows us to have an easily swappable curve definition for different fields.
7+
//!
8+
//! Note that this would be cleaner if we could use trait specialization to keep the default
9+
//! implementations in the trait itself, but this feature is not yet to that point of utility.
10+
11+
use super::*;
12+
13+
/// The [`PlutoBaseCurve`] is an the base field set to the [`PlutoBaseField`]. This is the curve
14+
/// used in the Pluto `ronkathon` system. The curve is defined by the equation `y^2 = x^3 + 3`.
15+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
16+
pub struct PlutoBaseCurve;
17+
18+
/// The [`PlutoExtendedCurve`] is an instance of the same curve as the [`PlutoBaseCurve`], but with
19+
/// field set to the [`PlutoBaseFieldExtension`].
20+
///
21+
/// This is the curve used in the Pluto `ronkathon` system. The curve is defined by the equation
22+
/// `y^2 = x^3 + 3`, but the field is extended to the quadratic extension field over the base field.
23+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
24+
pub struct PlutoExtendedCurve;
25+
26+
impl EllipticCurve for PlutoBaseCurve {
27+
type BaseField = PlutoBaseField;
28+
type Coefficient = PlutoBaseField;
29+
type ScalarField = PlutoScalarField;
30+
31+
const EQUATION_A: Self::Coefficient = PlutoBaseField::ZERO;
32+
const EQUATION_B: Self::Coefficient = PlutoBaseField::new(3);
33+
const GENERATOR: (Self::BaseField, Self::BaseField) =
34+
(PlutoBaseField::ONE, PlutoBaseField::new(2));
35+
}
36+
37+
impl EllipticCurve for PlutoExtendedCurve {
38+
type BaseField = PlutoBaseFieldExtension;
39+
type Coefficient = PlutoBaseField;
40+
// TODO: This scalar field is not correct yet. We need to implement the correct scalar field for
41+
// the extension field as `PlutoScalarFieldExtension`
42+
type ScalarField = PlutoScalarField;
43+
44+
const EQUATION_A: Self::Coefficient = PlutoBaseField::ZERO;
45+
const EQUATION_B: Self::Coefficient = PlutoBaseField::new(3);
46+
const GENERATOR: (Self::BaseField, Self::BaseField) = (
47+
PlutoBaseFieldExtension::new([PlutoBaseField::new(36), PlutoBaseField::ZERO]),
48+
PlutoBaseFieldExtension::new([PlutoBaseField::ZERO, PlutoBaseField::new(31)]),
49+
);
50+
}
51+
52+
#[cfg(test)]
53+
mod pluto_base_curve_tests {
54+
use super::*;
55+
56+
#[test]
57+
fn point_doubling() {
58+
let g = AffinePoint::<PlutoBaseCurve>::generator();
59+
60+
let two_g = g.point_doubling();
61+
let expected_2g =
62+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(68), PlutoBaseField::new(74));
63+
let expected_negative_2g =
64+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(68), PlutoBaseField::new(27));
65+
assert_eq!(two_g, expected_2g);
66+
assert_eq!(-two_g, expected_negative_2g);
67+
68+
let four_g = two_g.point_doubling();
69+
let expected_4g =
70+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(65), PlutoBaseField::new(98));
71+
let expected_negative_4g =
72+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(65), PlutoBaseField::new(3));
73+
assert_eq!(four_g, expected_4g);
74+
assert_eq!(-four_g, expected_negative_4g);
75+
76+
let eight_g = four_g.point_doubling();
77+
let expected_8g =
78+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(18), PlutoBaseField::new(49));
79+
let expected_negative_8g =
80+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(18), PlutoBaseField::new(52));
81+
assert_eq!(eight_g, expected_8g);
82+
assert_eq!(-eight_g, expected_negative_8g);
83+
84+
let sixteen_g = eight_g.point_doubling();
85+
let expected_16g =
86+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(1), PlutoBaseField::new(99));
87+
let expected_negative_16g =
88+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(1), PlutoBaseField::new(2));
89+
assert_eq!(sixteen_g, expected_16g);
90+
assert_eq!(-sixteen_g, expected_negative_16g);
91+
assert_eq!(g, -sixteen_g);
92+
}
93+
94+
#[test]
95+
fn order_17() {
96+
let g = AffinePoint::<PlutoBaseCurve>::generator();
97+
let mut g_double = g.point_doubling();
98+
let mut count = 2;
99+
while g_double != g && -g_double != g {
100+
g_double = g_double.point_doubling();
101+
count *= 2;
102+
}
103+
assert_eq!(count + 1, 17);
104+
}
105+
106+
#[test]
107+
fn point_addition() {
108+
let g = AffinePoint::<PlutoBaseCurve>::generator();
109+
let two_g = g.point_doubling();
110+
let three_g = g + two_g;
111+
let expected_3g =
112+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(26), PlutoBaseField::new(45));
113+
let expected_negative_3g =
114+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(26), PlutoBaseField::new(56));
115+
assert_eq!(three_g, expected_3g);
116+
assert_eq!(-three_g, expected_negative_3g);
117+
118+
let four_g = g + three_g;
119+
let expected_4g =
120+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(65), PlutoBaseField::new(98));
121+
let expected_negative_4g =
122+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(65), PlutoBaseField::new(3));
123+
assert_eq!(four_g, expected_4g);
124+
assert_eq!(-four_g, expected_negative_4g);
125+
126+
let five_g = g + four_g;
127+
let expected_5g =
128+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(12), PlutoBaseField::new(32));
129+
let expected_negative_5g =
130+
AffinePoint::<PlutoBaseCurve>::new(PlutoBaseField::new(12), PlutoBaseField::new(69));
131+
assert_eq!(five_g, expected_5g);
132+
assert_eq!(-five_g, expected_negative_5g);
133+
134+
assert_eq!(g + AffinePoint::Infinity, g);
135+
assert_eq!(AffinePoint::Infinity + g, g);
136+
assert_eq!(g + (-g), AffinePoint::Infinity);
137+
}
138+
139+
#[test]
140+
fn scalar_multiplication_rhs() {
141+
let g = AffinePoint::<PlutoBaseCurve>::generator();
142+
let two_g = g * 2;
143+
let expected_2g = g.point_doubling();
144+
assert_eq!(two_g, expected_2g);
145+
assert_eq!(-two_g, -expected_2g);
146+
}
147+
148+
#[test]
149+
fn scalar_multiplication_lhs() {
150+
let g = AffinePoint::<PlutoBaseCurve>::generator();
151+
let two_g = 2 * g;
152+
let expected_2g = g.point_doubling();
153+
assert_eq!(two_g, expected_2g);
154+
assert_eq!(-two_g, -expected_2g);
155+
}
156+
}
157+
158+
#[cfg(test)]
159+
mod pluto_extended_curve_tests {
160+
use super::*;
161+
162+
fn point() -> AffinePoint<PlutoExtendedCurve> {
163+
AffinePoint::<PlutoExtendedCurve>::new(
164+
PlutoBaseFieldExtension::new([PlutoBaseField::new(90), PlutoBaseField::ZERO]),
165+
PlutoBaseFieldExtension::new([PlutoBaseField::ZERO, PlutoBaseField::new(82)]),
166+
)
167+
}
168+
169+
fn false_point() -> AffinePoint<PlutoExtendedCurve> {
170+
AffinePoint::<PlutoExtendedCurve>::new(
171+
PlutoBaseFieldExtension::new([PlutoBaseField::new(36), PlutoBaseField::ZERO]),
172+
PlutoBaseFieldExtension::new([PlutoBaseField::ZERO, PlutoBaseField::new(81)]),
173+
)
174+
}
175+
176+
fn generator() -> AffinePoint<PlutoExtendedCurve> {
177+
AffinePoint::<PlutoExtendedCurve>::new(
178+
PlutoBaseFieldExtension::new([PlutoBaseField::new(36), PlutoBaseField::ZERO]),
179+
PlutoBaseFieldExtension::new([PlutoBaseField::ZERO, PlutoBaseField::new(31)]),
180+
)
181+
}
182+
183+
#[rstest]
184+
#[case(AffinePoint::<PlutoExtendedCurve>::generator())]
185+
#[case(generator())]
186+
#[case(point())]
187+
#[should_panic]
188+
#[case(false_point())]
189+
fn on_curve(#[case] p: AffinePoint<PlutoExtendedCurve>) { let _ = p; }
190+
191+
#[test]
192+
fn point_doubling() {
193+
let g = AffinePoint::<PlutoExtendedCurve>::generator();
194+
let two_g = g.point_doubling();
195+
196+
let expected_g = generator();
197+
let expected_two_g = point();
198+
199+
assert_eq!(two_g, expected_two_g);
200+
assert_eq!(g, expected_g);
201+
}
202+
203+
#[test]
204+
fn scalar_multiplication_rhs() {
205+
let g = AffinePoint::<PlutoExtendedCurve>::generator();
206+
let two_g = g * 2;
207+
let expected_two_g = g.point_doubling();
208+
assert_eq!(two_g, expected_two_g);
209+
assert_eq!(-two_g, -expected_two_g);
210+
}
211+
212+
#[test]
213+
fn scalar_multiplication_lhs() {
214+
let g = AffinePoint::<PlutoExtendedCurve>::generator();
215+
let two_g = 2 * g;
216+
let expected_two_g = g.point_doubling();
217+
assert_eq!(two_g, expected_two_g);
218+
assert_eq!(-two_g, -expected_two_g);
219+
}
220+
}

0 commit comments

Comments
 (0)