Skip to content

Commit 823fd69

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/private-input-memory-mapped
2 parents 149f022 + 64bad0e commit 823fd69

13 files changed

Lines changed: 724 additions & 755 deletions

File tree

crypto/crypto/src/merkle_tree/backends/field_element_vector.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,23 @@ impl<F, D: Digest, const NUM_BYTES: usize> Default for FieldElementVectorBackend
7171
}
7272
}
7373

74+
impl<F, D: Digest, const NUM_BYTES: usize> FieldElementVectorBackend<F, D, NUM_BYTES>
75+
where
76+
[u8; NUM_BYTES]: From<Output<D>>,
77+
{
78+
/// Hash raw bytes using the same digest (`D`) as this backend's leaf hashing.
79+
/// Enables callers to pre-serialize field elements into a byte buffer and hash
80+
/// once, avoiding per-element allocations while staying consistent with the
81+
/// backend's hash function.
82+
pub fn hash_bytes(data: &[u8]) -> [u8; NUM_BYTES] {
83+
let mut hasher = D::new();
84+
hasher.update(data);
85+
let mut result = [0u8; NUM_BYTES];
86+
result.copy_from_slice(&hasher.finalize());
87+
result
88+
}
89+
}
90+
7491
impl<F, D: Digest, const NUM_BYTES: usize> IsMerkleTreeBackend
7592
for FieldElementVectorBackend<F, D, NUM_BYTES>
7693
where

