From 154306f8c6c66fea8fcf5b77fceef50c43d580fe Mon Sep 17 00:00:00 2001 From: devloper <3347622+devloper@users.noreply.github.com> Date: Wed, 1 May 2024 17:22:56 -0700 Subject: [PATCH] Add custom field with Plonky3 types --- Cargo.lock | 211 +++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 +- rust-toolchain | 2 + src/field.rs | 240 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 7 ++ 6 files changed, 465 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock create mode 100644 rust-toolchain create mode 100644 src/field.rs create mode 100644 src/main.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..08ac036a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,211 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "p3-field" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git#2e274173200ece6254883e7e6eb8bc028574332e" +dependencies = [ + "itertools", + "num-bigint", + "num-traits", + "p3-util", + "rand", + "serde", +] + +[[package]] +name = "p3-util" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git#2e274173200ece6254883e7e6eb8bc028574332e" +dependencies = [ + "serde", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ronkathon" +version = "0.1.0" +dependencies = [ + "anyhow", + "itertools", + "num-bigint", + "p3-field", + "serde", +] + +[[package]] +name = "serde" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/Cargo.toml b/Cargo.toml index 8d944435..ed3037d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,7 @@ version ="0.1.0" [dependencies] anyhow ="1.0" -p3-field = { version = "0.1.0", git = "https://github.com/Plonky3/Plonky3.git"} \ No newline at end of file +p3-field = { version = "0.1.0", git = "https://github.com/Plonky3/Plonky3.git"} +itertools = "0.12.0" +serde = { version = "1.0", default-features = false, features = ["derive"] } +num-bigint = { version = "0.4.3", default-features = false } \ No newline at end of file diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 00000000..5168d8bf --- /dev/null +++ b/rust-toolchain @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly-2023-12-03" \ No newline at end of file diff --git a/src/field.rs b/src/field.rs new file mode 100644 index 00000000..695278ee --- /dev/null +++ b/src/field.rs @@ -0,0 +1,240 @@ +use p3_field::{AbstractField, Field, Packable, halve_u64}; +use core::iter::{Product, Sum}; +use core::hash::{Hash, Hasher}; +use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}; +use serde::{Deserialize, Serialize}; +use std::fmt; +use num_bigint::BigUint; + +const PLUTO_FIELD_PRIME: u64 = 101; +#[derive(Copy, Clone, Default, Serialize, Deserialize, Debug)] +pub struct PlutoField { + value: u64, +} + +impl PlutoField { + const ORDER_U64: u64 = PLUTO_FIELD_PRIME; + + pub fn new(value: u64) -> Self { + Self { value } + } +} + +impl PartialEq for PlutoField { + fn eq(&self, other: &Self) -> bool { + // TODO: removed canonicalization + self.value == other.value + //self.as_canonical_u64() == other.as_canonical_u64() + } +} + +impl fmt::Display for PlutoField { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +impl Eq for PlutoField {} +impl Packable for PlutoField {} + +impl Div for PlutoField { + type Output = Self; + + #[allow(clippy::suspicious_arithmetic_impl)] + fn div(self, rhs: Self) -> Self { + self * rhs.inverse() + } +} +impl Field for PlutoField { + // TODO: Add cfg-guarded Packing for AVX2, NEON, etc. + type Packing = Self; + + fn is_zero(&self) -> bool { + self.value == 0 || self.value == Self::ORDER_U64 + } + + #[inline] + fn exp_u64_generic>(val: AF, _power: u64) -> AF { + // TODO: Fix exponentiation + val + // match power { + // 10540996611094048183 => exp_10540996611094048183(val), // used to compute x^{1/7} + // _ => exp_u64_by_squaring(val, power), + // } + } + + fn try_inverse(&self) -> Option { + // TODO: Fix inverse + Some(Self::new(1)) + } + + #[inline] + fn halve(&self) -> Self { + PlutoField::new(halve_u64::(self.value)) + } + + #[inline] + fn order() -> BigUint { + PLUTO_FIELD_PRIME.into() + } +} + + +impl AbstractField for PlutoField { + type F = Self; + + fn zero() -> Self { + Self::new(0) + } + fn one() -> Self { + Self::new(1) + } + fn two() -> Self { + Self::new(2) + } + fn neg_one() -> Self { + Self::new(Self::ORDER_U64 - 1) + } + + #[inline] + fn from_f(f: Self::F) -> Self { + f + } + + fn from_bool(b: bool) -> Self { + Self::new(u64::from(b)) + } + + fn from_canonical_u8(n: u8) -> Self { + Self::new(u64::from(n)) + } + + fn from_canonical_u16(n: u16) -> Self { + Self::new(u64::from(n)) + } + + fn from_canonical_u32(n: u32) -> Self { + Self::new(u64::from(n)) + } + + fn from_canonical_u64(n: u64) -> Self { + Self::new(n) + } + + fn from_canonical_usize(n: usize) -> Self { + Self::new(n as u64) + } + + fn from_wrapped_u32(n: u32) -> Self { + // A u32 must be canonical, plus we don't store canonical encodings anyway, so there's no + // need for a reduction. + Self::new(u64::from(n)) + } + + fn from_wrapped_u64(n: u64) -> Self { + // There's no need to reduce `n` to canonical form, as our internal encoding is + // non-canonical, so there's no need for a reduction. + Self::new(n) + } + + // Sage: GF(2^64 - 2^32 + 1).multiplicative_generator() + fn generator() -> Self { + Self::new(7) + } +} + +impl Hash for PlutoField { + fn hash(&self, state: &mut H) { + state.write_u64(self.value); + // state.write_u64(self.as_canonical_u64()); + } +} + +// impl PrimeField for PlutoField { +// fn as_canonical_biguint(&self) -> BigUint { +// ::as_canonical_u32(self).into() +// } +// } + +// impl PrimeField64 for PlutoField { +// const ORDER_U64: u64 = ::ORDER_U32 as u64; + +// #[inline] +// fn as_canonical_u64(&self) -> u64 { +// u64::from(self.as_canonical_u32()) +// } +// } + +// impl PrimeField32 for PlutoField { +// const ORDER_U32: u32 = P; + +// #[inline] +// fn as_canonical_u32(&self) -> u32 { +// from_monty(self.value) +// } +// } + +impl Mul for PlutoField { + type Output = Self; + + fn mul(self, rhs: Self) -> Self { + // reduce128(u128::from(self.value) * u128::from(rhs.value)) + let mul = self.value * rhs.value; + Self::new(mul) + } +} + +impl Product for PlutoField { + fn product>(iter: I) -> Self { + iter.reduce(|x, y| x * y).unwrap_or(Self::one()) + } +} + +impl SubAssign for PlutoField { + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs; + } +} + +impl AddAssign for PlutoField { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs; + } +} + +impl MulAssign for PlutoField { + fn mul_assign(&mut self, rhs: Self) { + *self = *self * rhs; + } +} + +impl Neg for PlutoField { + type Output = Self; + + fn neg(self) -> Self::Output { + Self::new(Self::ORDER_U64 - self.value) + // Self::new(Self::ORDER_U64 - self.as_canonical_u64()) + } +} + +impl Add for PlutoField { + type Output = Self; + fn add(self, rhs: Self) -> Self { + Self::new(self.value + rhs.value) + } +} + +impl Sum for PlutoField { + fn sum>(iter: I) -> Self { + iter.reduce(|x, y| x + y).unwrap_or(Self::zero()) + } +} + +impl Sub for PlutoField { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + let diff = self.value-rhs.value; + Self::new(diff) + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 94dbbf93..509c1db7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,3 +7,4 @@ #![allow(unused_mut)] pub mod curve; +pub mod field; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 00000000..f0bc6870 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,7 @@ + +use ronkathon::field::PlutoField; + +fn main() { + let f = PlutoField::new(1); + println!("hello field={:?}", f); +} \ No newline at end of file