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    Groth16V2_1 = 0xf536085a,
47    SetVerifierV0_1 = 0xbfca9ccb,
48    SetVerifierV0_2 = 0x16a15cc8,
49    SetVerifierV0_4 = 0xf443ad7b,
50    SetVerifierV0_5 = 0xf2e6e6dc,
51    SetVerifierV0_6 = 0x80479d24,
52    SetVerifierV0_7 = 0x0f63ffd5,
53}
54
55impl Display for Selector {
56    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
57        write!(f, "{:#010x}", *self as u32)
58    }
59}
60
61impl TryFrom<u32> for Selector {
62    type Error = SelectorError;
63
64    fn try_from(value: u32) -> Result<Self, Self::Error> {
65        match value {
66            0xFFFFFFFF => Ok(Selector::FakeReceipt),
67            0x50bd1769 => Ok(Selector::Groth16V1_1),
68            0xc101b42b => Ok(Selector::Groth16V1_2),
69            0x9f39696c => Ok(Selector::Groth16V2_0),
70            0xf536085a => Ok(Selector::Groth16V2_1),
71            0xbfca9ccb => Ok(Selector::SetVerifierV0_1),
72            0x16a15cc8 => Ok(Selector::SetVerifierV0_2),
73            0xf443ad7b => Ok(Selector::SetVerifierV0_4),
74            0xf2e6e6dc => Ok(Selector::SetVerifierV0_5),
75            0x80479d24 => Ok(Selector::SetVerifierV0_6),
76            0x0f63ffd5 => Ok(Selector::SetVerifierV0_7),
77            _ => Err(SelectorError::UnsupportedSelector),
78        }
79    }
80}
81
82impl Selector {
83    pub fn verifier_parameters_digest(self) -> Result<Digest, SelectorError> {
84        match self {
85            Selector::FakeReceipt => {
86                Err(SelectorError::NoVerifierParameters(Selector::FakeReceipt))
87            }
88            Selector::Groth16V1_1 => Ok(Digest::from_hex(
89                "50bd1769093e74abda3711c315d84d78e3e282173f6304a33272d92abb590ef5",
90            )
91            .unwrap()),
92            Selector::Groth16V1_2 => Ok(Digest::from_hex(
93                "c101b42bcacd62e35222b1207223250814d05dd41d41f8cadc1f16f86707ae15",
94            )
95            .unwrap()),
96            Selector::Groth16V2_0 => Ok(Digest::from_hex(
97                "9f39696cb3ae9d6038d6b7a55c09017f0cf35e226ad7582b82dbabb0dae53385",
98            )
99            .unwrap()),
100            Selector::Groth16V2_1 => Ok(Digest::from_hex(
101                "f536085a791bdbc6cb46ab3074f88e9e94eabb192de8daca3caee1f4ed811b08",
102            )
103            .unwrap()),
104            Selector::SetVerifierV0_1 => Ok(Digest::from_hex(
105                "bfca9ccb59eb38b8c78ddc399a734d8e0e84e8028b7d616fa54fe707a1ff1b3b",
106            )
107            .unwrap()),
108            Selector::SetVerifierV0_2 => Ok(Digest::from_hex(
109                "16a15cc8c94a59dc3e4e41226bc560ecda596a371a487b7ecc6b65d9516dfbdb",
110            )
111            .unwrap()),
112            Selector::SetVerifierV0_4 => Ok(Digest::from_hex(
113                "f443ad7bfe538ec90fa38498afd30b27b7d06336f20249b620a6d85ab3c615b6",
114            )
115            .unwrap()),
116            Selector::SetVerifierV0_5 => Ok(Digest::from_hex(
117                "f2e6e6dc660ed3ec9d8abb666cd481509c74990fc4d599f3f4a34b9df151f3fd",
118            )
119            .unwrap()),
120            Selector::SetVerifierV0_6 => Ok(Digest::from_hex(
121                "80479d24c20613acbaae52f5498cb60f661a26c0681ff2b750611dbaf9ecaa66",
122            )
123            .unwrap()),
124            Selector::SetVerifierV0_7 => Ok(Digest::from_hex(
125                "0f63ffd5b1579bf938597f82089ca639a393341e888f58c12d0c91065eb2a3de",
126            )
127            .unwrap()),
128        }
129    }
130
131    pub fn get_type(self) -> SelectorType {
132        match self {
133            Selector::FakeReceipt => SelectorType::FakeReceipt,
134            Selector::Groth16V1_1
135            | Selector::Groth16V1_2
136            | Selector::Groth16V2_0
137            | Selector::Groth16V2_1 => SelectorType::Groth16,
138            Selector::SetVerifierV0_1
139            | Selector::SetVerifierV0_2
140            | Selector::SetVerifierV0_4
141            | Selector::SetVerifierV0_5
142            | Selector::SetVerifierV0_6
143            | Selector::SetVerifierV0_7 => SelectorType::SetVerifier,
144        }
145    }
146
147    pub fn from_bytes(bytes: [u8; 4]) -> Option<Self> {
148        Self::try_from(u32::from_be_bytes(bytes)).ok()
149    }
150
151    /// Returns the selector corresponding to the Groth16 verifier for the latest zkVM version.
152    pub const fn groth16_latest() -> Self {
153        Self::Groth16V2_1
154    }
155
156    /// Returns the selector corresponding to the latest version of the set inclusion verifier (aka
157    /// aggregation verifier).
158    pub const fn set_inclusion_latest() -> Self {
159        Self::SetVerifierV0_7
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use hex::FromHex;
166    use risc0_aggregation::SetInclusionReceiptVerifierParameters;
167    use risc0_zkvm::{
168        sha::{Digest, Digestible},
169        Groth16ReceiptVerifierParameters,
170    };
171
172    // SetBuilder image ID v0.7.0 (built using cargo risczero build v2.0.2)
173    const SET_BUILDER_ID: &str = "a218e889a26852fd3d57a80983c76b53ff6d5fa4b469779511dd4d99329ae7aa";
174
175    #[test]
176    fn print_verifier_parameters() {
177        let digest = Groth16ReceiptVerifierParameters::default().digest();
178        println!("Groth16ReceiptVerifierParameters {}", digest);
179
180        let digest = SetInclusionReceiptVerifierParameters {
181            image_id: Digest::from_hex(SET_BUILDER_ID).unwrap(),
182        }
183        .digest();
184        println!("SetInclusionReceiptVerifierParameters {}", digest);
185    }
186}