Skip to main content

lib_q_poseidon/
lib.rs

1//! Poseidon hash function optimized for zero-knowledge proofs
2//!
3//! This crate provides a field-native implementation of the Poseidon hash function,
4//! specifically optimized for use in STARK proof systems with `Complex<Mersenne31>`.
5//!
6//! # Design
7//!
8//! Poseidon is an algebraic hash function designed for efficient implementation in
9//! zero-knowledge proof systems. Unlike traditional hashes like SHA-3, Poseidon
10//! operates directly on field elements, making it orders of magnitude more efficient
11//! in circuit constraints.
12//!
13//! # Security
14//!
15//! - Uses round counts and an MDS construction inspired by the Poseidon design.
16//! - MDS matrices use a Cauchy construction (every square submatrix is invertible).
17//!
18//! WARNING: the round counts and sponge parameters in this crate have NOT been
19//! independently verified for the `Complex<Mersenne31>` extension field GF(p²).
20//! The standard Poseidon security analysis is stated over a prime field and does
21//! not directly cover this exact field and state. Do NOT rely on a specific
22//! bit-security level (e.g. 128-bit or 256-bit) for these parameters until they
23//! have been regenerated and analyzed for GF(p²).
24//!
25//! # Example
26//!
27//! ```rust,ignore
28//! use lib_q_poseidon::{Poseidon, Poseidon128};
29//! use lib_q_stark_field::extension::Complex;
30//! use lib_q_stark_mersenne31::Mersenne31;
31//!
32//! type Val = Complex<Mersenne31>;
33//!
34//! let hasher = Poseidon128::permutation();
35//! let input = vec![Val::from(1u32), Val::from(2u32)];
36//! let hash = hasher.hash(&input);
37//! ```
38
39#![cfg_attr(not(feature = "std"), no_std)]
40#![deny(unsafe_code)]
41#![deny(unused_qualifications)]
42
43#[cfg(feature = "alloc")]
44extern crate alloc;
45
46#[cfg(feature = "alloc")]
47use alloc::string::String;
48#[cfg(all(feature = "alloc", feature = "std"))]
49use alloc::string::ToString;
50
51mod constants;
52#[cfg(feature = "alloc")]
53mod params;
54#[cfg(feature = "alloc")]
55mod permutation;
56#[cfg(feature = "alloc")]
57mod sponge;
58
59// Export constants for AIR constraint generation
60pub use constants::sbox;
61#[cfg(feature = "alloc")]
62pub use constants::{
63    mds_matrix_5x5,
64    mds_matrix_7x7,
65};
66#[cfg(feature = "alloc")]
67pub use constants::{
68    round_constants_128,
69    round_constants_256,
70};
71#[cfg(feature = "alloc")]
72pub use params::{
73    Poseidon128,
74    Poseidon256,
75    PoseidonField,
76    PoseidonParams,
77};
78#[cfg(feature = "alloc")]
79pub use permutation::{
80    PoseidonPermutation,
81    PoseidonState,
82};
83#[cfg(feature = "alloc")]
84pub use sponge::{
85    Poseidon,
86    PoseidonSponge,
87    PoseidonSpongeSqueeze,
88};
89
90#[cfg(feature = "wasm")]
91pub mod wasm;
92
93/// Error types for Poseidon operations
94#[derive(Debug, Clone, PartialEq, Eq)]
95pub enum PoseidonError {
96    /// Input size exceeds maximum allowed
97    InputTooLarge { max: usize, actual: usize },
98    /// Invalid parameter configuration
99    #[cfg(feature = "alloc")]
100    InvalidParams { reason: String },
101    /// Internal error during hashing
102    #[cfg(feature = "alloc")]
103    InternalError { reason: String },
104}
105
106impl core::fmt::Display for PoseidonError {
107    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
108        match self {
109            PoseidonError::InputTooLarge { max, actual } => {
110                write!(f, "Input size {} exceeds maximum {}", actual, max)
111            }
112            #[cfg(feature = "alloc")]
113            PoseidonError::InvalidParams { reason } => {
114                write!(f, "Invalid Poseidon parameters: {}", reason)
115            }
116            #[cfg(feature = "alloc")]
117            PoseidonError::InternalError { reason } => {
118                write!(f, "Internal Poseidon error: {}", reason)
119            }
120        }
121    }
122}
123
124#[cfg(all(feature = "alloc", feature = "std"))]
125impl From<PoseidonError> for lib_q_core::Error {
126    fn from(err: PoseidonError) -> Self {
127        lib_q_core::Error::InternalError {
128            operation: "Poseidon hash".into(),
129            details: err.to_string(),
130        }
131    }
132}
133
134#[cfg(all(not(feature = "alloc"), feature = "std"))]
135impl From<PoseidonError> for lib_q_core::Error {
136    fn from(err: PoseidonError) -> Self {
137        match err {
138            PoseidonError::InputTooLarge { .. } => lib_q_core::Error::InternalError {
139                operation: "Poseidon hash",
140                details: "input too large",
141            },
142        }
143    }
144}