boundless_market/
selector.rs1use std::collections::HashMap;
18use std::fmt::{self, Display, Formatter};
19
20use alloy_primitives::FixedBytes;
21use clap::ValueEnum;
22use risc0_aggregation::SetInclusionReceiptVerifierParameters;
23use risc0_ethereum_contracts::selector::Selector;
24use risc0_zkvm::sha::{Digest, Digestible};
25use thiserror::Error;
26
27use crate::contracts::UNSPECIFIED_SELECTOR;
28use crate::util::is_dev_mode;
29
30#[derive(Debug, Error)]
31#[non_exhaustive]
32pub enum SelectorExtError {
34 #[error("Unsupported selector")]
36 UnsupportedSelector,
37 #[error("Selector {0} does not have verifier parameters")]
39 NoVerifierParameters(SelectorExt),
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43#[non_exhaustive]
44pub enum SelectorExtType {
46 FakeReceipt,
48 Groth16,
50 SetVerifier,
52 Blake3Groth16,
54 FakeBlake3Groth16,
56}
57
58#[repr(u32)]
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60#[non_exhaustive]
61pub enum SelectorExt {
63 FakeReceipt = 0xFFFFFFFF,
65 FakeBlake3Groth16 = 0xFFFF0000,
67 Groth16V3_0 = Selector::Groth16V3_0 as u32,
69 SetVerifierV0_9 = Selector::SetVerifierV0_9 as u32,
71 Blake3Groth16V0_1 = 0x62f049f6,
73}
74
75impl Display for SelectorExt {
76 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
77 write!(f, "{:#010x}", *self as u32)
78 }
79}
80
81impl TryFrom<u32> for SelectorExt {
82 type Error = SelectorExtError;
83
84 fn try_from(value: u32) -> Result<Self, Self::Error> {
85 match value {
86 0xFFFFFFFF => Ok(SelectorExt::FakeReceipt),
87 0xFFFF0000 => Ok(SelectorExt::FakeBlake3Groth16),
88 0x73c457ba => Ok(SelectorExt::Groth16V3_0),
89 0x242f9d5b => Ok(SelectorExt::SetVerifierV0_9),
90 0x62f049f6 => Ok(SelectorExt::Blake3Groth16V0_1),
91 _ => Err(SelectorExtError::UnsupportedSelector),
92 }
93 }
94}
95
96impl TryFrom<Selector> for SelectorExt {
97 type Error = SelectorExtError;
98
99 fn try_from(value: Selector) -> Result<Self, Self::Error> {
100 Self::try_from(value as u32)
101 }
102}
103
104impl SelectorExt {
105 pub fn groth16_latest() -> SelectorExt {
107 SelectorExt::Groth16V3_0
108 }
109
110 pub fn set_inclusion_latest() -> SelectorExt {
112 SelectorExt::SetVerifierV0_9
113 }
114
115 pub fn blake3_groth16_latest() -> SelectorExt {
117 SelectorExt::Blake3Groth16V0_1
119 }
120
121 pub fn from_bytes(bytes: [u8; 4]) -> Option<Self> {
123 Self::try_from(u32::from_be_bytes(bytes)).ok()
124 }
125
126 pub fn get_type(self) -> SelectorExtType {
128 match self {
129 SelectorExt::FakeReceipt => SelectorExtType::FakeReceipt,
130 SelectorExt::FakeBlake3Groth16 => SelectorExtType::FakeBlake3Groth16,
131 SelectorExt::Groth16V3_0 => SelectorExtType::Groth16,
132 SelectorExt::SetVerifierV0_9 => SelectorExtType::SetVerifier,
133 SelectorExt::Blake3Groth16V0_1 => SelectorExtType::Blake3Groth16,
134 }
135 }
136}
137
138#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, ValueEnum)]
142#[non_exhaustive]
143pub enum ProofType {
144 #[default]
146 Any,
147 Groth16,
149 Inclusion,
151 Blake3Groth16,
153}
154
155#[derive(Clone, Debug)]
157pub struct SupportedSelectors {
158 pub selectors: HashMap<FixedBytes<4>, ProofType>,
160}
161
162impl Default for SupportedSelectors {
163 fn default() -> Self {
164 let mut supported_selectors = Self::new()
165 .with_selector(UNSPECIFIED_SELECTOR, ProofType::Any)
166 .with_selector(
167 FixedBytes::from(SelectorExt::groth16_latest() as u32),
168 ProofType::Groth16,
169 )
170 .with_selector(
171 FixedBytes::from(SelectorExt::blake3_groth16_latest() as u32),
172 ProofType::Blake3Groth16,
173 );
174 if is_dev_mode() {
175 supported_selectors = supported_selectors
176 .with_selector(FixedBytes::from(SelectorExt::FakeReceipt as u32), ProofType::Any)
177 .with_selector(
178 FixedBytes::from(SelectorExt::FakeBlake3Groth16 as u32),
179 ProofType::Blake3Groth16,
180 )
181 }
182 supported_selectors
183 }
184}
185
186impl SupportedSelectors {
187 pub fn new() -> Self {
189 Self { selectors: HashMap::new() }
190 }
191
192 pub fn with_selector(mut self, selector: FixedBytes<4>, proof_type: ProofType) -> Self {
194 self.add_selector(selector, proof_type);
195 self
196 }
197
198 pub fn add_selector(&mut self, selector: FixedBytes<4>, proof_type: ProofType) -> &mut Self {
200 self.selectors.insert(selector, proof_type);
201 self
202 }
203
204 pub fn remove(&mut self, selector: FixedBytes<4>) {
206 if self.selectors.contains_key(&selector) {
207 self.selectors.remove(&selector);
208 }
209 }
210
211 pub fn is_supported(&self, selector: FixedBytes<4>) -> bool {
213 self.selectors.contains_key(&selector)
214 }
215
216 pub fn proof_type(&self, selector: FixedBytes<4>) -> Option<ProofType> {
218 self.selectors.get(&selector).cloned()
219 }
220
221 pub fn with_set_builder_image_id(&self, set_builder_image_id: impl Into<Digest>) -> Self {
226 let verifier_params =
227 SetInclusionReceiptVerifierParameters { image_id: set_builder_image_id.into() }
228 .digest();
229 let set_builder_selector: FixedBytes<4> =
230 verifier_params.as_bytes()[0..4].try_into().unwrap();
231 let mut selectors = self.selectors.clone();
232 selectors.insert(set_builder_selector, ProofType::Inclusion);
233
234 Self { selectors }
235 }
236}
237
238pub fn is_groth16_selector(selector: FixedBytes<4>) -> bool {
240 let sel = SelectorExt::from_bytes(selector.into());
241 match sel {
242 Some(selector) => {
243 selector.get_type() == SelectorExtType::FakeReceipt
244 || selector.get_type() == SelectorExtType::Groth16
245 }
246 None => false,
247 }
248}
249
250pub fn is_blake3_groth16_selector(selector: FixedBytes<4>) -> bool {
252 let sel = SelectorExt::from_bytes(selector.into());
253 match sel {
254 Some(selector) => {
255 selector.get_type() == SelectorExtType::FakeBlake3Groth16
256 || selector.get_type() == SelectorExtType::Blake3Groth16
257 }
258 None => false,
259 }
260}
261
262#[cfg(test)]
263mod tests {
264 use super::*;
265
266 #[test]
267 fn test_supported_selectors() {
268 let mut supported_selectors = SupportedSelectors::new();
269 let selector = FixedBytes::from(SelectorExt::groth16_latest() as u32);
270 supported_selectors = supported_selectors.with_selector(selector, ProofType::Groth16);
271 assert!(supported_selectors.is_supported(selector));
272 supported_selectors.remove(selector);
273 assert!(!supported_selectors.is_supported(selector));
274 }
275
276 #[test]
277 fn test_is_groth16_selector() {
278 let selector = FixedBytes::from(SelectorExt::groth16_latest() as u32);
279 assert!(is_groth16_selector(selector));
280 let fake_selector = FixedBytes::from(SelectorExt::FakeReceipt as u32);
281 assert!(is_groth16_selector(fake_selector));
282 }
283
284 #[test]
285 fn test_is_blake3_groth16_selector() {
286 let selector = FixedBytes::from(SelectorExt::blake3_groth16_latest() as u32);
287 assert!(is_blake3_groth16_selector(selector));
288 let fake_selector = FixedBytes::from(SelectorExt::FakeBlake3Groth16 as u32);
289 assert!(is_blake3_groth16_selector(fake_selector));
290 }
291}