Skip to content

Commit fd571cf

Browse files
authored
field agnostic refactor (part 1) (#875)
extract from #873, refactor ceno stark to field agnostic
1 parent 62103a9 commit fd571cf

File tree

15 files changed

+432
-237
lines changed

15 files changed

+432
-237
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ itertools = "0.13"
3737
num-bigint = { version = "0.4.6" }
3838
num-derive = "0.4"
3939
num-traits = "0.2"
40+
p3-baby-bear = { git = "https://github.com/scroll-tech/plonky3", rev = "8d2be81" }
4041
p3-challenger = { git = "https://github.com/scroll-tech/plonky3", rev = "8d2be81" }
4142
p3-field = { git = "https://github.com/scroll-tech/plonky3", rev = "8d2be81" }
4243
p3-goldilocks = { git = "https://github.com/scroll-tech/plonky3", rev = "8d2be81" }

ceno_rt/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ repository = "https://github.com/scroll-tech/ceno"
1010
version = "0.1.0"
1111

1212
[dependencies]
13-
getrandom = { version = "*", features = ["custom"], default-features = false }
13+
getrandom = { version = "0.2.15", features = ["custom"], default-features = false }
1414
rkyv = { version = "0.8", features = ["pointer_width_32"] }

ceno_zkvm/src/scheme/mock_prover.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{
1818
use ark_std::test_rng;
1919
use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
2020
use ceno_emul::{ByteAddr, CENO_PLATFORM, Platform, Program};
21-
use ff_ext::{ExtensionField, GoldilocksExt2, SmallField};
21+
use ff_ext::{BabyBearExt4, ExtensionField, GoldilocksExt2, SmallField};
2222
use generic_static::StaticTypeMap;
2323
use itertools::{Itertools, chain, enumerate, izip};
2424
use multilinear_extensions::{mle::IntoMLEs, virtual_poly::ArcMultilinearExtension};
@@ -72,6 +72,12 @@ impl LkMultiplicityKey for GoldilocksExt2 {
7272
}
7373
}
7474

75+
impl LkMultiplicityKey for BabyBearExt4 {
76+
fn to_u64(&self) -> Option<u64> {
77+
None
78+
}
79+
}
80+
7581
#[allow(clippy::enum_variant_names)]
7682
#[derive(Debug, Clone)]
7783
pub enum MockProverError<E: ExtensionField, K: LkMultiplicityKey> {

ff_ext/src/babybear.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
pub mod impl_babybear {
2+
use crate::array_try_from_uniform_bytes;
3+
use p3::{
4+
self,
5+
babybear::{BabyBear, Poseidon2BabyBear},
6+
challenger::DuplexChallenger,
7+
field::{
8+
BasedVectorSpace, Field, PackedValue, PrimeCharacteristicRing, PrimeField32,
9+
TwoAdicField,
10+
extension::{BinomialExtensionField, BinomiallyExtendable},
11+
},
12+
poseidon2::ExternalLayerConstants,
13+
};
14+
15+
use crate::{
16+
ExtensionField, FieldFrom, FieldInto, FromUniformBytes, PoseidonField, SmallField,
17+
impl_from_uniform_bytes_for_binomial_extension,
18+
};
19+
20+
pub type BabyBearExt4 = BinomialExtensionField<BabyBear, 4>;
21+
22+
pub const POSEIDON2_BABYBEAR_WIDTH: usize = 16;
23+
pub const POSEIDON2_BABYBEAR_RATE: usize = 8;
24+
25+
pub const BABYBEAR_RC16_EXTERNAL_INITIAL: [[BabyBear; 16]; 4] = BabyBear::new_2d_array([
26+
[
27+
0x69cbb6af, 0x46ad93f9, 0x60a00f4e, 0x6b1297cd, 0x23189afe, 0x732e7bef, 0x72c246de,
28+
0x2c941900, 0x0557eede, 0x1580496f, 0x3a3ea77b, 0x54f3f271, 0x0f49b029, 0x47872fe1,
29+
0x221e2e36, 0x1ab7202e,
30+
],
31+
[
32+
0x487779a6, 0x3851c9d8, 0x38dc17c0, 0x209f8849, 0x268dcee8, 0x350c48da, 0x5b9ad32e,
33+
0x0523272b, 0x3f89055b, 0x01e894b2, 0x13ddedde, 0x1b2ef334, 0x7507d8b4, 0x6ceeb94e,
34+
0x52eb6ba2, 0x50642905,
35+
],
36+
[
37+
0x05453f3f, 0x06349efc, 0x6922787c, 0x04bfff9c, 0x768c714a, 0x3e9ff21a, 0x15737c9c,
38+
0x2229c807, 0x0d47f88c, 0x097e0ecc, 0x27eadba0, 0x2d7d29e4, 0x3502aaa0, 0x0f475fd7,
39+
0x29fbda49, 0x018afffd,
40+
],
41+
[
42+
0x0315b618, 0x6d4497d1, 0x1b171d9e, 0x52861abd, 0x2e5d0501, 0x3ec8646c, 0x6e5f250a,
43+
0x148ae8e6, 0x17f5fa4a, 0x3e66d284, 0x0051aa3b, 0x483f7913, 0x2cfe5f15, 0x023427ca,
44+
0x2cc78315, 0x1e36ea47,
45+
],
46+
]);
47+
48+
pub const BABYBEAR_RC16_EXTERNAL_FINAL: [[BabyBear; 16]; 4] = BabyBear::new_2d_array([
49+
[
50+
0x7290a80d, 0x6f7e5329, 0x598ec8a8, 0x76a859a0, 0x6559e868, 0x657b83af, 0x13271d3f,
51+
0x1f876063, 0x0aeeae37, 0x706e9ca6, 0x46400cee, 0x72a05c26, 0x2c589c9e, 0x20bd37a7,
52+
0x6a2d3d10, 0x20523767,
53+
],
54+
[
55+
0x5b8fe9c4, 0x2aa501d6, 0x1e01ac3e, 0x1448bc54, 0x5ce5ad1c, 0x4918a14d, 0x2c46a83f,
56+
0x4fcf6876, 0x61d8d5c8, 0x6ddf4ff9, 0x11fda4d3, 0x02933a8f, 0x170eaf81, 0x5a9c314f,
57+
0x49a12590, 0x35ec52a1,
58+
],
59+
[
60+
0x58eb1611, 0x5e481e65, 0x367125c9, 0x0eba33ba, 0x1fc28ded, 0x066399ad, 0x0cbec0ea,
61+
0x75fd1af0, 0x50f5bf4e, 0x643d5f41, 0x6f4fe718, 0x5b3cbbde, 0x1e3afb3e, 0x296fb027,
62+
0x45e1547b, 0x4a8db2ab,
63+
],
64+
[
65+
0x59986d19, 0x30bcdfa3, 0x1db63932, 0x1d7c2824, 0x53b33681, 0x0673b747, 0x038a98a3,
66+
0x2c5bce60, 0x351979cd, 0x5008fb73, 0x547bca78, 0x711af481, 0x3f93bf64, 0x644d987b,
67+
0x3c8bcd87, 0x608758b8,
68+
],
69+
]);
70+
71+
pub const BABYBEAR_RC16_INTERNAL: [BabyBear; 13] = BabyBear::new_array([
72+
0x5a8053c0, 0x693be639, 0x3858867d, 0x19334f6b, 0x128f0fd8, 0x4e2b1ccb, 0x61210ce0,
73+
0x3c318939, 0x0b5b2f22, 0x2edb11d5, 0x213effdf, 0x0cac4606, 0x241af16d,
74+
]);
75+
76+
impl FieldFrom<u64> for BabyBear {
77+
fn from_v(v: u64) -> Self {
78+
Self::from_u64(v)
79+
}
80+
}
81+
82+
impl FieldFrom<u64> for BabyBearExt4 {
83+
fn from_v(v: u64) -> Self {
84+
Self::from_u64(v)
85+
}
86+
}
87+
88+
impl FieldInto<BabyBear> for BabyBear {
89+
fn into_f(self) -> BabyBear {
90+
self
91+
}
92+
}
93+
94+
impl PoseidonField for BabyBear {
95+
type P = Poseidon2BabyBear<POSEIDON2_BABYBEAR_WIDTH>;
96+
type T = DuplexChallenger<Self, Self::P, POSEIDON2_BABYBEAR_WIDTH, POSEIDON2_BABYBEAR_RATE>;
97+
fn get_default_challenger() -> Self::T {
98+
let p = Poseidon2BabyBear::new(
99+
ExternalLayerConstants::new(
100+
BABYBEAR_RC16_EXTERNAL_INITIAL.to_vec(),
101+
BABYBEAR_RC16_EXTERNAL_FINAL.to_vec(),
102+
),
103+
BABYBEAR_RC16_INTERNAL.to_vec(),
104+
);
105+
DuplexChallenger::<
106+
Self,
107+
Self::P,
108+
POSEIDON2_BABYBEAR_WIDTH,
109+
POSEIDON2_BABYBEAR_RATE,
110+
>::new(p)
111+
}
112+
}
113+
114+
impl FromUniformBytes for BabyBear {
115+
type Bytes = [u8; 8];
116+
117+
fn try_from_uniform_bytes(bytes: [u8; 8]) -> Option<Self> {
118+
let value = u32::from_le_bytes(bytes[..4].try_into().unwrap());
119+
let is_canonical = value < Self::ORDER_U32;
120+
is_canonical.then(|| Self::from_u32(value))
121+
}
122+
}
123+
124+
impl SmallField for BabyBear {
125+
const MODULUS_U64: u64 = Self::ORDER_U32 as u64;
126+
127+
/// Convert a byte string into a list of field elements
128+
fn bytes_to_field_elements(bytes: &[u8]) -> Vec<Self> {
129+
bytes
130+
.chunks(8)
131+
.map(|chunk| {
132+
let mut array = [0u8; 8];
133+
array[..chunk.len()].copy_from_slice(chunk);
134+
unsafe { std::ptr::read_unaligned(array.as_ptr() as *const u64) }
135+
})
136+
.map(Self::from_u64)
137+
.collect::<Vec<_>>()
138+
}
139+
140+
/// Convert a field elements to a u64.
141+
fn to_canonical_u64(&self) -> u64 {
142+
self.as_canonical_u32() as u64
143+
}
144+
}
145+
146+
impl_from_uniform_bytes_for_binomial_extension!(p3::babybear::BabyBear, 4);
147+
148+
impl ExtensionField for BabyBearExt4 {
149+
const DEGREE: usize = 4;
150+
const MULTIPLICATIVE_GENERATOR: Self = <BabyBearExt4 as Field>::GENERATOR;
151+
const TWO_ADICITY: usize = BabyBear::TWO_ADICITY;
152+
// Passing two-adacity itself to this function will get the root of unity
153+
// with the largest order, i.e., order = 2^two-adacity.
154+
const BASE_TWO_ADIC_ROOT_OF_UNITY: Self::BaseField = BabyBear::new(0x78000000);
155+
const TWO_ADIC_ROOT_OF_UNITY: Self =
156+
BinomialExtensionField::new_unchecked([BabyBear::new(0x78000000); 4]);
157+
// non-residue is the value w such that the extension field is
158+
// F[X]/(X^2 - w)
159+
const NONRESIDUE: Self::BaseField = <BabyBear as BinomiallyExtendable<4>>::W;
160+
161+
type BaseField = BabyBear;
162+
163+
fn from_bases(bases: &[BabyBear]) -> Self {
164+
debug_assert_eq!(bases.len(), 2);
165+
Self::from_basis_coefficients_slice(bases)
166+
}
167+
168+
fn as_bases(&self) -> &[BabyBear] {
169+
self.as_basis_coefficients_slice()
170+
}
171+
172+
/// Convert limbs into self
173+
fn from_limbs(limbs: &[Self::BaseField]) -> Self {
174+
Self::from_bases(&limbs[0..4])
175+
}
176+
177+
fn to_canonical_u64_vec(&self) -> Vec<u64> {
178+
self.as_basis_coefficients_slice()
179+
.iter()
180+
.map(|v: &Self::BaseField| v.as_canonical_u32() as u64)
181+
.collect()
182+
}
183+
}
184+
}

0 commit comments

Comments
 (0)