Skip to content

Commit a7a3017

Browse files
authored
Split Params into base and developer-defined (#458)
I thought it would be nice to have a Predicate for the typed value so that the developer can work with predicates as values comfortably. Then I noticed that hashing a predicate required `Params` which would have been annoying for converting a `TypedValue::Predicate` to `RawValue` and this led to a small refactor over how `Params` work. We already had some fields in the `Params` struct that determine compatibility between encoded data. They can be seen as determining a kind of ABI compatibility. In general it's better if those parameters don't change so that different circuit configurations can still verify proofs from each other. So I decided to force those parameters to be constant in the code base and not allow the user of our library to change them. Many field element serialization/deserialization functions in our code depended on those parameters, and since now they are constant many functions get rid of the `Params` argument, which simplifies the code. This includes the serialization of a `Predicate` which was required to calculate its hash.
1 parent 498e946 commit a7a3017

File tree

20 files changed

+376
-468
lines changed

20 files changed

+376
-468
lines changed

src/backends/plonky2/circuits/common.rs

Lines changed: 73 additions & 149 deletions
Large diffs are not rendered by default.

src/backends/plonky2/circuits/mainpod.rs

Lines changed: 77 additions & 101 deletions
Large diffs are not rendered by default.

src/backends/plonky2/emptypod.rs

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,9 @@ fn verify_empty_pod_circuit(
6767
builder: &mut CircuitBuilder,
6868
empty_pod: &EmptyPodVerifyTarget,
6969
) {
70-
let empty_statement = StatementTarget::from_flattened(
71-
params,
72-
&builder.constants(&empty_statement().to_fields(params)),
73-
);
74-
let sts_hash = calculate_statements_hash_circuit(params, builder, &[empty_statement]);
70+
let empty_statement =
71+
StatementTarget::from_flattened(params, &builder.constants(&empty_statement().to_fields()));
72+
let sts_hash = calculate_statements_hash_circuit(builder, &[empty_statement]);
7573
builder.register_public_inputs(&sts_hash.elements);
7674
builder.register_public_inputs(&empty_pod.vds_root.elements);
7775
}
@@ -126,7 +124,7 @@ fn build() -> Result<(EmptyPodVerifyTarget, CircuitData)> {
126124
}
127125

128126
impl EmptyPod {
129-
fn new(params: &Params, vd_set: VDSet) -> Result<EmptyPod> {
127+
fn new(vd_set: VDSet) -> Result<EmptyPod> {
130128
let (empty_pod_verify_target, data) = &*cache_get_standard_empty_pod_circuit_data();
131129

132130
let mut pw = PartialWitness::<F>::new();
@@ -139,23 +137,18 @@ impl EmptyPod {
139137
};
140138
let common_hash = hash_common_data(&data.common).expect("hash ok");
141139
Ok(EmptyPod {
142-
params: params.clone(),
140+
params: Params::default(),
143141
verifier_only: VerifierOnlyCircuitDataSerializer(data.verifier_only.clone()),
144142
common_hash,
145143
sts_hash,
146144
vd_set,
147145
proof: proof.proof,
148146
})
149147
}
150-
pub fn new_boxed(params: &Params, vd_set: VDSet) -> Box<dyn Pod> {
151-
let default_params = Params::default();
152-
assert_eq!(default_params.id_params(), params.id_params());
153-
154-
let empty_pod = cache::get(
155-
"empty_pod",
156-
&(default_params, vd_set),
157-
|(params, vd_set)| Self::new(params, vd_set.clone()).expect("prove EmptyPod"),
158-
)
148+
pub fn new_boxed(vd_set: VDSet) -> Box<dyn Pod> {
149+
let empty_pod = cache::get("empty_pod", &vd_set, |vd_set| {
150+
Self::new(vd_set.clone()).expect("prove EmptyPod")
151+
})
159152
.expect("cache ok");
160153
Box::new(empty_pod.clone())
161154
}
@@ -178,13 +171,13 @@ impl Pod for EmptyPod {
178171
.into_iter()
179172
.map(mainpod::Statement::from)
180173
.collect_vec();
181-
let sts_hash = calculate_statements_hash(&statements, &self.params);
174+
let sts_hash = calculate_statements_hash(&statements);
182175
if sts_hash != self.sts_hash {
183176
return Err(Error::statements_hash_not_equal(self.sts_hash, sts_hash));
184177
}
185178

186179
let public_inputs = sts_hash
187-
.to_fields(&self.params)
180+
.to_fields()
188181
.iter()
189182
.chain(self.vd_set.root().0.iter())
190183
.cloned()
@@ -258,9 +251,7 @@ pub mod tests {
258251

259252
#[test]
260253
fn test_empty_pod() {
261-
let params = Params::default();
262-
263-
let empty_pod = EmptyPod::new_boxed(&params, VDSet::new(&[]));
254+
let empty_pod = EmptyPod::new_boxed(VDSet::new(&[]));
264255
empty_pod.verify().unwrap();
265256
}
266257
}

src/backends/plonky2/mainpod/mod.rs

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,20 @@ use crate::{
5050
/// circuits with a small `max_public_statements` only pay for `max_public_statements` by starting
5151
/// the poseidon state with a precomputed constant corresponding to the front-padding part: `id =
5252
/// hash(serialize(reverse(statements || none-statements)))`
53-
pub fn calculate_statements_hash(statements: &[Statement], params: &Params) -> middleware::Hash {
54-
assert!(statements.len() <= params.num_public_statements_hash);
55-
assert!(params.max_public_statements <= params.num_public_statements_hash);
53+
pub fn calculate_statements_hash(statements: &[Statement]) -> middleware::Hash {
54+
assert!(statements.len() <= Params::num_public_statements_hash());
5655

5756
let mut none_st: Statement = middleware::Statement::None.into();
58-
pad_statement(params, &mut none_st);
57+
pad_statement(&mut none_st);
5958
let statements_back_padded = statements
6059
.iter()
6160
.chain(iter::repeat(&none_st))
62-
.take(params.num_public_statements_hash)
61+
.take(Params::num_public_statements_hash())
6362
.collect_vec();
6463
let field_elems = statements_back_padded
6564
.iter()
6665
.rev()
67-
.flat_map(|statement| statement.to_fields(params))
66+
.flat_map(|statement| statement.to_fields())
6867
.collect::<Vec<_>>();
6968
Hash(PoseidonHash::hash_no_pad(&field_elems).elements)
7069
}
@@ -115,7 +114,7 @@ pub(crate) fn extract_custom_predicate_verifications(
115114
.find_map(|(i, cpb)| (cpb.id() == cpr.batch.id()).then_some(i))
116115
.expect("find the custom predicate from the extracted unique list");
117116
let custom_predicate_table_index =
118-
batch_index * params.max_custom_batch_size + cpr.index;
117+
batch_index * Params::max_custom_batch_size() + cpr.index;
119118
aux_list[i] = OperationAux::CustomPredVerifyIndex(table.len());
120119
table.push(CustomPredicateVerification {
121120
custom_predicate_table_index,
@@ -326,8 +325,8 @@ fn fill_pad<T: Clone>(v: &mut Vec<T>, pad_value: T, len: usize) {
326325
}
327326
}
328327

329-
pub fn pad_statement(params: &Params, s: &mut Statement) {
330-
fill_pad(&mut s.1, StatementArg::None, params.max_statement_args)
328+
pub fn pad_statement(s: &mut Statement) {
329+
fill_pad(&mut s.1, StatementArg::None, Params::max_statement_args())
331330
}
332331

333332
fn pad_operation_args(params: &Params, args: &mut Vec<OperationArg>) {
@@ -353,7 +352,7 @@ pub(crate) fn layout_statements(
353352
// We mocking or we don't need padding so we skip creating an EmptyPod
354353
MockEmptyPod::new_boxed(params, inputs.vd_set.clone())
355354
} else {
356-
EmptyPod::new_boxed(params, inputs.vd_set.clone())
355+
EmptyPod::new_boxed(inputs.vd_set.clone())
357356
};
358357
let empty_pod = empty_pod_box.as_ref();
359358
assert!(inputs.pods.len() <= params.max_input_pods);
@@ -367,7 +366,7 @@ pub(crate) fn layout_statements(
367366
.unwrap_or(&middleware::Statement::None)
368367
.clone()
369368
.into();
370-
pad_statement(params, &mut st);
369+
pad_statement(&mut st);
371370
statements.push(st);
372371
}
373372
}
@@ -386,7 +385,7 @@ pub(crate) fn layout_statements(
386385
.unwrap_or(&middleware::Statement::None)
387386
.clone()
388387
.into();
389-
pad_statement(params, &mut st);
388+
pad_statement(&mut st);
390389
statements.push(st);
391390
}
392391

@@ -399,7 +398,7 @@ pub(crate) fn layout_statements(
399398
.unwrap_or(&middleware::Statement::None)
400399
.clone()
401400
.into();
402-
pad_statement(params, &mut st);
401+
pad_statement(&mut st);
403402
statements.push(st);
404403
}
405404

@@ -475,7 +474,7 @@ impl MainPodProver for Prover {
475474
// We don't need padding so we skip creating an EmptyPod
476475
MockEmptyPod::new_boxed(params, inputs.vd_set.clone())
477476
} else {
478-
EmptyPod::new_boxed(params, inputs.vd_set.clone())
477+
EmptyPod::new_boxed(inputs.vd_set.clone())
479478
};
480479
let inputs = MainPodInputs {
481480
pods: &inputs
@@ -491,10 +490,7 @@ impl MainPodProver for Prover {
491490
let input_pods_pub_self_statements = inputs
492491
.pods
493492
.iter()
494-
.map(|pod| {
495-
assert_eq!(params.id_params(), pod.params().id_params());
496-
pod.pub_self_statements()
497-
})
493+
.map(|pod| pod.pub_self_statements())
498494
.collect_vec();
499495

500496
// Aux values for backend::Operation
@@ -527,7 +523,7 @@ impl MainPodProver for Prover {
527523
let operations = process_public_statements_operations(params, &statements, operations)?;
528524

529525
// get the id out of the public statements
530-
let sts_hash = calculate_statements_hash(&public_statements, params);
526+
let sts_hash = calculate_statements_hash(&public_statements);
531527

532528
let common_hash: String = cache_get_rec_main_pod_common_hash(params).clone();
533529
let proofs = inputs
@@ -718,7 +714,7 @@ impl Pod for MainPod {
718714
)));
719715
}
720716
// 2. get the id out of the public statements
721-
let sts_hash = calculate_statements_hash(&self.public_statements, &self.params);
717+
let sts_hash = calculate_statements_hash(&self.public_statements);
722718
if sts_hash != self.sts_hash {
723719
return Err(Error::statements_hash_not_equal(self.sts_hash, sts_hash));
724720
}
@@ -738,7 +734,7 @@ impl Pod for MainPod {
738734
let rec_main_pod_verifier_circuit_data =
739735
&*cache_get_rec_main_pod_verifier_circuit_data(&self.params);
740736
let public_inputs = sts_hash
741-
.to_fields(&self.params)
737+
.to_fields()
742738
.iter()
743739
.chain(self.vd_set.root().0.iter())
744740
.cloned()
@@ -998,14 +994,10 @@ pub mod tests {
998994
max_input_pods_public_statements: 2,
999995
max_statements: 5,
1000996
max_public_statements: 2,
1001-
num_public_statements_hash: 4,
1002-
max_statement_args: 4,
1003-
max_operation_args: 4,
997+
max_operation_args: 5,
1004998
max_custom_predicate_batches: 2,
1005999
max_custom_predicate_verifications: 2,
1006-
max_custom_predicate_arity: 2,
10071000
max_custom_predicate_wildcards: 3,
1008-
max_custom_batch_size: 2,
10091001
max_merkle_proofs_containers: 2,
10101002
max_merkle_tree_state_transition_proofs_containers: 2,
10111003
max_public_key_of: 2,
@@ -1067,10 +1059,7 @@ pub mod tests {
10671059
max_input_pods: 0,
10681060
max_statements: 9,
10691061
max_public_statements: 4,
1070-
max_statement_args: 4,
1071-
max_operation_args: 4,
1072-
max_custom_predicate_arity: 3,
1073-
max_custom_batch_size: 3,
1062+
max_operation_args: 5,
10741063
max_custom_predicate_wildcards: 4,
10751064
max_custom_predicate_verifications: 2,
10761065
max_merkle_proofs_containers: 3,

src/backends/plonky2/mainpod/statement.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
44

55
use crate::{
66
backends::plonky2::error::{Error, Result},
7-
middleware::{self, NativePredicate, Params, Predicate, StatementArg, ToFields, Value},
7+
middleware::{self, NativePredicate, Predicate, StatementArg, ToFields, Value, BASE_PARAMS},
88
};
99

1010
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@@ -30,14 +30,14 @@ impl Statement {
3030
}
3131

3232
impl ToFields for Statement {
33-
fn to_fields(&self, params: &Params) -> Vec<middleware::F> {
34-
let mut fields = self.0.hash(params).to_fields(params);
33+
fn to_fields(&self) -> Vec<middleware::F> {
34+
let mut fields = self.0.hash().to_fields();
3535
fields.extend(
3636
self.1
3737
.iter()
3838
.chain(iter::repeat(&StatementArg::None))
39-
.take(params.max_statement_args)
40-
.flat_map(|arg| arg.to_fields(params)),
39+
.take(BASE_PARAMS.max_statement_args)
40+
.flat_map(|arg| arg.to_fields()),
4141
);
4242
fields
4343
}

src/backends/plonky2/mock/emptypod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn empty_statement() -> Statement {
3030
impl MockEmptyPod {
3131
pub fn new_boxed(params: &Params, vd_set: VDSet) -> Box<dyn Pod> {
3232
let statements = [mainpod::Statement::from(empty_statement())];
33-
let sts_hash = calculate_statements_hash(&statements, params);
33+
let sts_hash = calculate_statements_hash(&statements);
3434
Box::new(Self {
3535
params: params.clone(),
3636
sts_hash,
@@ -49,7 +49,7 @@ impl Pod for MockEmptyPod {
4949
.into_iter()
5050
.map(mainpod::Statement::from)
5151
.collect_vec();
52-
let sts_hash = calculate_statements_hash(&statements, &self.params);
52+
let sts_hash = calculate_statements_hash(&statements);
5353
if sts_hash != self.sts_hash {
5454
return Err(Error::statements_hash_not_equal(self.sts_hash, sts_hash));
5555
}

src/backends/plonky2/mock/mainpod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl MockMainPod {
167167
let operations = process_public_statements_operations(params, &statements, operations)?;
168168

169169
// get the id out of the public statements
170-
let sts_hash = calculate_statements_hash(&public_statements, params);
170+
let sts_hash = calculate_statements_hash(&public_statements);
171171

172172
let pad_pod = MockEmptyPod::new_boxed(params, inputs.vd_set.clone());
173173
let input_pods: Vec<Box<dyn Pod>> = inputs

src/examples/mod.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,21 +258,21 @@ pub fn great_boy_pod_builder(
258258

259259
let mut great_boy = MainPodBuilder::new(params, vd_set);
260260
for good_boy_signed_dict in good_boy_signed_dicts {
261-
great_boy.pub_op(Operation::dict_signed_by(good_boy_signed_dict))?;
261+
great_boy.priv_op(Operation::dict_signed_by(good_boy_signed_dict))?;
262262
}
263263
for friend_signed_dict in friend_signed_dicts {
264-
great_boy.pub_op(Operation::dict_signed_by(friend_signed_dict))?;
264+
great_boy.priv_op(Operation::dict_signed_by(friend_signed_dict))?;
265265
}
266266

267267
for good_boy_idx in 0..2 {
268268
for issuer_idx in 0..2 {
269269
// Each good boy POD comes from a valid issuer
270-
great_boy.pub_op(Operation::set_contains(
270+
great_boy.priv_op(Operation::set_contains(
271271
good_boy_issuers,
272272
good_boy_signed_dicts[good_boy_idx * 2 + issuer_idx].public_key,
273273
))?;
274274
// Each good boy has 2 good boy pods
275-
great_boy.pub_op(Operation::eq(
275+
great_boy.priv_op(Operation::eq(
276276
(good_boy_signed_dicts[good_boy_idx * 2 + issuer_idx], "user"),
277277
friend_signed_dicts[good_boy_idx].public_key,
278278
))?;
@@ -302,8 +302,6 @@ pub fn great_boy_pod_full_flow() -> Result<MainPodBuilder> {
302302
max_signed_by: 6,
303303
max_input_pods: 0,
304304
max_statements: 100,
305-
max_public_statements: 50,
306-
num_public_statements_hash: 50,
307305
..Default::default()
308306
};
309307
let vd_set = &*MOCK_VD_SET;

src/frontend/custom.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,19 +171,19 @@ impl CustomPredicateBatchBuilder {
171171
priv_args: &[&str],
172172
sts: &[StatementTmplBuilder],
173173
) -> Result<Predicate> {
174-
if self.predicates.len() >= self.params.max_custom_batch_size {
174+
if self.predicates.len() >= Params::max_custom_batch_size() {
175175
return Err(Error::max_length(
176176
"self.predicates.len".to_string(),
177177
self.predicates.len(),
178-
self.params.max_custom_batch_size,
178+
Params::max_custom_batch_size(),
179179
));
180180
}
181181

182-
if args.len() > self.params.max_statement_args {
182+
if args.len() > Params::max_statement_args() {
183183
return Err(Error::max_length(
184184
"args.len".to_string(),
185185
args.len(),
186-
self.params.max_statement_args,
186+
Params::max_statement_args(),
187187
));
188188
}
189189
if (args.len() + priv_args.len()) > self.params.max_custom_predicate_wildcards {
@@ -278,7 +278,6 @@ mod tests {
278278
use StatementTmplBuilder as STB;
279279

280280
let params = Params {
281-
max_statement_args: 6,
282281
max_custom_predicate_wildcards: 12,
283282
..Default::default()
284283
};
@@ -292,7 +291,7 @@ mod tests {
292291

293292
let eth_dos_batch_mw: middleware::CustomPredicateBatch =
294293
Arc::unwrap_or_clone(eth_dos_batch);
295-
let fields = eth_dos_batch_mw.to_fields(&params);
294+
let fields = eth_dos_batch_mw.to_fields();
296295
println!("Batch b, serialized: {:?}", fields);
297296

298297
Ok(())

src/frontend/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ impl MainPodBuilder {
600600
}
601601
wildcard_map[index] = Some(value);
602602
}
603-
fill_wildcard_values(&self.params, pred, &args, &mut wildcard_map)?;
603+
fill_wildcard_values(pred, &args, &mut wildcard_map)?;
604604
let v_default = Value::from(0);
605605
let st_args: Vec<_> = wildcard_map
606606
.into_iter()

0 commit comments

Comments
 (0)