Last active
September 13, 2022 18:58
-
-
Save DrPeterVanNostrand/9ace9895cab7f4b59070da9349e59ec5 to your computer and use it in GitHub Desktop.
Halo2 verification key serialization without constraint system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// halo2_proofs/src/poly/domain.rs | |
#[derive(Clone, Debug, PartialEq, Eq)] | |
pub struct EvaluationDomain<G: Group> { | |
pub(crate) n: u64, | |
pub(crate) k: u32, | |
pub(crate) extended_k: u32, | |
pub(crate) omega: G::Scalar, | |
pub(crate) omega_inv: G::Scalar, | |
pub(crate) extended_omega: G::Scalar, | |
pub(crate) extended_omega_inv: G::Scalar, | |
pub(crate) g_coset: G::Scalar, | |
pub(crate) g_coset_inv: G::Scalar, | |
pub(crate) quotient_poly_degree: u64, | |
pub(crate) ifft_divisor: G::Scalar, | |
pub(crate) extended_ifft_divisor: G::Scalar, | |
pub(crate) t_evaluations: Vec<G::Scalar>, | |
pub(crate) barycentric_weight: G::Scalar, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// halo2_proofs/src/plonk/keygen.rs | |
pub(crate) struct Assembly<F: Field> { | |
pub(crate) k: u32, | |
pub(crate) fixed: Vec<Polynomial<Assigned<F>, LagrangeCoeff>>, | |
pub(crate) permutation: permutation::keygen::Assembly, | |
pub(crate) selectors: Vec<Vec<bool>>, | |
// A range of available rows for assignment and copies. | |
pub(crate) usable_rows: Range<usize>, | |
pub(crate) _marker: std::marker::PhantomData<F>, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// halo2_proofs/src/plonk/permutation.rs | |
pub(crate) struct Argument { | |
/// A sequence of columns involved in the argument. | |
pub(crate) columns: Vec<Column<Any>>, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// halo2_proofs/src/plonk.rs | |
use std::io::{self, Read, Write}; | |
const FIELD_SIZE: usize = 32; | |
const AFFINE_SIZE: usize = 2 * FIELD_SIZE; | |
impl<C: CurveAffine> PartialEq for VerifyingKey<C> { | |
fn eq(&self, other: &Self) -> bool { | |
format!("{:?}", self) == format!("{:?}", other) | |
} | |
} | |
impl<C: CurveAffine> Eq for VerifyingKey<C> {} | |
impl<C: CurveAffine> VerifyingKey<C> { | |
... | |
/// Serialize evaluation domain, fixed commitments, and permutation verification key. | |
#[allow(unsafe_code)] | |
pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> { | |
assert_eq!(std::mem::size_of::<C::Scalar>(), FIELD_SIZE); | |
assert_eq!(std::mem::size_of::<C>(), AFFINE_SIZE); | |
writer.write_all(&self.domain.n.to_le_bytes())?; | |
writer.write_all(&self.domain.k.to_le_bytes())?; | |
writer.write_all(&self.domain.extended_k.to_le_bytes())?; | |
{ | |
let bytes_ptr = (&self.domain.omega as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let bytes_ptr = (&self.domain.omega_inv as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let bytes_ptr = (&self.domain.extended_omega as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let bytes_ptr = (&self.domain.extended_omega_inv as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let bytes_ptr = (&self.domain.g_coset as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let bytes_ptr = (&self.domain.g_coset_inv as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
writer.write_all(&self.domain.quotient_poly_degree.to_le_bytes())?; | |
{ | |
let bytes_ptr = (&self.domain.ifft_divisor as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let bytes_ptr = (&self.domain.extended_ifft_divisor as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let byte_len = self.domain.t_evaluations.len() * FIELD_SIZE; | |
let bytes_ptr = self.domain.t_evaluations.as_ptr() as *const u8; | |
let bytes = unsafe { std::slice::from_raw_parts(bytes_ptr, byte_len) }; | |
writer.write_all(&bytes)?; | |
} | |
{ | |
let bytes_ptr = (&self.domain.barycentric_weight as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
{ | |
let byte_len = self.fixed_commitments.len() * AFFINE_SIZE; | |
let bytes_ptr = self.fixed_commitments.as_ptr() as *const u8; | |
let bytes = unsafe { std::slice::from_raw_parts(bytes_ptr, byte_len) }; | |
writer.write_all(&bytes)?; | |
} | |
{ | |
let byte_len = self.permutation.commitments.len() * AFFINE_SIZE; | |
let bytes_ptr = self.permutation.commitments.as_ptr() as *const u8; | |
let bytes = unsafe { std::slice::from_raw_parts(bytes_ptr, byte_len) }; | |
writer.write_all(&bytes)?; | |
} | |
writer.write_all(&self.cs_degree.to_le_bytes())?; | |
{ | |
let bytes_ptr = (&self.transcript_repr as *const C::Scalar) as *const [u8; FIELD_SIZE]; | |
unsafe { writer.write_all(&*bytes_ptr)? }; | |
} | |
Ok(()) | |
} | |
/// Deserialize evaluation domain, fixed commitments, and permutation verification key. | |
#[allow(unsafe_code)] | |
pub fn read<R: Read, ConcreteCircuit: Circuit<C::Scalar>>( | |
reader: &mut R, | |
params: &Params<C>, | |
circuit: &ConcreteCircuit, | |
) -> io::Result<Self> { | |
assert_eq!(std::mem::size_of::<C::Scalar>(), FIELD_SIZE); | |
assert_eq!(std::mem::size_of::<C>(), AFFINE_SIZE); | |
let mut cs = ConstraintSystem::<C::Scalar>::default(); | |
let config = ConcreteCircuit::configure(&mut cs); | |
let empty_lagrange = Polynomial::<Assigned<C::Scalar>, LagrangeCoeff> { | |
values: vec![C::Scalar::group_zero().into(); params.n as usize], | |
_marker: std::marker::PhantomData, | |
}; | |
let mut assembly: Assembly<C::Scalar> = Assembly { | |
k: params.k, | |
fixed: vec![empty_lagrange; cs.num_fixed_columns], | |
permutation: permutation::keygen::Assembly::new(params.n as usize, &cs.permutation), | |
selectors: vec![vec![false; params.n as usize]; cs.num_selectors], | |
usable_rows: 0..params.n as usize - (cs.blinding_factors() + 1), | |
_marker: std::marker::PhantomData, | |
}; | |
ConcreteCircuit::FloorPlanner::synthesize( | |
&mut assembly, | |
circuit, | |
config, | |
cs.constants.clone(), | |
) | |
.expect("failed to synthesize circuit"); | |
let (cs, _selector_polys) = cs.compress_selectors(assembly.selectors); | |
let domain = { | |
let n = { | |
let mut buf = [0u8; 8]; | |
reader.read_exact(&mut buf)?; | |
u64::from_le_bytes(buf) | |
}; | |
assert_eq!(n, params.n); | |
let k = { | |
let mut buf = [0u8; 4]; | |
reader.read_exact(&mut buf)?; | |
u32::from_le_bytes(buf) | |
}; | |
assert_eq!(k, params.k); | |
let extended_k = { | |
let mut buf = [0u8; 4]; | |
reader.read_exact(&mut buf)?; | |
u32::from_le_bytes(buf) | |
}; | |
assert!(extended_k >= k); | |
let omega = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
let omega_inv = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
assert_eq!(omega * &omega_inv, C::Scalar::one()); | |
let extended_omega = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
let extended_omega_inv = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
assert_eq!(extended_omega * &extended_omega_inv, C::Scalar::one()); | |
let g_coset = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
let g_coset_inv = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
assert_eq!(g_coset * &g_coset_inv, C::Scalar::one()); | |
let quotient_poly_degree = { | |
let mut buf = [0u8; 8]; | |
reader.read_exact(&mut buf)?; | |
u64::from_le_bytes(buf) | |
}; | |
assert_eq!(quotient_poly_degree, cs.degree() as u64 - 1); | |
let n_quotient_deg = n * quotient_poly_degree; | |
assert!(1 << extended_k >= n_quotient_deg); | |
assert!(1 << (extended_k - 1) < n_quotient_deg); | |
let ifft_divisor = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
let extended_ifft_divisor = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
let t_evaluations = { | |
let len = 1 << (extended_k - k); | |
let byte_len = len * FIELD_SIZE; | |
let mut buf = vec![0u8; byte_len]; | |
reader.read_exact(&mut buf)?; | |
let mut buf_no_drop = std::mem::ManuallyDrop::new(buf); | |
unsafe { Vec::from_raw_parts(buf_no_drop.as_mut_ptr() as *mut C::Scalar, len, len) } | |
}; | |
let barycentric_weight = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
EvaluationDomain::<C::Scalar> { | |
n, | |
k, | |
extended_k, | |
omega, | |
omega_inv, | |
extended_omega, | |
extended_omega_inv, | |
g_coset, | |
g_coset_inv, | |
quotient_poly_degree, | |
ifft_divisor, | |
extended_ifft_divisor, | |
t_evaluations, | |
barycentric_weight, | |
} | |
}; | |
let fixed_commitments = { | |
let len = cs.num_fixed_columns; | |
let byte_len = len * AFFINE_SIZE; | |
let mut buf = vec![0u8; byte_len]; | |
reader.read_exact(&mut buf)?; | |
let mut buf_no_drop = std::mem::ManuallyDrop::new(buf); | |
unsafe { Vec::from_raw_parts(buf_no_drop.as_mut_ptr() as *mut C, len, len) } | |
}; | |
let permutation = { | |
let len = cs.permutation.columns.len(); | |
let byte_len = len * AFFINE_SIZE; | |
let mut buf = vec![0u8; byte_len]; | |
reader.read_exact(&mut buf)?; | |
let mut buf_no_drop = std::mem::ManuallyDrop::new(buf); | |
let commitments = unsafe { Vec::from_raw_parts(buf_no_drop.as_mut_ptr() as *mut C, len, len) }; | |
permutation::VerifyingKey::<C> { commitments } | |
}; | |
let cs_degree = { | |
let mut buf = [0u8; 8]; | |
reader.read_exact(&mut buf)?; | |
usize::from_le_bytes(buf) | |
}; | |
let transcript_repr = { | |
let mut buf = [0u8; FIELD_SIZE]; | |
reader.read_exact(&mut buf)?; | |
unsafe { *(buf.as_ptr() as *const C::Scalar) } | |
}; | |
let vk = Self::from_parts(domain, fixed_commitments, permutation, cs); | |
assert_eq!(cs_degree, vk.cs_degree); | |
assert_eq!(transcript_repr, vk.transcript_repr); | |
Ok(vk) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// halo2_proofs/tests/plonk_api.rs | |
#[test] | |
fn plonk_api() { | |
... | |
// Test verification key serializtion. | |
use halo2_proofs::plonk::VerifyingKey; | |
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); | |
let mut vk_bytes = Vec::<u8>::new(); | |
vk.write(&mut vk_bytes).unwrap(); | |
let mut vk_reader = std::io::Cursor::new(vk_bytes); | |
let vk2 = VerifyingKey::<EqAffine>::read(&mut vk_reader, ¶ms, &empty_circuit).unwrap(); | |
assert_eq!(vk, vk2); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// halo2_proofs/src/poly.rs | |
pub struct Polynomial<F, B> { | |
pub(crate) values: Vec<F>, | |
pub(crate) _marker: PhantomData<B>, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment