1use alloc::vec::Vec;
2
3use vm_core::{
4 crypto::hash::{Blake3_192, Blake3_256, Hasher, Rpo256, Rpx256},
5 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
6};
7use winter_air::proof::Proof;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ExecutionProof {
18 pub proof: Proof,
19 pub hash_fn: HashFunction,
20}
21
22impl ExecutionProof {
23 pub const fn new(proof: Proof, hash_fn: HashFunction) -> Self {
29 Self { proof, hash_fn }
30 }
31
32 pub const fn stark_proof(&self) -> &Proof {
37 &self.proof
38 }
39
40 pub const fn hash_fn(&self) -> HashFunction {
42 self.hash_fn
43 }
44
45 pub fn security_level(&self) -> u32 {
47 match self.hash_fn {
48 HashFunction::Blake3_192 => self.proof.security_level::<Blake3_192>(true),
49 HashFunction::Blake3_256 => self.proof.security_level::<Blake3_256>(true),
50 HashFunction::Rpo256 => self.proof.security_level::<Rpo256>(true),
51 HashFunction::Rpx256 => self.proof.security_level::<Rpx256>(true),
52 }
53 }
54
55 pub fn to_bytes(&self) -> Vec<u8> {
60 let mut bytes = self.proof.to_bytes();
61 assert!(!bytes.is_empty(), "invalid STARK proof");
62 bytes.insert(0, self.hash_fn as u8);
64 bytes
65 }
66
67 pub fn from_bytes(source: &[u8]) -> Result<Self, DeserializationError> {
69 if source.len() < 2 {
70 return Err(DeserializationError::UnexpectedEOF);
71 }
72 let hash_fn = HashFunction::try_from(source[0])?;
73 let proof = Proof::from_bytes(&source[1..])?;
74 Ok(Self::new(proof, hash_fn))
75 }
76
77 pub fn into_parts(self) -> (HashFunction, Proof) {
82 (self.hash_fn, self.proof)
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
91#[repr(u8)]
92pub enum HashFunction {
93 Blake3_192 = 0x00,
95 Blake3_256 = 0x01,
97 Rpo256 = 0x02,
99 Rpx256 = 0x03,
101}
102
103impl Default for HashFunction {
104 fn default() -> Self {
105 Self::Blake3_192
106 }
107}
108
109impl HashFunction {
110 pub const fn collision_resistance(&self) -> u32 {
112 match self {
113 HashFunction::Blake3_192 => Blake3_192::COLLISION_RESISTANCE,
114 HashFunction::Blake3_256 => Blake3_256::COLLISION_RESISTANCE,
115 HashFunction::Rpo256 => Rpo256::COLLISION_RESISTANCE,
116 HashFunction::Rpx256 => Rpx256::COLLISION_RESISTANCE,
117 }
118 }
119}
120
121impl TryFrom<u8> for HashFunction {
122 type Error = DeserializationError;
123
124 fn try_from(repr: u8) -> Result<Self, Self::Error> {
125 match repr {
126 0x00 => Ok(Self::Blake3_192),
127 0x01 => Ok(Self::Blake3_256),
128 0x02 => Ok(Self::Rpo256),
129 0x03 => Ok(Self::Rpx256),
130 _ => Err(DeserializationError::InvalidValue(format!(
131 "the hash function representation {repr} is not valid!"
132 ))),
133 }
134 }
135}
136
137impl Serializable for HashFunction {
141 fn write_into<W: ByteWriter>(&self, target: &mut W) {
142 target.write_u8(*self as u8);
143 }
144}
145
146impl Deserializable for HashFunction {
147 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
148 source.read_u8()?.try_into()
149 }
150}
151
152impl Serializable for ExecutionProof {
153 fn write_into<W: ByteWriter>(&self, target: &mut W) {
154 self.proof.write_into(target);
155 self.hash_fn.write_into(target);
156 }
157}
158
159impl Deserializable for ExecutionProof {
160 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
161 let proof = Proof::read_from(source)?;
162 let hash_fn = HashFunction::read_from(source)?;
163
164 Ok(ExecutionProof { proof, hash_fn })
165 }
166}