Skip to content

Commit d30ec8a

Browse files
committed
accelerate to_affine conversion
1 parent d7454af commit d30ec8a

File tree

5 files changed

+58
-26
lines changed

5 files changed

+58
-26
lines changed

p256/src/arithmetic/field.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,10 @@ primeorder::impl_mont_field_element!(
6363

6464
impl FieldElement {
6565
#[cfg(all(target_os = "zkvm", target_arch = "riscv32"))]
66-
#[inline(never)]
6766
pub(crate) fn from_words_le(fe: [u32; 8]) -> CtOption<Self> {
68-
// use elliptic_curve::bigint::Encoding;
69-
// println!("r2: {:0X?}", fe_from_montgomery(R_2.as_words()));
70-
7167
let fe = FieldElement256::new_unchecked(fe);
68+
69+
// Convert to montgomery form with aR mod p
7270
let mut mont = FieldElement256::default();
7371
fe.mul_unchecked(&R_2_LE, &mut mont);
7472

@@ -81,16 +79,24 @@ impl FieldElement {
8179
CtOption::new(Self(uint), is_within_modulus)
8280
}
8381

82+
#[cfg(all(target_os = "zkvm", target_arch = "riscv32"))]
83+
pub(crate) fn to_words_le(&self) -> [u32; 8] {
84+
use crate::elliptic_curve::bigint::Encoding;
85+
// NOTE: this from mont conversion could be accelerated, but it's very little cycles.
86+
let canonical = self.to_canonical();
87+
let input = canonical.to_le_bytes();
88+
let array = bytemuck::cast::<_, [u32; 8]>(input);
89+
90+
array
91+
}
92+
8493
/// Returns the multiplicative inverse of self, if self is non-zero.
85-
#[inline(never)]
8694
pub fn invert(&self) -> CtOption<Self> {
8795
#[cfg(all(target_os = "zkvm", target_arch = "riscv32"))]
8896
{
8997
use crate::elliptic_curve::bigint::Encoding;
9098

91-
let canonical = self.to_canonical();
92-
let input = canonical.to_le_bytes();
93-
let input_words = bytemuck::cast::<_, [u32; 8]>(input);
99+
let input_words = self.to_words_le();
94100
let mut output = [0u32; 8];
95101
risc0_bigint2::field::modinv_256_unchecked(
96102
&input_words,

p256/src/arithmetic/field/field32.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::arithmetic::util::{adc, mac, sbb};
99
pub type Fe = [u32; 8];
1010

1111
/// Translate a field element out of the Montgomery domain.
12-
#[inline]
1312
pub const fn fe_from_montgomery(w: &Fe) -> Fe {
1413
let w = fe32_to_fe64(w);
1514
montgomery_reduce(&[w[0], w[1], w[2], w[3], 0, 0, 0, 0])

primeorder/src/field.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,6 @@ macro_rules! impl_field_op {
456456
impl ::core::ops::$op for $fe {
457457
type Output = $fe;
458458

459-
#[inline]
460459
fn $op_fn(self, rhs: $fe) -> $fe {
461460
$fe($func(self.as_ref(), rhs.as_ref()).into())
462461
}
@@ -465,7 +464,6 @@ macro_rules! impl_field_op {
465464
impl ::core::ops::$op<&$fe> for $fe {
466465
type Output = $fe;
467466

468-
#[inline]
469467
fn $op_fn(self, rhs: &$fe) -> $fe {
470468
$fe($func(self.as_ref(), rhs.as_ref()).into())
471469
}
@@ -474,7 +472,6 @@ macro_rules! impl_field_op {
474472
impl ::core::ops::$op<&$fe> for &$fe {
475473
type Output = $fe;
476474

477-
#[inline]
478475
fn $op_fn(self, rhs: &$fe) -> $fe {
479476
$fe($func(self.as_ref(), rhs.as_ref()).into())
480477
}

primeorder/src/projective.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,37 @@ where
5757

5858
/// Returns the affine representation of this point, or `None` if it is the identity.
5959
pub fn to_affine(&self) -> AffinePoint<C> {
60+
#[cfg(all(target_os = "zkvm", target_arch = "riscv32"))]
61+
{
62+
use crate::risc0::felt_to_u32_words_le;
63+
let z = felt_to_u32_words_le::<C>(&self.z);
64+
let mut z_inv = [0u32; 8];
65+
risc0_bigint2::field::modinv_256_unchecked(&z, &C::PRIME_LE_WORDS, &mut z_inv);
66+
67+
let mut buffer = [0u32; 8];
68+
let x_buffer = felt_to_u32_words_le::<C>(&self.x);
69+
let y_buffer = felt_to_u32_words_le::<C>(&self.y);
70+
risc0_bigint2::field::modmul_256_unchecked(
71+
&x_buffer,
72+
&z_inv,
73+
&C::PRIME_LE_WORDS,
74+
&mut buffer,
75+
);
76+
77+
let x = C::from_u32_words_le(buffer);
78+
79+
risc0_bigint2::field::modmul_256_unchecked(
80+
&y_buffer,
81+
&z_inv,
82+
&C::PRIME_LE_WORDS,
83+
&mut buffer,
84+
);
85+
let y = C::from_u32_words_le(buffer);
86+
return x
87+
.and_then(|x| y.map(|y| AffinePoint { x, y, infinity: 0 }))
88+
.unwrap_or(AffinePoint::IDENTITY);
89+
}
90+
6091
self.z
6192
.invert()
6293
.map(|zinv| AffinePoint {

primeorder/src/risc0.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -175,27 +175,26 @@ where
175175
}
176176
}
177177

178-
// TODO remove inline
179-
#[inline(never)]
178+
pub(crate) fn felt_to_u32_words_le<C>(data: &C::FieldElement) -> [u32; 8]
179+
where
180+
C: PrimeCurveParams,
181+
{
182+
// TODO alignment
183+
let mut data_bytes: [u8; 32] = data.to_repr().as_slice().try_into().unwrap();
184+
data_bytes.reverse();
185+
bytemuck::cast::<_, [u32; 8]>(data_bytes)
186+
}
187+
180188
pub(crate) fn projective_to_affine<C>(p: &ProjectivePoint<C>) -> ec::AffinePoint<8, C>
181189
where
182190
C: PrimeCurveParams,
183191
{
184192
let aff = p.to_affine();
185-
let x_bytes = aff.x.to_repr();
186-
let y_bytes = aff.y.to_repr();
187-
let mut x_bytes_arr: [u8; 32] = x_bytes.as_slice().try_into().unwrap();
188-
let mut y_bytes_arr: [u8; 32] = y_bytes.as_slice().try_into().unwrap();
189-
x_bytes_arr.reverse();
190-
y_bytes_arr.reverse();
191-
// TODO make more alignment safe
192-
let x = bytemuck::cast::<_, [u32; 8]>(x_bytes_arr);
193-
let y = bytemuck::cast::<_, [u32; 8]>(y_bytes_arr);
193+
let x = felt_to_u32_words_le::<C>(&aff.x);
194+
let y = felt_to_u32_words_le::<C>(&aff.y);
194195
ec::AffinePoint::new_unchecked(x, y)
195196
}
196197

197-
// TODO remove inline
198-
#[inline(never)]
199198
pub(crate) fn affine_to_projective<C>(affine: &ec::AffinePoint<8, C>) -> ProjectivePoint<C>
200199
where
201200
C: PrimeCurveParams,
@@ -216,11 +215,11 @@ where
216215
}
217216
}
218217

219-
#[inline(never)]
220218
pub(crate) fn scalar_to_words<C>(s: &Scalar<C>) -> [u32; 8]
221219
where
222220
C: PrimeCurveParams,
223221
{
222+
// TODO alignment
224223
let mut bytes: [u8; 32] = s.to_repr().as_slice().try_into().unwrap();
225224
// U256 is big endian, need to flip to little endian.
226225
bytes.reverse();

0 commit comments

Comments
 (0)