docs: add module and function documentation (#408)
This commit is contained in:
parent
03647457d9
commit
c1920e3a1a
6 changed files with 47 additions and 1 deletions
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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 polynomial’s
|
||||||
|
//! 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>);
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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>);
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue