Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/provablehq/snarkvm/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The crypto_hash module provides cryptographic hash functions designed for efficient use in zero-knowledge proof systems. The primary hash function is Poseidon, an algebraic hash optimized for ZK circuits.

Poseidon Hash

Poseidon Struct

The Poseidon hash function with fixed output size.
pub struct Poseidon<F: PrimeField, const RATE: usize> {
    parameters: Arc<PoseidonParameters<F, RATE, 1>>,
}
F
PrimeField
The prime field over which the hash function operates
RATE
const usize
The rate of the sponge (number of field elements absorbed per permutation)

Methods

setup

Initializes a new Poseidon hash function with default parameters.
pub fn setup() -> Self
return
Poseidon<F, RATE>
A new Poseidon instance with default parameters for the field
Example:
use snarkvm_algorithms::crypto_hash::Poseidon;
use snarkvm_curves::bls12_377::Fr;

// Create a Poseidon hash with rate 4
let poseidon = Poseidon::<Fr, 4>::setup();

evaluate

Evaluates the hash function over a list of field elements.
pub fn evaluate(&self, input: &[F]) -> F
input
&[F]
Slice of field elements to hash
return
F
The hash output as a single field element
Example:
let input = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)];
let hash = poseidon.evaluate(&input);

evaluate_many

Evaluates the hash function and returns multiple output elements.
pub fn evaluate_many(&self, input: &[F], num_outputs: usize) -> Vec<F>
input
&[F]
Slice of field elements to hash
num_outputs
usize
Number of field elements to output
return
Vec<F>
Vector of hash output field elements
Example:
// Get 3 hash outputs from the input
let hashes = poseidon.evaluate_many(&input, 3);
assert_eq!(hashes.len(), 3);

evaluate_with_len

Evaluates the hash function, including the input length in the hash.
pub fn evaluate_with_len(&self, input: &[F]) -> F
input
&[F]
Slice of field elements to hash
return
F
The hash output including length commitment
Note: This method prepends the length to prevent length-extension attacks. Example:
// Hash with length protection
let hash = poseidon.evaluate_with_len(&input);

PoseidonSponge

PoseidonSponge Struct

A duplex sponge construction using the Poseidon permutation.
pub struct PoseidonSponge<F: PrimeField, const RATE: usize, const CAPACITY: usize> {
    parameters: Arc<PoseidonParameters<F, RATE, CAPACITY>>,
    state: State<F, RATE, CAPACITY>,
    mode: DuplexSpongeMode,
}
RATE
const usize
Number of field elements absorbed/squeezed per permutation
CAPACITY
const usize
Number of field elements in the capacity (typically 1 for 128-bit security)

AlgebraicSponge Implementation

PoseidonSponge implements the AlgebraicSponge trait for Fiat-Shamir transformations.

absorb_native_field_elements

Absorbs field elements into the sponge state.
pub fn absorb_native_field_elements<T: ToConstraintField<F>>(&mut self, elements: &[T])
elements
&[T]
Elements to absorb (automatically converted to field elements)
Example:
use snarkvm_algorithms::{crypto_hash::PoseidonSponge, AlgebraicSponge};

let params = PoseidonSponge::<Fr, 4, 1>::sample_parameters();
let mut sponge = PoseidonSponge::new_with_parameters(&params);

// Absorb field elements
sponge.absorb_native_field_elements(&[Fr::from(1u64), Fr::from(2u64)]);

squeeze_native_field_elements

Squeezes field elements from the sponge state.
pub fn squeeze_native_field_elements(&mut self, num_elements: usize) -> SmallVec<[F; 10]>
num_elements
usize
Number of field elements to squeeze
return
SmallVec<[F; 10]>
Squeezed field elements
Example:
// Squeeze 3 challenge field elements
let challenges = sponge.squeeze_native_field_elements(3);

absorb_nonnative_field_elements

Absorbs non-native field elements (from a different field).
pub fn absorb_nonnative_field_elements<Target: PrimeField>(
    &mut self,
    elements: impl IntoIterator<Item = Target>
)
elements
impl IntoIterator<Item = Target>
Non-native field elements to absorb
Example:
use snarkvm_curves::edwards_bls12::Fr as EdwardsFr;

// Absorb elements from a different field
let edwards_elements = vec![EdwardsFr::from(1u64), EdwardsFr::from(2u64)];
sponge.absorb_nonnative_field_elements(edwards_elements.into_iter());

squeeze_nonnative_field_elements

Squeezes non-native field elements.
pub fn squeeze_nonnative_field_elements<Target: PrimeField>(
    &mut self,
    num: usize
) -> SmallVec<[Target; 10]>
num
usize
Number of non-native field elements to squeeze
return
SmallVec<[Target; 10]>
Squeezed non-native field elements

Sponge State Management

State Struct

Internal state of the Poseidon sponge.
pub struct State<F: PrimeField, const RATE: usize, const CAPACITY: usize> {
    capacity_state: [F; CAPACITY],
    rate_state: [F; RATE],
}
The state is split into:
  • Capacity: Hidden state providing security
  • Rate: Public state for absorbing/squeezing

DuplexSpongeMode Enum

Tracks the current mode of the sponge.
pub enum DuplexSpongeMode {
    Absorbing { next_absorb_index: usize },
    Squeezing { next_squeeze_index: usize },
}

Advanced Methods

get_limbs_representations

Converts a non-native field element to limb representation.
pub fn get_limbs_representations<TargetField: PrimeField>(
    elem: &TargetField,
    optimization_type: OptimizationType,
) -> SmallVec<[F; 10]>
elem
&TargetField
The field element to convert
optimization_type
OptimizationType
Whether to optimize for weight or constraints
return
SmallVec<[F; 10]>
Limb representation in the base field

get_bits

Obtains random bits from the sponge.
pub fn get_bits(&mut self, num_bits: usize) -> Vec<bool>
num_bits
usize
Number of random bits to generate
return
Vec<bool>
Random bits derived from the sponge state
Note: Not uniformly distributed; use for specific applications only.

Implementation Details

Permutation

The Poseidon permutation consists of:
  1. Full rounds: S-box applied to all state elements
  2. Partial rounds: S-box applied to only the first state element
  3. MDS matrix multiplication: Mixing layer
fn permute(&mut self) {
    for i in 0..(partial_rounds + full_rounds) {
        let is_full_round = !partial_round_range.contains(&i);
        self.apply_ark(i);        // Add round constants
        self.apply_s_box(is_full_round); // S-box layer
        self.apply_mds();          // MDS mixing
    }
}

Parameters

Poseidon parameters include:
  • Alpha: S-box exponent (typically 5 or 17)
  • Full rounds: Number of full S-box rounds
  • Partial rounds: Number of partial S-box rounds
  • ARK: Round constants for domain separation
  • MDS: Maximum distance separable matrix

Security

Poseidon provides:
  • 128-bit security with CAPACITY = 1
  • Collision resistance via sponge construction
  • Preimage resistance via one-way permutation

Usage in Fiat-Shamir

PoseidonSponge is used for Fiat-Shamir transformations in proof systems:
type FS = PoseidonSponge<Fq, 2, 1>;
let mut fs_rng = FS::new_with_parameters(&fs_parameters);

// Absorb commitments
fs_rng.absorb_native_field_elements(&commitments);

// Generate challenge
let challenge = fs_rng.squeeze_native_field_elements(1)[0];

See Also

Build docs developers (and LLMs) love