1use alloc::{string::ToString, vec::Vec};
2
3use miden_core::{
4 crypto::hash::{Blake3_192, Blake3_256, Hasher, Poseidon2, Rpo256, Rpx256},
5 precompile::PrecompileRequest,
6 utils::{
7 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
8 },
9};
10use winter_air::proof::Proof;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct ExecutionProof {
21 pub proof: Proof,
22 pub hash_fn: HashFunction,
23 pub pc_requests: Vec<PrecompileRequest>,
24}
25
26impl ExecutionProof {
27 pub const fn new(
33 proof: Proof,
34 hash_fn: HashFunction,
35 pc_requests: Vec<PrecompileRequest>,
36 ) -> Self {
37 Self { proof, hash_fn, pc_requests }
38 }
39
40 pub const fn stark_proof(&self) -> &Proof {
45 &self.proof
46 }
47
48 pub const fn hash_fn(&self) -> HashFunction {
50 self.hash_fn
51 }
52
53 pub fn precompile_requests(&self) -> &[PrecompileRequest] {
55 &self.pc_requests
56 }
57
58 pub fn security_level(&self) -> u32 {
60 let conjectured_security = match self.hash_fn {
61 HashFunction::Blake3_192 => self.proof.conjectured_security::<Blake3_192>(),
62 HashFunction::Blake3_256 => self.proof.conjectured_security::<Blake3_256>(),
63 HashFunction::Rpo256 => self.proof.conjectured_security::<Rpo256>(),
64 HashFunction::Rpx256 => self.proof.conjectured_security::<Rpx256>(),
65 HashFunction::Poseidon2 => self.proof.conjectured_security::<Poseidon2>(),
66 };
67 conjectured_security.bits()
68 }
69
70 pub fn to_bytes(&self) -> Vec<u8> {
75 let mut bytes = Vec::new();
76 self.write_into(&mut bytes);
77 bytes
78 }
79
80 pub fn from_bytes(source: &[u8]) -> Result<Self, DeserializationError> {
82 let mut reader = SliceReader::new(source);
83 Self::read_from(&mut reader)
84 }
85
86 pub fn into_parts(self) -> (HashFunction, Proof, Vec<PrecompileRequest>) {
91 (self.hash_fn, self.proof, self.pc_requests)
92 }
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
100#[repr(u8)]
101pub enum HashFunction {
102 Blake3_192 = 0x00,
104 Blake3_256 = 0x01,
106 Rpo256 = 0x02,
108 Rpx256 = 0x03,
110 Poseidon2 = 0x04,
112}
113
114impl HashFunction {
115 pub const fn collision_resistance(&self) -> u32 {
117 match self {
118 HashFunction::Blake3_192 => Blake3_192::COLLISION_RESISTANCE,
119 HashFunction::Blake3_256 => Blake3_256::COLLISION_RESISTANCE,
120 HashFunction::Rpo256 => Rpo256::COLLISION_RESISTANCE,
121 HashFunction::Rpx256 => Rpx256::COLLISION_RESISTANCE,
122 HashFunction::Poseidon2 => Poseidon2::COLLISION_RESISTANCE,
123 }
124 }
125}
126
127impl TryFrom<u8> for HashFunction {
128 type Error = DeserializationError;
129
130 fn try_from(repr: u8) -> Result<Self, Self::Error> {
131 match repr {
132 0x00 => Ok(Self::Blake3_192),
133 0x01 => Ok(Self::Blake3_256),
134 0x02 => Ok(Self::Rpo256),
135 0x03 => Ok(Self::Rpx256),
136 0x04 => Ok(Self::Poseidon2),
137 _ => Err(DeserializationError::InvalidValue(format!(
138 "the hash function representation {repr} is not valid!"
139 ))),
140 }
141 }
142}
143
144impl TryFrom<&str> for HashFunction {
145 type Error = super::ExecutionOptionsError;
146
147 fn try_from(hash_fn_str: &str) -> Result<Self, Self::Error> {
148 match hash_fn_str {
149 "blake3-192" => Ok(Self::Blake3_192),
150 "blake3-256" => Ok(Self::Blake3_256),
151 "rpo" => Ok(Self::Rpo256),
152 "rpx" => Ok(Self::Rpx256),
153 "poseidon2" => Ok(Self::Poseidon2),
154 _ => Err(super::ExecutionOptionsError::InvalidHashFunction {
155 hash_function: hash_fn_str.to_string(),
156 }),
157 }
158 }
159}
160
161impl Serializable for HashFunction {
165 fn write_into<W: ByteWriter>(&self, target: &mut W) {
166 target.write_u8(*self as u8);
167 }
168}
169
170impl Deserializable for HashFunction {
171 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
172 source.read_u8()?.try_into()
173 }
174}
175
176impl Serializable for ExecutionProof {
177 fn write_into<W: ByteWriter>(&self, target: &mut W) {
178 self.proof.write_into(target);
179 self.hash_fn.write_into(target);
180 self.pc_requests.write_into(target);
181 }
182}
183
184impl Deserializable for ExecutionProof {
185 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
186 let proof = Proof::read_from(source)?;
187 let hash_fn = HashFunction::read_from(source)?;
188 let pc_requests = Vec::<PrecompileRequest>::read_from(source)?;
189
190 Ok(ExecutionProof { proof, hash_fn, pc_requests })
191 }
192}
193
194#[cfg(any(test, feature = "testing"))]
198impl ExecutionProof {
199 pub fn new_dummy() -> Self {
203 ExecutionProof {
204 proof: Proof::new_dummy(),
205 hash_fn: HashFunction::Blake3_192,
206 pc_requests: Vec::new(),
207 }
208 }
209}