1use alloc::{
2 string::{String, ToString},
3 vec::Vec,
4};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 crypto::hash::{Blake3_256, Poseidon2, Rpo256, Rpx256},
11 precompile::PrecompileRequest,
12 serde::{
13 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
14 },
15};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27pub struct ExecutionProof {
28 pub proof: Vec<u8>,
29 pub hash_fn: HashFunction,
30 pub pc_requests: Vec<PrecompileRequest>,
31}
32
33impl ExecutionProof {
34 pub const fn new(
40 proof: Vec<u8>,
41 hash_fn: HashFunction,
42 pc_requests: Vec<PrecompileRequest>,
43 ) -> Self {
44 Self { proof, hash_fn, pc_requests }
45 }
46
47 pub fn stark_proof(&self) -> &[u8] {
52 &self.proof
53 }
54
55 pub const fn hash_fn(&self) -> HashFunction {
57 self.hash_fn
58 }
59
60 pub fn precompile_requests(&self) -> &[PrecompileRequest] {
62 &self.pc_requests
63 }
64
65 pub fn security_level(&self) -> u32 {
73 96
74 }
75
76 pub fn to_bytes(&self) -> Vec<u8> {
81 let mut bytes = Vec::new();
82 self.write_into(&mut bytes);
83 bytes
84 }
85
86 pub fn from_bytes(source: &[u8]) -> Result<Self, DeserializationError> {
90 let mut reader = SliceReader::new(source);
91 Self::read_from(&mut reader)
92 }
93
94 pub fn into_parts(self) -> (HashFunction, Vec<u8>, Vec<PrecompileRequest>) {
99 (self.hash_fn, self.proof, self.pc_requests)
100 }
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
109#[repr(u8)]
110pub enum HashFunction {
111 Blake3_256 = 0x01,
113 Rpo256 = 0x02,
115 Rpx256 = 0x03,
117 Poseidon2 = 0x04,
119 Keccak = 0x05,
121}
122
123impl HashFunction {
124 pub const fn collision_resistance(&self) -> u32 {
126 match self {
127 HashFunction::Blake3_256 => Blake3_256::COLLISION_RESISTANCE,
128 HashFunction::Rpo256 => Rpo256::COLLISION_RESISTANCE,
129 HashFunction::Rpx256 => Rpx256::COLLISION_RESISTANCE,
130 HashFunction::Poseidon2 => Poseidon2::COLLISION_RESISTANCE,
131 HashFunction::Keccak => 128,
132 }
133 }
134}
135
136impl TryFrom<u8> for HashFunction {
137 type Error = DeserializationError;
138
139 fn try_from(repr: u8) -> Result<Self, Self::Error> {
140 match repr {
141 0x01 => Ok(Self::Blake3_256),
142 0x02 => Ok(Self::Rpo256),
143 0x03 => Ok(Self::Rpx256),
144 0x04 => Ok(Self::Poseidon2),
145 0x05 => Ok(Self::Keccak),
146 _ => Err(DeserializationError::InvalidValue(format!(
147 "the hash function representation {repr} is not valid!"
148 ))),
149 }
150 }
151}
152
153impl TryFrom<&str> for HashFunction {
154 type Error = InvalidHashFunctionError;
155
156 fn try_from(hash_fn_str: &str) -> Result<Self, Self::Error> {
157 match hash_fn_str {
158 "blake3-256" => Ok(Self::Blake3_256),
159 "rpo" => Ok(Self::Rpo256),
160 "rpx" => Ok(Self::Rpx256),
161 "poseidon2" => Ok(Self::Poseidon2),
162 "keccak" => Ok(Self::Keccak),
163 _ => Err(InvalidHashFunctionError { hash_function: hash_fn_str.to_string() }),
164 }
165 }
166}
167
168impl Serializable for HashFunction {
172 fn write_into<W: ByteWriter>(&self, target: &mut W) {
173 target.write_u8(*self as u8);
174 }
175}
176
177impl Deserializable for HashFunction {
178 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
179 source.read_u8()?.try_into()
180 }
181}
182
183impl Serializable for ExecutionProof {
184 fn write_into<W: ByteWriter>(&self, target: &mut W) {
185 self.proof.write_into(target);
186 self.hash_fn.write_into(target);
187 self.pc_requests.write_into(target);
188 }
189}
190
191impl Deserializable for ExecutionProof {
192 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
193 let proof = Vec::<u8>::read_from(source)?;
194 let hash_fn = HashFunction::read_from(source)?;
195 let pc_requests = Vec::<PrecompileRequest>::read_from(source)?;
196
197 Ok(ExecutionProof { proof, hash_fn, pc_requests })
198 }
199}
200
201#[derive(Debug, thiserror::Error)]
206#[error(
207 "invalid hash function '{hash_function}'. Valid options are: blake3-256, rpo, rpx, poseidon2, keccak"
208)]
209pub struct InvalidHashFunctionError {
210 pub hash_function: String,
211}
212
213#[cfg(any(test, feature = "testing"))]
217impl ExecutionProof {
218 pub fn new_dummy() -> Self {
222 ExecutionProof {
223 proof: Vec::new(),
224 hash_fn: HashFunction::Blake3_256,
225 pc_requests: Vec::new(),
226 }
227 }
228}