snark_verifier_sdk/
lib.rs
1#[cfg(feature = "display")]
2use ark_std::{end_timer, start_timer};
3use halo2_base::halo2_proofs::{self};
4use halo2_proofs::{
5 halo2curves::{
6 bn256::{Bn256, Fr, G1Affine},
7 group::ff::Field,
8 },
9 plonk::{keygen_pk, keygen_vk, Circuit, ProvingKey, Selector},
10 poly::kzg::commitment::ParamsKZG,
11 SerdeFormat,
12};
13use itertools::Itertools;
14use serde::{Deserialize, Serialize};
15pub use snark_verifier::loader::native::NativeLoader;
16use snark_verifier::{
17 pcs::kzg::{Bdfg21, Gwc19, KzgAs, LimbsEncoding},
18 verifier::{self, plonk::PlonkProtocol},
19};
20use std::{
21 fs::{self, File},
22 io::{self, BufReader, BufWriter},
23 path::Path,
24};
25
26pub use snark_verifier;
27
28#[cfg(feature = "loader_evm")]
29pub mod evm;
30#[cfg(feature = "loader_halo2")]
31pub mod halo2;
32
33pub const LIMBS: usize = 3;
34pub const BITS: usize = 88;
35
36const BUFFER_SIZE: usize = 1024 * 1024; pub type PlonkVerifier<AS> = verifier::plonk::PlonkVerifier<AS, LimbsEncoding<LIMBS, BITS>>;
41pub type PlonkSuccinctVerifier<AS> =
42 verifier::plonk::PlonkSuccinctVerifier<AS, LimbsEncoding<LIMBS, BITS>>;
43pub type SHPLONK = KzgAs<Bn256, Bdfg21>;
44pub type GWC = KzgAs<Bn256, Gwc19>;
45
46#[derive(Clone, Debug, Serialize, Deserialize)]
47pub struct Snark {
48 pub protocol: PlonkProtocol<G1Affine>,
49 pub instances: Vec<Vec<Fr>>,
50 pub proof: Vec<u8>,
51}
52
53impl Snark {
54 pub fn new(protocol: PlonkProtocol<G1Affine>, instances: Vec<Vec<Fr>>, proof: Vec<u8>) -> Self {
55 Self { protocol, instances, proof }
56 }
57
58 pub fn proof(&self) -> &[u8] {
59 &self.proof[..]
60 }
61}
62
63pub trait CircuitExt<F: Field>: Circuit<F> {
64 fn num_instance(&self) -> Vec<usize>;
67
68 fn instances(&self) -> Vec<Vec<F>>;
69
70 fn accumulator_indices() -> Option<Vec<(usize, usize)>> {
71 None
72 }
73
74 fn selectors(_: &Self::Config) -> Vec<Selector> {
76 vec![]
77 }
78}
79
80pub fn read_pk<C: Circuit<Fr>>(path: &Path, params: C::Params) -> io::Result<ProvingKey<G1Affine>> {
81 read_pk_with_capacity::<C>(BUFFER_SIZE, path, params)
82}
83
84pub fn read_pk_with_capacity<C: Circuit<Fr>>(
85 capacity: usize,
86 path: impl AsRef<Path>,
87 params: C::Params,
88) -> io::Result<ProvingKey<G1Affine>> {
89 let f = File::open(path.as_ref())?;
90 #[cfg(feature = "display")]
91 let read_time = start_timer!(|| format!("Reading pkey from {:?}", path.as_ref()));
92
93 let mut bufreader = BufReader::with_capacity(capacity, f);
95 let pk =
101 ProvingKey::read::<_, C>(&mut bufreader, SerdeFormat::RawBytesUnchecked, params).unwrap();
102
103 #[cfg(feature = "display")]
104 end_timer!(read_time);
105
106 Ok(pk)
107}
108
109#[allow(clippy::let_and_return)]
110pub fn gen_pk<C: Circuit<Fr>>(
111 params: &ParamsKZG<Bn256>, circuit: &C,
113 path: Option<&Path>,
114) -> ProvingKey<G1Affine> {
115 if let Some(path) = path {
116 if let Ok(pk) = read_pk::<C>(path, circuit.params()) {
117 return pk;
118 }
119 }
120 #[cfg(feature = "display")]
121 let pk_time = start_timer!(|| "Generating vkey & pkey");
122
123 let vk = keygen_vk(params, circuit).unwrap();
124 let pk = keygen_pk(params, vk, circuit).unwrap();
125
126 #[cfg(feature = "display")]
127 end_timer!(pk_time);
128
129 if let Some(path) = path {
130 #[cfg(feature = "display")]
131 let write_time = start_timer!(|| format!("Writing pkey to {path:?}"));
132
133 path.parent().and_then(|dir| fs::create_dir_all(dir).ok()).unwrap();
134 let mut f = BufWriter::with_capacity(BUFFER_SIZE, File::create(path).unwrap());
135 pk.write(&mut f, SerdeFormat::RawBytesUnchecked).unwrap();
136
137 #[cfg(feature = "display")]
138 end_timer!(write_time);
139 }
140 pk
141}
142
143pub fn read_instances(path: impl AsRef<Path>) -> Result<Vec<Vec<Fr>>, bincode::Error> {
144 let f = File::open(path)?;
145 let reader = BufReader::new(f);
146 let instances: Vec<Vec<[u8; 32]>> = bincode::deserialize_from(reader)?;
147 instances
148 .into_iter()
149 .map(|instance_column| {
150 instance_column
151 .iter()
152 .map(|bytes| {
153 Option::from(Fr::from_bytes(bytes)).ok_or(Box::new(bincode::ErrorKind::Custom(
154 "Invalid finite field point".to_owned(),
155 )))
156 })
157 .collect::<Result<Vec<_>, _>>()
158 })
159 .collect()
160}
161
162pub fn write_instances(instances: &[&[Fr]], path: impl AsRef<Path>) {
163 let instances: Vec<Vec<[u8; 32]>> = instances
164 .iter()
165 .map(|instance_column| instance_column.iter().map(|x| x.to_bytes()).collect_vec())
166 .collect_vec();
167 let f = BufWriter::new(File::create(path).unwrap());
168 bincode::serialize_into(f, &instances).unwrap();
169}