pub use miden_air::config::{
Blake3Config, KeccakConfig, Poseidon2Config, RelationDigest, RpoConfig, RpxConfig,
blake3_256_config, keccak_config, observe_protocol_params, poseidon2_config, rpo_config,
rpx_config,
};
use miden_core::Felt;
use miden_crypto::{
field::Field,
hash::poseidon2::Poseidon2Permutation256,
stark::{
GenericStarkConfig, challenger::DuplexChallenger, dft::Radix2DitParallel,
hasher::StatefulSponge, lmcs::config::LmcsConfig, pcs::PcsParams,
symmetric::TruncatedPermutation,
},
};
pub type PrecompileStarkConfig<L, Ch> = miden_air::config::MidenStarkConfig<L, Ch>;
pub type PackedFelt = <Felt as Field>::Packing;
const COMPRESSION_INPUTS: usize = 2;
pub const PRECOMPILE_RELATION_DIGEST: RelationDigest = [
Felt::new_unchecked(15901056294547705196),
Felt::new_unchecked(13548154566962352054),
Felt::new_unchecked(13148050606838836712),
Felt::new_unchecked(2433548564999773594),
];
pub const DEFAULT_HASH_FUNCTION: miden_core::proof::HashFunction =
miden_core::proof::HashFunction::Poseidon2;
pub fn precompile_pcs_params() -> PcsParams {
PcsParams::new(
3, 2, 7, 4, 12, 27, 17, )
.expect("invalid precompile PCS parameters")
}
const WIDTH: usize = 12;
const RATE: usize = 8;
const DIGEST: usize = 4;
pub type Perm = Poseidon2Permutation256;
pub type Sponge = StatefulSponge<Perm, WIDTH, RATE, DIGEST>;
pub type Compress = TruncatedPermutation<Perm, COMPRESSION_INPUTS, DIGEST, WIDTH>;
pub type Challenger = DuplexChallenger<Felt, Perm, WIDTH, RATE>;
type AlgLmcs<P> = LmcsConfig<
PackedFelt,
PackedFelt,
StatefulSponge<P, WIDTH, RATE, DIGEST>,
TruncatedPermutation<P, COMPRESSION_INPUTS, DIGEST, WIDTH>,
WIDTH,
DIGEST,
>;
pub type Lmcs = AlgLmcs<Perm>;
pub type Dft = Radix2DitParallel<Felt>;
pub type TestConfig = Poseidon2Config;
pub fn test_pcs_params() -> PcsParams {
PcsParams::new(
3, 1, 3, 0, 0, 4, 0, )
.expect("invalid test PCS params")
}
pub fn test_challenger() -> Challenger {
DuplexChallenger::new(Poseidon2Permutation256)
}
pub fn test_lmcs() -> Lmcs {
LmcsConfig::new(Sponge::new(Poseidon2Permutation256), Compress::new(Poseidon2Permutation256))
}
pub fn test_config() -> TestConfig {
GenericStarkConfig::new(test_pcs_params(), test_lmcs(), Dft::default(), test_challenger())
}
#[cfg(test)]
mod tests {
extern crate alloc;
use alloc::{format, vec::Vec};
use miden_ace_codegen::{AceConfig, LayoutKind};
use miden_core::{Felt, crypto::hash::Poseidon2};
use crate::{ace, session::NUM_CHIPLETS};
const PROTOCOL_ID: u64 = 0;
const REGEN_HINT: &str = "update PRECOMPILE_RELATION_DIGEST in crates/precompiles-prover/src/stark_config.rs and accept the insta snapshot";
#[test]
fn precompile_relation_digest_matches_current_air() {
let config = AceConfig {
num_quotient_chunks: 8,
layout: LayoutKind::Masm,
num_airs: NUM_CHIPLETS,
};
let circuit = ace::build_precompile_multi_air_ace_circuit(config).unwrap();
let encoded = circuit.to_ace().unwrap();
let circuit_commitment: [Felt; 4] = encoded.circuit_hash().into();
let input: Vec<Felt> = core::iter::once(Felt::new_unchecked(PROTOCOL_ID))
.chain(circuit_commitment.iter().copied())
.collect();
let digest = Poseidon2::hash_elements(&input);
let expected: Vec<u64> = digest.as_elements().iter().map(Felt::as_canonical_u64).collect();
let snapshot = format!(
"num_inputs: {}\nnum_eval_gates: {}\nstream_len: {}\nrelation_digest: {:?}",
encoded.num_vars(),
encoded.num_eval_rows(),
encoded.size_in_felt(),
expected,
);
insta::assert_snapshot!(snapshot);
let actual: Vec<u64> =
super::PRECOMPILE_RELATION_DIGEST.iter().map(Felt::as_canonical_u64).collect();
assert_eq!(
actual, expected,
"PRECOMPILE_RELATION_DIGEST in stark_config.rs is stale; {REGEN_HINT}"
);
}
}