Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

integrate babybear #107

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
7f13794
feat: BabyBear base field
Sep 16, 2024
cd30560
feat: BabyBearExt4
Sep 16, 2024
13b7184
GKR BabyBear config (no SIMD)
Sep 16, 2024
795b8bc
fix: avx256 feature
Sep 16, 2024
c93b8b8
feat: BabyBear AVX512
Sep 16, 2024
e203f8f
feat: BabyBearExt4 AVX512
Sep 16, 2024
46fcba2
fix: sumcheck_helper poly degree
Sep 17, 2024
6af2318
temp: cargo config
Sep 17, 2024
69bd157
feat: BabyBear config
Sep 17, 2024
0f11134
wip
zhenfeizhang Sep 19, 2024
ef6eb50
wip
zhenfeizhang Sep 19, 2024
0fba45a
wip
zhenfeizhang Sep 19, 2024
04e5cb5
feat: avx256 BabyBear
Sep 19, 2024
5368adb
feat: neon BabyBear
Sep 19, 2024
756edfc
wip
zhenfeizhang Sep 19, 2024
b4e7899
Test vectors for BabyBearExt4
Sep 19, 2024
f104b47
FIX: field for babybearext4x16
Sep 19, 2024
54c2026
feat: Babybear ext3
Sep 16, 2024
dfb0e42
chore: add missing babybear configs
Sep 19, 2024
7271121
update
zhenfeizhang Sep 19, 2024
044d649
fmt
zhenfeizhang Sep 19, 2024
e1fcc02
chore: add babybear to benchmark, correctness test
Sep 19, 2024
6ddbc57
wip
zhenfeizhang Sep 19, 2024
8505543
chore: move p3 imports to workspace
Sep 19, 2024
56f31a2
chore: double instead of mul by W
Sep 19, 2024
bbbc463
chore: remove dummy simd impls
Sep 19, 2024
9172aad
update CI
zhenfeizhang Sep 23, 2024
443119d
ipdate
zhenfeizhang Sep 23, 2024
d23b587
simplify CI
zhenfeizhang Sep 23, 2024
d9dc03c
fix
zhenfeizhang Sep 23, 2024
3fb9815
fix
zhenfeizhang Sep 23, 2024
c8703ce
add arith
zhenfeizhang Sep 23, 2024
e19d26c
reenable bench
zhenfeizhang Sep 23, 2024
940cf17
Merge branch 'zz/fix-ci-avx-target' into HEAD
zhenfeizhang Sep 23, 2024
0bf673b
Merge branch 'zz/fix-ci-avx-target' into zz/field_refactor
zhenfeizhang Sep 23, 2024
05e2b1e
wip
zhenfeizhang Sep 23, 2024
e129e64
almost there
zhenfeizhang Sep 24, 2024
e49820e
clippy and fmt
zhenfeizhang Sep 24, 2024
6064eb7
more fixes
zhenfeizhang Sep 24, 2024
1781036
fmt
zhenfeizhang Sep 24, 2024
8a7011d
fix neon
zhenfeizhang Sep 24, 2024
cc18ea1
Update rust-toolchain
zhenfeizhang Sep 24, 2024
b96f7be
wip
zhenfeizhang Sep 24, 2024
2290c0a
Merge remote-tracking branch 'refs/remotes/origin/zz/field_refactor' …
zhenfeizhang Sep 24, 2024
342445b
wip
zhenfeizhang Sep 24, 2024
404c0af
older nightly version
zhenfeizhang Sep 24, 2024
7e5a14f
fix bench module
zhenfeizhang Sep 24, 2024
eb45863
Merge branch 'main' into zz/field_refactor
zhenfeizhang Sep 24, 2024
3681256
Merge branch 'baby-bear' into zz/field_refactor
zhenfeizhang Sep 24, 2024
35f4987
move babybear to its own crate
zhenfeizhang Sep 24, 2024
8d56926
fmt
zhenfeizhang Sep 24, 2024
b4e46f9
fix neon
zhenfeizhang Sep 24, 2024
b641093
fmt
zhenfeizhang Sep 24, 2024
f8e59e6
fix size bug
zhenfeizhang Sep 24, 2024
9bfbbec
fix CI
zhenfeizhang Sep 24, 2024
59d4645
Merge branch 'main' into zz/integrate_babybear
zhenfeizhang Sep 25, 2024
4115aa0
Update ci.yml
zhenfeizhang Sep 25, 2024
ad99dc7
clippy
zhenfeizhang Sep 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["-C", "target-cpu=native"]
15 changes: 7 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ jobs:
with:
components: rustfmt, clippy
- run: cargo fmt --all -- --check
- run: cargo clippy
- run: cargo clippy --all
env:
RUSTFLAGS: "-Dwarnings -C target-cpu=native -C target-feature=+avx512f"

