export the constant columns (selectors too) for third-party tooling

This commit is contained in:
Balazs Komuves 2024-12-13 11:35:36 +01:00
parent 4625d3a63c
commit 32753831d2
No known key found for this signature in database
GPG Key ID: F63B7AEF18435562
4 changed files with 44 additions and 8 deletions

View File

@ -1185,7 +1185,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let fft_root_table = fft_root_table(max_fft_points);
let constants_sigmas_commitment = if commit_to_sigma {
let constants_sigmas_vecs = [constant_vecs, sigma_vecs.clone()].concat();
let constants_sigmas_vecs = [constant_vecs.clone(), sigma_vecs.clone()].concat();
PolynomialBatch::<F, C, D>::from_values(
constants_sigmas_vecs,
rate_bits,
@ -1296,6 +1296,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
let prover_only = ProverOnlyCircuitData::<F, C, D> {
generators: self.generators,
generator_indices_by_watches,
constants_vecs: constant_vecs.into_iter().map(|x| x.values.clone()).collect(),
constants_sigmas_commitment,
sigmas: transpose_poly_values(sigma_vecs),
subgroup,

View File

@ -369,6 +369,8 @@ pub struct ProverOnlyCircuitData<
/// Generator indices (within the `Vec` above), indexed by the representative of each target
/// they watch.
pub generator_indices_by_watches: BTreeMap<usize, Vec<usize>>,
/// the constant vectors themselves (including the selectors)
pub constants_vecs: Vec<Vec<F>>,
/// Commitments to the constants polynomials and sigma polynomials.
pub constants_sigmas_commitment: PolynomialBatch<F, C, D>,
/// The transpose of the list of sigma polynomials.

View File

@ -129,21 +129,38 @@ pub const DEFAULT_PROVER_OPTIONS: ProverOptions = ProverOptions {
// things we want to export to be used by third party tooling
#[derive(Debug,Clone,Serialize)]
struct ThingsToExport<F> {
gates: Vec<String>,
selector_vector: Vec<usize>,
matrix: Vec<Vec<F>>,
gates: Vec<String>, // list of gates used in the circuit
selector_vector: Vec<usize>, // the full selector vector (a gate index for each row)
selector_columns: Vec<Vec<F>>, // the selector columns (column-major)
constants_columns: Vec<Vec<F>>, // the constant columns (column-major)
matrix: Vec<Vec<F>>, // the witness matrix (column-major)
// circuit_digest: Vec<F>,
}
// the idea is to export the witness (plus some more information),
// so that third-party tools can for example visualize it
fn collect_things_to_export<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
common_data: &CommonCircuitData<F, D>,
prover_data : &ProverOnlyCircuitData<F, C, D>,
wires_matrix: &MatrixWitness<F>,
) -> ThingsToExport<F> {
let num_consts_selectors = common_data.num_constants;
let num_selectors = common_data.selectors_info.num_selectors();
let _num_constants = num_consts_selectors - num_selectors;
let constants_vecs = &prover_data.constants_vecs;
assert!( num_consts_selectors == constants_vecs.len() );
let selector_cols: Vec<Vec<F>> = constants_vecs[0..num_selectors].to_vec();
let constant_cols: Vec<Vec<F>> = constants_vecs[num_selectors.. ].to_vec();
ThingsToExport {
gates: common_data.gates.iter().map(|g| g.0.short_id()).collect(),
selector_vector: common_data.selectors_info.selector_vector.clone(),
matrix: wires_matrix.wire_values.clone(),
gates: common_data.gates.iter().map(|g| g.0.short_id()).collect(),
selector_vector: common_data.selectors_info.selector_vector.clone(),
selector_columns: selector_cols,
constants_columns: constant_cols,
matrix: wires_matrix.wire_values.clone(),
// circuit_digest: prover_data.circuit_digest,
}
}
@ -243,7 +260,7 @@ where
match &prover_options.export_witness {
None => (),
Some(fname) => {
let things_to_export = collect_things_to_export::<F, C, D>( &common_data, &witness );
let things_to_export = collect_things_to_export::<F, C, D>( &common_data, &prover_data, &witness );
write_json_file(&fname, &things_to_export)?;
println!("exported witness to `{}`",fname);
},

View File

@ -850,7 +850,15 @@ pub trait Read {
generator_indices_by_watches.insert(k, self.read_usize_vec()?);
}
let constants_vecs_len = self.read_usize()?;
let mut constants_vecs = Vec::with_capacity(constants_vecs_len);
for _ in 0..constants_vecs_len {
let vec_len = self.read_usize()?;
constants_vecs.push(self.read_field_vec(vec_len)?);
}
let constants_sigmas_commitment = self.read_polynomial_batch()?;
let sigmas_len = self.read_usize()?;
let mut sigmas = Vec::with_capacity(sigmas_len);
for _ in 0..sigmas_len {
@ -900,6 +908,7 @@ pub trait Read {
Ok(ProverOnlyCircuitData {
generators,
generator_indices_by_watches,
constants_vecs,
constants_sigmas_commitment,
sigmas,
subgroup,
@ -1854,6 +1863,7 @@ pub trait Write {
let ProverOnlyCircuitData {
generators,
generator_indices_by_watches,
constants_vecs,
constants_sigmas_commitment,
sigmas,
subgroup,
@ -1876,6 +1886,12 @@ pub trait Write {
self.write_usize_vec(v)?;
}
self.write_usize(constants_vecs.len())?;
for i in 0..constants_vecs.len() {
self.write_usize(constants_vecs[i].len())?;
self.write_field_vec(&constants_vecs[i])?;
}
self.write_polynomial_batch(constants_sigmas_commitment)?;
self.write_usize(sigmas.len())?;
for i in 0..sigmas.len() {