risc0_ethereum_contracts/
selector.rs

1// Copyright 2025 RISC Zero, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::{self, Display, Formatter};
16
17use hex::FromHex;
18use risc0_zkvm::sha::Digest;
19use thiserror::Error;
20
21#[derive(Debug, Error)]
22#[non_exhaustive]
23pub enum SelectorError {
24    #[error("Unsupported selector")]
25    UnsupportedSelector,
26    #[error("Selector {0} does not have verifier parameters")]
27    NoVerifierParameters(Selector),
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31#[non_exhaustive]
32pub enum SelectorType {
33    FakeReceipt,
34    Groth16,
35    SetVerifier,
36}
37
38#[repr(u32)]
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40#[non_exhaustive]
41pub enum Selector {
42    FakeReceipt = 0xFFFFFFFF,
43    Groth16V1_1 = 0x50bd1769,
44    Groth16V1_2 = 0xc101b42b,
45    Groth16V2_0 = 0x9f39696c,
46    SetVerifierV0_1 = 0xbfca9ccb,
47    SetVerifierV0_2 = 0x16a15cc8,
48    SetVerifierV0_4 = 0xf443ad7b,
49    SetVerifierV0_5 = 0xf2e6e6dc,
50}
51
52impl Display for Selector {
53    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
54        write!(f, "{:#010x}", *self as u32)
55    }
56}
57
58impl TryFrom<u32> for Selector {
59    type Error = SelectorError;
60
61    fn try_from(value: u32) -> Result<Self, Self::Error> {
62        match value {
63            0xFFFFFFFF => Ok(Selector::FakeReceipt),
64            0x50bd1769 => Ok(Selector::Groth16V1_1),
65            0xc101b42b => Ok(Selector::Groth16V1_2),
66            0x9f39696c => Ok(Selector::Groth16V2_0),
67            0xbfca9ccb => Ok(Selector::SetVerifierV0_1),
68            0x16a15cc8 => Ok(Selector::SetVerifierV0_2),
69            0xf443ad7b => Ok(Selector::SetVerifierV0_4),
70            0xf2e6e6dc => Ok(Selector::SetVerifierV0_5),
71            _ => Err(SelectorError::UnsupportedSelector),
72        }
73    }
74}
75
76impl Selector {
77    pub fn verifier_parameters_digest(self) -> Result<Digest, SelectorError> {
78        match self {
79            Selector::FakeReceipt => {
80                Err(SelectorError::NoVerifierParameters(Selector::FakeReceipt))
81            }
82            Selector::Groth16V1_1 => Ok(Digest::from_hex(
83                "50bd1769093e74abda3711c315d84d78e3e282173f6304a33272d92abb590ef5",
84            )
85            .unwrap()),
86            Selector::Groth16V1_2 => Ok(Digest::from_hex(
87                "c101b42bcacd62e35222b1207223250814d05dd41d41f8cadc1f16f86707ae15",
88            )
89            .unwrap()),
90            Selector::Groth16V2_0 => Ok(Digest::from_hex(
91                "9f39696cb3ae9d6038d6b7a55c09017f0cf35e226ad7582b82dbabb0dae53385",
92            )
93            .unwrap()),
94            Selector::SetVerifierV0_1 => Ok(Digest::from_hex(
95                "bfca9ccb59eb38b8c78ddc399a734d8e0e84e8028b7d616fa54fe707a1ff1b3b",
96            )
97            .unwrap()),
98            Selector::SetVerifierV0_2 => Ok(Digest::from_hex(
99                "16a15cc8c94a59dc3e4e41226bc560ecda596a371a487b7ecc6b65d9516dfbdb",
100            )
101            .unwrap()),
102            Selector::SetVerifierV0_4 => Ok(Digest::from_hex(
103                "f443ad7bfe538ec90fa38498afd30b27b7d06336f20249b620a6d85ab3c615b6",
104            )
105            .unwrap()),
106            Selector::SetVerifierV0_5 => Ok(Digest::from_hex(
107                "f2e6e6dc660ed3ec9d8abb666cd481509c74990fc4d599f3f4a34b9df151f3fd",
108            )
109            .unwrap()),
110        }
111    }
112
113    pub fn get_type(self) -> SelectorType {
114        match self {
115            Selector::FakeReceipt => SelectorType::FakeReceipt,
116            Selector::Groth16V1_1 | Selector::Groth16V1_2 | Selector::Groth16V2_0 => {
117                SelectorType::Groth16
118            }
119            Selector::SetVerifierV0_1
120            | Selector::SetVerifierV0_2
121            | Selector::SetVerifierV0_4
122            | Selector::SetVerifierV0_5 => SelectorType::SetVerifier,
123        }
124    }
125
126    pub fn from_bytes(bytes: [u8; 4]) -> Option<Self> {
127        Self::try_from(u32::from_be_bytes(bytes)).ok()
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use hex::FromHex;
134    use risc0_aggregation::SetInclusionReceiptVerifierParameters;
135    use risc0_zkvm::{
136        sha::{Digest, Digestible},
137        Groth16ReceiptVerifierParameters,
138    };
139
140    // SetBuilder image ID v0.5.0 (built using cargo risczero build v2.0.1)
141    const SET_BUILDER_ID: &str = "79fd473a707e7c064af3edabf63cad6c7ab9205766fd8d8160bdef97fdd15c74";
142
143    #[test]
144    fn print_verifier_parameters() {
145        let digest = Groth16ReceiptVerifierParameters::default().digest();
146        println!("Groth16ReceiptVerifierParameters {}", digest);
147
148        let digest = SetInclusionReceiptVerifierParameters {
149            image_id: Digest::from_hex(SET_BUILDER_ID).unwrap(),
150        }
151        .digest();
152        println!("SetInclusionReceiptVerifierParameters {}", digest);
153    }
154}