build-and-test:
name: Build and Test (${{ matrix.os }}${{ matrix.feature != '' && format(', {0}', matrix.feature) || '' }})
Expand All @@ -40,9 +42,7 @@ jobs:
run: |
cargo run --bin=dev-setup --release
cargo build --all-features --release
cargo test --all-features --release
cargo test -p arith --release
cargo test -p bi-kzg --release
cargo test --all-features --release --workspace

benchmark:
name: Benchmark (${{ matrix.os }}${{ matrix.feature != '' && format(', {0}', matrix.feature) || '' }}, ${{ matrix.field }})
Expand All @@ -66,13 +66,13 @@ jobs:
feature: avx2
field: gf2ext128
- os: 7950x3d
feature: avx512
feature: avx512f
field: m31ext3
- os: 7950x3d
feature: avx512
feature: avx512f
field: fr
- os: 7950x3d
feature: avx512
feature: avx512f
field: gf2ext128
steps:
- uses: actions/checkout@v4
Expand All @@ -85,4 +85,3 @@ jobs:
run: |
cargo run --bin=dev-setup --release
cargo run --release -- -t ${{ matrix.os == 'macos-latest' && 2 || 16 }} -f ${{ matrix.field }}

6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ output.txt
# circuit files
/data/*

# Generated by SageMath
*.sage.py

# idea
.idea/
/data

# vscode settings
.vscode/
39 changes: 33 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ default-run = "expander-rs" # default

[dependencies]
arith = { path = "arith" }
babybear = { path = "arith/babybear" }
gf2 = { path = "arith/gf2" }
gf2_128 = { path = "arith/gf2_128" }
mersenne31 = { path = "arith/mersenne31" }

ark-std.workspace = true
clap.workspace = true
env_logger.workspace = true
Expand Down Expand Up @@ -35,13 +40,21 @@ name = "dev-setup"
path = "src/utils.rs"

[features]
avx256 = [ "arith/avx256" ]
default = []
# default = [ "grinding" ]
grinding = []
avx256 = ["arith/avx256"]

[workspace]
members = ["arith", "bi-kzg"]
members = [
"arith", # definitions of Field, Extensions, SIMDS
"arith/babybear",
"arith/gf2",
"arith/gf2_128",
"arith/goldilocks",
"arith/mersenne31",
"bi-kzg"
]

[workspace.dependencies]
ark-std = "0.4"
Expand All @@ -58,6 +71,10 @@ halo2curves = { git = "https://github.com/PolyhedraZK/halo2curves", default-feat
] }
itertools = "0.13"
log = "0.4"
p3-baby-bear = { git = "https://github.com/Plonky3/Plonky3.git", version = "0.1.0", features = ["nightly-features"] }
p3-field = { git = "https://github.com/Plonky3/Plonky3.git", version = "0.1.0" }
# This import should be unnecessary but p3-baby-bear fails to turn on "nightly-features" for this dependency
p3-monty-31 = { git = "https://github.com/Plonky3/Plonky3.git", version = "0.1.0", features = ["nightly-features"] }
rand = "0.8.5"
rayon = "1.10"
sha2 = "0.10.8"
Expand All @@ -69,14 +86,24 @@ thiserror = "1.0.63"
ethnum = "1.5.0"

[[bench]]
name = "arith"
name = "bn254_fr"
harness = false
path = "arith/benches/fr.rs"

[[bench]]
name = "gf2"
harness = false
path = "arith/gf2/benches/gf2.rs"

[[bench]]
name = "gf2_128"
harness = false
path = "arith/benches/field.rs"
path = "arith/gf2_128/benches/gf2_128.rs"

[[bench]]
name = "arith-ext-by-base"
name = "m31"
harness = false
path = "arith/benches/ext_field.rs"
path = "arith/mersenne31/benches/m31.rs"

[[bench]]
name = "gkr-hashes"
Expand Down
15 changes: 7 additions & 8 deletions arith/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@ edition = "2021"

[dependencies]
ark-std.workspace = true
criterion.workspace = true
ethnum.workspace = true
halo2curves.workspace = true
log.workspace = true
p3-baby-bear.workspace = true
p3-field.workspace = true
p3-monty-31.workspace = true
rand.workspace = true
sha2.workspace = true
thiserror.workspace = true
ethnum.workspace = true
tynm.workspace = true

raw-cpuid = "11.1.0"
cfg-if = "1.0"

[dev-dependencies]
tynm.workspace = true
criterion.workspace = true

[[bench]]
name = "field"
harness = false

[[bench]]
name = "ext_field"
name = "fr"
harness = false

[features]
Expand Down
14 changes: 14 additions & 0 deletions arith/babybear/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "babybear"
version = "0.1.0"
edition = "2021"

[dependencies]
arith = {path = "../"}

ark-std.workspace = true
ethnum.workspace = true
p3-baby-bear.workspace = true
p3-field.workspace = true
p3-monty-31.workspace = true
rand.workspace = true
208 changes: 208 additions & 0 deletions arith/babybear/src/baby_bear.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
use core::{
iter::{Product, Sum},
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};

use arith::{field_common, Field, FieldForECC, FieldSerde, FieldSerdeResult, SimdField};
use ark_std::Zero;
use p3_baby_bear::BabyBear as P3BabyBear;
use p3_field::{Field as P3Field, PrimeField32};
use rand::distributions::{Distribution, Standard};
use std::io::{Read, Write};

mod baby_bearx16;
pub use baby_bearx16::BabyBearx16;

#[cfg(target_arch = "x86_64")]
pub(crate) mod baby_bear_avx;
#[cfg(target_arch = "aarch64")]
pub(crate) mod baby_bear_neon;
#[cfg(target_arch = "x86_64")]
pub use baby_bear_avx::AVXBabyBear;

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct BabyBear(P3BabyBear);

pub const BABYBEAR_MODULUS: u32 = 0x78000001;

field_common!(BabyBear);

impl BabyBear {
/// Input is provided in canonical form and converted into Montgomery form.
pub const fn new(value: u32) -> Self {
Self(P3BabyBear::new(value))
}
}

impl FieldSerde for BabyBear {
const SERIALIZED_SIZE: usize = 32 / 8;

#[inline(always)]
fn serialize_into<W: Write>(&self, mut writer: W) -> FieldSerdeResult<()> {
// Note: BabyBear's impl of as_u32_unchecked() converts to canonical form
writer.write_all(self.as_u32_unchecked().to_le_bytes().as_ref())?;
Ok(())
}

/// Note: This function performs modular reduction on inputs and
/// converts from canonical to Montgomery form.
#[inline(always)]
fn deserialize_from<R: Read>(mut reader: R) -> FieldSerdeResult<Self> {
let mut u = [0u8; Self::SERIALIZED_SIZE];
reader.read_exact(&mut u)?;
let v = u32::from_le_bytes(u);
Ok(Self::from(v))
}

#[inline]
fn try_deserialize_from_ecc_format<R: Read>(mut reader: R) -> FieldSerdeResult<Self> {
let mut buf = [0u8; 32];
reader.read_exact(&mut buf)?;
assert!(
buf.iter().skip(4).all(|&x| x == 0),
"non-zero byte found in witness byte"
);
Ok(Self::from(u32::from_le_bytes(buf[..4].try_into().unwrap())))
}
}

impl Field for BabyBear {
const NAME: &'static str = "Baby Bear Field";

const SIZE: usize = 32 / 8;

const FIELD_SIZE: usize = 32;

const ZERO: Self = BabyBear::new(0);

const ONE: Self = BabyBear::new(1);

// See test below
const INV_2: Self = BabyBear::new(1006632961);

#[inline(always)]
fn zero() -> Self {
Self::ZERO
}

#[inline(always)]
fn is_zero(&self) -> bool {
*self == Self::ZERO
}

#[inline(always)]
fn one() -> Self {
Self::ONE
}

/// Uses rejection sampling to avoid bias.
fn random_unsafe(mut rng: impl rand::RngCore) -> Self {
let dist = Standard;
Self(dist.sample(&mut rng))
}

fn random_bool(mut rng: impl rand::RngCore) -> Self {
(rng.next_u32() & 1).into()
}

fn exp(&self, exponent: u128) -> Self {
let mut e = exponent;
let mut res = Self::one();
let mut t = *self;
while !e.is_zero() {
let b = e & 1;
if b == 1 {
res *= t;
}
t = t * t;
e >>= 1;
}
res
}

fn inv(&self) -> Option<Self> {
self.0.try_inverse().map(Self)
}

/// Converts to canonical form.
#[inline(always)]
fn as_u32_unchecked(&self) -> u32 {
self.0.as_canonical_u32()
}

#[inline(always)]
fn from_uniform_bytes(bytes: &[u8; 32]) -> Self {
// Note: From<u32> performs modular reduction
u32::from_le_bytes(bytes[..4].try_into().unwrap()).into()
}
}

impl FieldForECC for BabyBear {
fn modulus() -> ethnum::U256 {
ethnum::U256::from(<P3BabyBear as PrimeField32>::ORDER_U32)
}

fn from_u256(x: ethnum::U256) -> Self {
Self::new((x % Self::modulus()).as_u32())
}

fn to_u256(&self) -> ethnum::U256 {
// Converts to canonical form before casting to U256
ethnum::U256::from(self.as_u32_unchecked())
}
}

// TODO: Actual SIMD impl
// This is a dummy implementation to satisfy trait bounds
impl SimdField for BabyBear {
type Scalar = Self;

fn scale(&self, challenge: &Self::Scalar) -> Self {
self * challenge
}

fn pack(base_vec: &[Self::Scalar]) -> Self {
debug_assert!(base_vec.len() == 1);
base_vec[0]
}

fn unpack(&self) -> Vec<Self::Scalar> {
vec![*self]
}

fn pack_size() -> usize {
1
}
}

impl Neg for BabyBear {
type Output = Self;

#[inline(always)]
fn neg(self) -> Self::Output {
Self(self.0.neg())
}
}

impl From<u32> for BabyBear {
#[inline(always)]
fn from(value: u32) -> Self {
Self::new(value)
}
}

#[inline(always)]
fn add_internal(a: &BabyBear, b: &BabyBear) -> BabyBear {
BabyBear(a.0 + b.0)
}

#[inline(always)]
fn sub_internal(a: &BabyBear, b: &BabyBear) -> BabyBear {
BabyBear(a.0 - b.0)
}

#[inline(always)]
fn mul_internal(a: &BabyBear, b: &BabyBear) -> BabyBear {
BabyBear(a.0 * b.0)
}
Loading
Loading