openvm_circuit/system/poseidon2/
mod.rs

1//! Chip to handle **native kernel** instructions for Poseidon2 `compress` and `permute`.
2//! This chip is put in `intrinsics` for organizational convenience, but
3//! it is used as a system chip for persistent memory and as a native kernel chip for aggregation.
4//!
5//! Note that neither `compress` nor `permute` on its own
6//! is a cryptographic hash. `permute` is a cryptographic permutation, which can be made
7//! into a hash by applying a sponge construction. `compress` can be used as a hash in the
8//! internal leaves of a Merkle tree but **not** as the leaf hash because `compress` does not
9//! add any padding.
10
11use openvm_poseidon2_air::Poseidon2Config;
12use openvm_stark_backend::{
13    config::{StarkGenericConfig, Val},
14    interaction::BusIndex,
15    p3_field::PrimeField32,
16    prover::types::AirProofInput,
17    AirRef, Chip, ChipUsageGetter,
18};
19
20#[cfg(test)]
21pub mod tests;
22
23pub mod air;
24mod chip;
25pub use chip::*;
26
27use crate::arch::hasher::{Hasher, HasherChip};
28pub mod columns;
29pub mod trace;
30
31pub const PERIPHERY_POSEIDON2_WIDTH: usize = 16;
32pub const PERIPHERY_POSEIDON2_CHUNK_SIZE: usize = 8;
33
34pub enum Poseidon2PeripheryChip<F: PrimeField32> {
35    Register0(Poseidon2PeripheryBaseChip<F, 0>),
36    Register1(Poseidon2PeripheryBaseChip<F, 1>),
37}
38impl<F: PrimeField32> Poseidon2PeripheryChip<F> {
39    pub fn new(
40        poseidon2_config: Poseidon2Config<F>,
41        bus_idx: BusIndex,
42        max_constraint_degree: usize,
43    ) -> Self {
44        if max_constraint_degree >= 7 {
45            Self::Register0(Poseidon2PeripheryBaseChip::new(poseidon2_config, bus_idx))
46        } else {
47            Self::Register1(Poseidon2PeripheryBaseChip::new(poseidon2_config, bus_idx))
48        }
49    }
50}
51
52impl<SC: StarkGenericConfig> Chip<SC> for Poseidon2PeripheryChip<Val<SC>>
53where
54    Val<SC>: PrimeField32,
55{
56    fn air(&self) -> AirRef<SC> {
57        match self {
58            Poseidon2PeripheryChip::Register0(chip) => chip.air(),
59            Poseidon2PeripheryChip::Register1(chip) => chip.air(),
60        }
61    }
62
63    fn generate_air_proof_input(self) -> AirProofInput<SC> {
64        match self {
65            Poseidon2PeripheryChip::Register0(chip) => chip.generate_air_proof_input(),
66            Poseidon2PeripheryChip::Register1(chip) => chip.generate_air_proof_input(),
67        }
68    }
69}
70
71impl<F: PrimeField32> ChipUsageGetter for Poseidon2PeripheryChip<F> {
72    fn air_name(&self) -> String {
73        match self {
74            Poseidon2PeripheryChip::Register0(chip) => chip.air_name(),
75            Poseidon2PeripheryChip::Register1(chip) => chip.air_name(),
76        }
77    }
78
79    fn current_trace_height(&self) -> usize {
80        match self {
81            Poseidon2PeripheryChip::Register0(chip) => chip.current_trace_height(),
82            Poseidon2PeripheryChip::Register1(chip) => chip.current_trace_height(),
83        }
84    }
85
86    fn trace_width(&self) -> usize {
87        match self {
88            Poseidon2PeripheryChip::Register0(chip) => chip.trace_width(),
89            Poseidon2PeripheryChip::Register1(chip) => chip.trace_width(),
90        }
91    }
92}
93
94impl<F: PrimeField32> Hasher<PERIPHERY_POSEIDON2_CHUNK_SIZE, F> for Poseidon2PeripheryChip<F> {
95    fn compress(
96        &self,
97        lhs: &[F; PERIPHERY_POSEIDON2_CHUNK_SIZE],
98        rhs: &[F; PERIPHERY_POSEIDON2_CHUNK_SIZE],
99    ) -> [F; PERIPHERY_POSEIDON2_CHUNK_SIZE] {
100        match self {
101            Poseidon2PeripheryChip::Register0(chip) => chip.compress(lhs, rhs),
102            Poseidon2PeripheryChip::Register1(chip) => chip.compress(lhs, rhs),
103        }
104    }
105}
106
107impl<F: PrimeField32> HasherChip<PERIPHERY_POSEIDON2_CHUNK_SIZE, F> for Poseidon2PeripheryChip<F> {
108    fn compress_and_record(
109        &mut self,
110        lhs: &[F; PERIPHERY_POSEIDON2_CHUNK_SIZE],
111        rhs: &[F; PERIPHERY_POSEIDON2_CHUNK_SIZE],
112    ) -> [F; PERIPHERY_POSEIDON2_CHUNK_SIZE] {
113        match self {
114            Poseidon2PeripheryChip::Register0(chip) => chip.compress_and_record(lhs, rhs),
115            Poseidon2PeripheryChip::Register1(chip) => chip.compress_and_record(lhs, rhs),
116        }
117    }
118}