docs: add module and function documentation (#408)

This commit is contained in:
Himess 2025-05-09 08:01:46 +03:00 committed by GitHub
parent 03647457d9
commit c1920e3a1a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 47 additions and 1 deletions

View file

@ -1,6 +1,7 @@
## 0.15.0 (TBD)
- Added default constructors to `MmrPeaks` and `PartialMmr` (#409).
- Add module and function documentation. (#408).
## 0.14.0 (2025-03-15)

View file

@ -1,3 +1,13 @@
//! Public key types for the RPO Falcon 512 digital signature scheme used in Miden VM.
//!
//! This module defines two main types:
//! - `PublicKey`: A commitment to a polynomial, represented as a hash of the polynomials
//! coefficients.
//! - `PubKeyPoly`: A public key represented directly as a polynomial over FalconFelt coefficients.
//!
//! The `PublicKey` is used for signature verification.
//! The `PubKeyPoly` provides the raw polynomial form of a public key.
use alloc::string::ToString;
use core::ops::Deref;
@ -50,6 +60,8 @@ impl From<PublicKey> for Word {
// PUBLIC KEY POLYNOMIAL
// ================================================================================================
/// Public key represented as a polynomial with coefficients over the Falcon prime field.
/// Used in the RPO Falcon 512 signature scheme.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PubKeyPoly(pub Polynomial<FalconFelt>);

View file

@ -1,3 +1,5 @@
//! Generic polynomial type and operations used in Falcon.
use alloc::vec::Vec;
use core::{
default::Default,
@ -13,8 +15,10 @@ use crate::{
dsa::rpo_falcon512::{MODULUS, N},
};
/// Represents a polynomial with coefficients of type F.
#[derive(Debug, Clone, Default)]
pub struct Polynomial<F> {
/// Coefficients of the polynomial, ordered from lowest to highest degree.
pub coefficients: Vec<F>,
}
@ -22,6 +26,7 @@ impl<F> Polynomial<F>
where
F: Clone,
{
/// Creates a new polynomial from the provided coefficients.
pub fn new(coefficients: Vec<F>) -> Self {
Self { coefficients }
}
@ -30,6 +35,7 @@ where
impl<F: Mul<Output = F> + Sub<Output = F> + AddAssign + Zero + Div<Output = F> + Clone + Inverse>
Polynomial<F>
{
/// Multiplies two polynomials coefficient-wise (Hadamard multiplication).
pub fn hadamard_mul(&self, other: &Self) -> Self {
Polynomial::new(
self.coefficients
@ -39,6 +45,7 @@ impl<F: Mul<Output = F> + Sub<Output = F> + AddAssign + Zero + Div<Output = F> +
.collect(),
)
}
/// Divides two polynomials coefficient-wise (Hadamard division).
pub fn hadamard_div(&self, other: &Self) -> Self {
let other_coefficients_inverse = F::batch_inverse_or_zero(&other.coefficients);
Polynomial::new(
@ -50,6 +57,7 @@ impl<F: Mul<Output = F> + Sub<Output = F> + AddAssign + Zero + Div<Output = F> +
)
}
/// Computes the coefficient-wise inverse (Hadamard inverse).
pub fn hadamard_inv(&self) -> Self {
let coefficients_inverse = F::batch_inverse_or_zero(&self.coefficients);
Polynomial::new(coefficients_inverse)
@ -57,6 +65,7 @@ impl<F: Mul<Output = F> + Sub<Output = F> + AddAssign + Zero + Div<Output = F> +
}
impl<F: Zero + PartialEq + Clone> Polynomial<F> {
/// Returns the degree of the polynomial.
pub fn degree(&self) -> Option<usize> {
if self.coefficients.is_empty() {
return None;
@ -72,6 +81,7 @@ impl<F: Zero + PartialEq + Clone> Polynomial<F> {
Some(max_index)
}
/// Returns the leading coefficient of the polynomial.
pub fn lc(&self) -> F {
match self.degree() {
Some(non_negative_degree) => self.coefficients[non_negative_degree].clone(),
@ -392,20 +402,24 @@ where
}
impl<F: Zero + Clone> Polynomial<F> {
/// Shifts the polynomial by the specified amount (adds leading zeros).
pub fn shift(&self, shamt: usize) -> Self {
Self {
coefficients: [vec![F::zero(); shamt], self.coefficients.clone()].concat(),
}
}
/// Creates a constant polynomial with a single coefficient.
pub fn constant(f: F) -> Self {
Self { coefficients: vec![f] }
}
/// Applies a function to each coefficient and returns a new polynomial.
pub fn map<G: Clone, C: FnMut(&F) -> G>(&self, closure: C) -> Polynomial<G> {
Polynomial::<G>::new(self.coefficients.iter().map(closure).collect())
}
/// Folds the coefficients using the provided function and initial value.
pub fn fold<G, C: FnMut(G, &F) -> G + Clone>(&self, mut initial_value: G, closure: C) -> G {
for c in self.coefficients.iter() {
initial_value = (closure.clone())(initial_value, c);
@ -544,6 +558,7 @@ impl From<&Vec<i16>> for Polynomial<FalconFelt> {
}
impl Polynomial<FalconFelt> {
/// Computes the squared L2 norm of the polynomial.
pub fn norm_squared(&self) -> u64 {
self.coefficients
.iter()

View file

@ -56,6 +56,9 @@ pub struct Signature {
impl Signature {
// CONSTRUCTOR
// --------------------------------------------------------------------------------------------
/// Creates a new signature from the given nonce, public key polynomial, and signature
/// polynomial.
pub fn new(nonce: Nonce, h: PubKeyPoly, s2: SignaturePoly) -> Signature {
Self {
header: SignatureHeader::default(),
@ -73,7 +76,7 @@ impl Signature {
&self.h
}
// Returns the polynomial representation of the signature in Z_p[x]/(phi).
/// Returns the polynomial representation of the signature in Z_p\[x\]/(phi).
pub fn sig_poly(&self) -> &Polynomial<FalconFelt> {
&self.s2
}
@ -124,6 +127,7 @@ impl Deserializable for Signature {
// SIGNATURE HEADER
// ================================================================================================
/// The header byte used to encode the signature metadata.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SignatureHeader(u8);
@ -174,6 +178,7 @@ impl Deserializable for SignatureHeader {
// SIGNATURE POLYNOMIAL
// ================================================================================================
/// A polynomial used as the `s2` component of the signature.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SignaturePoly(pub Polynomial<FalconFelt>);

View file

@ -2,13 +2,17 @@
use super::{CubeExtension, Felt, FieldElement, StarkField, ZERO};
/// Blake2s hash function.
pub mod blake;
mod rescue;
/// Rescue Prime Optimized (RPO) hash function.
pub mod rpo {
pub use super::rescue::{Rpo256, RpoDigest, RpoDigestError};
}
/// Rescue Prime Extended (RPX) hash function.
pub mod rpx {
pub use super::rescue::{Rpx256, RpxDigest, RpxDigestError};
}

View file

@ -21,6 +21,7 @@ use crate::{
// DIGEST TRAIT IMPLEMENTATIONS
// ================================================================================================
/// An RPO digest consisting of 4 field elements.
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(into = "String", try_from = "&str"))]
@ -30,18 +31,22 @@ impl RpoDigest {
/// The serialized size of the digest in bytes.
pub const SERIALIZED_SIZE: usize = DIGEST_BYTES;
/// Creates a new RpoDigest from the given field elements.
pub const fn new(value: [Felt; DIGEST_SIZE]) -> Self {
Self(value)
}
/// Returns the digest as a slice of field elements.
pub fn as_elements(&self) -> &[Felt] {
self.as_ref()
}
/// Returns the digest as a byte array.
pub fn as_bytes(&self) -> [u8; DIGEST_BYTES] {
<Self as Digest>::as_bytes(self)
}
/// Returns an iterator over the elements of multiple digests.
pub fn digests_as_elements_iter<'a, I>(digests: I) -> impl Iterator<Item = &'a Felt>
where
I: Iterator<Item = &'a Self>,
@ -49,6 +54,7 @@ impl RpoDigest {
digests.flat_map(|d| d.0.iter())
}
/// Returns all elements of multiple digests as a slice.
pub fn digests_as_elements(digests: &[Self]) -> &[Felt] {
let p = digests.as_ptr();
let len = digests.len() * DIGEST_SIZE;
@ -141,10 +147,13 @@ impl Randomizable for RpoDigest {
// CONVERSIONS: FROM RPO DIGEST
// ================================================================================================
/// Errors that can occur when working with RpoDigest.
#[derive(Debug, Error)]
pub enum RpoDigestError {
/// Failed to convert digest field element to the specified type.
#[error("failed to convert digest field element to {0}")]
TypeConversion(&'static str),
/// Field element conversion failed due to invalid value.
#[error("failed to convert to field element: {0}")]
InvalidFieldElement(String),
}