crypto/math/src/fft/polynomial.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ impl<E: IsField> Polynomial<FieldElement<E>> {
215215
///
216216
/// Unlike [`coset_lde_full_into`], this skips the `clear + extend_from_slice` step
217217
/// since data is already in the buffer. Used for transpose elimination: columns are
218-
/// extracted directly into pool buffers, then expanded in-place.
218+
/// extracted directly into owned buffers, then expanded in-place.
219219
pub fn coset_lde_full_expand<F: IsFFTField + IsSubFieldOf<E> + Send + Sync>(
220220
buffer: &mut Vec<FieldElement<E>>,
221221
blowup_factor: usize,

crypto/math/src/field/extensions_goldilocks.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use crate::field::{
1212
use crate::traits::{AsBytes, ByteConversion};
1313

1414
impl ByteConversion for [FpE; 2] {
15+
const BYTE_LEN: usize = 16;
16+
1517
#[cfg(feature = "alloc")]
1618
fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
1719
unimplemented!()
@@ -38,6 +40,8 @@ impl ByteConversion for [FpE; 2] {
3840
}
3941

4042
impl ByteConversion for [FpE; 3] {
43+
const BYTE_LEN: usize = 24;
44+
4145
#[cfg(feature = "alloc")]
4246
fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
4347
let mut bytes = ByteConversion::to_bytes_be(&self[2]);
@@ -470,6 +474,17 @@ impl Fp3E {
470474
// =====================================================
471475

472476
impl ByteConversion for FieldElement<Degree3GoldilocksExtensionField> {
477+
const BYTE_LEN: usize = 24;
478+
479+
#[inline(always)]
480+
fn write_bytes_be(&self, buf: &mut [u8]) {
481+
debug_assert!(buf.len() >= 24);
482+
let components = self.value();
483+
components[0].write_bytes_be(&mut buf[0..8]);
484+
components[1].write_bytes_be(&mut buf[8..16]);
485+
components[2].write_bytes_be(&mut buf[16..24]);
486+
}
487+
473488
#[cfg(feature = "alloc")]
474489
fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
475490
let mut byte_slice = ByteConversion::to_bytes_be(&self.value()[0]);
@@ -554,3 +569,27 @@ impl HasDefaultTranscript for Degree3GoldilocksExtensionField {
554569
fn mul_by_7(a: &FpE) -> FpE {
555570
FpE::from_raw(mul_by_7_raw(*a.value()))
556571
}
572+
573+
#[cfg(test)]
574+
mod tests {
575+
use super::*;
576+
use crate::traits::ByteConversion;
577+
578+
#[test]
579+
fn write_bytes_be_matches_as_bytes() {
580+
let cases = [
581+
FieldElement::<Degree3GoldilocksExtensionField>::zero(),
582+
FieldElement::<Degree3GoldilocksExtensionField>::one(),
583+
FieldElement::<Degree3GoldilocksExtensionField>::new([
584+
FpE::from(1u64),
585+
FpE::from(2u64),
586+
FpE::from(3u64),
587+
]),
588+
];
589+
for elem in &cases {
590+
let mut buf = [0u8; 24];
591+
elem.write_bytes_be(&mut buf);
592+
assert_eq!(&buf[..], elem.as_bytes().as_slice());
593+
}
594+
}
595+
}

crypto/math/src/field/goldilocks.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,14 @@ impl GoldilocksElement {
434434
// =====================================================
435435

436436
impl ByteConversion for FieldElement<GoldilocksField> {
437+
const BYTE_LEN: usize = 8;
438+
439+
#[inline(always)]
440+
fn write_bytes_be(&self, buf: &mut [u8]) {
441+
debug_assert!(buf.len() >= 8);
442+
buf[..8].copy_from_slice(&self.canonical_u64().to_be_bytes());
443+
}
444+
437445
#[cfg(feature = "alloc")]
438446
fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
439447
self.canonical_u64().to_be_bytes().to_vec()
@@ -543,3 +551,32 @@ impl HasDefaultTranscript for GoldilocksField {
543551
}
544552
}
545553
}
554+
555+
#[cfg(test)]
556+
mod tests {
557+
use super::*;
558+
use crate::traits::ByteConversion;
559+
560+
#[test]
561+
fn write_bytes_be_matches_as_bytes() {
562+
let cases = [
563+
FieldElement::<GoldilocksField>::from(0u64),
564+
FieldElement::<GoldilocksField>::from(1u64),
565+
FieldElement::<GoldilocksField>::from(GOLDILOCKS_PRIME - 1),
566+
];
567+
for elem in &cases {
568+
let mut buf = [0u8; 8];
569+
elem.write_bytes_be(&mut buf);
570+
assert_eq!(&buf[..], elem.as_bytes().as_slice());
571+
}
572+
}
573+
574+
#[test]
575+
fn write_bytes_be_matches_as_bytes_noncanonical() {
576+
// Values stored as-is via from_raw are non-canonical (>= p) until serialized.
577+
let elem = FieldElement::<GoldilocksField>::from_raw(GOLDILOCKS_PRIME + 5);
578+
let mut buf = [0u8; 8];
579+
elem.write_bytes_be(&mut buf);
580+
assert_eq!(&buf[..], elem.as_bytes().as_slice());
581+
}
582+
}

crypto/math/src/field/test_fields/u32_test_field.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use crate::traits::ByteConversion;
1111
pub struct U32Field<const MODULUS: u32>;
1212

1313
impl ByteConversion for u32 {
14+
const BYTE_LEN: usize = 4;
15+
1416
#[cfg(feature = "alloc")]
1517
fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
1618
unimplemented!()

crypto/math/src/traits.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use crate::errors::ByteConversionError;
55
/// for getting an element from its byte representation in big-endian or
66
/// little-endian order.
77
pub trait ByteConversion {
8-
/// Returns the byte representation of the element in big-endian order.}
8+
/// Byte length of the big-endian representation.
9+
const BYTE_LEN: usize;
10+
11+
/// Returns the byte representation of the element in big-endian order.
912
#[cfg(feature = "alloc")]
1013
fn to_bytes_be(&self) -> alloc::vec::Vec<u8>;
1114

@@ -22,6 +25,14 @@ pub trait ByteConversion {
2225
fn from_bytes_le(bytes: &[u8]) -> Result<Self, ByteConversionError>
2326
where
2427
Self: Sized;
28+
29+
/// Write big-endian bytes into `buf[..BYTE_LEN]`.
30+
/// Override for zero-allocation performance in hot paths.
31+
#[cfg(feature = "alloc")]
32+
fn write_bytes_be(&self, buf: &mut [u8]) {
33+
let bytes = self.to_bytes_be();
34+
buf[..bytes.len()].copy_from_slice(&bytes);
35+
}
2536
}
2637

2738
/// Serialize function without args
@@ -47,6 +58,8 @@ impl AsBytes for u64 {
4758
}
4859

4960
impl ByteConversion for u64 {
61+
const BYTE_LEN: usize = 8;
62+
5063
#[cfg(feature = "alloc")]
5164
fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
5265
self.to_be_bytes().to_vec()

crypto/stark/src/instruments.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ use std::time::Duration;
55
/// Sub-operation timing breakdown for a single table in Rounds 2-4.
66
#[derive(Clone, Debug, Default)]
77
pub struct TableSubOps {
8-
/// reconstruct_round1 (expand_pool_to_lde)
9-
pub trace_lde: Duration,
108
/// evaluator.evaluate()
119
pub constraints: Duration,
1210
/// decompose_and_extend_d2
@@ -28,11 +26,11 @@ pub struct TableSubOps {
2826
/// Sub-operation breakdown for Round 1 aux commit pass.
2927
#[derive(Clone, Debug, Default)]
3028
pub struct Round1SubOps {
31-
/// Main trace: expand_pool_to_lde (LDE/FFT)
29+
/// Main trace: expand_columns_to_lde (LDE/FFT)
3230
pub main_lde: Duration,
3331
/// Main trace: commit_columns_bit_reversed (Merkle)
3432
pub main_merkle: Duration,
35-
/// Aux trace: expand_pool_to_lde (LDE/FFT)
33+
/// Aux trace: expand_columns_to_lde (LDE/FFT)
3634
pub aux_lde: Duration,
3735
/// Aux trace: commit_columns_bit_reversed (Merkle)
3836
pub aux_merkle: Duration,

0 commit comments

Comments
 (0)