add gate count metrics (#238)
* add gate count metrics * tweak params * move metrics to its own file
This commit is contained in:
parent
de9b206852
commit
c3c9e7f99c
8 changed files with 222 additions and 18 deletions
|
|
@ -28,6 +28,7 @@ use crate::{
|
|||
},
|
||||
signedpod::SignedPod,
|
||||
},
|
||||
measure_gates_begin, measure_gates_end,
|
||||
middleware::{
|
||||
AnchoredKey, CustomPredicate, CustomPredicateBatch, CustomPredicateRef, NativeOperation,
|
||||
NativePredicate, Params, PodType, PredicatePrefix, Statement, StatementArg, ToFields,
|
||||
|
|
@ -79,12 +80,14 @@ impl OperationVerifyGadget {
|
|||
merkle_claims: &[MerkleClaimTarget],
|
||||
custom_predicate_verification_table: &[HashOutTarget],
|
||||
) -> Result<()> {
|
||||
let measure = measure_gates_begin!(builder, "OperationVerify");
|
||||
let _true = builder._true();
|
||||
let _false = builder._false();
|
||||
|
||||
// Verify that the operation `op` correctly generates the statement `st`. The operation
|
||||
// can reference any of the `prev_statements`.
|
||||
// TODO: Clean this up.
|
||||
let measure_resolve_op_args = measure_gates_begin!(builder, "ResolveOpArgs");
|
||||
let resolved_op_args = if prev_statements.is_empty() {
|
||||
(0..self.params.max_operation_args)
|
||||
.map(|_| {
|
||||
|
|
@ -98,6 +101,7 @@ impl OperationVerifyGadget {
|
|||
.map(|&i| builder.vec_ref(&self.params, prev_statements, i))
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
measure_gates_end!(builder, measure_resolve_op_args);
|
||||
// TODO: Can we have a single table with merkel claims and verified custom predicates
|
||||
// together (with an identifying prefix) and then we only need one random access instead of
|
||||
// two?
|
||||
|
|
@ -113,14 +117,19 @@ impl OperationVerifyGadget {
|
|||
// Certain operations (Contains/NotContains) will refer to one
|
||||
// of the provided Merkle proofs (if any). These proofs have already
|
||||
// been verified, so we need only look up the claim.
|
||||
let measure_resolve_merkle_claim = measure_gates_begin!(builder, "ResolveMerkleClaim");
|
||||
let resolved_merkle_claim = (!merkle_claims.is_empty())
|
||||
.then(|| builder.vec_ref(&self.params, merkle_claims, op.aux[0]));
|
||||
measure_gates_end!(builder, measure_resolve_merkle_claim);
|
||||
|
||||
// Operations from custom statements will refer to one
|
||||
// of the provided custom predicates verifications (if any). These operations have already
|
||||
// been verified, so we need only look up the entry.
|
||||
let measure_resolve_custom_pred_verification =
|
||||
measure_gates_begin!(builder, "ResolveCustomPredVerification");
|
||||
let resolved_custom_pred_verification = (!custom_predicate_verification_table.is_empty())
|
||||
.then(|| builder.vec_ref(&self.params, custom_predicate_verification_table, op.aux[1]));
|
||||
measure_gates_end!(builder, measure_resolve_custom_pred_verification);
|
||||
|
||||
// The verification may require aux data which needs to be stored in the
|
||||
// `OperationVerifyTarget` so that we can set during witness generation.
|
||||
|
|
@ -140,7 +149,7 @@ impl OperationVerifyGadget {
|
|||
vec![]
|
||||
} else {
|
||||
vec![
|
||||
self.eval_copy(builder, st, &op.op_type, &resolved_op_args)?,
|
||||
self.eval_copy(builder, st, &op.op_type, &resolved_op_args),
|
||||
self.eval_eq_neq_from_entries(builder, st, &op.op_type, &resolved_op_args),
|
||||
self.eval_lt_lteq_from_entries(builder, st, &op.op_type, &resolved_op_args),
|
||||
self.eval_transitive_eq(builder, st, &op.op_type, &resolved_op_args),
|
||||
|
|
@ -190,6 +199,7 @@ impl OperationVerifyGadget {
|
|||
let ok = builder.any(op_checks);
|
||||
builder.assert_one(ok.target);
|
||||
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -201,6 +211,7 @@ impl OperationVerifyGadget {
|
|||
resolved_merkle_claim: MerkleClaimTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpContainsFromEntries");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::ContainsFromEntries);
|
||||
|
||||
let (arg_types_ok, [merkle_root_value, key_value, value_value]) =
|
||||
|
|
@ -235,7 +246,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_types_ok, merkle_proof_ok, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_types_ok, merkle_proof_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_not_contains_from_entries(
|
||||
|
|
@ -246,6 +259,7 @@ impl OperationVerifyGadget {
|
|||
resolved_merkle_claim: MerkleClaimTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpNotContainsFromEntries");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::NotContainsFromEntries);
|
||||
|
||||
let (arg_types_ok, [merkle_root_value, key_value]) =
|
||||
|
|
@ -278,7 +292,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_types_ok, merkle_proof_ok, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_types_ok, merkle_proof_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_custom(
|
||||
|
|
@ -289,16 +305,19 @@ impl OperationVerifyGadget {
|
|||
resolved_custom_pred_verification: HashOutTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpCustom");
|
||||
let query = CustomPredicateVerifyQueryTarget {
|
||||
statement: st.clone(),
|
||||
op_type: op_type.clone(),
|
||||
op_args: resolved_op_args.to_vec(),
|
||||
};
|
||||
let out_query_hash = query.hash(builder);
|
||||
builder.is_equal_slice(
|
||||
let ok = builder.is_equal_slice(
|
||||
&resolved_custom_pred_verification.elements,
|
||||
&out_query_hash.elements,
|
||||
)
|
||||
);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
/// Carries out the checks necessary for EqualFromEntries and
|
||||
|
|
@ -310,6 +329,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpEqNeqFromEntries");
|
||||
let eq_op_st_code_ok = {
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::EqualFromEntries);
|
||||
let st_code_ok = st.has_native_type(builder, &self.params, NativePredicate::Equal);
|
||||
|
|
@ -346,7 +366,9 @@ impl OperationVerifyGadget {
|
|||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
builder.all([op_st_code_ok, arg_types_ok, op_args_ok, st_args_ok])
|
||||
let ok = builder.all([op_st_code_ok, arg_types_ok, op_args_ok, st_args_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
/// Carries out the checks necessary for LtFromEntries and
|
||||
|
|
@ -358,6 +380,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpLtLteqFromEntries");
|
||||
let zero = ValueTarget::zero(builder);
|
||||
let one = ValueTarget::one(builder);
|
||||
|
||||
|
|
@ -414,7 +437,9 @@ impl OperationVerifyGadget {
|
|||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
builder.all([op_st_code_ok, arg_types_ok, st_args_ok])
|
||||
let ok = builder.all([op_st_code_ok, arg_types_ok, st_args_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_hash_of(
|
||||
|
|
@ -424,6 +449,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpHashOf");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::HashOf);
|
||||
|
||||
let (arg_types_ok, [arg1_value, arg2_value, arg3_value]) =
|
||||
|
|
@ -445,7 +471,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_types_ok, hash_value_ok, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_types_ok, hash_value_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_sum_of(
|
||||
|
|
@ -455,6 +483,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpSumOf");
|
||||
let value_zero = ValueTarget::zero(builder);
|
||||
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::SumOf);
|
||||
|
|
@ -481,7 +510,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_types_ok, sum_ok, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_types_ok, sum_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_product_of(
|
||||
|
|
@ -491,6 +522,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpProductOf");
|
||||
let value_zero = ValueTarget::zero(builder);
|
||||
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::ProductOf);
|
||||
|
|
@ -517,7 +549,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_types_ok, product_ok, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_types_ok, product_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_max_of(
|
||||
|
|
@ -527,6 +561,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpMaxOf");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::MaxOf);
|
||||
|
||||
let (arg_types_ok, [arg1_value, arg2_value, arg3_value]) =
|
||||
|
|
@ -560,7 +595,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_types_ok, arg1_check, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_types_ok, arg1_check, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_transitive_eq(
|
||||
|
|
@ -570,6 +607,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpTransitiveEq");
|
||||
let op_code_ok =
|
||||
op_type.has_native(builder, NativeOperation::TransitiveEqualFromStatements);
|
||||
|
||||
|
|
@ -594,7 +632,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_types_ok, inner_keys_match, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_types_ok, inner_keys_match, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
fn eval_none(
|
||||
&self,
|
||||
|
|
@ -602,13 +642,16 @@ impl OperationVerifyGadget {
|
|||
st: &StatementTarget,
|
||||
op_type: &OperationTypeTarget,
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpNone");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::None);
|
||||
|
||||
let expected_statement =
|
||||
StatementTarget::new_native(builder, &self.params, NativePredicate::None, &[]);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, st_ok])
|
||||
let ok = builder.all([op_code_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_new_entry(
|
||||
|
|
@ -618,6 +661,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
prev_statements: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpNewEntry");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::NewEntry);
|
||||
|
||||
let st_code_ok = st.has_native_type(builder, &self.params, NativePredicate::ValueOf);
|
||||
|
|
@ -643,7 +687,9 @@ impl OperationVerifyGadget {
|
|||
|
||||
let no_dupes_ok = builder.not(dupe_check);
|
||||
|
||||
builder.all([op_code_ok, st_code_ok, arg_prefix_ok, no_dupes_ok])
|
||||
let ok = builder.all([op_code_ok, st_code_ok, arg_prefix_ok, no_dupes_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_lt_to_neq(
|
||||
|
|
@ -653,6 +699,7 @@ impl OperationVerifyGadget {
|
|||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpLtToNeq");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::LtToNotEqual);
|
||||
|
||||
let arg_type_ok =
|
||||
|
|
@ -669,7 +716,9 @@ impl OperationVerifyGadget {
|
|||
);
|
||||
let st_ok = builder.is_equal_flattenable(st, &expected_statement);
|
||||
|
||||
builder.all([op_code_ok, arg_type_ok, st_ok])
|
||||
let ok = builder.all([op_code_ok, arg_type_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
|
||||
fn eval_copy(
|
||||
|
|
@ -678,13 +727,16 @@ impl OperationVerifyGadget {
|
|||
st: &StatementTarget,
|
||||
op_type: &OperationTypeTarget,
|
||||
resolved_op_args: &[StatementTarget],
|
||||
) -> Result<BoolTarget> {
|
||||
) -> BoolTarget {
|
||||
let measure = measure_gates_begin!(builder, "OpCopy");
|
||||
let op_code_ok = op_type.has_native(builder, NativeOperation::CopyStatement);
|
||||
|
||||
let expected_statement = &resolved_op_args[0];
|
||||
let st_ok = builder.is_equal_flattenable(st, expected_statement);
|
||||
|
||||
Ok(builder.all([op_code_ok, st_ok]))
|
||||
let ok = builder.all([op_code_ok, st_ok]);
|
||||
measure_gates_end!(builder, measure);
|
||||
ok
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -751,11 +803,13 @@ impl CustomOperationVerifyGadget {
|
|||
st_tmpl: &StatementTmplTarget,
|
||||
args: &[ValueTarget],
|
||||
) -> StatementTarget {
|
||||
let measure = measure_gates_begin!(builder, "StatementArgFromTemplate");
|
||||
let args = st_tmpl
|
||||
.args
|
||||
.iter()
|
||||
.map(|st_tmpl_arg| self.statement_arg_from_template(builder, st_tmpl_arg, args))
|
||||
.collect();
|
||||
measure_gates_end!(builder, measure);
|
||||
StatementTarget {
|
||||
predicate: st_tmpl.pred.clone(),
|
||||
args,
|
||||
|
|
@ -774,6 +828,7 @@ impl CustomOperationVerifyGadget {
|
|||
op_args: &[StatementTarget],
|
||||
args: &[ValueTarget], // arguments to the custom predicate, public and private
|
||||
) -> Result<(StatementTarget, OperationTypeTarget)> {
|
||||
let measure = measure_gates_begin!(builder, "CustomOperationVerify");
|
||||
// Some sanity checks
|
||||
assert_eq!(self.params.max_operation_args, op_args.len());
|
||||
assert_eq!(self.params.max_custom_predicate_wildcards, args.len());
|
||||
|
|
@ -828,6 +883,7 @@ impl CustomOperationVerifyGadget {
|
|||
));
|
||||
|
||||
builder.assert_one(is_op_args_ok.target);
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok((statement, op_type))
|
||||
}
|
||||
}
|
||||
|
|
@ -863,6 +919,7 @@ impl MainPodVerifyGadget {
|
|||
&self,
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
) -> Result<(Vec<HashOutTarget>, Vec<CustomPredicateBatchTarget>)> {
|
||||
let measure = measure_gates_begin!(builder, "BuildCustomPredicateTable");
|
||||
let params = &self.params;
|
||||
let mut custom_predicate_table =
|
||||
Vec::with_capacity(params.max_custom_predicate_batches * params.max_custom_batch_size);
|
||||
|
|
@ -892,6 +949,7 @@ impl MainPodVerifyGadget {
|
|||
}
|
||||
custom_predicate_batches.push(cpb); // We keep this for witness assignment
|
||||
}
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok((custom_predicate_table, custom_predicate_batches))
|
||||
}
|
||||
|
||||
|
|
@ -903,6 +961,7 @@ impl MainPodVerifyGadget {
|
|||
builder: &mut CircuitBuilder<F, D>,
|
||||
custom_predicate_table: &[HashOutTarget],
|
||||
) -> Result<(Vec<HashOutTarget>, Vec<CustomPredicateVerifyEntryTarget>)> {
|
||||
let measure = measure_gates_begin!(builder, "BuildCustomPredicateVerificationTable");
|
||||
let params = &self.params;
|
||||
let mut custom_predicate_verifications =
|
||||
Vec::with_capacity(params.max_custom_predicate_verifications);
|
||||
|
|
@ -944,6 +1003,7 @@ impl MainPodVerifyGadget {
|
|||
custom_predicate_verification_table.push(in_query_hash);
|
||||
custom_predicate_verifications.push(entry); // We keep this for witness assignment
|
||||
}
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok((
|
||||
custom_predicate_verification_table,
|
||||
custom_predicate_verifications,
|
||||
|
|
@ -951,6 +1011,7 @@ impl MainPodVerifyGadget {
|
|||
}
|
||||
|
||||
fn eval(&self, builder: &mut CircuitBuilder<F, D>) -> Result<MainPodVerifyTarget> {
|
||||
let measure = measure_gates_begin!(builder, "MainPodVerify");
|
||||
let params = &self.params;
|
||||
// 1. Verify all input signed pods
|
||||
let mut signed_pods = Vec::new();
|
||||
|
|
@ -1022,8 +1083,10 @@ impl MainPodVerifyGadget {
|
|||
self.build_custom_predicate_verification_table(builder, &custom_predicate_table)?;
|
||||
|
||||
// 2. Calculate the Pod Id from the public statements
|
||||
let measure_calc_id = measure_gates_begin!(builder, "MainPodId");
|
||||
let pub_statements_flattened = pub_statements.iter().flat_map(|s| s.flatten()).collect();
|
||||
let id = builder.hash_n_to_hash_no_pad::<PoseidonHash>(pub_statements_flattened);
|
||||
measure_gates_end!(builder, measure_calc_id);
|
||||
|
||||
// 4. Verify type
|
||||
let type_statement = &pub_statements[0];
|
||||
|
|
@ -1059,6 +1122,7 @@ impl MainPodVerifyGadget {
|
|||
)?;
|
||||
}
|
||||
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok(MainPodVerifyTarget {
|
||||
params: params.clone(),
|
||||
id,
|
||||
|
|
|
|||
117
src/backends/plonky2/circuits/metrics.rs
Normal file
117
src/backends/plonky2/circuits/metrics.rs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{LazyLock, Mutex},
|
||||
};
|
||||
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
use crate::{backends::plonky2::basetypes::D, middleware::F};
|
||||
|
||||
pub static METRICS: LazyLock<Mutex<Metrics>> = LazyLock::new(|| Mutex::new(Metrics::default()));
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Metrics {
|
||||
gates: Vec<(String, usize)>,
|
||||
stack: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct MetricsMeasure {
|
||||
name: String,
|
||||
start_num_gates: usize,
|
||||
ended: bool,
|
||||
}
|
||||
|
||||
impl Drop for MetricsMeasure {
|
||||
fn drop(&mut self) {
|
||||
if !self.ended {
|
||||
panic!("Measure \"{}\" not ended", self.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Metrics {
|
||||
#[must_use]
|
||||
pub fn begin(
|
||||
&mut self,
|
||||
builder: &CircuitBuilder<F, D>,
|
||||
name: impl Into<String>,
|
||||
) -> MetricsMeasure {
|
||||
let name = name.into();
|
||||
self.stack.push(name);
|
||||
MetricsMeasure {
|
||||
name: self.stack.join("/"),
|
||||
start_num_gates: builder.num_gates(),
|
||||
ended: false,
|
||||
}
|
||||
}
|
||||
pub fn end(&mut self, builder: &CircuitBuilder<F, D>, mut measure: MetricsMeasure) {
|
||||
self.stack.pop();
|
||||
measure.ended = true;
|
||||
let num_gates = builder.num_gates();
|
||||
let delta_gates = num_gates - measure.start_num_gates;
|
||||
self.gates.push((measure.name.clone(), delta_gates));
|
||||
}
|
||||
pub fn print(&self) {
|
||||
println!("Gate count:");
|
||||
let mut count = HashMap::new();
|
||||
for (name, num_gates) in &self.gates {
|
||||
let n = count.entry(name).or_insert(0);
|
||||
*n += 1;
|
||||
println!("- {} [{}]: {}", name, *n, num_gates);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "metrics")]
|
||||
pub mod measure_macros {
|
||||
#[macro_export]
|
||||
macro_rules! measure_gates_begin {
|
||||
($builder:expr, $name:expr) => {{
|
||||
use $crate::backends::plonky2::circuits::utils::METRICS;
|
||||
let mut metrics = METRICS.lock().unwrap();
|
||||
metrics.begin($builder, $name)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! measure_gates_end {
|
||||
($builder:expr, $measure:expr) => {{
|
||||
use $crate::backends::plonky2::circuits::utils::METRICS;
|
||||
let mut metrics = METRICS.lock().unwrap();
|
||||
metrics.end($builder, $measure);
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! measure_gates_print {
|
||||
() => {{
|
||||
use $crate::backends::plonky2::circuits::utils::METRICS;
|
||||
let metrics = METRICS.lock().unwrap();
|
||||
metrics.print();
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "metrics"))]
|
||||
pub mod measure_macros {
|
||||
#[macro_export]
|
||||
macro_rules! measure_gates_begin {
|
||||
($builder:expr, $name:expr) => {
|
||||
()
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! measure_gates_end {
|
||||
($builder:expr, $measure:expr) => {
|
||||
let _ = $measure;
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! measure_gates_print {
|
||||
() => {{
|
||||
println!("Gate count disabled: \"metrics\" feature not enabled.");
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
pub mod common;
|
||||
pub mod mainpod;
|
||||
pub mod metrics;
|
||||
pub mod signedpod;
|
||||
pub mod utils;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use crate::{
|
|||
},
|
||||
signedpod::SignedPod,
|
||||
},
|
||||
measure_gates_begin, measure_gates_end,
|
||||
middleware::{
|
||||
hash_str, Key, NativePredicate, Params, PodType, RawValue, Value, F, KEY_SIGNER, KEY_TYPE,
|
||||
SELF,
|
||||
|
|
@ -34,6 +35,7 @@ pub struct SignedPodVerifyGadget {
|
|||
|
||||
impl SignedPodVerifyGadget {
|
||||
pub fn eval(&self, builder: &mut CircuitBuilder<F, D>) -> Result<SignedPodVerifyTarget> {
|
||||
let measure = measure_gates_begin!(builder, "SignedPodVerify");
|
||||
// 1. Verify id
|
||||
let id = builder.add_virtual_hash();
|
||||
let mut mt_proofs = Vec::new();
|
||||
|
|
@ -65,6 +67,7 @@ impl SignedPodVerifyGadget {
|
|||
// 3.c. connect signed message to pod.id
|
||||
builder.connect_values(ValueTarget::from_slice(&id.elements), signature.msg);
|
||||
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok(SignedPodVerifyTarget {
|
||||
params: self.params.clone(),
|
||||
id,
|
||||
|
|
|
|||
|
|
@ -623,9 +623,12 @@ pub mod tests {
|
|||
let params = middleware::Params {
|
||||
// Currently the circuit uses random access that only supports vectors of length 64.
|
||||
// With max_input_main_pods=3 we need random access to a vector of length 73.
|
||||
max_input_main_pods: 1,
|
||||
max_input_main_pods: 0,
|
||||
max_custom_predicate_batches: 0,
|
||||
max_custom_predicate_verifications: 0,
|
||||
..Default::default()
|
||||
};
|
||||
println!("{:#?}", params);
|
||||
|
||||
let (gov_id_builder, pay_stub_builder, sanction_list_builder) =
|
||||
zu_kyc_sign_pod_builders(¶ms);
|
||||
|
|
@ -640,6 +643,7 @@ pub mod tests {
|
|||
|
||||
let mut prover = Prover {};
|
||||
let kyc_pod = kyc_builder.prove(&mut prover, ¶ms)?;
|
||||
crate::measure_gates_print!();
|
||||
let pod = (kyc_pod.pod as Box<dyn Any>).downcast::<MainPod>().unwrap();
|
||||
|
||||
Ok(pod.verify()?)
|
||||
|
|
@ -741,6 +745,7 @@ pub mod tests {
|
|||
max_custom_predicate_verifications: 8,
|
||||
..Default::default()
|
||||
};
|
||||
println!("{:#?}", params);
|
||||
|
||||
let mut alice = Signer(SecretKey(RawValue::from(1)));
|
||||
let bob = Signer(SecretKey(RawValue::from(2)));
|
||||
|
|
@ -768,6 +773,7 @@ pub mod tests {
|
|||
|
||||
let mut prover = Prover {};
|
||||
let alice_bob_ethdos = alice_bob_ethdos_builder.prove(&mut prover, ¶ms)?;
|
||||
crate::measure_gates_print!();
|
||||
let pod = (alice_bob_ethdos.pod as Box<dyn Any>)
|
||||
.downcast::<MainPod>()
|
||||
.unwrap();
|
||||
|
|
@ -790,6 +796,7 @@ pub mod tests {
|
|||
max_custom_predicate_verifications: 2,
|
||||
..Default::default()
|
||||
};
|
||||
println!("{:#?}", params);
|
||||
|
||||
let mut cpb_builder = CustomPredicateBatchBuilder::new(params.clone(), "cpb".into());
|
||||
let stb0 = STB::new(NP::ValueOf)
|
||||
|
|
@ -824,6 +831,7 @@ pub mod tests {
|
|||
|
||||
let mut prover = Prover {};
|
||||
let pod = pod_builder.prove(&mut prover, ¶ms)?;
|
||||
crate::measure_gates_print!();
|
||||
|
||||
let pod = (pod.pod as Box<dyn Any>).downcast::<MainPod>().unwrap();
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ use crate::{
|
|||
error::Result,
|
||||
primitives::merkletree::MerkleClaimAndProof,
|
||||
},
|
||||
measure_gates_begin, measure_gates_end,
|
||||
middleware::{EMPTY_HASH, EMPTY_VALUE, F, HASH_SIZE},
|
||||
};
|
||||
|
||||
|
|
@ -59,6 +60,7 @@ pub struct MerkleClaimAndProofTarget {
|
|||
impl MerkleProofGadget {
|
||||
/// creates the targets and defines the logic of the circuit
|
||||
pub fn eval(&self, builder: &mut CircuitBuilder<F, D>) -> Result<MerkleClaimAndProofTarget> {
|
||||
let measure = measure_gates_begin!(builder, format!("MerkleProof_{}", self.max_depth));
|
||||
let enabled = builder.add_virtual_bool_target_safe();
|
||||
let root = builder.add_virtual_hash();
|
||||
let key = builder.add_virtual_value();
|
||||
|
|
@ -139,6 +141,7 @@ impl MerkleProofGadget {
|
|||
for j in 0..HASH_SIZE {
|
||||
builder.connect(computed_root[j], expected_root[j]);
|
||||
}
|
||||
measure_gates_end!(builder, measure);
|
||||
|
||||
Ok(MerkleClaimAndProofTarget {
|
||||
max_depth: self.max_depth,
|
||||
|
|
@ -221,6 +224,8 @@ pub struct MerkleProofExistenceTarget {
|
|||
impl MerkleProofExistenceGadget {
|
||||
/// creates the targets and defines the logic of the circuit
|
||||
pub fn eval(&self, builder: &mut CircuitBuilder<F, D>) -> Result<MerkleProofExistenceTarget> {
|
||||
let measure =
|
||||
measure_gates_begin!(builder, format!("MerkleProofExistence_{}", self.max_depth));
|
||||
let enabled = builder.add_virtual_bool_target_safe();
|
||||
let root = builder.add_virtual_hash();
|
||||
let key = builder.add_virtual_value();
|
||||
|
|
@ -249,6 +254,7 @@ impl MerkleProofExistenceGadget {
|
|||
for j in 0..HASH_SIZE {
|
||||
builder.connect(computed_root[j], expected_root[j]);
|
||||
}
|
||||
measure_gates_end!(builder, measure);
|
||||
|
||||
Ok(MerkleProofExistenceTarget {
|
||||
max_depth: self.max_depth,
|
||||
|
|
@ -494,6 +500,7 @@ pub mod tests {
|
|||
for max_depth in [10, 16, 32, 40, 64, 128, 130, 250, 256] {
|
||||
test_merkleproof_verify_opt(max_depth, true)?;
|
||||
}
|
||||
crate::measure_gates_print!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ use crate::{
|
|||
PublicKey, SecretKey, Signature, DUMMY_PUBLIC_INPUTS, DUMMY_SIGNATURE, VP,
|
||||
},
|
||||
},
|
||||
measure_gates_begin, measure_gates_end,
|
||||
middleware::{Hash, RawValue, EMPTY_HASH, EMPTY_VALUE, F, VALUE_SIZE},
|
||||
};
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ impl SignatureVerifyGadget {
|
|||
impl SignatureVerifyGadget {
|
||||
/// creates the targets and defines the logic of the circuit
|
||||
pub fn eval(&self, builder: &mut CircuitBuilder<F, D>) -> Result<SignatureVerifyTarget> {
|
||||
let measure = measure_gates_begin!(builder, "SignatureVerify");
|
||||
let enabled = builder.add_virtual_bool_target_safe();
|
||||
|
||||
let common_data = VP.0.common.clone();
|
||||
|
|
@ -115,6 +117,7 @@ impl SignatureVerifyGadget {
|
|||
|
||||
builder.verify_proof::<C>(&proof_targ, &verifier_data_targ, &common_data);
|
||||
|
||||
measure_gates_end!(builder, measure);
|
||||
Ok(SignatureVerifyTarget {
|
||||
verifier_data_targ,
|
||||
enabled,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue