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) ## 0.15.0 (TBD)
- Added default constructors to `MmrPeaks` and `PartialMmr` (#409). - Added default constructors to `MmrPeaks` and `PartialMmr` (#409).
- Add module and function documentation. (#408).
## 0.14.0 (2025-03-15) ## 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 alloc::string::ToString;
use core::ops::Deref; use core::ops::Deref;
@ -50,6 +60,8 @@ impl From<PublicKey> for Word {
// PUBLIC KEY POLYNOMIAL // 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)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct PubKeyPoly(pub Polynomial<FalconFelt>); 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 alloc::vec::Vec;
use core::{ use core::{
default::Default, default::Default,
@ -13,8 +15,10 @@ use crate::{
dsa::rpo_falcon512::{MODULUS, N}, dsa::rpo_falcon512::{MODULUS, N},
}; };
/// Represents a polynomial with coefficients of type F.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct Polynomial<F> { pub struct Polynomial<F> {
/// Coefficients of the polynomial, ordered from lowest to highest degree.
pub coefficients: Vec<F>, pub coefficients: Vec<F>,
} }
@ -22,6 +26,7 @@ impl<F> Polynomial<F>
where where
F: Clone, F: Clone,
{ {
/// Creates a new polynomial from the provided coefficients.
pub fn new(coefficients: Vec<F>) -> Self { pub fn new(coefficients: Vec<F>) -> Self {
Self { coefficients } Self { coefficients }
} }
@ -30,6 +35,7 @@ where
impl<F: Mul<Output = F> + Sub<Output = F> + AddAssign + Zero + Div<Output = F> + Clone + Inverse> impl<F: Mul<Output = F> + Sub<Output = F> + AddAssign + Zero + Div<Output = F> + Clone + Inverse>
Polynomial<F> Polynomial<F>
{ {
/// Multiplies two polynomials coefficient-wise (Hadamard multiplication).
pub fn hadamard_mul(&self, other: &Self) -> Self { pub fn hadamard_mul(&self, other: &Self) -> Self {
Polynomial::new( Polynomial::new(
self.coefficients self.coefficients
@ -39,6 +45,7 @@ impl<F: Mul<Output = F> + Sub<Output = F> + AddAssign + Zero + Div<Output = F> +
.collect(), .collect(),
) )
} }
/// Divides two polynomials coefficient-wise (Hadamard division).
pub fn hadamard_div(&self, other: &Self) -> Self { pub fn hadamard_div(&self, other: &Self) -> Self {
let other_coefficients_inverse = F::batch_inverse_or_zero(&other.coefficients); let other_coefficients_inverse = F::batch_inverse_or_zero(&other.coefficients);
Polynomial::new( 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 { pub fn hadamard_inv(&self) -> Self {
let coefficients_inverse = F::batch_inverse_or_zero(&self.coefficients); let coefficients_inverse = F::batch_inverse_or_zero(&self.coefficients);
Polynomial::new(coefficients_inverse) 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> { impl<F: Zero + PartialEq + Clone> Polynomial<F> {
/// Returns the degree of the polynomial.
pub fn degree(&self) -> Option<usize> { pub fn degree(&self) -> Option<usize> {
if self.coefficients.is_empty() { if self.coefficients.is_empty() {
return None; return None;
@ -72,6 +81,7 @@ impl<F: Zero + PartialEq + Clone> Polynomial<F> {
Some(max_index) Some(max_index)
} }
/// Returns the leading coefficient of the polynomial.
pub fn lc(&self) -> F { pub fn lc(&self) -> F {
match self.degree() { match self.degree() {
Some(non_negative_degree) => self.coefficients[non_negative_degree].clone(), Some(non_negative_degree) => self.coefficients[non_negative_degree].clone(),
@ -392,20 +402,24 @@ where
} }
impl<F: Zero + Clone> Polynomial<F> { impl<F: Zero + Clone> Polynomial<F> {
/// Shifts the polynomial by the specified amount (adds leading zeros).
pub fn shift(&self, shamt: usize) -> Self { pub fn shift(&self, shamt: usize) -> Self {
Self { Self {
coefficients: [vec![F::zero(); shamt], self.coefficients.clone()].concat(), coefficients: [vec![F::zero(); shamt], self.coefficients.clone()].concat(),
} }
} }
/// Creates a constant polynomial with a single coefficient.
pub fn constant(f: F) -> Self { pub fn constant(f: F) -> Self {
Self { coefficients: vec![f] } 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> { pub fn map<G: Clone, C: FnMut(&F) -> G>(&self, closure: C) -> Polynomial<G> {
Polynomial::<G>::new(self.coefficients.iter().map(closure).collect()) 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 { pub fn fold<G, C: FnMut(G, &F) -> G + Clone>(&self, mut initial_value: G, closure: C) -> G {
for c in self.coefficients.iter() { for c in self.coefficients.iter() {
initial_value = (closure.clone())(initial_value, c); initial_value = (closure.clone())(initial_value, c);
@ -544,6 +558,7 @@ impl From<&Vec<i16>> for Polynomial<FalconFelt> {
} }
impl Polynomial<FalconFelt> { impl Polynomial<FalconFelt> {
/// Computes the squared L2 norm of the polynomial.
pub fn norm_squared(&self) -> u64 { pub fn norm_squared(&self) -> u64 {
self.coefficients self.coefficients
.iter() .iter()

View file

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

View file

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

View file

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